Re: [Python-Dev] PEP 492: async/await in Python; version 4

2015-05-05 Thread Koos Zevenhoven
tds333  gmail.com  gmail.com> writes:

> 
> Hi,
> 
> still watching progress here. Read all posts and changes.
> 
> Everything improved and I know it is a lot of work. Thx for doing this.
> 
> But I still think this PEP goes to far.
> 
> [...]
> 
> We forget to address the major problems here. How can someone in a
> "sync" script use this async stuff easy. How can async and sync stuff
> cooperate and we don't need to rewrite the world for async stuff.
> How can a normal user access the power of async stuff without rewriting
> all his code. So he can use a simple asyc request library in his code.
> How can a normal user learn and use all this in an easy way.
> 
> [...]

Hi Wolfgang,

You may want to see what I just posted on python-ideas. What I wrote about 
is related to several things you mention, and might provide a remedy.

-- Koos



___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 550 v4

2017-09-07 Thread Koos Zevenhoven
On Thu, Sep 7, 2017 at 10:54 AM, Greg Ewing 
wrote:

> Yury Selivanov wrote:
>
>> def foo():
>>  var = ContextVar()
>>  var.set(1)
>>
>> for _ in range(10**6): foo()
>>
>> If 'var' is strongly referenced, we would have a bunch of them.
>>
>
> Erk. This is not how I envisaged context vars would be
> used. What I thought you would do is this:
>
>my_context_var = ContextVar()
>
>def foo():
>   my_context_var.set(1)
>
> This problem would also not arise if context vars
> simply had names instead of being magic key objects:
>
>def foo():
>   contextvars.set("mymodule.myvar", 1)
>
> That's another thing I think would be an improvement,
> but it's orthogonal to what we're talking about here
> and would be best discussed separately.
>
>
​​​There are lots of things in this discussion that I should have commented
on, but here's one related to this.

PEP 555 does not have the resource-management issue described above and
needs no additional tricks to achieve that:

# using PEP 555

def foo():
   var = contextvars.Var()
   with var.assign(1):
   # do something [*]

​for _ in range(10**6):
foo(​)


Every time foo is called, a new context variable is created, but that's
perfectly fine, and lightweight. As soon as the context manager exits,
there are no references to the Assignment object returned by var.assign(1),
and as soon as foo() returns, there are no references to var, so everything
should get cleaned up nicely.

And regarding string keys, they have pros and cons, and they can be added
easily, so let's not go there now.

-- Koos


[*] (nit-picking) without closures that would keep the var reference alive


-- 
+ Koos Zevenhoven + http://twitter.com/k7hoven +
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Consolidate stateful runtime globals

2017-09-07 Thread Koos Zevenhoven
On Wed, Sep 6, 2017 at 8:17 PM, Benjamin Peterson 
wrote:

> On Wed, Sep 6, 2017, at 10:08, Antoine Pitrou wrote:
> > On Wed, 06 Sep 2017 09:42:29 -0700
> > Benjamin Peterson  wrote:
> > > On Wed, Sep 6, 2017, at 03:14, Antoine Pitrou wrote:
> > > >
> > > > Hello,
> > > >
> > > > I'm a bit concerned about
> > > > https://github.com/python/cpython/commit/76d5abc8684bac4f2fc
> 7cccfe2cd940923357351
> > > >
> > > > My main gripe is that makes writing C code more tedious.  Simple C
> > > > global variables such as "_once_registry" are now spelled
> > > > "_PyRuntime.warnings.once_registry".  The most egregious example
> seems
> > > > to be "_PyRuntime.ceval.gil.locked" (used to be simply "gil_locked").
> > > >
> > > > Granted, C is more verbose than Python, but it doesn't have to become
> > > > that verbose.  I don't know about you, but when code becomes annoying
> > > > to type, I tend to try and take shortcuts.
> > >
> > > How often are you actually typing the names of runtime globals, though?
> >
> > Not very often, but if I want to experiment with some low-level
> > implementation details, it is nice to avoid the hassle.
>
> It seems like this could be remediated with some inline functions or
> macros, which would also help safely encapsulate state.
>
> >
> > There's also a readability argument: with very long names, expressions
> > can become less easy to parse.
> >
> > > If you are using a globals, perhaps the typing time will allow you to
> > > fully consider the gravity of the situation.
> >
> > Right, I needed to be reminded of how perilous the use of C globals is.
> > Perhaps I should contact the PSRT the next time I contemplate using a C
> > global.
>
> It's not just you but future readers.


Great. Related to this, there is also discussion on dangers of globals and
other widely-scoped variables in the Rationale section of PEP 555
(Context-local variables), for anyone interested. But if you read the draft
I posted on python-ideas last Monday, you've already seen it.

––Koos


-- 
+ Koos Zevenhoven + http://twitter.com/k7hoven +
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Consolidate stateful runtime globals

2017-09-07 Thread Koos Zevenhoven
On Wed, Sep 6, 2017 at 8:17 PM, Benjamin Peterson 
wrote:

> On Wed, Sep 6, 2017, at 10:08, Antoine Pitrou wrote:
> > On Wed, 06 Sep 2017 09:42:29 -0700
> > Benjamin Peterson  wrote:
> > > On Wed, Sep 6, 2017, at 03:14, Antoine Pitrou wrote:
> > > >
> > > > Hello,
> > > >
> > > > I'm a bit concerned about
> > > > https://github.com/python/cpython/commit/
> 76d5abc8684bac4f2fc7cccfe2cd940923357351
> > > >
> > > > My main gripe is that makes writing C code more tedious.  Simple C
> > > > global variables such as "_once_registry" are now spelled
> > > > "_PyRuntime.warnings.once_registry".  The most egregious example
> seems
> > > > to be "_PyRuntime.ceval.gil.locked" (used to be simply "gil_locked").
> > > >
> > > > Granted, C is more verbose than Python, but it doesn't have to become
> > > > that verbose.  I don't know about you, but when code becomes annoying
> > > > to type, I tend to try and take shortcuts.
> > >
> > > How often are you actually typing the names of runtime globals, though?
> >
> > Not very often, but if I want to experiment with some low-level
> > implementation details, it is nice to avoid the hassle.
>
> It seems like this could be remediated with some inline functions or
> macros, which would also help safely encapsulate state.
>
> >
> > There's also a readability argument: with very long names, expressions
> > can become less easy to parse.
> >
> > > If you are using a globals, perhaps the typing time will allow you to
> > > fully consider the gravity of the situation.
> >
> > Right, I needed to be reminded of how perilous the use of C globals is.
> > Perhaps I should contact the PSRT the next time I contemplate using a C
> > global.
>
> It's not just you but future readers.


Great. Related to this, there is also discussion on dangers of globals and
other widely-scoped variables in the Rationale section of PEP 555
(Context-local variables), for anyone interested. But if you read the draft
I posted on python-ideas last Monday, you've already seen it.

––Koos


-- 
+ Koos Zevenhoven + http://twitter.com/k7hoven +
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 559 - built-in noop()

2017-09-09 Thread Koos Zevenhoven
On Sat, Sep 9, 2017 at 10:54 PM, Victor Stinner 
wrote:

> I always wanted this feature (no kidding).
>
> Would it be possible to add support for the context manager?
>
> with noop(): ...
>
> Maybe noop can be an instance of:
>
> class Noop:
>   def __enter__(self, *args, **kw): return self
>   def __exit__(self, *args): pass
>   def __call__(self, *args, **kw): return self
>
>

​This worries me. Clearly, assuming a None-coercing noop, we must have:

noop(foo) is None
noop[foo] is None
noop * ​foo is None
foo * noop is None
noop + foo is None
foo + noop is None
noop - noop is None
...
noop / 0 is None
...
(noop == None) is None

which can all sort of be implicitly extrapolated to be in the PEP.

But how are you planning to implement:

(noop is None) is None
(obj in noop) is None
(noop in obj) is None

or

(None or noop) is None
(None and noop) is None

and finally:

foo(noop) is None

?

Sooner or later, someone will need all these features, and the PEP does not
seem to address the issue in any way.

-- Koos




> Victor
>
> Le 9 sept. 2017 11:48 AM, "Barry Warsaw"  a écrit :
>
>> I couldn’t resist one more PEP from the Core sprint.  I won’t reveal
>> where or how this one came to me.
>>
>> -Barry
>>
>> PEP: 559
>> Title: Built-in noop()
>> Author: Barry Warsaw 
>> Status: Draft
>> Type: Standards Track
>> Content-Type: text/x-rst
>> Created: 2017-09-08
>> Python-Version: 3.7
>> Post-History: 2017-09-09
>>
>>
>> Abstract
>> 
>>
>> This PEP proposes adding a new built-in function called ``noop()`` which
>> does
>> nothing but return ``None``.
>>
>>
>> Rationale
>> =
>>
>> It is trivial to implement a no-op function in Python.  It's so easy in
>> fact
>> that many people do it many times over and over again.  It would be
>> useful in
>> many cases to have a common built-in function that does nothing.
>>
>> One use case would be for PEP 553, where you could set the breakpoint
>> environment variable to the following in order to effectively disable it::
>>
>> $ setenv PYTHONBREAKPOINT=noop
>>
>>
>> Implementation
>> ==
>>
>> The Python equivalent of the ``noop()`` function is exactly::
>>
>> def noop(*args, **kws):
>> return None
>>
>> The C built-in implementation is available as a pull request.
>>
>>
>> Rejected alternatives
>> =
>>
>> ``noop()`` returns something
>> 
>>
>> YAGNI.
>>
>> This is rejected because it complicates the semantics.  For example, if
>> you
>> always return both ``*args`` and ``**kws``, what do you return when none
>> of
>> those are given?  Returning a tuple of ``((), {})`` is kind of ugly, but
>> provides consistency.  But you might also want to just return ``None``
>> since
>> that's also conceptually what the function was passed.
>>
>> Or, what if you pass in exactly one positional argument, e.g.
>> ``noop(7)``.  Do
>> you return ``7`` or ``((7,), {})``?  And so on.
>>
>> The author claims that you won't ever need the return value of ``noop()``
>> so
>> it will always return ``None``.
>>
>> Coghlin's Dialogs (edited for formatting):
>>
>> My counterargument to this would be ``map(noop, iterable)``,
>> ``sorted(iterable, key=noop)``, etc. (``filter``, ``max``, and
>> ``min`` all accept callables that accept a single argument, as do
>> many of the itertools operations).
>>
>> Making ``noop()`` a useful default function in those cases just
>> needs the definition to be::
>>
>>def noop(*args, **kwds):
>>return args[0] if args else None
>>
>> The counterargument to the counterargument is that using ``None``
>> as the default in all these cases is going to be faster, since it
>> lets the algorithm skip the callback entirely, rather than calling
>> it and having it do nothing useful.
>>
>>
>> Copyright
>> =
>>
>> This document has been placed in the public domain.
>>
>>
>> ..
>>Local Variables:
>>mode: indented-text
>>indent-tabs-mode: nil
>>sentence-end-double-space: t
>>fill-column: 70
>>coding: utf-8
>>End:
>>
>>
>> ___
>> Python-Dev mailing list
>> Python-Dev@python.org
>> https://mail.python.org/mailman/listinfo/python-dev
>> Unsubscribe: https://mail.python.org/mailman/options/python-dev/victor.
>> stinner%40gmail.com
>>
>>
> ___
> Python-Dev mailing list
> Python-Dev@python.org
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe: https://mail.python.org/mailman/options/python-dev/
> k7hoven%40gmail.com
>
>


-- 
+ Koos Zevenhoven + http://twitter.com/k7hoven +
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 559 - built-in noop()

2017-09-10 Thread Koos Zevenhoven
On Sun, Sep 10, 2017 at 8:21 PM, Barry Warsaw  wrote:

> On Sep 9, 2017, at 15:12, Guido van Rossum  wrote:
> >
> > I can't tell whether this was meant seriously, but I don't think it's
> worth it. People can easily write their own dummy function and give it any
> damn semantics they want. Let's reject the PEP.
>
> Alrighty then!  (Yes, it was serious, but I claim post-sprint
> euphoria/delirium).
>
>
​Just for future reference, here's a slightly more serious comment:

I think the "pass" statement wasn't mentioned yet, but clearly noop() would
be duplication of functionality. So maybe the closest thing without
duplication would be to make "pass" an expression which evaluates to a
no-op function, but which the compiler could perhaps optimize away if it's
a statement by itself, or is a builtin.

-- Koos


-- 
+ Koos Zevenhoven + http://twitter.com/k7hoven +
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 554 v2 (new "interpreters" module)

2017-09-10 Thread Koos Zevenhoven
On Mon, Sep 11, 2017 at 8:51 AM, Nick Coghlan  wrote:

> On 10 September 2017 at 04:04, Nathaniel Smith  wrote:
> > On Sep 8, 2017 4:06 PM, "Eric Snow"  wrote:
> >
> >
> >run(code):
> >
> >   Run the provided Python code in the interpreter, in the current
> >   OS thread.  If the interpreter is already running then raise
> >   RuntimeError in the interpreter that called ``run()``.
> >
> >   The current interpreter (which called ``run()``) will block until
> >   the subinterpreter finishes running the requested code.  Any
> >   uncaught exception in that code will bubble up to the current
> >   interpreter.
> >
> >
> > This phrase "bubble up" here is doing a lot of work :-). Can you
> elaborate
> > on what you mean? The text now makes it seem like the exception will just
> > pass from one interpreter into another, but that seems impossible – it'd
> > mean sharing not just arbitrary user defined exception classes but full
> > frame objects...
>
> Indeed, I think this will need to be something more akin to
> https://docs.python.org/3/library/subprocess.html#
> subprocess.CalledProcessError,
> where the child interpreter is able to pass back encoded text data
> (perhaps including a full rendered traceback), but the exception
> itself won't be able to be propagated.
>

​It would be helpful if at least the exception type could somehow be
preserved / restored / mimicked. Otherwise you need if-elif statements in
your try-excepts and other annoying stuff.

-- Koos​


-- 
+ Koos Zevenhoven + http://twitter.com/k7hoven +
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Intention to accept PEP 552 soon (deterministic pyc files)

2017-10-01 Thread Koos Zevenhoven
On Sep 29, 2017 18:21, "Guido van Rossum"  wrote:


PS. PEP 550 is still unaccepted, awaiting a new revision from Yury and
Elvis.


This is getting really off-topic, but I do have updates to add to PEP 555
if there is interest in that. IMO, 555 is better and most likely faster
than 550, but on the other hand, the issues with PEP 550 are most likely
not going to be a problem for me personally.

-- Koos
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Intention to accept PEP 552 soon (deterministic pyc files)

2017-10-01 Thread Koos Zevenhoven
On Oct 1, 2017 19:26, "Guido van Rossum"  wrote:

Your PEP is currently incomplete. If you don't finish it, it is not even a
contender. But TBH it's not my favorite anyway, so you could also just
withdraw it.


I can withdraw it if you ask me to, but I don't want to withdraw it without
any reason. I haven't changed my mind about the big picture. OTOH, PEP 521
is elegant and could be used to implement PEP 555, but 521 is almost
certainly less performant and has some problems regarding context manager
wrappers that use composition instead of inheritance.

-- Koos



On Oct 1, 2017 9:13 AM, "Koos Zevenhoven"  wrote:

> On Sep 29, 2017 18:21, "Guido van Rossum"  wrote:
>
>
> PS. PEP 550 is still unaccepted, awaiting a new revision from Yury and
> Elvis.
>
>
> This is getting really off-topic, but I do have updates to add to PEP 555
> if there is interest in that. IMO, 555 is better and most likely faster
> than 550, but on the other hand, the issues with PEP 550 are most likely
> not going to be a problem for me personally.
>
> -- Koos
>
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Intention to accept PEP 552 soon (deterministic pyc files)

2017-10-02 Thread Koos Zevenhoven
On Mon, Oct 2, 2017 at 6:42 AM, Guido van Rossum  wrote:

> On Sun, Oct 1, 2017 at 1:52 PM, Koos Zevenhoven  wrote:
>
>> On Oct 1, 2017 19:26, "Guido van Rossum"  wrote:
>>
>> Your PEP is currently incomplete. If you don't finish it, it is not even
>> a contender. But TBH it's not my favorite anyway, so you could also just
>> withdraw it.
>>
>>
>> I can withdraw it if you ask me to, but I don't want to withdraw it
>> without any reason. I haven't changed my mind about the big picture. OTOH,
>> PEP 521 is elegant and could be used to implement PEP 555, but 521 is
>> almost certainly less performant and has some problems regarding context
>> manager wrappers that use composition instead of inheritance.
>>
>
> It is my understanding that PEP 521 (which proposes to add optional
> __suspend__ and __resume__ methods to the context manager protocol, to be
> called whenever a frame is suspended or resumed inside a `with` block) is
> no longer a contender because it would be way too slow. I haven't read it
> recently or thought about it, so I don't know what the second issue you
> mention is about (though it's presumably about the `yield` in a context
> manager implemented using a generator decorated with
> `@contextlib.contextmanager`).
>
>
​Well, it's not completely unrelated to that. The problem I'm talking about
is perhaps most easily seen from a simple context manager wrapper that uses
composition instead of inheritance:

class Wrapper:
def __init__(self):
self._wrapped = SomeContextManager()

def __enter__(self):
print("Entering context")
return self._wrapped.__enter__()

def __exit__(self):
self._wrapped.__exit__()
print("Exited context")


Now, if the wrapped contextmanager becomes a PEP 521 one with __suspend__
and __resume__, the Wrapper class is broken, because it does not respect
__suspend__ and __resume__. So actually this is a backwards compatiblity
issue.

But if the wrapper is made using inheritance, the problem goes away:


class Wrapper(SomeContextManager):
def __enter__(self):
print("Entering context")
return super().__enter__()

def __exit__(self):
super().__exit__()
print("Exited context")


Now the wrapper cleanly inherits the new optional __suspend__ and
__resume__ from the wrapped context manager type.


––Koos

>


-- 
+ Koos Zevenhoven + http://twitter.com/k7hoven +
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] Inheritance vs composition in backcompat (PEP521)

2017-10-02 Thread Koos Zevenhoven
Hi all, It was suggested that I start a new thread, because the other
thread drifted away from its original topic. So here, in case someone is
interested:

On Oct 2, 2017 17:03, "Koos Zevenhoven  wrote:

On Mon, Oct 2, 2017 at 6:42 AM, Guido van Rossum  wrote:

On Sun, Oct 1, 2017 at 1:52 PM, Koos Zevenhoven  wrote:

On Oct 1, 2017 19:26, "Guido van Rossum"  wrote:

Your PEP is currently incomplete. If you don't finish it, it is not even a
contender. But TBH it's not my favorite anyway, so you could also just
withdraw it.


I can withdraw it if you ask me to, but I don't want to withdraw it without
any reason. I haven't changed my mind about the big picture. OTOH, PEP 521
is elegant and could be used to implement PEP 555, but 521 is almost
certainly less performant and has some problems regarding context manager
wrappers that use composition instead of inheritance.


It is my understanding that PEP 521 (which proposes to add optional
__suspend__ and __resume__ methods to the context manager protocol, to be
called whenever a frame is suspended or resumed inside a `with` block) is
no longer a contender because it would be way too slow. I haven't read it
recently or thought about it, so I don't know what the second issue you
mention is about (though it's presumably about the `yield` in a context
manager implemented using a generator decorated with
`@contextlib.contextmanager`).


​Well, it's not completely unrelated to that. The problem I'm talking about
is perhaps most easily seen from a simple context manager wrapper that uses
composition instead of inheritance:

class Wrapper:
def __init__(self):
self._wrapped = SomeContextManager()

def __enter__(self):
print("Entering context")
return self._wrapped.__enter__()

def __exit__(self):
self._wrapped.__exit__()
print("Exited context")


Now, if the wrapped contextmanager becomes a PEP 521 one with __suspend__
and __resume__, the Wrapper class is broken, because it does not respect
__suspend__ and __resume__. So actually this is a backwards compatiblity
issue.

But if the wrapper is made using inheritance, the problem goes away:


class Wrapper(SomeContextManager):
def __enter__(self):
print("Entering context")
return super().__enter__()

def __exit__(self):
super().__exit__()
print("Exited context")


Now the wrapper cleanly inherits the new optional __suspend__ and
__resume__ from the wrapped context manager type.


––Koos




-- 
+ Koos Zevenhoven + http://twitter.com/k7hoven +
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Inheritance vs composition in backcompat (PEP521)

2017-10-02 Thread Koos Zevenhoven
On Oct 3, 2017 00:02, "Guido van Rossum"  wrote:

On Mon, Oct 2, 2017 at 10:13 AM, Koos Zevenhoven  wrote:

> Hi all, It was suggested that I start a new thread, because the other
> thread drifted away from its original topic. So here, in case someone is
> interested:
>
> On Oct 2, 2017 17:03, "Koos Zevenhoven  wrote:
>
> On Mon, Oct 2, 2017 at 6:42 AM, Guido van Rossum  wrote:
>
> On Sun, Oct 1, 2017 at 1:52 PM, Koos Zevenhoven  wrote:
>
> On Oct 1, 2017 19:26, "Guido van Rossum"  wrote:
>
> Your PEP is currently incomplete. If you don't finish it, it is not even a
> contender. But TBH it's not my favorite anyway, so you could also just
> withdraw it.
>
>
> I can withdraw it if you ask me to, but I don't want to withdraw it
> without any reason. I haven't changed my mind about the big picture. OTOH,
> PEP 521 is elegant and could be used to implement PEP 555, but 521 is
> almost certainly less performant and has some problems regarding context
> manager wrappers that use composition instead of inheritance.
>
>
> It is my understanding that PEP 521 (which proposes to add optional
> __suspend__ and __resume__ methods to the context manager protocol, to be
> called whenever a frame is suspended or resumed inside a `with` block) is
> no longer a contender because it would be way too slow. I haven't read it
> recently or thought about it, so I don't know what the second issue you
> mention is about (though it's presumably about the `yield` in a context
> manager implemented using a generator decorated with
> `@contextlib.contextmanager`).
>
>
> ​Well, it's not completely unrelated to that. The problem I'm talking
> about is perhaps most easily seen from a simple context manager wrapper
> that uses composition instead of inheritance:
>
> class Wrapper:
> def __init__(self):
> self._wrapped = SomeContextManager()
>
> def __enter__(self):
> print("Entering context")
> return self._wrapped.__enter__()
>
> def __exit__(self):
> self._wrapped.__exit__()
> print("Exited context")
>
>
> Now, if the wrapped contextmanager becomes a PEP 521 one with __suspend__
> and __resume__, the Wrapper class is broken, because it does not respect
> __suspend__ and __resume__. So actually this is a backwards compatiblity
> issue.
>
>
Why is it backwards incompatible? I'd think that without PEP 521 it would
be broken in exactly the same way because there's no __suspend__/__resume__
at all.



The wrapper is (would be) broken because it depends on the internal
implementation of the wrapped CM.

Maybe the author of SomeContextManager wants to upgrade the CM to also work
in coroutines and generators. But it could be a more subtle change in the
CM implementation.

The problem becomes more serious and more obvious if you don't know which
context manager you are wrapping:

class Wrapper:
def __init__(self, contextmanager):
self._wrapped = contextmanager

def __enter__(self):
print("Entering context")
return self._wrapped.__enter__()

def __exit__(self):
self._wrapped.__exit__()
print("Exited context")


The wrapper is (would be) broken because it does not work for all CMs
anymore.


But if the wrapper is made using inheritance, the problem goes away:
>
>
> class Wrapper(SomeContextManager):
> def __enter__(self):
> print("Entering context")
> return super().__enter__()
>
> def __exit__(self):
> super().__exit__()
> print("Exited context")
>
>
> Now the wrapper cleanly inherits the new optional __suspend__ and
> __resume__ from the wrapped context manager type.
>
>
In any case this is completely academic because PEP 521 is not going to
happen. Nathaniel himself has said so (I think in the context of discussing
PEP 550).


I don't mind this (or Nathaniel ;-) being academic. The backwards
incompatibility issue I've just described applies to any extension via
composition, if the underlying type/protocol grows new members (like the CM
protocol would have gained __suspend__ and __resume__ in PEP521).


-- Koos (mobile)
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Inheritance vs composition in backcompat (PEP521)

2017-10-02 Thread Koos Zevenhoven
On Oct 3, 2017 01:00, "Guido van Rossum"  wrote:

 Mon, Oct 2, 2017 at 2:52 PM, Koos Zevenhoven  wrote

I don't mind this (or Nathaniel ;-) being academic. The backwards
> incompatibility issue I've just described applies to any extension via
> composition, if the underlying type/protocol grows new members (like the CM
> protocol would have gained __suspend__ and __resume__ in PEP521).
>

Since you seem to have a good grasp on this issue, does PEP 550 suffer from
the same problem? (Or PEP 555, for that matter? :-)



Neither has this particular issue, because they don't extend an existing
protocol. If this thread has any significance, it will most likely be
elsewhere.

-- Koos (mobile)


-- 
--Guido van Rossum (python.org/~guido)
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Inheritance vs composition in backcompat (PEP521)

2017-10-02 Thread Koos Zevenhoven
On Oct 3, 2017 01:11, "Koos Zevenhoven"  wrote:

On Oct 3, 2017 01:00, "Guido van Rossum"  wrote:

 Mon, Oct 2, 2017 at 2:52 PM, Koos Zevenhoven  wrote

I don't mind this (or Nathaniel ;-) being academic. The backwards
> incompatibility issue I've just described applies to any extension via
> composition, if the underlying type/protocol grows new members (like the CM
> protocol would have gained __suspend__ and __resume__ in PEP521).
>

Since you seem to have a good grasp on this issue, does PEP 550 suffer from
the same problem? (Or PEP 555, for that matter? :-)



Neither has this particular issue, because they don't extend an existing
protocol. If this thread has any significance, it will most likely be
elsewhere.


That said, I did come across this thought while trying to find flaws in my
own PEP ;)

-- Koos
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Investigating time for `import requests`

2017-10-03 Thread Koos Zevenhoven
I've probably missed a lot of this discussion, but this lazy import
discussion confuses me. We already have both eager import (import at the
top of the file), and lazy import (import right before use).

The former is good when you know you need the module, and the latter is
good when you having the overhead at first use is preferable over having
the overhead at startup. But like Raymond was saying, this is of course
especially relevant when that import is likely never used.

Maybe the fact that the latter is not recommended gives people the feeling
that we don't have lazy imports, although we do.

What we *don't* have, however, is *partially* lazy imports and partially
executed code, something like:

on demand:
class Foo:
# a lot of stuff here

def foo_function(my_foo, bar):
# more stuff here


When executed, the `on demand` block would only keep track of which names
are being bound to (here, "Foo" and "foo_function"), and on the lookup of
those names in the namespace, the code would actually be run.

Then you could also do

on demand:
import sometimes_needed_module

Or

on demand:
from . import all, submodules, of, this, package


This would of course drift away from "namespaces are simply dicts". But who
cares, if they still provide the dict interface. See e.g. this example with
automatic lazy imports:

https://gist.github.com/k7hoven/21c5532ce19b306b08bb4e82cfe5a609


Another thing we *don't* have is unimporting. What if I know that I'm only
going to need some particular module in this one initialization function.
Why should I keep it in memory for the whole lifetime of the program?

––Koos


-- 
+ Koos Zevenhoven + http://twitter.com/k7hoven +
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Inheritance vs composition in backcompat (PEP521)

2017-10-04 Thread Koos Zevenhoven
On Wed, Oct 4, 2017 at 8:07 AM, Nick Coghlan  wrote:

> On 3 October 2017 at 03:13, Koos Zevenhoven  wrote:
> > Well, it's not completely unrelated to that. The problem I'm talking
> about
> > is perhaps most easily seen from a simple context manager wrapper that
> uses
> > composition instead of inheritance:
> >
> > class Wrapper:
> > def __init__(self):
> > self._wrapped = SomeContextManager()
> >
> > def __enter__(self):
> > print("Entering context")
> > return self._wrapped.__enter__()
> >
> > def __exit__(self):
> > self._wrapped.__exit__()
> > print("Exited context")
> >
> >
> > Now, if the wrapped contextmanager becomes a PEP 521 one with __suspend__
> > and __resume__, the Wrapper class is broken, because it does not respect
> > __suspend__ and __resume__. So actually this is a backwards compatiblity
> > issue.
>
> This is a known problem, and one of the main reasons that having a
> truly transparent object proxy like
> https://wrapt.readthedocs.io/en/latest/wrappers.html#object-proxy as
> part of the standard library would be highly desirable.
>
>
This is barely related to the problem I describe. The wrapper is not
supposed to pretend to *be* the underlying object. It's just supposed to
extend its functionality.

Maybe it's just me, but using a transparent object proxy for this sounds
like someone trying to avoid inheritance for no reason and at any cost.
Inheritance probably has faster method access, and makes it more obvious
what's going on:

def Wrapper(contextmanager):
class Wrapper(type(contextmanager)):
def __enter__(self):
print("Entering context")
return contextmanager.__enter__()

def __exit__(self):
contextmanager.__exit__()
print("Exited context")
return Wrapper()


A wrapper based on a transparent object proxy is just a non-transparent
replacement for inheritance. Its wrapper nature is non-transparent because
it pretends to `be` the original object, while it's actually a wrapper.

But an object cannot `be` another object as long as the `is` operator won't
return True. And any straightforward way to implement that would add
performance overhead for normal objects.

I do remember sometimes wanting a transparent object proxy. But not for
normal wrappers. But I don't think I've gone as far as looking for a
library to do that, because it seems that you can only go half way anyway.

––Koos

​--
+ Koos Zevenhoven + http://twitter.com/k7hoven +
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Inheritance vs composition in backcompat (PEP521)

2017-10-04 Thread Koos Zevenhoven
On Wed, Oct 4, 2017 at 3:33 PM, Nick Coghlan  wrote:

> On 4 October 2017 at 20:22, Koos Zevenhoven  wrote:
> > On Wed, Oct 4, 2017 at 8:07 AM, Nick Coghlan  wrote:
> >>
> >> On 3 October 2017 at 03:13, Koos Zevenhoven  wrote:
> >> > Well, it's not completely unrelated to that. The problem I'm talking
> >> > about
> >> > is perhaps most easily seen from a simple context manager wrapper that
> >> > uses
> >> > composition instead of inheritance:
> >> >
> >> > class Wrapper:
> >> > def __init__(self):
> >> > self._wrapped = SomeContextManager()
> >> >
> >> > def __enter__(self):
> >> > print("Entering context")
> >> > return self._wrapped.__enter__()
> >> >
> >> > def __exit__(self):
> >> > self._wrapped.__exit__()
> >> > print("Exited context")
> >> >
> >> >
> >> > Now, if the wrapped contextmanager becomes a PEP 521 one with
> >> > __suspend__
> >> > and __resume__, the Wrapper class is broken, because it does not
> respect
> >> > __suspend__ and __resume__. So actually this is a backwards
> compatiblity
> >> > issue.
> >>
> >> This is a known problem, and one of the main reasons that having a
> >> truly transparent object proxy like
> >> https://wrapt.readthedocs.io/en/latest/wrappers.html#object-proxy as
> >> part of the standard library would be highly desirable.
> >>
> >
> > This is barely related to the problem I describe. The wrapper is not
> > supposed to pretend to *be* the underlying object. It's just supposed to
> > extend its functionality.
>
> If a wrapper *isn't* trying to act as a transparent object proxy, and
> is instead adapting it to a particular protocol, then yes, you'll need
> to update the wrapper when the protocol is extended.
>
>
​Yes, but it still means that the change in the dependency (in this case a
standard Python protocol) breaks the wrapper code.​

Remember that the wrappeR class and the wrappeD class can be implemented in
different libraries.



> That's not a backwards compatibility problem, because the only way to
> encounter it is to update your code to rely on the new extended
> protocol - your *existing* code will continue to work fine, since
> that, by definition, can't be relying on the new protocol extension.
>
>
​No, not all code is "your" code. Clearly this is not a well-known problem.
This is a backwards-compatibility problem for the author of the wrappeR,
not for the author of the wrappeD object.

––Koos
​

-- 
+ Koos Zevenhoven + http://twitter.com/k7hoven +
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Inheritance vs composition in backcompat (PEP521)

2017-10-04 Thread Koos Zevenhoven
On Wed, Oct 4, 2017 at 4:04 PM, Nick Coghlan  wrote:

> On 4 October 2017 at 22:45, Koos Zevenhoven  wrote:
> > On Wed, Oct 4, 2017 at 3:33 PM, Nick Coghlan  wrote:
> >> That's not a backwards compatibility problem, because the only way to
> >> encounter it is to update your code to rely on the new extended
> >> protocol - your *existing* code will continue to work fine, since
> >> that, by definition, can't be relying on the new protocol extension.
> >>
> >
> > No, not all code is "your" code. Clearly this is not a well-known
> problem.
> > This is a backwards-compatibility problem for the author of the wrappeR,
> not
> > for the author of the wrappeD object.
>
> No, you're misusing the phrase "backwards compatibility", and
> confusing it with "feature enablement".
>
> Preserving backwards compatibility just means "existing code and
> functionality don't break". It has nothing to do with whether or not
> other support libraries and frameworks might need to change in order
> to enable full access to a new language feature.
>
>
​It's not about full access to a new language feature. It's about the
wrappeR promising it can wrap any ​context manager, which it then no longer
can. If the __suspend__ and __resume__ methods are ignored, that is not
about "not having full access to a new feature" — that's broken code. The
error message you get (if any) may not contain any hint of what went wrong.

Take the length hint protocol defined in PEP 424 for example: that
> extended the iterator protocol to include a new optional
> __length_hint__ method, such that container constructors can make a
> more reasonable guess as to how much space they should pre-allocate
> when being initialised from an iterator or iterable rather than
> another container.
>
>
​This is slightly similar, but not really. Not using __length_hint__ does
not affect the correctness of code.


> That protocol means that many container wrappers break the
> optimisation. That's not a compatibility problem, it just means those
> wrappers don't support the feature, and it would potentially be a
> useful enhancement if they did.
>
>
​Again, ignoring __length_hint__ does not lead to broken code, so that just
means the wrapper is as slow or as fast as it was before.

​So I still think it's an issue for the author of the wrapper to fix––even
if just by documenting that the wrapper does not support the new protocol
members. But that would not be necessary if the wrapper uses inheritance.

(Of course there may be another reason to not use inheritance, but just
overriding two methods seems like a good case for inheritance.).
​
​This discussion seems pretty pointless by now. It's true that *some* code
needs to change for this to be a problem. Updating only the Python version
does not break a codebase if libraries aren't updated, and even then,
breakage is not very likely, I suppose.

It all depends on the kind of change that is made. For __length_hint__, you
only risk not getting the performance improvement. For __suspend__ and
__resume__, there's a small chance of problems. For some other change, it
might be even riskier. But this is definitely not the most dangerous type
of compatibility issue.

––Koos


-- 
+ Koos Zevenhoven + http://twitter.com/k7hoven +
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 554 v3 (new interpreters module)

2017-10-04 Thread Koos Zevenhoven
On Wed, Oct 4, 2017 at 4:51 PM, Eric Snow 
wrote:

> On Tue, Oct 3, 2017 at 11:36 PM, Nick Coghlan  wrote:
> > The problem relates to the fact that there aren't any memory barriers
> > around CPython's INCREF operations (they're implemented as an ordinary
> > C post-increment operation), so you can get the following scenario:
> >
> > * thread on CPU A has the sole reference (ob_refcnt=1)
> > * thread on CPU B acquires a new reference, but hasn't pushed the
> > updated ob_refcnt value back to the shared memory cache yet
> > * original thread on CPU A drops its reference, *thinks* the refcnt is
> > now zero, and deletes the object
> > * bad things now happen in CPU B as the thread running there tries to
> > use a deleted object :)
>
> I'm not clear on where we'd run into this problem with channels.
> Mirroring your scenario:
>
> * interpreter A (in thread on CPU A) INCREFs the object (the GIL is still
> held)
> * interp A sends the object to the channel
> * interp B (in thread on CPU B) receives the object from the channel
> * the new reference is held until interp B DECREFs the object
>
> From what I see, at no point do we get a refcount of 0, such that
> there would be a race on the object being deleted.
>
> ​
So what you're saying is that when Larry finishes the gilectomy,
subinterpreters will work GIL-free too?​-)

​––Koos
​

The only problem I'm aware of (it dawned on me last night), is in the
> case that the interpreter that created the object gets deleted before
> the object does.  In that case we can't pass the deletion back to the
> original interpreter.  (I don't think this problem is necessarily
> exclusive to the solution I've proposed for Bytes.)
>
> -eric
> ___
> Python-Dev mailing list
> Python-Dev@python.org
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe: https://mail.python.org/mailman/options/python-dev/
> k7hoven%40gmail.com
>



-- 
+ Koos Zevenhoven + http://twitter.com/k7hoven +
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Inheritance vs composition in backcompat (PEP521)

2017-10-05 Thread Koos Zevenhoven
On Tue, Oct 3, 2017 at 1:11 AM, Koos Zevenhoven  wrote:

> On Oct 3, 2017 01:00, "Guido van Rossum"  wrote:
>
>  Mon, Oct 2, 2017 at 2:52 PM, Koos Zevenhoven  wrote
>
> I don't mind this (or Nathaniel ;-) being academic. The backwards
>> incompatibility issue I've just described applies to any extension via
>> composition, if the underlying type/protocol grows new members (like the CM
>> protocol would have gained __suspend__ and __resume__ in PEP521).
>>
>
> Since you seem to have a good grasp on this issue, does PEP 550 suffer
> from the same problem? (Or PEP 555, for that matter? :-)
>
>
>
> Neither has this particular issue, because they don't extend an existing
> protocol. If this thread has any significance, it will most likely be
> elsewhere.
>

​Actually, I realize I should be more precise with terminology regarding
"extending an existing protocol"/"growing new members". Below, I'm still
using PEP 521 as an example (sorry).

In fact, in some sense, "adding" __suspend__ and __resume__ to context
managers *does not* extend the context manager protocol, even though it
kind of looks like it does.

There would instead be two separate protocols:

(A) The traditional PEP 343 context manager:
__enter__
__exit__

(B) The hyphothetical PEP 521 context manager:
__enter__
__suspend__
__resume__
__exit__

Protocols A and B are incompatible in both directions:

* It is generally not safe to use a type-A context manager assuming it
implements B.

* It is generally not safe to use a type-B context manager assuming it
implements A.

But if you now have a type-B object, it looks like it's also type-A,
especially for code that is not aware of the existence of B. This is where
the problems come from: a wrapper for type A does the wrong thing when
wrapping a type-B object (except when using inheritance).


[Side note:

Another interpretation of the situation is that, instead of adding protocol
B, A is removed and is replaced with:

(C) The hypothetical PEP 521 context manager with optional members:
__enter__
__suspend__ (optional)
__resume__  (optional)
__exit__

But now the same problems just come from the fact that A no longer exists
while there is code out there that assumes A. But this is only a useful
interpretation if you are the only user of the protocol or if it's
otherwise ok to remove A. So let's go back to the A-B interpretation.]


Q: Could the problem of protocol conflict be solved?

One way to tell A and B apart would be to always explicitly mark the
protocol with a base class. Obviously this is not the case with existing
uses of context managers.

But there's another way, which is to change the naming:

(A) The traditional PEP 343 context manager:
__enter__
__exit__

(Z) The *modified* hyphothetical PEP 521 context manager:
__begin__
__suspend__
__resume__
__end__

Now, A and Z are easy to tell apart. A context manager wrapper designed for
type A immediately fails if used to wrap a type-Z object. But of course the
whole context manager concept now suddenly became a lot more complicated.


It is interesting that, in the A-B scheme, making a general context manager
wrapper using inheritance *just works*, even if A is not a subprotocol of B
and B is not a subprotocol of A.

Anyway, a lot of this is amplified by the fact that the methods of the
context manager protocols are not independent functionality. Instead,
calling one of them leads to the requirement that the other methods are
also called at the right moments.

--Koos

-- 
+ Koos Zevenhoven + http://twitter.com/k7hoven +
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 554 v3 (new interpreters module)

2017-10-06 Thread Koos Zevenhoven
rk through subclassing or a registry
>>   + a lot of conceptual similarity with tp_share+tp_free
>> * a CIV-like proxy
>>   + you wrap the object, send() the proxy, and recv() a proxy
>>   + this is entirely compatible with tp_share()
>>
>
> * Allow for multiple channel types, such that MemChannel is merely the
> *first* channel type, rather than the *only* channel type
>   + Allows PEP 554 to be restricted to things we already know can be made
> to work
>   + Doesn't block the introduction of an object-sharing based Channel in
> some future release
>   + Allows for at least some channel types to be adapted for use with
> shared memory and multiprocessing
>
>
>> Here are what I consider the key metrics relative to the utility of a
>> solution (not in any significant order):
>>
>> * how hard to understand as a Python programmer?
>>
>
> Not especially important yet - this is more a criterion for the final API,
> not the initial experimental platform.
>
>
>> * how much extra work (if any) for folks calling Channel.send()?
>> * how much extra work (if any) for folks calling Channel.recv()?
>>
>
> I don't think either are particularly important yet, although we also
> don't want to raise any pointless barriers to experimentation.
>
>
>> * how complex is the CPython implementation?
>>
>
> This is critical, since we want to minimise any potential for undesirable
> side effects on regular single interpreter code.
>
>
>> * how hard to understand as a type author (wanting to add support for
>> their type)?
>> * how hard to add support for a new type?
>> * what variety of types could be supported?
>> * what breadth of experimentation opens up?
>>
>
> You missed the big one: what risk does the initial channel design pose to
> the underlying objective of making the GIL a genuinely per-interpreter lock?
>
> If we don't eventually reach the latter goal, then subinterpreters won't
> really offer much in the way of compelling benefits over just using a
> thread pool and queue.Queue.
>
> MemChannel poses zero additional risk to that, since we wouldn't be
> sharing actual Python objects between interpreters, only C pointers and
> structs.
>
> By contrast, introducing an object channel early poses significant new
> risks to that goal, since it will force you to solve hard protocol design
> and refcount management problems *before* making the switch, rather than
> being able to defer the design of the object channel protocol until *after*
> you've already enabled the ability to run subinterpreters in completely
> independent threads.
>
>
>> The most important thing to me is keeping things simple for Python
>> programmers.  After that is ease-of-use for type authors.  However, I
>> also want to put us in a good position in 3.7 to experiment
>> extensively with subinterpreters, so that's a big consideration.
>>
>> Consequently, for PEP 554 my goal is to find a solution for object
>> sharing that keeps things simple in Python while laying a basic
>> foundation we can build on at the C level, so we don't get locked in
>> but still maximize our opportunities to experiment. :)
>>
>
> I think our priorities are quite different then, as I believe PEP 554
> should be focused on defining a relatively easy to implement API that
> nevertheless makes it possible to write interesting programs while working
> on the goal of making the GIL per-interpreter, without worrying too much
> about whether or not the initial cross-interpreter communication channels
> closely resemble the final ones that will be intended for more general use.
>
> Cheers,
> Nick.
>
> --
> Nick Coghlan   |   ncogh...@gmail.com   |   Brisbane, Australia
>
> ___
> Python-Dev mailing list
> Python-Dev@python.org
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe: https://mail.python.org/mailman/options/python-dev/
> k7hoven%40gmail.com
>
>


-- 
+ Koos Zevenhoven + http://twitter.com/k7hoven +
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Investigating time for `import requests`

2017-10-08 Thread Koos Zevenhoven
On Sun, Oct 8, 2017 at 11:02 AM, David Cournapeau 
wrote:

>
> On Mon, Oct 2, 2017 at 6:42 PM, Raymond Hettinger <
> raymond.hettin...@gmail.com> wrote:
>
>>
>> > On Oct 2, 2017, at 12:39 AM, Nick Coghlan  wrote:
>> >
>> >  "What requests uses" can identify a useful set of
>> > avoidable imports. A Flask "Hello world" app could likely provide
>> > another such sample, as could some example data analysis notebooks).
>>
>> Right.  It is probably worthwhile to identify which parts of the library
>> are typically imported but are not ever used.  And likewise, identify a
>> core set of commonly used tools that are going to be almost unavoidable in
>> sufficiently interesting applications (like using requests to access a REST
>> API, running a micro-webframework, or invoking mercurial).
>>
>> Presumably, if any of this is going to make a difference to end users, we
>> need to see if there is any avoidable work that takes a significant
>> fraction of the total time from invocation through the point where the user
>> first sees meaningful output.  That would include loading from nonvolatile
>> storage, executing the various imports, and doing the actual application.
>>
>> I don't expect to find anything that would help users of Django, Flask,
>> and Bottle since those are typically long-running apps where we value
>> response time more than startup time.
>>
>> For scripts using the requests module, there will be some fruit because
>> not everything that is imported is used.  However, that may not be
>> significant because scripts using requests tend to be I/O bound.  In the
>> timings below, 6% of the running time is used to load and run python.exe,
>> another 16% is used to import requests, and the remaining 78% is devoted to
>> the actual task of running a simple REST API query. It would be interesting
>> to see how much of the 16% could be avoided without major alterations to
>> requests, to urllib3, and to the standard library.
>>
>
> It is certainly true that for a CLI tool that actually makes any network
> I/O, especially SSL, import times will quickly be negligible. It becomes
> tricky for complex tools, because of error management. For example, a
> common pattern I have used in the past is to have a high level "catch all
> exceptions" function that dispatch the CLI command:
>
> try:
> main_function(...)
> except ErrorKind1:
> 
> except requests.exceptions.SSLError:
> # gives complete message about options when receiving SSL errors, e.g.
> invalid certificate
>
> This pattern requires importing requests every time the command is run,
> even if no network IO is actually done. For complex CLI tools, maybe most
> command don't use network IO (the tool in question was a complete packages
> manager), but you pay ~100 ms because of requests import for every command.
> It is particularly visible because commands latency starts to be felt
> around 100-150 ms, and while you can do a lot in python in 100-150 ms, you
> can't do much in 0-50 ms.
>
>
Yes. ​OTOH, ​it can also happen that the *imports* are in fact what use the
network IO. At the office, I usually import from a network drive. For
instance, `import requests` takes a little less than a second, and `import
IPython` usually takes more than a second, with some variation.

––Koos


-- 
+ Koos Zevenhoven + http://twitter.com/k7hoven +
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Investigating time for `import requests`

2017-10-08 Thread Koos Zevenhoven
On Sun, Oct 8, 2017 at 2:44 PM, Chris Angelico  wrote:

> On Sun, Oct 8, 2017 at 7:02 PM, David Cournapeau 
> wrote:
> > It is certainly true that for a CLI tool that actually makes any network
> > I/O, especially SSL, import times will quickly be negligible. It becomes
> > tricky for complex tools, because of error management. For example, a
> common
> > pattern I have used in the past is to have a high level "catch all
> > exceptions" function that dispatch the CLI command:
> >
> > try:
> > main_function(...)
> > except ErrorKind1:
> > 
> > except requests.exceptions.SSLError:
> > # gives complete message about options when receiving SSL errors,
> e.g.
> > invalid certificate
> >
> > This pattern requires importing requests every time the command is run,
> even
> > if no network IO is actually done. For complex CLI tools, maybe most
> command
> > don't use network IO (the tool in question was a complete packages
> manager),
> > but you pay ~100 ms because of requests import for every command. It is
> > particularly visible because commands latency starts to be felt around
> > 100-150 ms, and while you can do a lot in python in 100-150 ms, you
> can't do
> > much in 0-50 ms.
>
> This would be a perfect use-case for lazy importing, then. You'd pay
> the price of the import only if you get an error that isn't caught by
> one of the preceding except blocks.
>


​I suppose it might be convenient to be able to do something like:

with autoimport:
try:
main_function(...)
   ​ except ErrorKind1:
...
except requests.exceptions.SLLError:
...


The easiest workaround at the moment is still pretty clumsy:

def import_SLLError():
from requests.exceptions import SLLError
return SLLError

...


except import_SLLError():


But what happens if that gives you an ImportError?

––Koos


-- 
+ Koos Zevenhoven + http://twitter.com/k7hoven +
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] What is the design purpose of metaclasses vs code generating decorators? (was Re: PEP 557: Data Classes)

2017-10-13 Thread Koos Zevenhoven
 as the dataclass interaction with `__slots__` goes, that's a
> problem largely specific to slots (and `__metaclass__` before it), in that
> they're the only characteristics of a class definition that affect how
> CPython allocates memory for the class object itself (the descriptors for
> the slots are stored as a pointer array after the class struct, rather than
> only in the class dict).
>
> Given PEP 526 variable annotations, __slots__ could potentially benefit
> from a __metaclass__ style makeover, allowing an "infer_slots=True" keyword
> argument to type.__new__ to request that the list of slots be inferred from
> __annotations__ (Slot inference would conflict with setting class level
> default values, but that's a real conflict, as you'd be trying to use the
> same name on the class object for both the slot descriptor and the default
> value)
>
> Cheers,
> Nick.
>
> --
> Nick Coghlan   |   ncogh...@gmail.com   |   Brisbane, Australia
>
> ___
> Python-Dev mailing list
> Python-Dev@python.org
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe: https://mail.python.org/mailman/options/python-dev/
> k7hoven%40gmail.com
>
>


-- 
+ Koos Zevenhoven + http://twitter.com/k7hoven +
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 563: Postponed Evaluation of Annotations

2017-11-10 Thread Koos Zevenhoven
On Thu, Nov 9, 2017 at 9:51 PM, Guido van Rossum  wrote:

> If we have to change the name I'd vote for string_annotations -- "lazy"
> has too many other connotations (e.g. it might cause people to think it's
> the thunks). I find str_annotations too abbreviated, and
> stringify_annotations is too hard to spell.
>
>
​I can't say I disagree. ​And maybe importing string_annotations from the
__future__ doesn't sound quite as sad as importing something from the
__past__.

Anyway, it's not obvious to me that it is the module author that should
decide how the annotations are handled. See also this quote below:

(Quoted from the end of
https://mail.python.org/pipermail/python-ideas/2017-October/047311.html )

On Thu, Oct 12, 2017 at 3:59 PM, Koos Zevenhoven  wrote:

>
> ​​[*] Maybe somehow make the existing functionality a phantom easter
> egg––a blast from the past which you can import and use, but which is
> otherwise invisible :-). Then later give warnings and finally remove it
> completely.
>
> But we need better smooth upgrade paths anyway, maybe something like:
>
> from __compat__ import unintuitive_decimal_contexts
>
> with unintuitive_decimal_contexts:
> do_stuff()
>
> ​Now code bases can more quickly switch to new python versions and make
> the occasional compatibility adjustments more lazily, while already
> benefiting from other new language features.
>
>
> ––Koos​
>
>
>
-- 
+ Koos Zevenhoven + http://twitter.com/k7hoven +
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 563: Postponed Evaluation of Annotations

2017-11-10 Thread Koos Zevenhoven
On Fri, Nov 10, 2017 at 7:50 PM, Ethan Furman  wrote:

> On 11/10/2017 07:48 AM, Guido van Rossum wrote:
>
> I don't mind the long name. Of all the options so far I really only like
>> 'string_annotations' so let's go with that.
>>
>
> As someone else mentioned, we have function annotations and variable
> annotations already, which makes string_annotations sound like it's
> annotations for strings.
>
>
> Contriwise, "annotation_strings" sounds like a different type of
> annotation -- they are now being stored as strings, instead of something
> else.
>
>
​Or a step further (longer), with annotations_as_strings.

––Koos​


-- 
+ Koos Zevenhoven + http://twitter.com/k7hoven +
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Analog of PEP 448 for dicts (unpacking in assignment with dict rhs)

2017-11-11 Thread Koos Zevenhoven
Oops, forgot to reply to the list.

On Nov 12, 2017 03:35, "Koos Zevenhoven"  wrote:

On Nov 12, 2017 02:12, "Joao S. O. Bueno"  wrote:

Ben, I have a small package which enables one to do:

with MapGetter(my_dictionary):
from my_dictionary import a, b, parameter3

If this interests you, contributions so it can get hardenned for
mainstram acceptance are welcome.
https://github.com/jsbueno/extradict


Your VersionDict in fact has some similarities to what I have thought of
implementing using the PEP 555 machinery, but it is also a bit different.
Interesting...

-- Koos (mobile)



On 11 November 2017 at 04:26, Ben Usman  wrote:
> Got it, thank you. I'll go and check it out!
>
> On Nov 11, 2017 01:22, "Jelle Zijlstra"  wrote:
>>
>>
>>
>> 2017-11-10 19:53 GMT-08:00 Ben Usman :
>>>
>>> The following works now:
>>>
>>> seq = [1, 2]
>>> d = {'c': 3, 'a': 1, 'b': 2}
>>>
>>> (el1, el2) = *seq
>>> el1, el2 = *seq
>>> head, *tail = *seq
>>>
>>> seq_new = (*seq, *tail)
>>> dict_new = {**d, **{'c': 4}}
>>>
>>> def f(arg1, arg2, a, b, c):
>>> pass
>>>
>>> f(*seq, **d)
>>>
>>> It seems like dict unpacking syntax would not be fully coherent with
>>> list unpacking syntax without something like:
>>>
>>> {b, a, **other} = **d
>>>
>>> Because iterables have both syntax for function call unpacking and
>>> "rhs in assignment unpacking" and dict has only function call
>>> unpacking syntax.
>>>
>>> I was not able to find any PEPs that suggest this (search keywords:
>>> "PEP 445 dicts", "dictionary unpacking assignment", checked PEP-0),
>>> however, let me know if I am wrong.
>>>
>> It was discussed at great length on Python-ideas about a year ago. There
>> is a thread called "Unpacking a dict" from May 2016.
>>
>>>
>>> The main use-case, in my understating, is getting shortcuts to
>>> elements of a dictionary if they are going to be used more then
>>> ones later in the scope. A made-up example is using a config to
>>> initiate a bunch of things with many config arguments with long
>>> names that have overlap in keywords used in initialization.
>>>
>>> One should either write long calls like
>>>
>>> start_a(config['parameter1'], config['parameter2'],
>>> config['parameter3'], config['parameter4'])
>>>
>>> start_b(config['parameter3'], config['parameter2'],
>>> config['parameter3'], config['parameter4'])
>>>
>>> many times or use a list-comprehension solution mentioned above.
>>>
>>> It becomes even worse (in terms of readability) with nested structures.
>>>
>>> start_b(config['group2']['parameter3'], config['parameter2'],
>>> config['parameter3'], config['group2']['parameter3'])
>>>
>>>
>>> ## Rationale
>>>
>>> Right now this problem is often solved using [list] comprehensions,
>>> but this is somewhat verbose:
>>>
>>> a, b = (d[k] for k in ['a', 'b'])
>>>
>>> or direct per-instance assignment (looks simple for with
>>> single-character keys, but often becomes very verbose with
>>> real-world long key names)
>>>
>>> a = d['a']
>>> b = d['b']
>>>
>>> Alternatively one could have a very basic method\function
>>> get_n() or __getitem__() accepting more then a single argument
>>>
>>> a, b = d.get_n('a', 'b')
>>> a, b = get_n(d, 'a', 'b')
>>> a, b = d['a', 'b']
>>>
>>> All these approaches require verbose double-mentioning of same
>>> key. It becomes even worse if you have nested structures
>>> of dictionaries.
>>>
>>> ## Concerns and questions:
>>>
>>> 0. This is the most troubling part,  imho, other questions
>>> are more like common thoughts. It seems (to put it mildly)
>>> weird that execution flow depends on names of local variables.
>>>
>>> For example, one can not easily refactor these variable names. However,
>>> same is true for dictionary keys anyway: you can not suddenly decide
>>> and refactor your code to expect dictionaries wi

Re: [Python-Dev] PEP 563: Postponed Evaluation of Annotations

2017-11-12 Thread Koos Zevenhoven
On Sun, Nov 12, 2017 at 7:07 AM, Guido van Rossum  wrote:

> On Fri, Nov 10, 2017 at 11:02 PM, Nick Coghlan  wrote:
>
>> On 11 November 2017 at 01:48, Guido van Rossum  wrote:
>> > I don't mind the long name. Of all the options so far I really only like
>> > 'string_annotations' so let's go with that.
>>
>> +1 from me.
>>
>
> I'd like to reverse my stance on this. We had `from __future__ import
> division` for many years in Python 2, and nobody argued that it implied
> that Python 2 doesn't have division -- it just meant to import the future
> *version* of division. So I think the original idea, `from __future__
> import annotations` is fine. I don't expect there will be *other* things
> related to annotations that we'll be importing from the future.
>
>
Furthermore, *​nobody* expects the majority of programmers to look at
__annotations__ either. But those who do need to care about the
'implementation detail' of whether it's a string won't be surprised to find
nested strings like "'ForwardReferencedThing'". But one might fear that
those cases get ruthlessly converted into being equivalent to just
"ForwardReferencedThing".

So actually my question is: What should happen when the annotation is
already a string literal?

-- Koos
  ​
-- 
+ Koos Zevenhoven + http://twitter.com/k7hoven +
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 563: Postponed Evaluation of Annotations

2017-11-12 Thread Koos Zevenhoven
On Nov 12, 2017 19:10, "Guido van Rossum"  wrote:

On Sun, Nov 12, 2017 at 4:14 AM, Koos Zevenhoven  wrote:

> So actually my question is: What should happen when the annotation is
> already a string literal?
>

The PEP answers that clearly (under Implementation):

> If an annotation was already a string, this string is preserved
> verbatim.


Oh sorry, I was looking for a spec, so I somehow assumed I can ignore the
gory implementation details just like I routinely ignore things like
headers and footers of emails.

There's two thing I don't understand here:

* What does it mean to preserve the string verbatim? No matter how I read
it, I can't tell if it's with quotes or without.

Maybe I'm missing some context.


-- Koos (mobile)
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 562

2017-11-15 Thread Koos Zevenhoven
On Tue, Nov 14, 2017 at 10:34 PM, Ivan Levkivskyi 
wrote:
​[..]​


> Rationale
> =
>
> It is sometimes convenient to customize or otherwise have control over
> access to module attributes. A typical example is managing deprecation
> warnings. Typical workarounds are assigning ``__class__`` of a module
> object
> to a custom subclass of ``types.ModuleType`` or replacing the
> ``sys.modules``
> item with a custom wrapper instance. It would be convenient to simplify
> this
> procedure by recognizing ``__getattr__`` defined directly in a module that
> would act like a normal ``__getattr__`` method, except that it will be
> defined
> on module *instances*. For example::
>
>
  # lib.py
>
>   from warnings import warn
>
>   deprecated_names = ["old_function", ...]
>
>   def _deprecated_old_function(arg, other):
>   ...
>
>   def __getattr__(name):
>   if name in deprecated_names:
>   warn(f"{name} is deprecated", DeprecationWarning)
>   return globals()[f"_deprecated_{name}"]
>   raise AttributeError(f"module {__name__} has no attribute {name}")
>
>   # main.py
>
>   from lib import old_function  # Works, but emits the warning
>
>
​Deprecating functions is already possible, so I assume the reason for this
would be performance? If so, are you sure this would help for performance?
​
​Deprecating module attributes / globals is indeed difficult to do at
present. This PEP would allow deprecation warnings for accessing
attributes, which is nice!  However, as thread-unsafe as it is, many
modules use module attributes to configure the state of the module. In that
case, the user is more likely to *set* the attribute that to *get* it. Is
this outside the scope of the PEP?


​[..]​


> There is a related proposal PEP 549 that proposes to support instance
> properties for a similar functionality. The difference is this PEP proposes
> a faster and simpler mechanism, but provides more basic customization.
>

​I'm not surprised that the comparison is in favor of this PEP ;-).​


​[..]​


> Specification
> =
>
> The ``__getattr__`` function at the module level should accept one argument
> which is the name of an attribute and return the computed value or raise
> an ``AttributeError``::
>
>   def __getattr__(name: str) -> Any: ...
>
> This function will be called only if ``name`` is not found in the module
> through the normal attribute lookup.
>
>
The Rationale (quoted in the beginning of this email) easily leaves a
different impression of this.​


​[..]
​

>
> Discussion
> ==
>
> Note that the use of module ``__getattr__`` requires care to keep the
> referred
> objects pickleable. For example, the ``__name__`` attribute of a function
> should correspond to the name with which it is accessible via
> ``__getattr__``::
>
>   def keep_pickleable(func):
>   func.__name__ = func.__name__.replace('_deprecated_', '')
>   func.__qualname__ = func.__qualname__.replace('_deprecated_', '')
>   return func
>
>   @keep_pickleable
>   def _deprecated_old_function(arg, other):
>   ...
>
> One should be also careful to avoid recursion as one would do with
> a class level ``__getattr__``.
>
>
Off-topic: In some sense, I'm happy to hear something about pickleability.
But in some sense not.

I think there are three kinds of people regarding pickleability:

1. Those who don't care about anything being pickleable

2. Those ​who care about some things being picklable

​3. ​Those who care about all things being picklable

Personally, I'd like to belong to group 3, but because group 3 cannot even
attempt to coexist with groups 1 and 2, I actually belong to group 1 most
of the time.

​––Koos
​


> References
> ==
>
> .. [1] PEP 484 section about ``__getattr__`` in stub files
>(https://www.python.org/dev/peps/pep-0484/#stub-files)
>
> .. [2] The reference implementation
>(https://github.com/ilevkivskyi/cpython/pull/3/files)
>
>
> Copyright
> =
>
> This document has been placed in the public domain.
>
>
>
> ..
>Local Variables:
>    mode: indented-text
>indent-tabs-mode: nil
>sentence-end-double-space: t
>fill-column: 70
>coding: utf-8
>End:
>
> ___
> Python-Dev mailing list
> Python-Dev@python.org
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe: https://mail.python.org/mailman/options/python-dev/
> k7hoven%40gmail.com
>
>


-- 
+ Koos Zevenhoven + http://twitter.com/k7hoven +
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 560: bases classes / confusion

2017-11-15 Thread Koos Zevenhoven
For anyone confused about similar things, I expect you to be interested in
my post on python-ideas from today:

https://mail.python.org/pipermail/python-ideas/2017-November/047896.html

––Koos


On Wed, Nov 15, 2017 at 4:20 PM, Jim J. Jewett  wrote:

> (1)  I found the following (particularly "bases classes") very confusing:
>
> """
> If an object that is not a class object appears in the bases of a class
>
> definition, then ``__mro_entries__`` is searched on it. If found,
> it is called with the original tuple of bases as an argument. The result
> of the call must be a tuple, that is unpacked in the bases classes in place
> of this object. (If the tuple is empty, this means that the original bases
> is
> simply discarded.)
> """
>
> Based on the following GenericAlias/NewList/Tokens example, I think I
> now I understand what you mean, and would have had somewhat less
> difficulty if it were expressed as:
>
> """
> When an object that is not a class object appears in the (tuple of)
> bases of a class
> definition, then attribute ``__mro_entries__`` is searched on that
> non-class object.  If ``__mro_entries__`` found,
> it is called with the entire original tuple of bases as an argument. The
> result
> of the call must be a tuple, which is unpacked and replaces only the
> non-class object in the tuple of bases.  (If the tuple is empty, this
> means that the original bases
> is
> simply discarded.)
> """
>
> Note that this makes some assumptions about the __mro_entries__
> signature that I wasn't quite sure about from the example.  So
> building on that:
>
> class ABList(A, NewList[int], B):
>
> I *think* the following will happen:
>
> "NewList[int]" will be evaluated, and __class_getitem__ called, so
> that the bases tuple will be (A, GenericAlias(NewList, int), B)
>
> # (A)  I *think* __mro_entries__ gets called with the full tuple,
> # instead of just the object it is found on.
> # (B) I *think* it is called on the results of evaluating
> # the terms within the tuple, instead of the original
> # string representation.
> _tmp = __mro_entries__(A, GenericAlias(NewList, int), B)
>
> # (C)  I *think* __mro_entries__ returns a replacement for
> # just the single object, even though it was called on
> # the whole tuple, without knowing which object it
> # represents.
> bases = (A, _tmp, B)
>
> # (D) If there are two non-class objects, I *think* the
> # second one gets the same arguments as the first,
> # rather than an intermediate tuple with the first such
> # object already substituted out.
>
> -jJ
> ___
> Python-Dev mailing list
> Python-Dev@python.org
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe: https://mail.python.org/mailman/options/python-dev/
> k7hoven%40gmail.com
>



-- 
+ Koos Zevenhoven + http://twitter.com/k7hoven +
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 560: bases classes / confusion

2017-11-15 Thread Koos Zevenhoven
On Wed, Nov 15, 2017 at 5:37 PM, Nick Coghlan  wrote:

> On 16 November 2017 at 00:20, Jim J. Jewett  wrote:
>
>> I *think* the following will happen:
>>
>> "NewList[int]" will be evaluated, and __class_getitem__ called, so
>> that the bases tuple will be (A, GenericAlias(NewList, int), B)
>>
>> # (A)  I *think* __mro_entries__ gets called with the full tuple,
>> # instead of just the object it is found on.
>> # (B) I *think* it is called on the results of evaluating
>> # the terms within the tuple, instead of the original
>> # string representation.
>> _tmp = __mro_entries__(A, GenericAlias(NewList, int), B)
>>
>> # (C)  I *think* __mro_entries__ returns a replacement for
>> # just the single object, even though it was called on
>> # the whole tuple, without knowing which object it
>> # represents.
>> bases = (A, _tmp, B)
>>
>
> My understanding of the method signature:
>
> def __mro_entries__(self, orig_bases):
> ...
> return replacement_for_self
>
> My assumption as to the purpose of the extra complexity was:
>
> - given orig_bases, a method could avoid injecting bases already listed if
> it wanted to
> - allowing multiple items to be returned provides a way to
> programmatically combine mixins without having to define a new subclass for
> each combination
>
>

​Thanks, this might provide an answer to my question about multiple mro
entries here

https://mail.python.org/pipermail/python-ideas/2017-November/047897.html​

​––Koos​



-- 
+ Koos Zevenhoven + http://twitter.com/k7hoven +
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 562

2017-11-15 Thread Koos Zevenhoven
On Wed, Nov 15, 2017 at 8:02 PM, Ethan Furman  wrote:

> On 11/15/2017 04:55 AM, Koos Zevenhoven wrote:
>
>> On Tue, Nov 14, 2017 at 10:34 PM, Ivan Levkivskyi wrote:
>>
>
>
>> Rationale
>>> =
>>>
>>> [...] It would be convenient to simplify this
>>> procedure by recognizing ``__getattr__`` defined directly in a module
>>> that
>>> would act like a normal ``__getattr__`` method
>>>
>> >>
> >> [...]
> >>
>
>> Specification
>>> =
>>>
>>> >> The ``__getattr__`` function at the module level should accept one
> argument
>
>> which is the name of an attribute and return the computed value or raise
>>> an ``AttributeError``::
>>>
>>
>>def __getattr__(name: str) -> Any: ...
>>>
>>
>> This function will be called only if ``name`` is not found in the module
>>> through the normal attribute lookup.
>>>
>>
>> The Rationale (quoted in the beginning of this email) easily leaves a
>> different impression of this.​
>>
>
> I don't see how.  This is exactly the way normal __getattr__ works.
>
>
>
​Oh sorry, I think I put this email together too quickly. I was writing
down a bunch of thoughts I had earlier but hadn't written down.​ I think I
was mixing this up in my head with overriding __getitem__ for the module
namespace dict and __class_getitem__ from PEP 560, which only gets called
if the metaclass doesn't implement __getitem__ (IIRC).

But I did have another thought related to this. I was wondering whether the
lack of passing the module to the methods as `self` would harm future
attempts to generalize these ideas.

-- Koos

-- 
+ Koos Zevenhoven + http://twitter.com/k7hoven +
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 560: bases classes / confusion

2017-11-16 Thread Koos Zevenhoven
On Thu, Nov 16, 2017 at 6:28 PM, brent bejot  wrote:

> Hello all,
>
> Noticed that "MRO" is not actually defined in the PEP and it seems like it
> should be.  Probably in the Performance section where the abbreviation is
> first used outside of a function name.
>
>
​I don't think it will hurt if I suggest that __bases__, bases, "original
bases"​, mro, __orig_bases__, MRO, __mro__ and "concatenated mro entries"
are all defined as synonyms of each other, except with different meanings
:-)

––Koos



> -Brent
>
> On Thu, Nov 16, 2017 at 7:22 AM, Ivan Levkivskyi 
> wrote:
>
>> On 16 November 2017 at 07:56, Nick Coghlan  wrote:
>>
>>> On 16 November 2017 at 04:39, Ivan Levkivskyi 
>>> wrote:
>>>
>>>> Nick is exactly right here. Jim, if you want to propose alternative
>>>> wording, then we could consider it.
>>>>
>>>
>>> Jim also raised an important point that needs clarification at the spec
>>> level: given multiple entries in "orig_bases" with __mro_entries__ methods,
>>> do all such methods get passed the *same* orig_bases tuple? Or do they
>>> receive partially resolved ones, such that bases listed before them have
>>> already been resolved to their MRO entries by the time they run.
>>>
>>>
>>>
>> Yes, they all get the same initial bases tuple as an argument. Passing
>> updated ones will cost a bit more and I don't think it will be needed (in
>> the worst case a base can resolve another base by calling its
>> __mro_entries__ manually).
>> I will clarify this in the PEP.
>>
>> --
>> Ivan
>>
>>
>>
>> ___
>> Python-Dev mailing list
>> Python-Dev@python.org
>> https://mail.python.org/mailman/listinfo/python-dev
>> Unsubscribe: https://mail.python.org/mailman/options/python-dev/brent.
>> bejot%40gmail.com
>>
>>
>
> ___
> Python-Dev mailing list
> Python-Dev@python.org
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe: https://mail.python.org/mailman/options/python-dev/
> k7hoven%40gmail.com
>
>


-- 
+ Koos Zevenhoven + http://twitter.com/k7hoven +
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Python possible vulnerabilities in concurrency

2017-11-17 Thread Koos Zevenhoven
On Thu, Nov 16, 2017 at 6:53 AM, Guido van Rossum  wrote:

> On Wed, Nov 15, 2017 at 6:50 PM, Guido van Rossum 
> wrote:
>>
>>
>> Actually it linked to http://standards.iso.org/ittf/
>> PubliclyAvailableStandards/index.html from which I managed to download
>> what looks like the complete c061457_ISO_IEC_TR_24772_2013.pdf (336
>> pages) after clicking on an "I accept" button (I didn't read what I
>> accepted :-). The $200 is for the printed copy I presume.
>>
>
> So far I learned one thing from the report. They use the term
> "vulnerabilities" liberally, defining it essentially as "bug":
>
> All programming languages contain constructs that are incompletely
>> specified, exhibit undefined behaviour, are implementation-dependent, or
>> are difficult to use correctly. The use of those constructs may therefore
>> give rise to *vulnerabilities*, as a result of which, software programs
>> can execute differently than intended by the writer.
>>
>
> They then go on to explain that sometimes vulnerabilities can be
> exploited, but I object to calling all bugs vulnerabilities -- that's just
> using a scary word to get attention for a sleep-inducing document
> containing such gems as "Use floating-point arithmetic only when absolutely
> needed" (page 230).
>
>
​I don't like such a definition of "vulnerability" either. Some bugs can be
vulnerabilities (those that can be exploited) and some vulnerabilities can
be bugs. But there are definitely types of vulnerabilities that are not
bugs––the DoS vulnerability that is eliminated by hash randomization is one.

There may also be a gray area of bugs that can be vulnerabilities but only
in some special situation. I think it's ok to call those vulnerabilities
too.

​––Koos​


​PS. How come I haven't seen a proposal to remove the float type from
builtins yet?-)​


-- 
+ Koos Zevenhoven + http://twitter.com/k7hoven +
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Python possible vulnerabilities in concurrency

2017-11-17 Thread Koos Zevenhoven
On Fri, Nov 17, 2017 at 3:40 PM, Koos Zevenhoven  wrote:

> On Thu, Nov 16, 2017 at 6:53 AM, Guido van Rossum 
> wrote:
>
>> On Wed, Nov 15, 2017 at 6:50 PM, Guido van Rossum 
>> wrote:
>>>
>>>
>>> Actually it linked to http://standards.iso.org/ittf/
>>> PubliclyAvailableStandards/index.html from which I managed to download
>>> what looks like the complete c061457_ISO_IEC_TR_24772_2013.pdf (336
>>> pages) after clicking on an "I accept" button (I didn't read what I
>>> accepted :-). The $200 is for the printed copy I presume.
>>>
>>
>> So far I learned one thing from the report. They use the term
>> "vulnerabilities" liberally, defining it essentially as "bug":
>>
>> All programming languages contain constructs that are incompletely
>>> specified, exhibit undefined behaviour, are implementation-dependent, or
>>> are difficult to use correctly. The use of those constructs may therefore
>>> give rise to *vulnerabilities*, as a result of which, software programs
>>> can execute differently than intended by the writer.
>>>
>>
>> They then go on to explain that sometimes vulnerabilities can be
>> exploited, but I object to calling all bugs vulnerabilities -- that's just
>> using a scary word to get attention for a sleep-inducing document
>> containing such gems as "Use floating-point arithmetic only when absolutely
>> needed" (page 230).
>>
>>
> ​I don't like such a definition of "vulnerability" either. Some bugs can
> be vulnerabilities (those that can be exploited) and some vulnerabilities
> can be bugs. But there are definitely types of vulnerabilities that are not
> bugs––the DoS vulnerability that is eliminated by hash randomization is one.
>
> There may also be a gray area of bugs that can be vulnerabilities but only
> in some special situation. I think it's ok to call those vulnerabilities
> too.
>
>
​Just to clarify the obvious: By the above, I *don't* mean that one could
use the word "vulnerability" for any functionality that can be used in such
a way that it creates a vulnerability. For example, `eval` or `exec` or
`open` by themselves are not vulnerabilities.

––Koos


-- 
+ Koos Zevenhoven + http://twitter.com/k7hoven +
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Make the stable API-ABI usable

2017-11-18 Thread Koos Zevenhoven
> "stable API" but change its implementation to a *function call* rather
> than the existing macro, so the compiled C extension will use a
> function call and so don't rely on the ABI anymore.
>
>
> My plan is to have two main milestones:
>
> (1) Python 3.7: Extend the *existing* opt-in "stable API" which
> requires to compile C extensions in a special mode. Add maybe an
> option in distutils to ease the compilation of a C extension with the
> "stable API"?
>
> (2) In Python 3.8, --if the project is successful and the performance
> overhead is acceptable compared the advantages of having C extensions
> working on multiple Python verisons--, make the "stable API (without
> implementation details)" the default, but add a new opt-in option to
> give access to the "full API (with implementation details)" for
> debuggers and other people who understand what they do (like Cython?).
>
> Note: currently, the "stable API" is accessible using Py_LIMITED_API
> define, and the "full API" is accessible using Py_BUILD_CORE define.
> No define gives the current C API.
>
>
> My problem is more on the concrete implementation:
>
> * Need to provide two different API using the same filenames (like:
> #include "Python.h")
>
> * Need to extend distutils to have a flag to compile a C extension
> with one specific API (define Py_LIMITED_API or Py_BUILD_CORE?)
>
> * Need to test many C extensions and check how many extensions are broken
>
>
> My plan for Python 3.7 is to not touch the current API at all. There
> is no risk of backward incompatibility. You should only get issues if
> you opt-in for the new API without implementation details.
>
>
> Final note: Nothing new under the sun: PyPy already implemented my
> "idea"! Where the idea is a C API without macros; PyTuple_GET_ITEM()
> is already a function call in PyPy ;-)
>
>
> Final question: Is it acceptable to iterate on many small changes on
> the C API implement this idea in Python 3.7? Maybe only write partial
> implementation, and finish it in Python 3.8?
>
> Victor
> ___
> Python-Dev mailing list
> Python-Dev@python.org
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe: https://mail.python.org/mailman/options/python-dev/
> k7hoven%40gmail.com
>



-- 
+ Koos Zevenhoven + http://twitter.com/k7hoven +
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] __future__ imports and breaking code (was: PEP 563: Postponed Evaluation of Annotations)

2017-11-19 Thread Koos Zevenhoven
Previously, I expressed some concerns about PEP 563 regarding what should
happen when a string is used as an annotation. Since my point here is more
general, I'm starting yet another thread.

For a lot of existing type-annotated code, adding "from __tuture__ import
annotations" [1] *doesn't break anything*.

But that doesn't seem right. The whole point of __future__ imports is to
break things. Maybe the __future__ import will not give a 100% equivalent
functionality to what will be in Python 4 by default, but anyway, it's
Python 4 that should break as little as possible. This leaves the breaking
business to the future import, if necessary.

If someone cares enough to add the future import that avoids needing string
annotations for forward references, it shouldn't be such a big deal to get
a warning if there's a string annotation left. But the person upgrading to
Python 4 (or whatever they might be upgrading) will have a lot less
motivation to figure out what went wrong.

Then again, code that works in both Python 3 and 4 could still have the
future import. But that would defeat the purpose of Python 4 as a clean and
high-performance dynamic language.

—Koos


[1] As defined in the PEP 563 draft:
https://mail.python.org/pipermail/python-dev/2017-November/150062.html

-- 
+ Koos Zevenhoven + http://twitter.com/k7hoven +
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 563: Postponed Evaluation of Annotations

2017-11-19 Thread Koos Zevenhoven
On Mon, Nov 13, 2017 at 11:59 PM, Brett Cannon  wrote:
​[..]​

> On Sun, Nov 12, 2017, 10:22 Koos Zevenhoven,  wrote:
> ​​
>
>>
>> There's two thing I don't understand here:
>>
>> * What does it mean to preserve the string verbatim? No matter how I read
>> it, I can't tell if it's with quotes or without.
>>
>> Maybe I'm missing some context.
>>
>
> I believe the string passes through unchanged (i.e. no quotes). Think of
> the PEP as simply turning all non-string annotations into string ones.
>
>
​Ok, maybe that was just wishful thinking on my part ;-).

More info in the other threads, for example:

https://mail.python.org/pipermail/python-dev/2017-November/150642.html
https://mail.python.org/pipermail/python-dev/2017-November/150637.html

-- Koos


-- 
+ Koos Zevenhoven + http://twitter.com/k7hoven +
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Comments on PEP 563 (Postponed Evaluation of Annotations)

2017-11-20 Thread Koos Zevenhoven
On Mon, Nov 20, 2017 at 7:58 PM, Lukasz Langa  wrote:

> I agree with you. The special handling of outermost strings vs. strings
> embedded inside annotations bugged me a lot. Now you convinced me that this
> functionality should be moved to `get_type_hints()` and the __future__
> import shouldn't try to special-case this one instance, while leaving
> others as is.
>
> ​
> 


That's better. I don't necessarily care if there will be a warning when a
string is given as annotation, but if the idea is to simplify things for
the future and get rid of strings to represent types, then this would be a
good moment to gently "enforce" it.

––Koos


-- 
+ Koos Zevenhoven + http://twitter.com/k7hoven +
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] generator vs iterator etc. (was: How assignment should work with generators?)

2017-11-27 Thread Koos Zevenhoven
On Mon, Nov 27, 2017 at 3:55 PM, Steven D'Aprano 
 wrote:

> On Mon, Nov 27, 2017 at 12:17:31PM +0300, Kirill Balunov wrote:
> ​​
>
> > 2. Should this work only for generators or for any iterators?
>
> I don't understand why you are even considering singling out *only*
> generators. A generator is a particular implementation of an iterator. I
> can write:
>
> def gen():
>yield 1; yield 2; yield 3
>
> it = gen()
>
> or I can write:
>
> it = iter([1, 2, 3])
>
> and the behaviour of `it` should be identical.
>
>
>
​I can see where this is coming from. The thing is that "iterator" and
"generator" are mostly synonymous, except two things:

(1) Generators are iterators that are produced by a generator function

(2) Generator functions are sometimes referred to as just "generators"

The concept of "generator" thus overlaps with both "iterator" and
"generator function".

Then there's also "iterator" and "iterable", which are two different things:

(3) If `obj` is an *iterable*, then `it = iter(obj)` is an *iterator* (over
the contents of `obj`)

(
​4) ​Iterators yield values, for example on explicit calls to next(it).

Personally I have leaned towards keeping a clear distinction between
"generator function" and "generator"​, which leads to the situation that
"generator" and "iterator" are mostly synonymous for me. Sometimes, for
convenience, I use the term "generator" to refer to "iterators" more
generally. This further seems to have a minor benefit that "generators" and
"iterables" are less easily confused with each other than "iterators" and
"iterables".

I thought about this issue some time ago for the `views` package, which has
a separation between sequences (seq) and other iterables (gen):

https://github.com/k7hoven/views

The functionality provided by `views.gen` is not that interesting—it's
essentially a subset of itertools functionality, but with an API that
parallels `views.seq` which works with sequences (iterable, sliceable,
chainable, etc.). I used the name `gen`, because iterator/iterable variants
of the functionality can be implemented with generator functions (although
also with other kinds of iterators/iterables). Calling the thing `iter`
would have conflicted with the builtin `iter`.

HOWEVER, this naming can be confusing for those that lean more towards
using "generator" to also mean "generator function", and for those that are
comfortable with the term "iterator" despite its resemblance to "iterable".

Now I'm actually seriously considering to consider renaming `views.gen` to `
views.iter` when I have time. After all, there's already `views.range`
which "conflicts" with the builtin range.

​Anyway, the point is that the naming is suboptimal.​

SOLUTION: Maybe (a) all iterators should be called iterators or (b) all
iterators should be called generators, regardless of whether they are
somehow a result of a generator function having been called in the past.

(I'm not going into the distinction between things that can receive values
via `send` or any other possible distinctions between different types of
iterators and iterables.)

​—Koos​

​(discussion originated from python-ideas, but cross-posted to python-dev
in case there's more interest there)​


-- 
+ Koos Zevenhoven + http://twitter.com/k7hoven +
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] Thoughts on "contexts". PEPs 550, 555, 567, 568

2018-01-09 Thread Koos Zevenhoven
Hi all,

I feel like I should write some thoughts regarding the "context"
discussion, related to the various PEPs.

I like PEP 567 (+ 567 ?) better than PEP 550. However, besides providing
cvar.set(), I'm not really sure about the gain compared to PEP 555 (which
could easily have e.g. a dict-like interface to the context). I'm still not
a big fan of "get"/"set" here, but the idea was indeed to provide those on
top of a PEP 555 type thing too.

"Tokens" in PEP 567, seems to resemble assignment context managers in PEP
555. However, they feel a bit messy to me, because they make it look like
one could just set a variable and then revert the change at any point in
time after that.

PEP 555 is in fact a simplification of my previous sketch that had a
.set(..) in it, but was somewhat different from PEP 550. The idea was to
always explicitly define the scope of contextvar values. A context manager
/ with statement determined the scope of .set(..) operations inside the
with statement:

# Version A:
cvar.set(1)
with context_scope():
cvar.set(2)

assert cvar.get() == 2

assert cvar.get() == 1

Then I added the ability to define scopes for different variables
separately:

# Version B
cvar1.set(1)
cvar2.set(2)
with context_scope(cvar1):
cvar1.set(11)
cvar2.set(22)

assert cvar1.get() == 1
assert cvar2.get() == 22


However, in practice, most libraries would wrap __enter__, set and __exit__
into another context manager. So maybe one might want to allow something
like

# Version C:
assert cvar.get() == something
with context_scope(cvar, 2):
assert cvar.get() == 2

assert cvar.get() == something


But this then led to combining "__enter__" and ".set(..)" into
Assignment.__enter__ -- and "__exit__" into Assignment.__exit__ like this:

# PEP 555 draft version:
assert cvar.value == something
with cvar.assign(1):
assert cvar.value == 1

assert cvar.value == something


Anyway, given the schedule, I'm not really sure about the best thing to do
here. In principle, something like in versions A, B and C above could be
done (I hope the proposal was roughly self-explanatory based on earlier
discussions). However, at this point, I'd probably need a lot of help to
make that happen for 3.7.

-- Koos
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Thoughts on "contexts". PEPs 550, 555, 567, 568

2018-01-09 Thread Koos Zevenhoven
On Jan 10, 2018 07:17, "Yury Selivanov"  wrote:

Wasn't PEP 555 rejected by Guido? What's the point of this post?


I sure hope there is a point. I don't think mentioning PEP 555 in the
discussions should hurt.

A typo in my post btw: should be "PEP 567 (+568 ?)" in the second paragraph
of course.

-- Koos (mobile)


Yury

On Wed, Jan 10, 2018 at 4:08 AM Koos Zevenhoven  wrote:

> Hi all,
>
> I feel like I should write some thoughts regarding the "context"
> discussion, related to the various PEPs.
>
> I like PEP 567 (+ 567 ?) better than PEP 550. However, besides providing
> cvar.set(), I'm not really sure about the gain compared to PEP 555 (which
> could easily have e.g. a dict-like interface to the context). I'm still not
> a big fan of "get"/"set" here, but the idea was indeed to provide those on
> top of a PEP 555 type thing too.
>
> "Tokens" in PEP 567, seems to resemble assignment context managers in PEP
> 555. However, they feel a bit messy to me, because they make it look like
> one could just set a variable and then revert the change at any point in
> time after that.
>
> PEP 555 is in fact a simplification of my previous sketch that had a
> .set(..) in it, but was somewhat different from PEP 550. The idea was to
> always explicitly define the scope of contextvar values. A context manager
> / with statement determined the scope of .set(..) operations inside the
> with statement:
>
> # Version A:
> cvar.set(1)
> with context_scope():
> cvar.set(2)
>
> assert cvar.get() == 2
>
> assert cvar.get() == 1
>
> Then I added the ability to define scopes for different variables
> separately:
>
> # Version B
> cvar1.set(1)
> cvar2.set(2)
> with context_scope(cvar1):
> cvar1.set(11)
> cvar2.set(22)
>
> assert cvar1.get() == 1
> assert cvar2.get() == 22
>
>
> However, in practice, most libraries would wrap __enter__, set and
> __exit__ into another context manager. So maybe one might want to allow
> something like
>
> # Version C:
> assert cvar.get() == something
> with context_scope(cvar, 2):
> assert cvar.get() == 2
>
> assert cvar.get() == something
>
>
> But this then led to combining "__enter__" and ".set(..)" into
> Assignment.__enter__ -- and "__exit__" into Assignment.__exit__ like this:
>
> # PEP 555 draft version:
> assert cvar.value == something
> with cvar.assign(1):
> assert cvar.value == 1
>
> assert cvar.value == something
>
>
> Anyway, given the schedule, I'm not really sure about the best thing to do
> here. In principle, something like in versions A, B and C above could be
> done (I hope the proposal was roughly self-explanatory based on earlier
> discussions). However, at this point, I'd probably need a lot of help to
> make that happen for 3.7.
>
> -- Koos
>
> ___
> Python-Dev mailing list
> Python-Dev@python.org
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe: https://mail.python.org/mailman/options/python-dev/
> yselivanov.ml%40gmail.com
>
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Thoughts on "contexts". PEPs 550, 555, 567, 568

2018-01-10 Thread Koos Zevenhoven
The status of PEP 555 is just a side track. Here, I took a step back
compared to what went into PEP 555.

—Koos


On Wed, Jan 10, 2018 at 6:21 PM, Guido van Rossum  wrote:

> The current status of PEP 555 is "Withdrawn". I have no interest in
> considering it any more, so if you'd rather see a decision from me I'll be
> happy to change it to "Rejected".
>
> On Tue, Jan 9, 2018 at 10:29 PM, Koos Zevenhoven 
> wrote:
>
>> On Jan 10, 2018 07:17, "Yury Selivanov"  wrote:
>>
>> Wasn't PEP 555 rejected by Guido? What's the point of this post?
>>
>>
>> I sure hope there is a point. I don't think mentioning PEP 555 in the
>> discussions should hurt.
>>
>> A typo in my post btw: should be "PEP 567 (+568 ?)" in the second
>> paragraph of course.
>>
>> -- Koos (mobile)
>>
>>
>> Yury
>>
>> On Wed, Jan 10, 2018 at 4:08 AM Koos Zevenhoven 
>> wrote:
>>
>>> Hi all,
>>>
>>> I feel like I should write some thoughts regarding the "context"
>>> discussion, related to the various PEPs.
>>>
>>> I like PEP 567 (+ 567 ?) better than PEP 550. However, besides providing
>>> cvar.set(), I'm not really sure about the gain compared to PEP 555 (which
>>> could easily have e.g. a dict-like interface to the context). I'm still not
>>> a big fan of "get"/"set" here, but the idea was indeed to provide those on
>>> top of a PEP 555 type thing too.
>>>
>>> "Tokens" in PEP 567, seems to resemble assignment context managers in
>>> PEP 555. However, they feel a bit messy to me, because they make it look
>>> like one could just set a variable and then revert the change at any point
>>> in time after that.
>>>
>>> PEP 555 is in fact a simplification of my previous sketch that had a
>>> .set(..) in it, but was somewhat different from PEP 550. The idea was to
>>> always explicitly define the scope of contextvar values. A context manager
>>> / with statement determined the scope of .set(..) operations inside the
>>> with statement:
>>>
>>> # Version A:
>>> cvar.set(1)
>>> with context_scope():
>>> cvar.set(2)
>>>
>>> assert cvar.get() == 2
>>>
>>> assert cvar.get() == 1
>>>
>>> Then I added the ability to define scopes for different variables
>>> separately:
>>>
>>> # Version B
>>> cvar1.set(1)
>>> cvar2.set(2)
>>> with context_scope(cvar1):
>>> cvar1.set(11)
>>> cvar2.set(22)
>>>
>>> assert cvar1.get() == 1
>>> assert cvar2.get() == 22
>>>
>>>
>>> However, in practice, most libraries would wrap __enter__, set and
>>> __exit__ into another context manager. So maybe one might want to allow
>>> something like
>>>
>>> # Version C:
>>> assert cvar.get() == something
>>> with context_scope(cvar, 2):
>>> assert cvar.get() == 2
>>>
>>> assert cvar.get() == something
>>>
>>>
>>> But this then led to combining "__enter__" and ".set(..)" into
>>> Assignment.__enter__ -- and "__exit__" into Assignment.__exit__ like this:
>>>
>>> # PEP 555 draft version:
>>> assert cvar.value == something
>>> with cvar.assign(1):
>>> assert cvar.value == 1
>>>
>>> assert cvar.value == something
>>>
>>>
>>> Anyway, given the schedule, I'm not really sure about the best thing to
>>> do here. In principle, something like in versions A, B and C above could be
>>> done (I hope the proposal was roughly self-explanatory based on earlier
>>> discussions). However, at this point, I'd probably need a lot of help to
>>> make that happen for 3.7.
>>>
>>> -- Koos
>>>
>>> ___
>>> Python-Dev mailing list
>>> Python-Dev@python.org
>>> https://mail.python.org/mailman/listinfo/python-dev
>>> Unsubscribe: https://mail.python.org/mailma
>>> n/options/python-dev/yselivanov.ml%40gmail.com
>>>
>>
>>
>> ___
>> Python-Dev mailing list
>> Python-Dev@python.org
>> https://mail.python.org/mailman/listinfo/python-dev
>> Unsubscribe: https://mail.python.org/mailman/options/python-dev/guido%
>> 40python.org
>>
>>
>
>
> --
> --Guido van Rossum (python.org/~guido)
>



-- 
+ Koos Zevenhoven + http://twitter.com/k7hoven +
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Thoughts on "contexts". PEPs 550, 555, 567, 568

2018-01-14 Thread Koos Zevenhoven
The timing of all of this is unfortunate. I'm sorry that my participation
in the discussion has been a bit "on-off" lately. But my recent
contributions have involved studying things like the interaction of
threading/concurrency aspects of signal handling, as well as investigating
subtleties of various proposals for context variables, including my own.
Those are not exactly low-hanging fruit, and I'm sorry about not being able
to eat them.

It is also unfortunate that I haven't written down this proposal
("versions" A-C) to anywhere near the amount of precision than I did for
PEP 555, which wasn't 100% specified in the first draft either. For
consideration, I just thought it's better to at least mention it, so that
those that now have a good understanding of the issues involved could
perhaps understand it. I can add more detail, but to make it a full
proposal now, I would probably need to join forces with a coauthor (with a
good understanding of these issues) to figure out missing parts. I could
tune in later to finish the PEP and write docs in case the approach gets
implemented.

-- Koos


On Wed, Jan 10, 2018 at 7:17 PM, Guido van Rossum  wrote:

> I'm sorry, Koos, but based on your past contributions I am not interested
> in discussing this topic with you.
>
> On Wed, Jan 10, 2018 at 8:58 AM, Koos Zevenhoven 
> wrote:
>
>> The status of PEP 555 is just a side track. Here, I took a step back
>> compared to what went into PEP 555.
>>
>> —Koos
>>
>>
>> On Wed, Jan 10, 2018 at 6:21 PM, Guido van Rossum 
>> wrote:
>>
>>> The current status of PEP 555 is "Withdrawn". I have no interest in
>>> considering it any more, so if you'd rather see a decision from me I'll be
>>> happy to change it to "Rejected".
>>>
>>> On Tue, Jan 9, 2018 at 10:29 PM, Koos Zevenhoven 
>>> wrote:
>>>
>>>> On Jan 10, 2018 07:17, "Yury Selivanov" 
>>>> wrote:
>>>>
>>>> Wasn't PEP 555 rejected by Guido? What's the point of this post?
>>>>
>>>>
>>>> I sure hope there is a point. I don't think mentioning PEP 555 in the
>>>> discussions should hurt.
>>>>
>>>> A typo in my post btw: should be "PEP 567 (+568 ?)" in the second
>>>> paragraph of course.
>>>>
>>>> -- Koos (mobile)
>>>>
>>>>
>>>> Yury
>>>>
>>>> On Wed, Jan 10, 2018 at 4:08 AM Koos Zevenhoven 
>>>> wrote:
>>>>
>>>>> Hi all,
>>>>>
>>>>> I feel like I should write some thoughts regarding the "context"
>>>>> discussion, related to the various PEPs.
>>>>>
>>>>> I like PEP 567 (+ 567 ?) better than PEP 550. However, besides
>>>>> providing cvar.set(), I'm not really sure about the gain compared to PEP
>>>>> 555 (which could easily have e.g. a dict-like interface to the context).
>>>>> I'm still not a big fan of "get"/"set" here, but the idea was indeed to
>>>>> provide those on top of a PEP 555 type thing too.
>>>>>
>>>>> "Tokens" in PEP 567, seems to resemble assignment context managers in
>>>>> PEP 555. However, they feel a bit messy to me, because they make it look
>>>>> like one could just set a variable and then revert the change at any point
>>>>> in time after that.
>>>>>
>>>>> PEP 555 is in fact a simplification of my previous sketch that had a
>>>>> .set(..) in it, but was somewhat different from PEP 550. The idea was to
>>>>> always explicitly define the scope of contextvar values. A context manager
>>>>> / with statement determined the scope of .set(..) operations inside the
>>>>> with statement:
>>>>>
>>>>> # Version A:
>>>>> cvar.set(1)
>>>>> with context_scope():
>>>>> cvar.set(2)
>>>>>
>>>>> assert cvar.get() == 2
>>>>>
>>>>> assert cvar.get() == 1
>>>>>
>>>>> Then I added the ability to define scopes for different variables
>>>>> separately:
>>>>>
>>>>> # Version B
>>>>> cvar1.set(1)
>>>>> cvar2.set(2)
>>>>> with context_scope(cvar1):
>>>>> cvar1.set(11)
>>>>> cvar2.set(22)
>>&g

Re: [Python-Dev] Thoughts on "contexts". PEPs 550, 555, 567, 568

2018-01-14 Thread Koos Zevenhoven
I'll quickly add a few things below just in case there's anyone that cares.

On Wed, Jan 10, 2018 at 2:06 AM, Koos Zevenhoven  wrote:

>
> The idea was to always explicitly define the scope of contextvar values. A
> context manager / with statement determined the scope of .set(..)
> operations inside the with statement:
>
> # Version A:
> cvar.set(1)
> with context_scope():
> cvar.set(2)
>
> assert cvar.get() == 2
>
> assert cvar.get() == 1
>
> Then I added the ability to define scopes for different variables
> separately:
>
> # Version B
> cvar1.set(1)
> cvar2.set(2)
> with context_scope(cvar1):
> cvar1.set(11)
> cvar2.set(22)
>
> assert cvar1.get() == 1
> assert cvar2.get() == 22
>
>
> However, in practice, most libraries would wrap __enter__, set and
> __exit__ into another context manager. So maybe one might want to allow
> something like
>
> # Version C:
> assert cvar.get() == something
> with context_scope(cvar, 2):
> assert cvar.get() == 2
>
> assert cvar.get() == something
>
>
Note here, that the point is to get a natural way to "undo" changes made to
variables when exiting the scope. Undoing everything that is done within
the defined scope is a very natural way to do it. Undoing individual
.set(..) operations is more problematic.

Features B+C could be essentially implemented as described in PEP 555,
except with context_scope(cvar) being essentially the same as pushing and
popping an empty Assignment object onto the reverse-linked stack. By empty,
I mean a "key-value pair with a missing value". Then any set operations
would replace the topmost assignment object for that variable with a new
key-value pair (or push a new Assignment if there isn't one).

​However, to also get feature A, the stack may have to contain full
mappings instead of assignemnt objects with just one key-value pair.

I hope that clarifies some parts. Otherwise, in terms of semantics, the
same things apply as for PEP 555 when it comes to generator function calls
and next(..) etc., so we'd need to make sure it works well enough for all
use cases. For instance, I'm not quite sure if I have a good enough
understanding of the timeout example that Nathaniel wrote in the PEP 550
discussion to tell what would be required in terms of semantics, but I
suppose it should be fine.

-- Koos


> But this then led to combining "__enter__" and ".set(..)" into
> Assignment.__enter__ -- and "__exit__" into Assignment.__exit__ like this:
>
> # PEP 555 draft version:
> assert cvar.value == something
> with cvar.assign(1):
> assert cvar.value == 1
>
> assert cvar.value == something
>
>
> Anyway, given the schedule, I'm not really sure about the best thing to do
> here. In principle, something like in versions A, B and C above could be
> done (I hope the proposal was roughly self-explanatory based on earlier
> discussions). However, at this point, I'd probably need a lot of help to
> make that happen for 3.7.
>
> -- Koos
>
>


-- 
+ Koos Zevenhoven + http://twitter.com/k7hoven +
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 567 v3

2018-01-21 Thread Koos Zevenhoven
On Thu, Jan 18, 2018 at 3:53 AM, Yury Selivanov 
wrote:

​[]


>
> Given the time frame of the Python 3.7 release schedule it was decided
> to defer this proposal to Python 3.8.
>

​It occurs to me that I had misread this to refer to the whole PEP.
Although I thought it's kind of sad that after all this, contextvars still
would not make it into 3.7, I also thought that it might be the right
decision. As you may already know, I think there are several problems with
this PEP. Would it be worth it to write down some thoughts on this PEP in
the morning?

-- Koos​



-- 
+ Koos Zevenhoven + http://twitter.com/k7hoven +
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Intention to accept PEP 567 (Context Variables)

2018-01-23 Thread Koos Zevenhoven
On Tue, Jan 23, 2018 at 2:23 AM, Victor Stinner 
wrote:

> The PEP 555 looks a competitor PEP of the PEP 567. Since the Yury's
> PEP 567 was approved, I understand that Koos's PEP 555 should be
> rejected, no?
>
>
If Guido prefers to reject it​, I assume he'll say so. Anyway, it's still
waiting for me to add references to earlier discussions and perhaps
summaries of some discussions.

Personally, I need to find some time to properly catch up with the latest
discussion to figure out why PEP 567 is better than PEP 555 (or similar
with .set(..), or PEP 550), despite problems of reasoning about the scopes
of variables and unset tokens.

In any case, congrats, Yury! This hasn't been an easy one for any of us,
and it seems like the implementation required quite a beastly patch too in
the end.

—Koos
​​
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Defining a path protocol (was: When should pathlib stop being provisional?)

2016-04-08 Thread Koos Zevenhoven
Nick Coghlan wrote:
> On 7 April 2016 at 03:26, Brett Cannon  wrote:
>>
>> Name: __path__, __fspath__, or something else?
>
> __fspath__
>

I think I might like this dunder name because it does not clutter the
list of regular methods and attributes, and is perhaps more pythonic.

>> Method or attribute? (changes what kind of one-liner you might use in
>> libraries, but I think historically all protocols have been methods and the
>> serialized string representation might be costly to build)
>
> Method, as long as there's a helper function somewhere

As a further minor benefit of it being a method, it may be easier to
distinguish it from from `__path__`, which is an iterable attribute.

>> Built-in? (name is dependent on #1 if we add one)
>
> os.fspath (alongside os.fsencode and os.fsdecode)
>
> (Putting this in a module low in the dependency stack makes it easy
> for other modules to access without pulling in all of pathlib's
> dependencies)

Strong +1 on putting it in os. This should also be implemented in
DirEntry, instances of which are "yielded" by os.scandir.

Also, you have a strong case regarding naming with the 'fs' prefix. It
is also easier to read fspath as f-s-path than it is to read ospath as
o-s-path, because ospath could also be pronounced as a single
(meaningless?) word.

I'm still thinking a little bit about 'pathname', which to me sounds
more like a string than fspath does [1]. It would be nice to have the
string/path distinction especially when pathlib adoption grows larger.
But who knows, maybe somewhere in the far future, no-one will care
much about fspath, fsencode, fsdecode or os.path.

>> Add the method/attribute to str? (I assume so, much like __index__() is on
>> int, but I have not seen it explicitly stated so I would rather clarify it)
>
> Makes sense

If added to str, it should also be added to bytes. But will that then
return str or bytes? See also the next point.

> Expand the C API to have something like PyObject_Path()?
>
> PyUnicode_FromFSPath, perhaps? The return type is well-defined here,
> so it can be done as an alternate constructor, and the C API
> counterparts of os.fsdecode and os.fsencode are PyUnicode functions
> (specifically PyUnicode_DecodeFSDefault and PyUnicode_EncodeFSDefault)

What about DirEntry, which may have a bytes representation? I would
expect the function return type of os.fspath to be Union[str, bytes],
unless bytes pathnames are decoded with surrogate escapes.

[1] https://mail.python.org/pipermail/python-ideas/2016-April/039595.html


PS. I have been reading this list occasionally on the google groups
mirror, and I now subscribed to it just to send this. (BTW, I probably
broke the thread, as I did not have Nick's email in my inbox to reply
to. Sorry about that.) I'll have to mention that I was surprised, to
say the least, to find that the pathlib discussion had moved here from
python-ideas, where I had mentioned I was working on a proposal. Then,
I also found that the solution discussed here was seemingly an
improved version of what I had proposed on python-ideas somewhat
earlier [1], but did not get any reactions to. While I can only make
guesses about what happened, these kinds of things easily make you go
from "Hey, maybe I'll be able to do something to improve Python!" to
"These people don't seem to want me here or appreciate my efforts.".
Not to accuse anyone in particular; just to let people know. Anyway, I
somehow got sucked into thinking deeply about pathlib etc. (which I do
use). Not that I really have much at stake here, except spending
ridiculous amounts of time thinking about paths, mainly during my
Easter holidays and after that. I really had a hard time explaining to
friends and family what the heck I was doing ;).
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Defining a path protocol (was: When should pathlib stop being provisional?)

2016-04-08 Thread Koos Zevenhoven
On Fri, Apr 8, 2016 at 7:42 PM, Chris Barker  wrote:
> On Fri, Apr 8, 2016 at 9:02 AM, Koos Zevenhoven  wrote:
>>
>> I'm still thinking a little bit about 'pathname', which to me sounds
>> more like a string than fspath does [1].
>
>
> I like that a lot - or even "__pathstr__" or "__pathstring__"
>
> after all, we're making a big deal out of the fact that a path is *not a
> string*, but rather a string is a *representation* (or serialization) of a
> path.

For me, the point here is the reverse: that any str is not a path, and
that it is misleading to call it *path* when whole point is to make it
*not* a specialized path object but a plain string. I think it's ok to
think of a path as special kind of string. For instance, an URI is
explicitly defined as a *sequence of characters*, and URIs can be
thought of as a more recent, improved and broadened concept than
paths. This is the point of view I took in my recent proposal, but I
don't think it's the only valid way to think about paths "in theory".
I like the "serialization" interpretation as well, but i tend to think
that that string serialization is what is called a path.

Anyway, I don't think these philosophical considerations should
dictate how Python is implemented. But it is always good to also have
a valid theoretical point of view to back up a design decision.

> For the record, this is pretty rare -- and it was announced on -ideas that
> the discussion had started up here -- maybe you missed that post?

If you mean in Ethan's response to my proposal, I noticed that, but
the discussions here had already gone quite far by that time. Even
more so by the time I had time to see what was going on.

I do have to say this is not the first time I felt there was some sort
of hostility towards newcomers on python-ideas. Sure, it might be
partly because those people don't know the culture on the list, but
I'm not sure if that should be used as an excuse.

-Koos
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Pathlib enhancments - method name only

2016-04-08 Thread Koos Zevenhoven
On Fri, Apr 8, 2016 at 9:20 PM, Chris Barker  wrote:
>
> we rejected plain old __path__ because this is already ued in another
> context, but if we add "str" on the end, that's not longer an issue, so do
> we need the "fs"?
>
> __pathstr__ # pathstring
>

Or perhaps __pathstring__ in case it may be or return byte strings.

-Koos
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Pathlib enhancments - method name only

2016-04-08 Thread Koos Zevenhoven
On Fri, Apr 8, 2016 at 11:39 PM, R. David Murray  wrote:
> On Fri, 08 Apr 2016 19:24:44 -, Brett Cannon  wrote:
>> On Fri, 8 Apr 2016 at 12:10 Chris Angelico  wrote:
>>
>> > On Sat, Apr 9, 2016 at 5:03 AM, Chris Barker 
>> > wrote:
>> > > On Fri, Apr 8, 2016 at 11:34 AM, Koos Zevenhoven 
>> > wrote:
>> > >>
>> > >> >
>> > >> > __pathstr__ # pathstring
>> > >> >
>> > >>
>> > >> Or perhaps __pathstring__ in case it may be or return byte strings.
>
> But there are other paths than OS file system paths.  I prefer
> __fspath__ or __os_path__ myself.  I think the fact that it is a string
> is implied by the fact that it is getting us the thing we can pass
> to the os (since Python3 deals with os paths as strings unless you
> specify otherwise, only converting them back to bytes, on unix, at the last
> moment).
>
> Heh, although I suppose one could make the argument that it should
> return whatever the native OS wants, and save the low level code
> from having to do that?  Pass the path object all the way down
> to that "final step" in the C layer?  (Just ignore me, I'm sure
> I'm only making trouble :)

My favorites are fspath and pathname, and since this is a dunder
methdod, it is not as crucial what it is called. I have the feeling
the consensus is converging towards fspath?

I'll comment on the bytes issue in the other thread. Boy these threads
are all over the place!

-Koos
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Defining a path protocol

2016-04-08 Thread Koos Zevenhoven
On Fri, Apr 8, 2016 at 8:34 PM, Brett Cannon  wrote:
> On Fri, 8 Apr 2016 at 09:39 Ethan Furman  wrote:
>> > I thought the whole point off all this is that not any old string can be
>> > a path! (whereas any int can be an index). Unless we go with Chris A's
>> > suggestion that this be a more generic lossless string protocol, rather
>> > than just for paths.
>>
>> That does seem to be a valid point against str.__fspath__.
>
> Yep, and I'm expecting we won't want that at this point. The fact that paths
> need strings for low-level OS stuff is a historical and technical detail, so
> no need to drag the entire str type into it if we can provide a reasonable
> helper function (for either the ABC or magic method solution).

I'm not sure I understand what these points are about. Anyway,
disallowing str or bytes as pathnames will break backwards
compatibility if done at some point in the future. There's no way
around that.

But regarding all this talk of mine about bytes is because it has not
been completely clear to me if something can break when converting a
bytes path to str. I did originally propose guaranteeing a str, but I
am so far only 85% convinced that that does not cause any problems. I
understand that fsencode(fsdecode(bytes_path)) should always be equal
to bytes_path. But can some other path operations fail when there are
surrogates in the strings? And again, not to forget DirEntry, which
may have a byte string path.

Either way, I suppose os.fspath should accept anything that has
__fspath__ or is a str or bytes (whether these have the dunder method
or not). Then the options are either to return Union[str, bytes] or to
always return str. And if the latter does not cause any problems, I
like it way better, and it seems others would do too. And in that case
it would probably be time to deprecate bytes paths on posix too (on
Windows, this is already the case).

But do we know that converting all paths to str does not cause any problems?

-Koos
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Defining a path protocol

2016-04-08 Thread Koos Zevenhoven
On Sat, Apr 9, 2016 at 12:53 AM, Brett Cannon  wrote:
> On Fri, 8 Apr 2016 at 14:23 Koos Zevenhoven  wrote:
>
> At this point no one wants to touch bytes paths. If you need that level of
> control because of multiple encodings within a single file system then you
> will probably have to stick with managing bytes paths on your own to get the
> encoding right.

What does this mean? I assume you don't mean os.path.* would stop
dealing with bytes? And if not, then you seem to mean that os.fspath
would do nothing except call .__fspath__(). In that case, I think we
should go back to it being an attribute (or property) and a variation
of the now very famous idiom getattr(path, '__fspath__', path) and
perhaps have os.fspath do exactly that.

> And just because DirEntry supports bytes doesn't mean that any magic method
> it gains has to carry that forward (it can always raise a TypeError if
> necessary).

No, but what if some code gets pathnames from whatever other places
and passes them on to os.scandir. Whenever it happens to get a bytes
path, a TypeError gets raised, but only when it picks one of the
DirEntry objects and for instance tries to open(...) it. Of course,
I'm not sure how common this is.

> It really depends on how we choose to structure the
> function in terms of just doing the right thing for objects that follow the
> protocol or if we want to introduce some required structure for the
> resulting path and implement some type guarantees so you have a better idea
> of what you will be working with after calling the function.

Do you have an example of potential 'required structure'?

>> Then the options are either to return Union[str, bytes] or to
>> always return str. And if the latter does not cause any problems, I
>> like it way better, and it seems others would do too.
>
> You don't have to convert byte paths to str, you can simply raise an
> exception in the face of them.
>

I thought the point was for existing APIs to start supporting path
objects, wouldn't raising an exception break the API?

-Koos
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Defining a path protocol (was: When should pathlib stop being provisional?)

2016-04-09 Thread Koos Zevenhoven
On Sat, Apr 9, 2016 at 10:16 AM, Ethan Furman  wrote:
> On 04/09/2016 12:07 AM, Victor Stinner wrote:
>>
>> os.DirEntry doesn't support bytes: os.scandir() only accept str. It's a
>> deliberate choice.
>
>
> 3.5.0 scandir supports bytes:
>
> --> huh = list(scandir(b'.'))
> --> huh
> [, ,  b'__MACOSX'>, , ,  b'index.html'>]
>
> --> huh[0].path
> b'./minicourse-ajax-project'
>
>

Maybe it's the bytes support in scandir that should be deprecated?
(And not bytes support in general, which cannot be done on posix, as I
hear Stephen T. will tell me).

-Koos
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Pathlib enhancments - method name only

2016-04-11 Thread Koos Zevenhoven
On Sat, Apr 9, 2016 at 10:48 AM, Nick Coghlan  wrote:
> On 9 April 2016 at 04:25, Brett Cannon  wrote:
>> On Fri, 8 Apr 2016 at 11:13 Ethan Furman  wrote:
>>> On 04/08/2016 10:46 AM, Koos Zevenhoven wrote:
>>>  > On Fri, Apr 8, 2016 at 7:42 PM, Chris Barker  wrote:
>>>  >> On Fri, Apr 8, 2016 at 9:02 AM, Koos Zevenhoven wrote:
>>>  >>>
>>>  >>> I'm still thinking a little bit about 'pathname', which to me sounds
>>>  >>> more like a string than fspath does.
>>>  >>
>>>  >>
>>>  >> I like that a lot - or even "__pathstr__" or "__pathstring__"
>>>  >> after all, we're making a big deal out of the fact that a path is
>>>  >> *not a string*, but rather a string is a *representation* (or
>>>  >> serialization) of a path.
>>>
>>> That's a decent point.
>>>
>>> So the plausible choices are, I think:
>>>
>>> - __fspath__  # File System Path -- possible confusion with Path
>>
>> +1
>
> I like __fspath__, but I'm also sympathetic to Koos' point that we're
> really dealing with path *names* being produced via this protocol,
> rather than the paths themselves.
>
> That would bring the completely explicit "__fspathname__" into the
> mix, which would be comparable in length to "__getattribute__" as a
> magic method name (both in terms of number of syllable and number of
> characters).
>
> Considering the helper function usage, here's some examples in
> combination with os.fsencode and os.fsdecode:
>
> # Status quo for binary/text path conversions
> text_path = os.fsdecode(bytes_path)
> bytes_path = os.fsencode(text_path)
>
> # Getting a text path from an arbitrary object
> text_path = os.fspath(obj) # This doesn't scream "returns text!" to me
> text_path = os.fspathname(obj) # This does
>
> # Getting a binary path from an arbitrary object
> bytes_path = os.fsencode(os.fspath(obj))
> bytes_path = os.fsencode(os.fspathname(obj))
>
> I'm starting to think the semantic nudge from the "name" suffix when
> reading the code is worth the extra four characters when writing it
> (keeping in mind that the whole point of this exercise is that most
> folks *won't* be writing explicit conversions - the stdlib will handle
> it on their behalf).
>

Regarding the name, I completely agree with Nick's reasoning (above).
I'm not sure it's a high priority to make dunder-method names short.
They are not typed very often, and when the number of these
"protocols" increases, you face potentially ambiguous names more and
more often (there already is a '__path__' and a '__file__' etc., as
has been brought up earlier in these threads.). In other words, it's a
good idea to have some information in the name.

> I also think the more explicit name helps answer some of the type
> signature questions that have arisen:
>
> 1. Does os.fspathname return rich Path objects? No, it returns names
> as str objects

Or byte strings, it seems, unfortunately.

> 2. Will file descriptors pass through os.fspathname? No, as they're
> not names, they're numeric descriptors.
> 3. Will bytes-like objects pass through os.fspathname? No, as they're
> not names, they're encodings of names
>

If fspathname(...) is to be used in os.path.*, it will break things if
it starts to turn encoded bytes pathnames into str pathnames, which it
did not previously do.

And if fspathname is not to be used in os.path.*, who would be our
intended user of fspathname? I assume we we don't want to encourage
typical 'users' to manipulate pathnames by hand.

>> I personally still like __ospath__ as well.
>
> That one fails the "Is it ambiguous when spoken aloud?" test for me:
> if someone mentions "oh-ess-path", are they talking about os.path or
> __ospath__? With "eff-ess-path" or "eff-ess-path-name", that problem
> doesn't arise.
>

+1 to this too.

-Koos
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Pathlib enhancements - acceptable inputs and outputs for __fspath__ and os.fspath()

2016-04-11 Thread Koos Zevenhoven
On Mon, Apr 11, 2016 at 9:27 AM, Nick Coghlan  wrote:
> On 11 April 2016 at 02:16, Ethan Furman  wrote:
>>
>> I guess I don't see the point of this.  Either DirEntry's [1] only get
>> partial support (which is only marginally better than the no support pathlib
>> currently has), or stdlib code will need to catch those errors and then do
>> an isinstance check to see if knows what the type is and how to deal with it
>> [1].
>
> What's wrong with only gaining partial support? Standard library code
> that doesn't currently support DirEntry at all will gain the ability
> to support str-based DirEntry objects, while bytes-based DirEntry
> objects will continue to be a low level object that isn't
> interoperable with most other APIs (which is fine - anyone writing low
> level POSIX-specific code can deal with unpacking the values
> explicitly, it just won't happen implicitly anywhere).
>

While I'm also tempted to lean towards 'marginalizing bytes support',
it seems a little bit dangerous to me. Currently, os.path is heavily
based on duck typing of str and bytes, so there may be code out there
that does all kinds of things with paths without knowing whether it
deals with bytes or str objects. If such code gets in contact with
this pathname protocol, it will raise an exception whenever it happens
to be fed a bytes path. That is, if the approach of 'partial support'
is taken.

And still there is the question I just posted in another branch of
this mess: Who should use os.fspathname(...)? If it's os.path.* and
other traditional (low-level?) functions that deal with paths, then
fspathname should, in the name of backwards compatiblity, be able to
deal with bytes and return bytes in those cases.  Otherwise fspathname
would do nothing for you, and all the work of
isinstance/hasattr/whatever would be left to the caller of
os.fspathname (or maybe this is what you want?).

So a somewhat useful fspathname might indeed look something like this:

 def fspathname(pathlike) -> Union[str, bytes]:
 pathname = getattr(pathlike, '__fspathname__', pathlike)
 if not isinstance(pathname, (str, bytes)):
 raise TypeError("your thing is not pathlike")
 return pathname

But maybe it is enough to have the __fspathname__ attribute, and make
fspathname() some internal implementation detail of os.path.* and the
like.

-Koos
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] pathlib - current status of discussions

2016-04-12 Thread Koos Zevenhoven
On Tue, Apr 12, 2016 at 11:56 AM, Nick Coghlan  wrote:
> One possible way to address this concern would be to have the
> underlying protocol be bytes/str (since boundary code frequently needs
> to handle the paths-are-bytes assumption in POSIX), but offer an
> "os.fspathname" API that rejected bytes output from os.fspath. That
> is, it would be equivalent to:
>
> def fspathname(path):
> name = os.fspath(path)
> if not isinstance(name, str):
> raise TypeError("Expected str for pathname, not
> {}".format(type(name)))
> return name
>
> That way folks that wanted the clean "must be str" signature could use
> os.fspathname, while those that wanted to accept either could use the
> lower level os.fspath.

I'm not necessarily opposed to this. I kept bringing up bytes in the
discussion because os.path.* etc. and DirEntry support bytes and will
need to keep doing so for backwards compatibility.  I have no
intention to use bytes pathnames myself. But it may break existing
code if functions, for instance, began to decode bytes paths to str if
they did not previously do so (or to reject them). It is indeed a lot
safer to make new code not support bytes paths than to change the
behavior of old code.

But then again, do we really recommend new code to use os.fspath (or
os.fspathname)? Should they not be using either pathlib or os.path.*
etc. so they don't have to care? I'm sure Ethan and his library (or
some other path library) will manage without the function in the
stdlib, as long as the dunder attribute is there.

So I'm, once again, posing this question (that I don't think got any
reactions previously): Is there a significant audience for this new
function, or is it enough to keep it a private function for the stdlib
to use? That handful of third-party path libraries can decide for
themselves if they want to (a) reject bytes or (b) implicitly fsdecode
them or (c) pass them through just like str, depending on whatever
their case requires in terms of backwards compatiblity or other goals.

If we forget about the os.fswhatever function, we only have to decide
whether the magic dunder attribute can be str or bytes or just str.

-Koos
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] pathlib - current status of discussions

2016-04-12 Thread Koos Zevenhoven
On Tue, Apr 12, 2016 at 7:19 PM, Chris Barker  wrote:
>
> One more though came up just now: there are different level sof abstractions
> and representations for paths. We don't want to make Path a subclass of
> string, because Path is supposed to be a higher level abstraction -- good.
>
> then at the bottom of the stack, we NEED the bytes level path, because that
> what ultimately gets passed to the OS.
>
> THe legacy from the single-byte encoding days is that bytes and strings were
> the same, so we could let people work with nice human readable strings,
> while also working with byte paths in the same way -- but those days are
> gone -- py3 make s clear (and important) distiction between nice human
> readable strings  and the bytes that represent them.
>
> So: why use strings as the lingua franca of paths? i.e. the basis of the
> path protocol. maybe we should support only two path representations:
>
> 1) A "proper" path object -- i.e. pathlib.Path or anything else that
> supports the path protocol.
>
> 2) the bytes that the OS actually needs.
>

You do have a point there. But since bytes pathnames are deprecated on
windows, this seems to lead to supporting both str and bytes in the
protocol, or having two protocols __fspathbytes__ and __fspathstr__
(and one being preferred over the other, potentially even depending on
the platform).,

-Koos
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] pathlib - current status of discussions

2016-04-12 Thread Koos Zevenhoven
On Tue, Apr 12, 2016 at 6:52 PM, Stephen J. Turnbull  wrote:
>
> (A) Why does anybody need bytes out of a pathlib.Path (or other
> __fspath__-toting, higher-level API) *inside* the boundary?  Note
> that the APIs in os (etc) *don't need* bytes because they are
> already polymorphic.
>

Indeed not from pathlib.*Path , but from DirEntry, which may have a
path as bytes. So the options for DirEntry (or things like Ethan's
'antipathy') are:

(1) Provide bytes or str via the protocol, depending on which type
this DirEntry has

Downside: The protocol needs to support str and bytes.

(2) Decode bytes using os.fsdecode and provide a str via the protocol

Downside: The user passed in bytes and maybe had a reason to do so.
This might lead to a weird mixture of str and bytes in the same code.

(3) Do not implement the protocol when dealing with bytes

Downside: If a function calling os.scandir accepts both bytes and str
in a duck-typing fashion, then, if this adopted something that uses
the new protocol, it will lose its bytes compatiblity. This risk might
not be huge, so perhaps (3) is an option?


> (B) If they do, why can't they just apply bytes() to the object?  I
> understand that that would offend Ethan's aesthetic sense, so it's
> worth looking for a nice way around it.  But allowing __fspath__
> to return bytes or str is hideous, because Paths are clearly on
> the application side of the boundary.
>
> Note that bytes() may not have the serious problem that str() does of
> being too catholic about its argument: nothing in __builtins__ has a
> __bytes__!  Of course there are a few things that do work: ints, and
> sequences of ints.

Good point. But this only applies to when the user _explicitly_ deals
with bytes. But when the user just deals with the type (str or bytes)
that is passed in, as os.path.* as well as DirEntry now do, this does
not work.

-Koos
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] List posting custom [was: current status of discussions]

2016-04-13 Thread Koos Zevenhoven
On Wed, Apr 13, 2016 at 5:56 AM, Stephen J. Turnbull  wrote:
> The following is my opinion, as will become obvious, but it's based on
> over a decade of observing these lists, and other open source
> development lists.  In a context where some core developers have
> unsubscribed from these lists, and others regularly report muting
> threads with a certain air of asperity, I think it's worth the risk of
> seeming arrogant to explain some of the customs (which are complex and
> subtle) around posting to Python developer lists.  I'm posting
> publicly because there are several new developers whose activity and
> fresh perspective is very welcome, but harmony *is* being disturbed,
> IMO unnecessarily.
>

Thank you for this thoughtful post. While none of the quotes you refer
to are mine, I did try to find whether any of the advice is something
I should learn from. While I didn't find a whole lot (please do
correct me if you think otherwise), it is also valuable to hear these
things from someone more experienced, even just to confirm what I may
have thought or guessed. I can't really tell, but possibly some of the
thoughts are interesting even to people significantly more experienced
than me.

I know you are not interested in discussing this further here, but
I'll add some inexperienced points of view inline below, just in case
someone is interested:

> This particular post caught my eye, but it's only an example of one of
> the most unharmonious posting styles that has become common recently.
> Attribution deliberately removed.
>
>  > Sorry for disturbing this thread's harmony.
>
> *sigh*  There is way too much of this on Python-Ideas recently, and
> there shouldn't be any on Python-Dev.  So please don't.  Specifically,
> disagreement with an apparently developing consensus is fine but
> please avoid this:
>
>  > >> Path is an alternative to os.path -- you don't need to use both.
>  >
>  > I agree with that quote of Chris.
>
> It's a waste of time to post *what* you agree with.[1]  Decisions are
> not taken by vote in this community, except for the color of the
> bikeshed, where it is agreed that *what* decision is taken doesn't
> matter, but that some decision should be taken expeditiously.[2]
> Chris already stated this position clearly and it's not a "color", so
> there is no need to reiterate.  It simply wastes others' time to read
> it.  (Whether it was a waste of the poster's time is not for me to
> comment on.)
>
> What matters to the decision is *why* you agree (or disagree).  If you
> think that some of Chris's arguments are bogus (and should be
> disregarded) and others are important, that is valuable information.
> It's even better if you can shed additional light on the matter
> (example below).
>
> Also, expression of agreement is often a prelude to a request for
> information.  "I agree with Z's post.  At least, I have never needed
> X.  *When* do you need X?  Let's look for a better way than X!"
>

That's what I thought too. I remember several times recently that I
have mentioned I agreed about something, then continuing to add more
to it, or even saying I disagree about something else. Part of the
reason to also state that I agree is an attempt to keep the overall
tone more positive. After all, the other person might be a highly
experienced core developer who just did not happen to have gone though
all the same thoughts regarding that specific question recently. I
hope that has not been interpreted as arrogance such as "I know better
than these people".

For me, as one of the (many?) newcomers, especially on -dev, it can
sometimes be difficult to tell whether not getting a reaction means
"Good point, I agree", "I did not understand so I'll just ignore it",
"I don't want to argue with you" or something else. Then again,
someone just saying essentially the same thing without a reference a
few posts later just feels strange. Also, if the only thing people
apparently do is disagree about things, it makes the overall tone of
the discussions at least *seem* very negative. From this point of view
there seems to be some good in positive comments.

> Unsupported (dis)agreement to statements about "needs" also may be
> taken as *rude*, because others may infer your arrogant claim to know
> what *they* do or don't need.  Admittedly there's a difficult
> distinction here between Chris's *idiom* where "you don't need to"
> translates to "In my understanding, it is generally not necessary to",
> and your *unsupported* agreement, which in my dialect of English
> changes the emphasis to imply you know better than those who disagree
> with you and Chris.  And, of course, the position that others are "too
> easily offended" is often reasonable, but you should be aware that
> there will be an impact on your reputation and ability to influence
> development of Python (even if it doesn't come near the point where
> a moderator invokes "Code of Conduct").
>
> "Me too" posts aren't entirely forbidden, but I feel that 

Re: [Python-Dev] pathlib - current status of discussions

2016-04-14 Thread Koos Zevenhoven
On Thu, Apr 14, 2016 at 7:46 PM, Ethan Furman  wrote:
>
> What many folks seem to be missing is that *you* (generic you) have control
> of your data.
>
> If you are not working at the bytes layer, you shouldn't be getting bytes
> objects because:
>
> - you specified str when asking for data from the OS, or
> - you transformed the incoming bytes from whatever external source
>   to str when you received them.

There is an apparent contradiction of the above with some previous
posts, including your own. Let me try to fix it:

Code that deals with paths can be divided in groups as follows:

(1) Code that has access to pathname/filename data and has some level
of control over what data type comes in. This code may for instance
choose to deal with either bytes or str

(2) Code that takes the path or file name that it happens to get and
does something with it. This type of code can be divided into
subgroups as follows:

  (2a) Code that accepts only one type of paths (e.g. str, bytes or
pathlib) and fails if it gets something else.

  (2b) Code that wants to support different types of paths such as
str, bytes or pathlib objects. This includes os.path.*, os.scandir,
and various other standard library code. Presumably there is also
third-party code that does the same. These functions may want to
preserve the str-ness or bytes-ness of the paths in case they return
paths, as the stdlib now does. But new code may even want to return
pathlib objects when they get such objects as inputs. This is the
duck-typing or polymorphic code we have been talking about. Code of
this type (2b) may want to avoid implicit conversions because it makes
the life of code of the other types more difficult.

(feel free to fill in more categories of code)

So the code of type (2b) is trying to make all categories happy by
returning objects of the same type that it gets as input, while the
other categories are probably in the situation where they don't
necessarily need to make other categories of code happy.

And the question is this: Do we need to make code using both bytes
*and* scandir happy? This is largely the same question as whether we
have to support bytes in addition to str in the protocol.

(We may of course talk about third-party path libraries that have the
same problem as scandir's DirEntry. Ethan's library is not exactly in
the same category as DirEntry since its path objects *are* instances
of bytes or str and therefore do not need this protocol to begin with,
except perhaps for conversions from other high-level path types so
that different path libraries work together nicely).

-Koos
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] pathlib - current status of discussions

2016-04-14 Thread Koos Zevenhoven
On Thu, Apr 14, 2016 at 9:35 PM, Random832  wrote:
> On Thu, Apr 14, 2016, at 13:56, Koos Zevenhoven wrote:
>> (1) Code that has access to pathname/filename data and has some level
>> of control over what data type comes in. This code may for instance
>> choose to deal with either bytes or str
>>
>> (2) Code that takes the path or file name that it happens to get and
>> does something with it. This type of code can be divided into
>> subgroups as follows:
>>
>>   (2a) Code that accepts only one type of paths (e.g. str, bytes or
>> pathlib) and fails if it gets something else.
>
> Ideally, these should go away.
>

I don't think so. (1) might even be the most common type of all code.
This is code that gets a path from user input, from a config file,
from a database etc. and then does things with it, typically including
passing it to type (2) code and potentially getting a path back from
there too.

>>   (2b) Code that wants to support different types of paths such as
>> str, bytes or pathlib objects. This includes os.path.*, os.scandir,
>> and various other standard library code. Presumably there is also
>> third-party code that does the same. These functions may want to
>> preserve the str-ness or bytes-ness of the paths in case they return
>> paths, as the stdlib now does. But new code may even want to return
>> pathlib objects when they get such objects as inputs.
>
> Hold on. None of the discussion I've seen has included any way to
> specify how to construct a new object representing a different path
> other than the ones passed in. Surely you're not suggesting type(a)(b).
>

That's right. This protocol is not solving the issue of returning
'rich' path objects. It's solving the issue of passing those objects
to lower-level functions or to interact with other 'rich' path types.
What I meant by this is that there may be code that *does* want to do
type(a)(b), which is out of our control. Maybe I should not have
mentioned that.

> Also, how does DirEntry fit in with any of this?
>

os.scandir + DirEntry are one of the many things in the stdlib that
give you pathnames of the same type as those that were put in.

>> This is the
>> duck-typing or polymorphic code we have been talking about. Code of
>> this type (2b) may want to avoid implicit conversions because it makes
>> the life of code of the other types more difficult.
>
> As long as the type it returns is still a path/bytes/str (and therefore
> can be accepted when the caller passes it somewhere else) what's the
> problem?

No, because not all paths are passed to the function that does the
implicit conversion, and then when for instance os.path.joining two
paths of a differenty type, it raises an error.

In other words: Most non-library code (even library code?) deals with
one specific type and does not want implicit conversions to other
types. Some code (2b) deals with several types and, at least in the
stdlib, such code returns paths of the same type as they are given,
which makes said "most non-library code" happy, because it does not
force the programmer to think about type conversions.

(Then there is also code that explicitly deals with type conversions,
such as os.fsencode and os.fsdecode.)

-Koos
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Pathlib enhancements - acceptable inputs and outputs for __fspath__ and os.fspath()

2016-04-17 Thread Koos Zevenhoven
On Sun, Apr 17, 2016 at 11:03 AM, Stephen J. Turnbull
 wrote:
> Nick Coghlan writes:
>
>  > str and bytes aren't going to implement __fspath__ (since they're
>  > only *sometimes* path objects), so asking people to call the
>  > protocol method directly for any purpose would be a pain.
>
> It *should* be a pain.  People who need bytes should call fsencode,
> people who need str should call fsdecode, and Ethan's antipathy checks
> for bytes and str, then calls __fspath__ if needed.  Who's left?  Just
> the bartender and the janitor, last call was hours ago.  OK, maybe
> there are enough clients to make it worthwhile to provide the utility,
> but it should be clearly marked as "double opt-in, for experts only
> (consenting adults must show proof of insurance)".

My doubts, expressed several times in these threads, about the need
for a *public* os.fspath function to complement the __fspath__
protocol, are now perhaps gone. I'll explain why (and how). The
reasons for my doubts were that

(1) The audience outside the stdlib for such a function should be
small, because it is preferred to either use existing tools in
os.path.* or pathlib (or similar) for manipulating paths.

(2) There are just too many different possible versions of this
function: rejecting str, rejecting bytes, coercion to str, coercion to
bytes, and accepting both str and bytes. That's a total of 5 different
cases. People also used to talk about versions that would not allow
passing through objects that are already bytes or str. That would make
it a total of 10 different versions!
(in principle, there could be even more, but let's not go there :-).
In other words, this argument was that it is probably best to
implement whatever flavor is needed for the context, perhaps based on
documented recipes.


Regarding (2), we can first rule out half of the 10 cases---the ones
that reject plain instances of bytes and/or str---because they would
not be very useful as all the isinstance/hasattr checking etc. would
be left to the caller. And here are the remaining five, explained
based on what they accept as argument, what they return, and where
they would be used:

(A) "polymorphic"
*Accept*: str and bytes, provided via __fspath__ as well as plain str
and bytes instances.
*Return*: str/bytes depending on input.
*Audience*: the stdlib, including os.path.things, os.things,
shutil.things, open, ... (some functions would need a C version).
There may even be a small audience outside the stdlib.

(B) "str-based only"
*Accept*: str, provided via __fspath__ as well as plain str.
*Return*: str.
*Audience*: relatively low-level code that works exclusively with str
paths but accepts specialized path objects as input.

(C) "bytes-based only"
*Accept*: bytes, provided via __fspath__ as well as plain bytes.
*Return*: bytes.
*Audience*: low-level code that explicitly deals with paths as bytes
(probably to deal with undefined/ill-defined encodings).

(D) "coerce to str"
*Accept*: str and bytes, provided via __fspath__ as well as plain str
and bytes instances.
*Return*: str (coerced / decoded if needed).
*Audience*: code that deals explicitly with str but wants to 'try'
supporting bytes-based path inputs too via implicit decoding (even if
it may result in surrogate escapes, which one cannot for instance
print(...).)

(E) "coerce to bytes"
*Accept*: str and bytes, provided via __fspath__ as well as plain str
and bytes instances.
*Return*: bytes (coerced / encoded if needed).
*Audience*: low-level code that explicitly deals with bytes paths but
wants to accept str-based path inputs too via implicit encoding.


Even if all options (A-E) probably have small audiences (compared to
e.g. os.path.*), some of them have larger audiences than others. But
all of them have at least *some* reasonable audience (as desribed
above).

Recently (well, a few days ago, but 'recently', considering the scale
of these discussions anyway ;-), Nick pointed out something I hadn't
realized---os.fsencode and os.fsdecode actually already implement
coercion to bytes and str, respectively. With those two functions made
compatible with the __fspath__ protocol [using (A) above], they would
in fact *be* (D) and (E), respectively.

Now, we only have options (A-C) left. They could all be implemented
roughly as follows:

def fspath(pathlike, *, output_types = (str,)):
  if hasattr(pathlike, '__fspath__'):
ret = pathlike.__fspath__()  # or pathlike.__fspath__ if it's not a method
  else:
ret = pathlike
  if not isinstance(ret, output_types):
raise TypeError("argument is not and does not provide an
acceptable pathname")
  return ret

With an implementation like the above, (A) would correspond to
output_types = (str, bytes), (B) to the default, and (C) to
output_types = (bytes,).


So, with the above considerations as a counterargument, I consider
argument (2) gone.

What about argument (1), that the audience for the os.fspath(...)
function (especially for one selected version of the 5 or 10
variation

Re: [Python-Dev] Pathlib enhancements - acceptable inputs and outputs for __fspath__ and os.fspath()

2016-04-17 Thread Koos Zevenhoven
On Sun, Apr 17, 2016 at 9:14 PM, Ethan Furman  wrote:
> On 04/17/2016 06:58 AM, Koos Zevenhoven wrote:
>
>> So, as a summary: With a str+bytes-polymorphic __fspath__, with the
>> above argumentation and the rough implementation of os.fspath(...),
>> the conclusion is that the os.fspath function should indeed be public,
>> and that no further variations are needed.
>
>
> Nice summation, thank you.  :)
>

Come on, Ethan, that summary was not for you ;) It was for lazy
people, people with bad memory, or people not so involved in the
topic. I wrote a big post, provided new arguments, with other points
collected into the same logical framework, wrote a new version of
os.fspath and argued why it is the right one --- and all you do is
read the stupid summary. You can do better than that: read the whole
thing! ;-).

-Koos
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Pathlib enhancements - acceptable inputs and outputs for __fspath__ and os.fspath()

2016-04-18 Thread Koos Zevenhoven
On Mon, Apr 18, 2016 at 5:03 PM, Ethan Furman  wrote:
> On 04/18/2016 12:41 AM, Nick Coghlan wrote:
>
>> Given the variant you [Koos] suggested, what if we defined the API
>> semantics
>> like this:
>>
>>  # Offer the simplest possible API as the public vesion
>>  def fspath(pathlike) -> str:
>>  return os._raw_fspath(pathlike)
>>
>>  # Expose the complexity in the "private" variant
>>  def _raw_fspath(pathlike, *, output_types = (str,)) -> (str, bytes):
>>  # Short-circuit for instances of the output type
>>  if isinstance(pathlike, output_types):
>>  return pathlike
>>  # We'd have a tidier error message here for non-path objects
>>  result = pathlike.__fspath__()
>>  if not isinstance(result, output_types):
>>  raise TypeError("argument is not and does not provide an
>> acceptable pathname")
>>  return result
>
> My initial reaction was that this was overly complex, but after thinking
> about it a couple days I /really/ like it.  It has a reasonable default for
> the 99% real-world use-case, while still allowing for custom and exact
> tailoring (for the 99% stdlib use-case ;) .
>

While it does seem we finally might be nearly there :), this still
seems to need some further discussion.

As described in that long post of mine, I suppose some third-party
code may need the variations (A-C), while it seems that in the stdlib,
most places need (str, bytes), i.e. (A), except in pathlib, which
needs (str,), i.e. (B). I'm not sure what I think about making the
variations private, even if "hiding" the bytes version is, as I said,
an important role of the public function.

Except for that type hint, there is *nothing* in the function that
might mislead the user to think bytes paths are something important in
Python 3. It's a matter of documentation whether it "supports" bytes
or not. In fact, that function (assuming the name os.fspath) could now
even be documented to support this:

patharg = os.fspath(patharg, output_types = (str, pathlib.PurePath))  # :-)

So are we still going to end up with two functions or can we deal with one?
What should the typehint be? Something new in typing.py? How about
FSPath[...] as follows:

FSPath[bytes]  # bytes-based pathlike, including bytes
FSPath[str]   # str-based pathlike, including str

pathstring = typing.TypeVar('pathstring', str, bytes)  # could be
extended with PurePath or some path ABC

So the above variation might become:

def fspathname(pathlike: FSPath[pathstring],
   *, output_types: tuple = (str,)) -> pathstring:
# Short-circuit for instances of the output type
if isinstance(pathlike, output_types):
return pathlike
# We'd have a tidier error message here for non-path objects
result = pathlike.__fspath__()
if not isinstance(result, output_types):
raise TypeError("valid output type not provided via __fspath__")
return result

And similar type hints would apply to os.path functions. For instance,
os.path.dirname:

def dirname(p: FSPath[pathstring]) -> pathstring:
...

This would say pathstring all over and not give anyone any ideas about
bytes, unless they know what they're doing.

Complicated? Yes, typing is. But I think we will need this kind of
hints for os.path functions anyway.

-Koos
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Pathlib enhancements - acceptable inputs and outputs for __fspath__ and os.fspath()

2016-04-19 Thread Koos Zevenhoven
On Tue, Apr 19, 2016 at 2:55 PM, Stephen J. Turnbull  wrote:
>
> AFAICS bytes return from __fspath__ is just YAGNI.  Show me something
> that actually wants it.

It might be, but as long as bytes paths are supported polymorphicly
all over the stdlib, we won't get rid of supporting bytes paths. So
are you proposing to deprecate bytes paths?

-Koos
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Pathlib enhancements - acceptable inputs and outputs for __fspath__ and os.fspath()

2016-04-20 Thread Koos Zevenhoven
On Wed, Apr 20, 2016 at 6:11 AM, Stephen J. Turnbull  wrote:
> Koos Zevenhoven writes:
>  > On Tue, Apr 19, 2016 at 2:55 PM, Stephen J. Turnbull  
> wrote:
>  > >
>  > > AFAICS bytes return from __fspath__ is just YAGNI.  Show me something
>  > > that actually wants it.
>  >
>  > It might be,
>
> May I take that as meaning you just jumped to the conclusion that
> extending polymorphism is useful on no actual evidence of usefulness?

No you may not! YAGNI almost never means "you are *never* going to
need it". And if you implement a feature, better implement it well. If
a variation of the feature is rarely used, that is perfectly fine. I
think leaving bytes out would complicate things. If os.fspath does its
job well, everyone should be happy.

I kept bringing up bytes paths, because that is already a feature in
Python 3. Then (already some time ago in these discussions) I briefly
visited the thought of 'can we deprecate bytes paths', and it then
quickly became clear to me that is not going to happen any time soon.

In other words: As long as bytes paths are supported, they should be
supported consistently. I don't want DirEntry to behave differently
when the underlying type is bytes, which is one of the things I've
been talking about all the time. That would just be broken. And as you
also understand, one point is to allow passing DirEntry to open. Or
any of the os.path functions.

An some more: I don't want open(direntry_obj) to ever raise because it
is the bytes flavor of direntry, because, when they are created,
DirEntry objects always point to existing objects on the file system.
I also don't want implicit conversions between str and bytes paths,
because there are cases where they will produce strange results and
exceptions. [Yes, way back in the p-string thread, I did first suggest
a similiar thing that implied implicit conversion, but I soon
abandoned that part.]

Not that I will ever use these features---just to do this right.

>  > but as long as bytes paths are supported polymorphicly all over the
>  > stdlib, we won't get rid of supporting bytes paths. So are you
>  > proposing to deprecate bytes paths?
>
> You claim "almost always want str", Ethan claims "bias against bytes."
> Sorry, guys, you can't have it both ways.  Either bytes paths are
> discouraged (not "deprecated", not yet), or they aren't.
>
> I say, let's not encourage them.

It's all essentially the same thing:

"almost always want str":
Yes, I still claim this. This is the reason for str (and rejecting
bytes) being the default for third-party code. If we wanted to, we
could even leave bytes support out of the documentation, so no-one
will know about it unless they already deal with bytes paths. However,
I dont think we should do that---we should just strongly discourage
using the bytes version unless there is a reason to, and you know what
you are doing.

"bias against bytes":
I agree with this too. This is in line with making str (and rejecting
bytes) the default for third-party code.

"let's not encourage them":
And I even agree with this, as you may have noticed.

I just don't believe in deliberately making implementations awkward
for the bytes-based paths. Bytes paths already exist, not because of
Python 2 (as you know), but because not all operating systems
guarantee that paths make sense in any encoding, and people may need
to work at that level.

There is no need to make working with bytes-based paths awkward, and
we can support them with little additional work compared to supporting
str-based rich path objects. The additional work is mostly this
discussion.

> Ie, keep the status quo for bytes,
> and make things better for the preferred str.  Yes, that means
> discouraging bytes relative to str in this context.  That's a Python 3
> principle, one strong enough to justify the huge compatibility break
> involved in making str be Unicode.  That compatibility break has been
> extremely successful in my personal experience as a sometime Python
> teacher and Mailman developer, though the Mercurial developers have a
> different POV.

Yes. Luckily, people are already using str-based paths. We don't need
any more discrete transitions. If linux will start to enforce an
encoding, as Guido and Random832 may be suggesting on python-ideas,
these already obscure bytes paths will slowly fade away.

-Koos
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Pathlib enhancements - acceptable inputs and outputs for __fspath__ and os.fspath()

2016-04-20 Thread Koos Zevenhoven
On Wed, Apr 20, 2016 at 6:16 AM, Stephen J. Turnbull  wrote:
>
> (1) some really attractive producer of pathlib.Paths will be
> published, and
>

Yes, pathlib is str-only, so this sounds just right.

> (2) people will want to plug that producer into their bytes paths
> consumers using os.fspath(path) "and be done with it".
>

No, fspath can't know that is the the right thing to do.  There should
be *someone* that is aware of the encoding that happens, either the
provider or the consumer. That byte path consumer, assuming it wants
to support the behavior you describe, should use os.fsencode instead
of os.fspath, which will do exactly what you want, and just as easy
for the bytes path consumer to implement!

(Unless you want to explicitly reject plain str objects, which you
would then indeed do *explicitly*, but I'm not sure there is a point
in accepting plain bytes and str-based pathlib objects but not str).

To avoid further unnecessary discussion, please read [1] carefully,
where I already explained this, among other things.

-Koos

[1] https://mail.python.org/pipermail/python-dev/2016-April/144239.html
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Pathlib enhancements - improve fsdecode and fsencode

2016-04-20 Thread Koos Zevenhoven
On Thu, Apr 14, 2016 at 9:55 AM, Stephen J. Turnbull  wrote:
> Please please please, junk both "filter out bytes" proposals.

If you were referring to some of the fspath versions, I think we will
need a bytes-rejecting version, for reasons explained in [1-2]. Of
course not eveŕyone wants or has to use it.

> Since they involve an exception, they impose an unnecessary "try" on
> all text applications that fear death on bytes returns.  May as well
> just wrap all objects with __fspath__ in fsdecode, and all is
> happy.
>
> Counterproposal: make fsdecode and fsencode grok __fspath__.  Then:

Not being a native English speaker, I'm relying on a Wikipedia
explanation of "grok", but if you mean that fsdecode and fsencode
would accept objects that implement __fspath__, then I think we all
agree on this. Making the stdlib accept path objects, after all, is
the whole point of the pathlib discussions :).

Anyway, I am happy that Nick [3] (and you [4] ?) pointed out that
os.fsencode and os.fsdecode currently implement coercion, i.e., they
both accept both str and bytes, and return just one of them. This was
important for my conclusion in [1]. When these two functions are made
__fspath__ compatible using `fspath(patharg, output_types = (str,
bytes))`, like most os functions, they will indeed implement coercion
to bytes or str from "any pathlike object".

[Side note: One may, for instance, ask why os.fsdecode passes str
objects through silently, even if they can't be decoded. Well, that's
the way it is, and I'm not expecting that to change. But maybe
fsdecode should have an additional keyword-only argument to tell them
that it should strictly return something it actually did decode. (And
similarly for os.fsencode.) But this has nothing to do with the path
protocol we are discussing.]

> (1) Bytes-lovers and str-addicts are both safe.

I don't think everyone is safe if you cant say "I don't want implicit
encoding/decoding".

> (2) They can omit fspath, too!

I think having *one* additonal function for the
non-encoding/non-decoding cases is too much, and as shown in [1], one
is enough.

> No, that doesn't work if the bytes objects aren't in the file system
> encoding, but these are *bytes*, mon ami: you have no way to find out
> what that encoding is, so you either know already and you substitute
> that + fspath for fsdecode, or you're hosed.  And in the only concrete
> use case so far, fsdecode Just Works.

Well, as you say yourself, fsdecode indeed works if your bytes are in
the default fs encoding, and when you know they are, go for it, use
fsdecode. But I, for instance, rarely have my paths as bytes.
Therefore, I would be happy to get an exception if I'm accidentally
passing bytes to some non-bytes-supporting function because I've
forgotten to decode some input that I got in an encoding other than
the file system encoding.

> I suppose a similar argument holds for applications that want bytes
> and fsencode, but I leave that as an exercise for the reader.

A similar counterargument holds, too :).

Unrelated to this particular post, I believe these discussions are
almost done and I truly hope we at least won't have to keep addressing
the same questions that we have already gone through, unless there is
something new on the table.

I hope it takes a shorter time to read these emails than it takes to
write them :).

-Koos

[1] https://mail.python.org/pipermail/python-dev/2016-April/144239.html
[2] https://mail.python.org/pipermail/python-dev/2016-April/144290.html

And somewhat older ones:

[3] https://mail.python.org/pipermail/python-dev/2016-April/144101.html
[4] https://mail.python.org/pipermail/python-dev/2016-April/144107.html
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Discussion on fspath: please wait for a PEP

2016-04-20 Thread Koos Zevenhoven
On Wed, Apr 20, 2016 at 2:52 PM, Victor Stinner
 wrote:
> Hi,
>
> I'm unable to count the number of threads about the fspath protocol.
> It's even more difficult to count the total number of emails. IMHO
> everyone had enough time to give him/her opinion.

Couldn't agree more.

> We even had multiple
> summaries :-)

I'm not quite as sure about this. Maybe the meaning of "summary" in
the subculture of python lists is different from the one I know.

> Can you please wait for a PEP? Brett Canon and Ethan Furman are
> working on a PEP. So please give them time to write it.

I wonder what happened there...

> The PEP should summarize the discussion and help a lot to make
> concrete progress on the design (avoid restarting to discuss the same
> points forever). I don't expect that more emails would add anything at
> the current state of the discussion.

Again, agreed, and this part makes me feel relieved. Personally, I got
tired of the discussion a long time ago, but felt it had to be
finished.

> I think that we have enough other topics to discuss in the meanwhile ;-)

No doubt about that.

> FYI there is already an article about fspath/pathlib on LWN. Here is a
> free link until the article is freely accessible:
>
> "Python looks at paths" By Jake Edge (April 13, 2016)
> https://lwn.net/SubscriberLink/683350/4f52334af09653c8/

Wow. Wasn't expecting that. A whole story about the notorious "path
discussions"! (well, up to some date). Anyway, the beginning seems
fairly accurate, but then, among other things, it fails to mention
this for example:

https://mail.python.org/pipermail/python-ideas/2016-March/039179.html
https://mail.python.org/pipermail/python-ideas/2016-April/039595.html

Since I did not get any responses to that suggestion, it felt like a
dead end, and I continued experimenting with other things and ended up
taking the approach of "subclassing path-types from str gives more
complete pathlib support, but the objects should not pretend to be
strings in every way". By the way, I even implemented this, which I
suppose I failed to mention. Admittedly, it became a little awkward in
the end, but the main point was to provide a smooth transition from a
str world to a PurePath-subclass world (as opposed to a discrete one
like Py3k).

While I was working on that, the discussions on -dev seemed to have
reopened the gate at exactly that 'dead end' I mentioned before, and
had started to step through it.

-Koos

>
> Victor
> ___
> Python-Dev mailing list
> Python-Dev@python.org
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe: 
> https://mail.python.org/mailman/options/python-dev/k7hoven%40gmail.com
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Discussion on fspath: please wait for a PEP

2016-04-20 Thread Koos Zevenhoven
On Wed, Apr 20, 2016 at 7:34 PM, Victor Stinner
 wrote:
>
> 2016-04-20 18:12 GMT+02:00 Brett Cannon :
>>
>> I thought Chris and I w/ Ethan helping with coding, but if it's just me for
>> the PEP then that's fine;

Well, just in case you didn't notice this on python-ideas, I offered
to work on the PEP in case there turns out to be one. This was when
Guido had asked if there is going to be a PEP, in response to my "Type
hinting for path-related functions" email. That offer is certainly
still valid.

>> luckily my firefighter gear is well-worn:
>> https://goo.gl/photos/R8oWdLE45d99ebaw8
>
> LOL, it seems appropriate for this topic...

It sure has been flammable XD

>> I'll try to get a PEP draft written and posted prior to PyCon US. I will
>> reply to any dangling comments/issues that have appeared overnight to close
>> those threads, but otherwise I will start ignoring all discussions so I can
>> focus on the PEP. Everyone can now consider themselves spared from any
>> further path-related discussions. :)

Yes, going from endless discussion to PEP seems like a very healthy
direction at this point.

> I hesitated to propose to create a fspath-sig mailing list, but I suck
> at humor and so I skipped this joke in my email ;-)

You did not have to tell that joke, the joke was present all the time ;).

> Victor
> ___
> Python-Dev mailing list
> Python-Dev@python.org
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe: 
> https://mail.python.org/mailman/options/python-dev/k7hoven%40gmail.com
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] file system path protocol PEP

2016-05-11 Thread Koos Zevenhoven
**another deep, calming breath**

On Wed, May 11, 2016 at 7:43 PM, Brett Cannon  wrote:
> Open Issues
> ===
>
> Should os.fspath() return bytes?
> 
>

In most cases, it of course should not. The section (or the title) do
not represent my view on the topic, but bytes paths are not going away
any time soon, so this requires considerations.

Below is a copy paste of my comment in the discussion on my pull
request ( https://github.com/brettcannon/path-pep/pull/2 ). It is
about whether os.fspath should look like

def fspath(path, *, type_constraint=str): ...

This was already discussed before, receiving positive reactions. It
would be an extension to what is in the draft Brett just posted. Note
that the return type, however, does not depend on `type_constraint`.
It fully depends on `path`. The constraint only determines when an
exception is raised instead of returning a value.  When using
str-based paths normally, one would do

os.fspath(path)

Calling it with

os.fspath(path, type_constraint=(str, bytes))

would turn off rejection of bytes paths (and be consistent with the
rest of `os` and `os.path` where functions accept both types). But the
default value for the keyword argument would be a good reminder that
str-based paths should be used by default. This str-constraint is also
present in the current drafted version, but it is not optional or
visible in the signature.

(See the diffs of my pull request for an example implementation of this.)

So below is the copy-paste from the pull request discussion that I promised:

"""
Nobody wants to promote using `bytes` for paths without a proper
reason. However, `os.fspath(path, type_contraint=str)` is already a
compromise from the current `os.*` convention (of symmetrically
supporting both `str` and `bytes`) towards enforcing `str`-based
paths.

As you know, the reason for using `os.fspath` is to switch to a
lower-level representation of paths as strings. When you use it, you
are already deciding that you are lower-level and want to examine or
manipulate path strings manually. I think the `type_constraint=str`
keyword-only argument (with the default) is a good way to remind the
'user' that `str` is the way to go unless you know what you are doing
and, to `bytes` users, that `os.fspath` (by default) rejects bytes.

Looking at the discussions on python-dev, one notices that the active
people in the discussions were mostly in favor of exposing the
bytes-supporting version in one way or the other. Some were even
against bytes-rejecting versions.

Most people (Python programmers), especially in the long term, should
not be using `os.fspath` a lot. If they want to print a path, they
should simply do so: `print(path_obj)`, or `print(f"The path is:
{path_obj}")`. However, there will always be people that for whatever
reason want to convert a pathlib object into a string, and without
even consulting the docs, they may write `str(path_obj)`. And that's
not the end of the world. It's not any worse than `str(integer)` for
instance. After all, if the main point is to convert something into a
generic string, the function should probably be called `str`, not
`fspath`. But if the idea is to convert any path object into something
that `os` and similar code internally understand, then `os.fspath`
sounds fine to me. So I would not go as far as 'never use
`str(path)`'. What we don't want is things like `open(str(path),
'w')`. I know you agree, because you wrote that yourself. But once
this protocol is available, I see no reason why people would
voluntarily wrap their path objects in `str(...)`, so I don't see that
as a problem in the future (thanks to this PEP). So, especially in the
long term, I don't expect `fspath` to be an everyday tool for people.
Even in shorter term, people don't usually need it, because the stdlib
will already support pathlib objects.

Since it is not an everyday tool, I think it's ok to have that extra
keyword-only argument. Even if it were an everyday tool, I can see the
keyword-only argument in the signature as useful thing in a
documentation sense.

[As a side note, I could imagine someone convincing me that `fspath`
should *always* accept both `str`- and `bytes`-based paths, because
that would simplify it and align it with the rest of `os`. This would
not be any worse than the status quo in terms of early failures. That
would, however, still not detect accidental use of bytes paths (when
forgotten to decode from the encoding it was received in).]
"""

-- Koos
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] file system path protocol PEP

2016-05-11 Thread Koos Zevenhoven
On Wed, May 11, 2016 at 11:04 PM, Brett Cannon  wrote:
> A quick comment about sending me fixes. While I do appreciate them, sending
> them as a pull request is much easier for me as (a) I don't have to hunt the
> changes down in the text, and (b) you will see the fixes others have done
> already to the PEP and I then don't have to figure out what changes have not
> already been fixed. And honestly, reading the PEP in its rendered format on
> GitHub is easier IMO than in the text format unless you have something
> specific to respond to (and even if you do, you can copy and paste the
> relevant bits into an email reply).
>

Personally, I find it more important to settle the open issues first,
so I will be looking for typos at a later stage. Besides, more typos
may be added in the process. I previously left some typos uncorrected
in attempt to keep the diffs of my commits cleaner. By the way, to see
what additions and wordings I have suggested, the right way is to look
at my PR(s).  I might send more PRs to clarify open issues etc., but
this will largely be based on my previous commits.

-- Koos
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] file system path protocol PEP

2016-05-11 Thread Koos Zevenhoven
On Thu, May 12, 2016 at 12:15 AM, Ethan Furman  wrote:
> On 05/11/2016 01:51 PM, Ethan Furman wrote:
>>
>> On 05/11/2016 01:44 PM, Serhiy Storchaka wrote:
>
>
 os.path
 '''

 The various path-manipulation functions of ``os.path`` [#os-path]_
 will be updated to accept path objects. For polymorphic functions that
 accept both bytes and strings, they will be updated to simply use
 code very much similar to
 ``path.__fspath__() if  hasattr(path, '__fspath__') else path``. This
 will allow for their pre-existing type-checking code to continue to
 function.
>>>
>>>
>>> I afraid that this will hit a performance. Some os.path functions are
>>> used in tight loops, they are hard optimized, and adding support of path
>>> protocol can have visible negative effect.
>>
>>
>> Do you have an example of os.path functions being used in a tight loop?
>

I'd be interested in this too.

>
> Also, the C code for fspath can check types first and take the fast path if
> bytes/str are passed in, only falling back to the __fspath__ protocol if
> something else was passed in -- which should make any performance hits
> negligible.

My suggestion for the *python version* already does this too (again,
see my PR). This is a win-win, as it also improves error messages (as
suggested by Nick in the earlier discussions).

-- Koos

>
>
> --
> ~Ethan~
>
> ___
> Python-Dev mailing list
> Python-Dev@python.org
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe:
> https://mail.python.org/mailman/options/python-dev/k7hoven%40gmail.com
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] file system path protocol PEP

2016-05-11 Thread Koos Zevenhoven
On Thu, May 12, 2016 at 12:28 AM, Nikolaus Rath  wrote:
> On May 11 2016, Brett Cannon  wrote:
>> This PEP proposes a protocol for classes which represent a file system
>> path to be able to provide a ``str`` or ``bytes`` representation.
> [...]
>
> As I said before, to me this seems like a lot of effort for a very
> specific use-case. So let me put forward two hypothetical scenarios to
> better understand your position:

I think you are touching important points.

> - A new module for URL handling is added to the standard library (or
>   urllib is suitably extended). There is a proposal to add a new
>   protocol that allows classes to provide a ``str`` or ``bytes``
>   representation of URLs.

This reminds me of the thread I recently started on python-ideas about
extending the concept of paths to URLs. I don't know if you are
referring to something like that or not.

Anyway, it would be important to know whether the str or bytes
representation is to be used a file system path or an URL, so that
would need to be a separate protocol. But everyone would have the
experience from these discussions, so hopefully less discussion then
:). (By the way, this is one reason to have 'fs' in the name of the
__fspath__ method, although I have not mentioned it before.)

>
> - A new (third-party) library for natural language processing arises
>   that exposes a specific class for representing audio data. Existing
>   language processing code just uses bytes objects. To ease transition
>   and interoperability, it is proposed to add a new protocol for classes
>   that represend audio data to provide a bytes representation.
>
> Do you think you would you be in favor of adding these protocols to
> the stdlib/languange reference as well? If not, what's the crucial
> difference to file system paths?
>

File system paths are very fundamental, and will probably be used in
context of your natural language example too.

-- Koos

>
> Thanks,
> -Nikolaus
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] file system path protocol PEP

2016-05-11 Thread Koos Zevenhoven
On Thu, May 12, 2016 at 1:13 AM, Brett Cannon  wrote:
>
>
> On Wed, 11 May 2016 at 13:45 Serhiy Storchaka  wrote:
>>
>> On 11.05.16 19:43, Brett Cannon wrote:
>> > os.path
>> > '''
>> >
>> > The various path-manipulation functions of ``os.path`` [#os-path]_
>> > will be updated to accept path objects. For polymorphic functions that
>> > accept both bytes and strings, they will be updated to simply use
>> > code very much similar to
>> > ``path.__fspath__() if  hasattr(path, '__fspath__') else path``. This
>> > will allow for their pre-existing type-checking code to continue to
>> > function.
>>
>> I afraid that this will hit a performance. Some os.path functions are
>> used in tight loops, they are hard optimized, and adding support of path
>> protocol can have visible negative effect.
>
>
> As others have asked, what specific examples do you have that os.path is
> used in a tight loop w/o any I/O that would overwhelm the performance?
>
>>
>>
>> I suggest first implement other changes and then look whether it is
>> worth to add support of path protocol in os.path functions.
>
>
> I see this whole discussion breaking down into a few groups which changes
> what gets done upfront and what might be done farther down the line:
>
> 1. Maximum acceptance: do whatever we can to make all representation of paths
> just work, which means making all places working with a path in the stdlib
> accept path objects, str, and bytes.

Since you are putting me in this camp, there is at least one thing you
are wrong about. I don't want all places that work with a path to
accept bytes. Only those that already do so, including os/os.path. And
yes, I think the stdlib should show a good example in accepting path
types (especially those provided in the stdlib itself).

Whether Ethan is fully in camp 1, I don't know. Not that I think he
would be any closer to the other camps, though.

> 2. Safely use path objects: __fspath__() is there to signal an object is a 
> file
> system path and to get back a lower-level representation so people stop
> calling str() on everything, providing some interface signaling that someone
> doesn't misuse an object as a path and only changing path consumptions APIs
> -- e.g. open() -- and not path manipulation APIs -- e.g. os.path -- in the
> stdlib.
>
> 3. It ain't worth it: those that would rather just skip all of this and drop
> pathlib from the stdlib.
>
> Ethan and Koos are in group #1 and I'm personally in group #2 but I tried to
> compromise somewhat and find a middle ground in the PEP with the level of
> changes in the stdlib but being more restrictive with os.fspath(). If I were
> doing a pure group #2 PEP I would drop os.path changes and make os.fspath()
> do what Ethan and Koos have suggested and simply pass through without checks
> whatever path.__fspath__() returned if the argument wasn't str or bytes.
>

Related to this, based on the earlier discussions, I had the
impression that you were largely in the same camp as me. In fact, I
thought you had politely left some things out of the PEP draft so I
could fill them in. It turned out I was wrong about that, because you
didn't merge them.

-- Koos

> ___
> Python-Dev mailing list
> Python-Dev@python.org
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe:
> https://mail.python.org/mailman/options/python-dev/k7hoven%40gmail.com
>
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] file system path protocol PEP

2016-05-11 Thread Koos Zevenhoven
On Thu, May 12, 2016 at 2:05 AM, Ethan Furman  wrote:
> On 05/11/2016 03:13 PM, Brett Cannon wrote:
>
>> If [...] I would drop os.path changes and make os.fspath() do what
>
>> Ethan and Koos have suggested and simply pass through without checks
>>
>> whatever path.__fspath__() returned if the argument wasn't str or bytes.
>
>
> Not to derail the conversation too much, as I know we're all getting burned
> out on the topic, but that last bit is not accurate: my druthers are to have
> __fspath__ be able to return str /or/ bytes, and if anything else comes from
> the object in question an exception must be raised. Maybe a word got lost
> between your thoughts and your fingers -- happens to me all the time.  :)

Yes. This would also be equivalent to my fspath(path,
type_constraint=(str,bytes)). And if the compromise I mentioned about
the rejecting (by default or optionally) is lifted, the keyword
argument would not be needed.  I might be ok with throwing away the
isinstance check on the return value of __fspath__() if it has
significant impact on performance in realistic cases (with DirEntry
most likely, I suppose), but I doubt it.

-- Koos

>
> --
> ~Ethan~
>
> ___
> Python-Dev mailing list
> Python-Dev@python.org
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe:
> https://mail.python.org/mailman/options/python-dev/k7hoven%40gmail.com
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] file system path protocol PEP

2016-05-11 Thread Koos Zevenhoven
On Thu, May 12, 2016 at 2:49 AM, Koos Zevenhoven  wrote:
> On Thu, May 12, 2016 at 2:05 AM, Ethan Furman  wrote:
>> On 05/11/2016 03:13 PM, Brett Cannon wrote:
>>
>>> If [...] I would drop os.path changes and make os.fspath() do what
>>
>>> Ethan and Koos have suggested and simply pass through without checks
>>>
>>> whatever path.__fspath__() returned if the argument wasn't str or bytes.
>>
>>
>> Not to derail the conversation too much, as I know we're all getting burned
>> out on the topic, but that last bit is not accurate: my druthers are to have
>> __fspath__ be able to return str /or/ bytes, and if anything else comes from
>> the object in question an exception must be raised. Maybe a word got lost
>> between your thoughts and your fingers -- happens to me all the time.  :)
>
> Yes. This would also be equivalent to my fspath(path,
> type_constraint=(str,bytes)). And if the compromise I mentioned about
> the rejecting (by default or optionally) is lifted, the keyword

the rejecting -> rejecting bytes

Good night.

-- Koos


> argument would not be needed.  I might be ok with throwing away the
> isinstance check on the return value of __fspath__() if it has
> significant impact on performance in realistic cases (with DirEntry
> most likely, I suppose), but I doubt it.
>
> -- Koos
>
>>
>> --
>> ~Ethan~
>>
>> ___
>> Python-Dev mailing list
>> Python-Dev@python.org
>> https://mail.python.org/mailman/listinfo/python-dev
>> Unsubscribe:
>> https://mail.python.org/mailman/options/python-dev/k7hoven%40gmail.com
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] file system path protocol PEP

2016-05-11 Thread Koos Zevenhoven
On Thu, May 12, 2016 at 2:53 AM, Koos Zevenhoven  wrote:
> On Thu, May 12, 2016 at 2:49 AM, Koos Zevenhoven  wrote:
>> On Thu, May 12, 2016 at 2:05 AM, Ethan Furman  wrote:
>>> On 05/11/2016 03:13 PM, Brett Cannon wrote:
>>>
>>>> If [...] I would drop os.path changes and make os.fspath() do what
>>>
>>>> Ethan and Koos have suggested and simply pass through without checks
>>>>
>>>> whatever path.__fspath__() returned if the argument wasn't str or bytes.
>>>
>>>
>>> Not to derail the conversation too much, as I know we're all getting burned
>>> out on the topic, but that last bit is not accurate: my druthers are to have
>>> __fspath__ be able to return str /or/ bytes, and if anything else comes from
>>> the object in question an exception must be raised. Maybe a word got lost
>>> between your thoughts and your fingers -- happens to me all the time.  :)
>>
>> Yes. This would also be equivalent to my fspath(path,
>> type_constraint=(str,bytes)). And if the compromise I mentioned about
>> the rejecting (by default or optionally) is lifted, the keyword
>
> the rejecting -> rejecting bytes
>
>> argument would not be needed.  I might be ok with throwing away the
>> isinstance check on the return value of __fspath__() if it has
>> significant impact on performance in realistic cases (with DirEntry
>> most likely, I suppose), but I doubt it.
>>
>> -- Koos
>>

I will send a pull request about this tomorrow.

-- Koos

>>>
>>> --
>>> ~Ethan~
>>>
>>> ___
>>> Python-Dev mailing list
>>> Python-Dev@python.org
>>> https://mail.python.org/mailman/listinfo/python-dev
>>> Unsubscribe:
>>> https://mail.python.org/mailman/options/python-dev/k7hoven%40gmail.com
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] file system path protocol PEP

2016-05-12 Thread Koos Zevenhoven
On Thu, May 12, 2016 at 11:14 AM, Serhiy Storchaka  wrote:
>
> This is cheap in C, but os.path functions are implemented in Python. They
> have to make at least one function call (os.fspath(), hasattr() or
> isinstance()), not counting a bytecode for retrieving arguments, resolving
> attributes, comparing, jumps. Currently os.path functions use tricks to
> avoid overheads
>

I suppose a C-implemented version of fspath *called from python* might
be the fastest option at least in some cases. After all, a function
call (isinstance or hasattr) is likely anyway, unless of course `try:
path.__fspath__` is used.

> Yet one problem is that currently many os,path functions work with
> duck-typed strings (e.g. UserString). Using os.fspath() likely limit
> supported types to str, bytes and types that support the path protocol.
>

Something like

path = path.__fspath__() if hasattr(path, '__fspath__') else path

as currently in the PEP, would not have this problem. However, I
wonder whether such duck string paths actually exist (although it does
remind me of my earlier experiments for solving the pathlib
compatibility problem ;-).


-- Koos

P.S: I think it's great that you are concerned about the performance,
and I find it important. However, this does feel like premature
optimization to me at this point. We should first decide what
functions should support the protocol, and after that, find the
performance concerns and fix them. I have the feeling that the cases
where this would be a performance bottleneck are quite rare, but if
they are not, they may well be fixable.
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] file system path protocol PEP

2016-05-12 Thread Koos Zevenhoven
On Thu, May 12, 2016 at 11:31 AM, Sven R. Kunze  wrote:
> On 11.05.2016 18:43, Brett Cannon wrote:
>>
>> Rationale
>> =
>>
>> Historically in Python, file system paths have been represented as
>> strings or bytes. This choice of representation has stemmed from C's
>> own decision to represent file system paths as
>> ``const char *`` [#libc-open]_. While that is a totally serviceable
>> format to use for file system paths, it's not necessarily optimal. At
>> issue is the fact that while all file system paths can be represented
>> as strings or bytes, not all strings or bytes represent a file system
>> path.
>
>
> I can remember this argument being made during the discussion. I am not sure
> if that 100% correct as soon as we talk about PurePaths.
>

I had suggested an alternative wording for this (see my commit on the
work on Rationale).


>> Proposal
>> 
>>
>> This proposal is split into two parts. One part is the proposal of a
>> protocol for objects to declare and provide support for exposing a
>> file system path representation.
>
>
> https://docs.python.org/3/whatsnew/changelog.html says:
>
> "Add ‘path’ attribute to pathlib.Path objects, returning the same as str(),
> to make it more similar to DirEntry. Library code can now write getattr(p,
> ‘path’, p) to get the path as a string from a Path, a DirEntry, or a plain
> string. This is essentially a small one-off protocol."
>
> So, in order to promote the "small one-off protocol" to a more broader
> protocol, this PEP proposes a simple rename of .path to .__fspath__, is that
> correct?
>

Well, I have brought this up previously several times. Indeed I see
this as a further development of that duck-typing compatiblity
approach.  However, while the .path attribute is prior art, it has not
been in a release yet.

> Unfortunately, I don't have anything to contribute to the open issues. All
> solutions have their pros and cons and everything that could be said has
> been said. I think you need to decide.
>

Surprising enough, there are new things being said all the time. But
luckily there seem to be signs of convergence.

-- Koos
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] file system path protocol PEP

2016-05-12 Thread Koos Zevenhoven
On Thu, May 12, 2016 at 3:04 PM, Nick Coghlan  wrote:
>
> I'd still like to see this exposed to Python code as os._raw_fspath()
> (with the leading underscore just meaning "this probably isn't the API
> you want" rather than indicating a private or unstable API), and then
> fspath() defined as a wrapper around it which disallows bytes as
> output.
>

I don't remember (should probably check) if you previously proposed
implementing exactly that in C, but I indeed agree with what you write
above, except that I don't like the "_raw_" prefix in the name. I
would be willing to call that simply fspath though, since as mentioned
before in this thread (I think by Brett and me), the reasons for
rejecting bytes in fspath are really quite minor.
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] file system path protocol PEP

2016-05-12 Thread Koos Zevenhoven
On Thu, May 12, 2016 at 4:20 PM, Nick Coghlan  wrote:
>
> It's not unusual for me to encounter "POSIX oughtta be enough for
> anyone" folks that are not yet entirely convinced that
> bytes-are-not-text, so I'm actually in favour of making the default
> Python-level API str-only as a healthy nudge away from the
> "text-is-just-bytes-with-an-encoding!" school of thought.
>

This was also how I convinced myself about the default str constraint.
However, I'm afraid it would be a weak weapon against using bytes
paths, since the people using bytes paths would not be likely to call
it, regardless of whether it supports bytes or not.

The nice thing is that pathlib is str-only and *that* will push people
away from bytes paths.

> However, in terms of the three groups Brett articulated (maximum
> flexibility, encouraging cross-platform correctness, and forgetting
> the whole idea), I'm in both camps 1 & 2 - I work with POSIX enough
> that I'm entirely on board with the notion that if you're specifically
> modelling *POSIX* paths, then bytes-with-an-assumed-encoding is
> frequently a good enough representation, but also deal with other
> environments (like Windows, the JVM and the CLR) enough to know that
> that particular representation of filesystem paths breaks down the
> moment you expand your scope of interest beyond *nix platforms.
>

I also agree with parts about Brett's "camp 2".

-- Koos
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] file system path protocol PEP

2016-05-12 Thread Koos Zevenhoven
On Thu, May 12, 2016 at 7:24 PM, Guido van Rossum  wrote:
> I am glad this is finally happening. There's quite a bit of noise in the
> thread which I have to ignore. The two issues that I want to respond to are
> speed and whether os.fspath() can return bytes.
>
> - Speed: We should trust our ability to optimize the implementations where
> necessary. First the API issues need to be settled.
>
> - Bytes: I strongly believe that os.fspath() should be a thin wrapper around
> the __fspath__ protocol, like next() wraps the .__next__ protocol. It should
> not get into bytes vs. string politics. If your app really needs strings,
> call os.fsdecode(). So this is my version (unoptimized):
>

:)

Thank you for this. I can breathe now.

Some questions remain:

> def fspath(p: Union[str, bytes, PathLike]) -> Union[str, bytes]:
> if isinstance(p, (str, bytes)):
> return p
> try:
> return p.__fspath__
> except AttributeError:
> raise TypeError(...)
>

(I know Brett already posted this question, but somehow it did not
show up in my mailbox before I had written this. I'm (re)posting
because there is some stuff here that is not in Brett's email )

You might be suggesting that __fspath__ should be an attribute, not a
method, or did you mean something like:

def fspath(p):
if isinstance(p, (str, bytes)):
return p
try:
p.__fspath__
except AttributeError:
raise TypeError(...)
return p.__fspath__()

IMO, either is fine, I suppose. As you know, it's mostly a question of
whether __fspath__ will be a property or a method (on PurePath for
instance). But if you meant the former, that would change also the ABC
and the protocol description.

-- Koos
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] file system path protocol PEP

2016-05-12 Thread Koos Zevenhoven
On Thu, May 12, 2016 at 8:22 PM, Sjoerd Job Postmus
 wrote:
> I would like to make just 1 comment regarding the question of accepting
> (or not) bytes as output of `os.fspath`.
>
> The whole point of adding `os.fspath` is to make it easier to use Path
> objects. This is in an effort to gain greater adoption of pathlib in
> libraries. Now, this is an excellent idea.
>
> However, if it were to reject bytes, that would mean that when libraries
> start to use pathlib, it would suddenly become harder for people that
> actually need bytes-support to use pathlib.
>
> Now, the claim 'if you need bytes, you should not be using pathlib` is a
> reasonable one. But what if I need bytes *and* a specific library (say,
> image handling, or a web framework, or ...). It's not up to me if that
> library uses pathlib or plain old os.path.join.
>
> Is using surrogate-escapes enough for this case? I myself am not sure,
> (and also not affected), but it sounds to me that rejecting bytes is a
> wrong approach if there is no proper workaround (assuming the use-case
> of pathlib is somewhere deep in library code).
>

This is out of the scope of this PEP and probably a very insignificant
issue (luckily, this is not the pathlib PEP). Surrogates will probably
work and if not, on can "blaim" broken filenames ;).

-- Koos
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] file system path protocol PEP

2016-05-13 Thread Koos Zevenhoven
This has just been discussed very recently in this thread (and earlier
too). It may make sense, but it's not among our current worries.
Besides, we already added the new fspath semantics to the PEP.

While I hope Brett is asleep in his time zone, I'm guessing he will
agree (just saying this because you write "@Brett").

-- Koos


On Fri, May 13, 2016 at 10:58 AM, Sven R. Kunze  wrote:
> On 12.05.2016 18:24, Guido van Rossum wrote:
>>
>> def fspath(p: Union[str, bytes, PathLike]) -> Union[str, bytes]:
>> if isinstance(p, (str, bytes)):
>> return p
>> try:
>> return p.__fspath__
>> except AttributeError:
>> raise TypeError(...)
>
>
> @Brett
> Would you think it makes sense to swap the str/bytes check and the
> __fspath__ check?
>
>
> I just thought of a class subclassing str/bytes and defines __fspath__. Its
> __fspath__ method would be ignored currently.
>
>
> Best,
> Sven
>
> ___
> Python-Dev mailing list
> Python-Dev@python.org
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe:
> https://mail.python.org/mailman/options/python-dev/k7hoven%40gmail.com
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] file system path protocol PEP

2016-05-13 Thread Koos Zevenhoven
On Fri, May 13, 2016 at 12:24 PM, Sven R. Kunze  wrote:
> On 13.05.2016 10:36, Koos Zevenhoven wrote:
>>
>> This has just been discussed very recently in this thread (and earlier
>> too).
>
>
> Could you point me to that? It seems I missed that part. I only found posts
> related to performance degradation.
>

This issue is coupled with the future optimization questions.

> However, the proposed semantics will change if the checks are swapped. So,
> my actual question is:
>
> Is that an intended API inconsistency or a known bug supposed to be resolved
> later?
>

Taking into account the description (and the drafted type hint), which
the documentation will probably reflect, the semantic effects of that
are very minor or nonexistent.

I do think the documentation of the protocol should say that str or
bytes subclasses should not implement __fspath__.

So no API inconsistency there.

-- Koos
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] File system path PEP, part 2

2016-05-13 Thread Koos Zevenhoven
Thanks Brett!

Now one thing is that, despite your suggestion, I had not added myself
as an author in my big pull request. Originally, it was because I
simply forgot to copy and paste it when I split my edits into separate
commits ;-). Sorry about that (not sure if you care though, and I've
been defending the PEP regardless).

Anyway, especially now that my main worry regarding the open questions
has been resolved, I would be more than happy to have my name on it.
So Brett, could you add me as author? (Koos Zevenhoven and
k7ho...@gmail.com will be fine)

It looks like this is finally happening :)

-- Koos

On Thu, May 12, 2016 at 11:53 PM, Brett Cannon  wrote:
> Second draft that takes Guido's comments into consideration. The biggest
> change is os.fspath() now returns whatever path.__fspath__() returns instead
> of restricting it to only str.
>
> Minor changes:
> - Renamed the C function to PyOS_FSPath()
> - Added an Implementation section with a TODO list
> - Bunch of things added to the Rejected Ideas section
>
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] File system path PEP, part 2

2016-05-13 Thread Koos Zevenhoven
On Fri, May 13, 2016 at 2:00 PM, Steven D'Aprano  wrote:
> Counter suggestion:
>
> - __fspath__() method may return either bytes or str (no change
>   from the PEP as it stands now);
>
> - but os.fspath() will only return str;
>
> - and os.fspathb() will only return bytes;
>
> - there is no os function that returns "str or bytes, I don't
>   care which". (If you really need that, call __fspath__ directly.)
>
> Note that this differs from the already rejected suggestion that there
> should be two dunder methods, __fspath__() and __fspathb__().
>
> Why?
>
> (1) Normally, the caller knows whether they want str or bytes. (That's
> been my experience, you may disagree.) If so, and they call os.fspath()
> expecting a str, they won't be surprised by it returning bytes. And visa
> versa for when you expect a bytes path.
>
> (2) This behaviour will match that of os.{environ[b],getcwd[b],getenv[b]}.

I would think these have the b suffix because there is no good way to
infer which type should be returned. In things like os.path.join or
os.path.dirname you pass in the object(s) that determine the return
type.

In os.fspath, you pass in an object, whose type (str/bytes) or
"underlying path string type" (as returned by __fspath__()) determines
the return type of fspath. I think this is well in line with os.path
functions.


-- Koos

>
> Cons:
>
> (3) Polymorphic code that truly doesn't care whether it gets bytes or
> str will have a slightly less convenient way of getting it, namely by
> calling __fspath__() itself, instead of os.fspath().
>
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] file system path protocol PEP

2016-05-13 Thread Koos Zevenhoven
On Fri, May 13, 2016 at 7:06 PM, Sven R. Kunze  wrote:
> On 13.05.2016 11:48, Koos Zevenhoven wrote:
>>
>> This issue is coupled with the future optimization questions.
>>
>
> AFAIC coupling API design to optimization is called premature optimization.
>

I suppose so, but currently I consider the API not to make guarantees
about what happens if you pass in something other than specified as
valid input. I'm not sure what level of precision is usual at this
point, but I think this is sufficient for now.

I'm sure we will pay attention to this (as we have been doing, both
while optimizing prematurely and for other reasons).

-- Koos
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] File system path PEP, part 2

2016-05-13 Thread Koos Zevenhoven
On Fri, May 13, 2016 at 8:52 PM, Steven D'Aprano  wrote:
> On Fri, May 13, 2016 at 03:43:29PM +, Brett Cannon wrote:
>> On Fri, 13 May 2016 at 04:00 Steven D'Aprano  wrote:
>
> [...]
>> > I think it is a bit confusing to refer to "path objects", as that seems
>> > like you are referring only to pathlib.Path objects. It took me far too
>> > long to realise that here you mean generic path-like objects that obey
>> > the __fspath__ protocol rather than a specific concrete class.
>> >

This terminology is indeed a bit difficult, not least because there
are 6 different path classes in pathlib. A couple of months ago, I
decided to start to call these pathlib objects and path objects,
because I did not know what else to call them without doubling the
length.

>> > Since the ABC is called "PathLike", I suggest we refer to "path-like
>> > objects" rather than "path objects", both in the PEP and in the Python
>> > docs for this protocol.
>>
>> I went back and forth with this in my head while writing the PEP. The
>> problem with making "path-like" mean "objects implementing the PathLike
>> ABC" becomes how do you refer to an argument of a function that accepts
>> anything os.fspath() does (i.e. PathLike, str, and bytes)?
>
> On further reflection, I think the right language is to use "path-like"
> for the union of Pathlike, str and bytes. That will, I think, cover the
> majority of cases: most functions which want to work on a file system
> path should accept all three. When you want to specify only an object
> which implements the PathLike ABC, that's called a (virtual) instance of
> PathLike.
>

As I've told Brett before, I think exactly this reasoning would be a
good enough reason not to call the ABC PathLike.

[...]
>> > Would I be right in saying that in practice this will actually end up
>> > being type(path).__fspath__() to match the behaviour of all(?) other
>> > dunder methods?
>>
>> I wasn't planning on it because for most types the accessing of the method
>> directly off of the type for magic methods is because of some special
>> struct field at the C level that we're pulling from. Since we're not
>> planning to have an equivalent struct field I don't see any need to do the
>> extra work of avoiding the instance participating in method lookup.
>> Obviously if people disagree for some reason then please let me know (maybe
>> for perf by avoiding the overhead of checking for the method on the
>> instance?).
>
> The reasons I would disagree are:
>
> (1) It took me a long time to learn the rule that dunder methods are
> always called from the class, not the instance, and now I have to learn
> that there are exceptions? G argggh.

Who knows, maybe the exception made it take a longer time..

IIRC the docs say that dunder methods are *not guaranteed* to be
called on the instance, because they may be called on the class.

> (2) If we ever do change to a C struct field, the behaviour will change.
> Maybe it's better to emulate the same behaviour from the start?
>
> (3) If there's a performance speed up, that's a bonus!
>
>
>
> --
> Steven
> ___
> Python-Dev mailing list
> Python-Dev@python.org
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe: 
> https://mail.python.org/mailman/options/python-dev/k7hoven%40gmail.com
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] File system path PEP, 3rd draft

2016-05-13 Thread Koos Zevenhoven
FYI, I recently sent a couple of emails in my earlier type hinting
thread on -ideas. What I wrote now is about the path ABC regarding
type hints.

-- Koos

On Sat, May 14, 2016 at 12:48 AM, Brett Cannon  wrote:
>
>
> On Fri, 13 May 2016 at 14:30 Philip Jenvey  wrote:
>>
>>
>> On May 13, 2016, at 11:37 AM, Brett Cannon  wrote:
>>
>> Biggest changes since the second draft:
>>
>> Resolve __fspath__() from the type, not the instance (for Guido)
>>
>>
>> if (PyObject_HasAttrString(path->ob_type, "__fspath__")) {
>> return PyObject_CallMethodObjArgs(path->ob_type, "__fspath__",
>> path,
>> NULL);
>>
>>
>> _PyObject_LookupSpecial would be preferable then.
>
>
> Yes it would be. :) I'll add it to the PEP.
>
> ___
> Python-Dev mailing list
> Python-Dev@python.org
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe:
> https://mail.python.org/mailman/options/python-dev/k7hoven%40gmail.com
>
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] file system path protocol PEP

2016-05-15 Thread Koos Zevenhoven
On Fri, May 13, 2016 at 7:43 PM, Chris Angelico  wrote:
[...]
> "Check" accepts subclasses; "CheckExact" doesn't (it's like "type(x)
> is str"). The question is, which one SHOULD be being done?

Indeed it should do "Check", so that path libraries that do inherit
from str will still work (see also below).

> What should this do:
>
> class TmpPath(str):
> def __fspath__(self):
> return "/tmp/"+self
> x = TmpPath("foo/bar")
> open(x, "w")
>
> Does that respect __fspath__, or respect the fact that it's a string?

It should not respect __fspath__ because that would mean the behavior
is different in older versions of Python(!). This also means that such
code should never be written (except for that example you wrote ;-).
So indeed, composition would be the way to go.

So yes, I still think str subclasses should not implement __fspath__,
and that, at the very least, the docs should say that :).

-- Koos


> ChrisA
> ___
> Python-Dev mailing list
> Python-Dev@python.org
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe: 
> https://mail.python.org/mailman/options/python-dev/k7hoven%40gmail.com
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Removing the provisional label from pathlib

2016-05-24 Thread Koos Zevenhoven
On Mon, May 23, 2016 at 10:38 PM, Chris Barker  wrote:
> On Mon, May 23, 2016 at 10:13 AM, Brett Cannon  wrote:
>>
>> 3.5 is still getting bugfixes:
>> https://docs.python.org/devguide/#status-of-python-branches
>>
>> As for backporting __fspath__() for pathlib, you can easily write your own
>> subclass that adds it. And since the stdlib won't be updated in 3.5 for
>> consumption of fspath
>
>
> OK -- when I said "it", I meant the whole shebang -- i.e. the stdlib stuff
> too. But fair enough, we can't be backporting everything, and I that would
> be touching a lot of the lib.
>
> -CHB

I guess we might consider adding __fspath__ in maintenance releases,
and make open() support it? That would cover a significant share of
use cases, although it might be weird if code written for 3.5.2
doesn't run on 3.5.1... So maybe just 3.6-> ?

I'm not quite as busy as last week, so I might consider working on the
stdlib changes if I find the time. Or is someone already working on
this?

-- Koos
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com



Re: [Python-Dev] Removing the provisional label from pathlib

2016-05-24 Thread Koos Zevenhoven
On Tue, May 24, 2016 at 4:56 PM, Barry Warsaw  wrote:
> On May 24, 2016, at 02:03 PM, Koos Zevenhoven wrote:
>
>>I guess we might consider adding __fspath__ in maintenance releases,
>>and make open() support it? That would cover a significant share of
>>use cases, although it might be weird if code written for 3.5.2
>>doesn't run on 3.5.1...
>
> Please, no.  We learned that lesson in Python 2.2.1 with True/False.

What happened? True was included in 2.2.1 but not False?-). Anyway, I
guess you are probably right, and "3.6->" is the way to go. Besides,
Guido already wrote that in the first response.

-- Koos

> Cheers,
> -Barry
> ___
> Python-Dev mailing list
> Python-Dev@python.org
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe: 
> https://mail.python.org/mailman/options/python-dev/k7hoven%40gmail.com
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] Re: Questions about about the DLS 2020

2020-11-26 Thread Koos Zevenhoven
I've had some things going on, and I'm still trying to catch up with the
discussions here. Can someone tell me what would be the best place to look
at the most recent proposal? Is one of the PEPs up to date?

On Mon, Nov 16, 2020 at 7:02 PM Tobias Kohn  wrote:

> Hi Mark,
>
> Thank you for your interest and the questions.
>
>
> 1.  This really comes down to how you look at it, or how you define
> pattern matching.  The issue here is that the concept of pattern matching
> has grown into a large and somewhat diverse flock of interpretations and
> implementations (as a side note: interestingly enough, some of the only
> universally agreed-upon standards are to use `_` as a wildcard and not to
> mark names that capture/bind values---which are quite exactly the points
> most fiercely debatted here).
>
> Anyway, the paper presents the pattern matching structure we are proposing
> as one of three major variants of pattern matching:
> (a)  Matching arguments to parameters in a function call,
> (b)  Matching elements to elements in iterable unpacking,
> (c)  Matching tree-like data to general patterns in a conditional pattern
> matching structure.
>
> The last one is the subject of the PEP and the paper.  Nonetheless, in the
> first two cases (a) and (b), we find that indeed the computer will validate
> that the data matched the pattern and raise an exception if this fails.
> This is where this way of looking at it comes from.
>
>
> 2.  Yes, that is indeed a deliberate simplification.  The idea is to
> abstract away from the details of how exactly Python implements abstract
> syntax trees (which I honestly believe are irrelevant for the sake of the
> entire narrative).  Moreover, using strings here allows us to exemplify the
> literal patterns, rather only showcasing only the constructor/class pattern.
>
> Essentially, this is a question of making the most out of the little space
> available.
>
>
> Since you have addressed this email to me directly, I would like to take
> this opportunity and briefly stress that this paper really grew out of a
> team effort.  While I might have been the one pushing for an academic
> publication, the DLS'20 paper represents the input and ideas of all the
> authors, as well as the long discussions we had.  Of course, I am happy to
> answer any questions about the paper, but it would be wrong to see me as
> the one person behind it.
>
> Cheers,
> Tobias
>
>
>
> Quoting Mark Shannon :
>
> Hi Tobias,
>
> A couple of questions about the DLS 2020 paper.
>
> 1. Why do you use the term "validate" rather than "test" for the process
> of selecting a match?
>
> It seems to me, that this is a test, not a validation, as no exception is
> raised if a case doesn't match.
>
>
> 2. Is the error in the ast matching example, an intentional
> "simplification" or just an oversight?
>
> The example:
>
> ```
> def simplify(node):
>match node:
>case BinOp(Num(left), '+', Num(right)):
>return Num(left + right)
>case BinOp(left, '+' | '-', Num(0)):
>return simplify(left)
>case UnaryOp('-', UnaryOp('-', item)):
>return simplify(item)
>case _:
>return node
>
> ```
>
> is wrong.
>
> The correct version is
>
> ```
> def simplify(node):
>match node:
>case BinOp(Num(left), Add(), Num(right)):
>return Num(left + right)
>case BinOp(left, Add() | Sub(), Num(0)):
>return simplify(left)
>case UnaryOp(USub(), UnaryOp(USub(), item)):
>return simplify(item)
>case _:
>return node
> ```
>
> Cheers,
> Mark.
> ___
> Python-Dev mailing list -- python-dev@python.org
> To unsubscribe send an email to python-dev-le...@python.org
> https://mail.python.org/mailman3/lists/python-dev.python.org/
> Message archived at
> https://mail.python.org/archives/list/python-dev@python.org/message/ETZGYRCF4DR6RJXTHGXIRZXINXJ76J2D/Code
> of Conduct: http://python.org/psf/codeofconduct/
>
>
>
> ___
> Python-Dev mailing list -- python-dev@python.org
> To unsubscribe send an email to python-dev-le...@python.org
> https://mail.python.org/mailman3/lists/python-dev.python.org/
> Message archived at
> https://mail.python.org/archives/list/python-dev@python.org/message/CUNO57W7KSIM2WRROC5R43ZT7HUQZCZ6/
> Code of Conduct: http://python.org/psf/codeofconduct/
>
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/FDP476BPKG55W2OP66VPMMGV5OBP67U3/
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-Dev] PEP 467: Minor API improvements to bytes, bytearray, and memoryview

2016-06-07 Thread Koos Zevenhoven
On Tue, Jun 7, 2016 at 11:28 PM, Ethan Furman  wrote:
>
> Minor changes: updated version numbers, add punctuation.
>
> The current text seems to take into account Guido's last comments.
>
> Thoughts before asking for acceptance?
>
> PEP: 467
> Title: Minor API improvements for binary sequences
> Version: $Revision$
> Last-Modified: $Date$
> Author: Nick Coghlan 
> Status: Draft
> Type: Standards Track
> Content-Type: text/x-rst
> Created: 2014-03-30
> Python-Version: 3.5
> Post-History: 2014-03-30 2014-08-15 2014-08-16
>
>
> Abstract
> 
>
> During the initial development of the Python 3 language specification, the 
> core ``bytes`` type for arbitrary binary data started as the mutable type 
> that is now referred to as ``bytearray``. Other aspects of operating in the 
> binary domain in Python have also evolved over the course of the Python 3 
> series.
>
> This PEP proposes four small adjustments to the APIs of the ``bytes``, 
> ``bytearray`` and ``memoryview`` types to make it easier to operate entirely 
> in the binary domain:
>
> * Deprecate passing single integer values to ``bytes`` and ``bytearray``
> * Add ``bytes.zeros`` and ``bytearray.zeros`` alternative constructors
> * Add ``bytes.byte`` and ``bytearray.byte`` alternative constructors
> * Add ``bytes.iterbytes``, ``bytearray.iterbytes`` and
>   ``memoryview.iterbytes`` alternative iterators
>

Why not bytes.viewbytes (or whatever name) so that one could also
subscript it? And if it were a property, one could perhaps
conveniently get the n'th byte:

b'abcde'.viewbytes[n]   # compared to b'abcde'[n:n+1]

Also, would it not be more clear to call the int -> bytes method
something like bytes.fromint or bytes.fromord and introduce the same
thing on str? And perhaps allow multiple arguments to create a
str/bytes of length > 1. I guess this may violate TOOWTDI, but anyway,
just a thought.

-- Koos
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 467: Minor API improvements to bytes, bytearray, and memoryview

2016-06-07 Thread Koos Zevenhoven
On Wed, Jun 8, 2016 at 12:57 AM, Barry Warsaw  wrote:
> On Jun 07, 2016, at 09:40 PM, Brett Cannon wrote:
>
>>On Tue, 7 Jun 2016 at 14:38 Paul Sokolovsky  wrote:
>>> What's wrong with b[i:i+1] ?
>>It always succeeds while indexing can trigger an IndexError.
>
> Right.  You want a method with the semantics of __getitem__() but that returns
> the desired type.
>

And if this is called __getitem__ (with slices delegated to
bytes.__getitem__) and implemented in a class, one has a view. Maybe
I'm missing something, but I fail to understand what makes this
significantly more problematic than an iterator. Ok, I guess we might
also need __len__.

-- Koos

> -Barry
>
> ___
> Python-Dev mailing list
> Python-Dev@python.org
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe: 
> https://mail.python.org/mailman/options/python-dev/k7hoven%40gmail.com
>
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] proposed os.fspath() change

2016-06-15 Thread Koos Zevenhoven
lass Huh:
>> ...   def __int__(self):
>> ... return 'string'
>> ...   def __index__(self):
>> ... return b'bytestring'
>> ...   def __bool__(self):
>> ... return 'true-ish'
>> ...
>> --> h = Huh()
>>
>> --> int(h)
>> Traceback (most recent call last):
>>   File "", line 1, in 
>> TypeError: __int__ returned non-int (type str)
>>
>> --> ''[h]
>> Traceback (most recent call last):
>>   File "", line 1, in 
>> TypeError: __index__ returned non-int (type bytes)
>>
>> --> bool(h)
>> Traceback (most recent call last):
>>   File "", line 1, in 
>> TypeError: __bool__ should return bool, returned str
>>
>> Arguments in favor or against?
>>
>> --
>> ~Ethan~
>> ___
>> Python-Dev mailing list
>> Python-Dev@python.org
>> https://mail.python.org/mailman/listinfo/python-dev
>> Unsubscribe:
>> https://mail.python.org/mailman/options/python-dev/guido%40python.org
>
>
>
>
> --
> --Guido van Rossum (python.org/~guido)
>
> ___
> Python-Dev mailing list
> Python-Dev@python.org
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe:
> https://mail.python.org/mailman/options/python-dev/k7hoven%40gmail.com
>



-- 
--
+ Koos Zevenhoven + http://twitter.com/k7hoven +
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


  1   2   >