Re: [Python-Dev] cpython: Remove some extraneous parentheses and swap the comparison order to
Terry Reedy wrote: On 6/7/2011 5:35 PM, David Malcolm wrote: I know that this style is unpopular, but if it helps, try mentally pronouncing "==" in C as "is the value of". In this example, when I read that line, my mind is thinking: "if 'u' is the value of typecode" After ~12 years of doing this, it comes naturally. I appreciate that this may come across as weird though :) Whereas I read it as 'has the value' (or just 'is' ;=). Am I the only one who reads == as "equals"? -- Steven ___ Python-Dev mailing list [email protected] http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
[Python-Dev] Can we improve support for abstract base classes with desciptors
I would like to try to address some shortfalls with the way python deals with
abstract base classes containing descriptors. I originally was just concerned
with improving support for defining abstract properties with the decorator
syntax and converting between abstract and concrete properties, but recently
realized that the problem extends to descriptors in general.
ABCs
First, a bit of background may be in order. An abstract base class is defined
by specifying its metaclass as ABCMeta (or a subclass thereof)::
class MyABC(metaclass=ABCMeta):
@abstractmethod
def foo(self):
pass
When trying to instantiate MyABC or any of its subclasses, ABCMeta inspects the
current class namespace for items tagged with __isabstractmethod__=True::
class ABCMeta(type):
#[...]
def __new__(mcls, name, bases, namespace):
cls = super().__new__(mcls, name, bases, namespace)
# Compute set of abstract method names
abstracts = {name
for name, value in namespace.items()
if getattr(value, "__isabstractmethod__", False)}
ABCMeta then checks if any of the base classes define any items tagged with
__isabstractmethod__ and whether they remain abstract in the current
class namespace::
for base in bases:
for name in getattr(base, "__abstractmethods__", set()):
value = getattr(cls, name, None)
if getattr(value, "__isabstractmethod__", False):
abstracts.add(name)
cls.__abstractmethods__ = frozenset(abstracts)
In Objects/typeobject.c, __abstractmethods__ is actually a descriptor, and
setting it gives the type a chance to set an internal flag specifying if it
has any abstract methods defined. When object_new is called in typeobject.c,
the flag is checked and an error is raised if any abstract methods were
identified.
Issues with ABCs and descriptors
In order for this scheme to work, ABCMeta needs to identify all of the abstract
methods, but there are some limitations when we consider descriptors. For
example, Python's property is a composite object, whose behavior is defined by
the getter, setter, and deleter methods with which it is composed. Since there
is already an @abstractmethod decorator, I would have suspected that defining
abstract properties would be intuitive::
class MyABC(metaclass=ABCMeta):
@abstractmethod
def _get_foo(self):
pass
@abstractmethod
def _set_foo(self, val):
pass
foo = property(_get_foo, _set_foo)
@property
@abstractmethod
def bar(self):
pass
@bar.setter
@abstractmethod
def bar(self, val):
pass
Ideally, one would want the flexibility of defining a concrete getter and an
abstract setter, for example. However, ABCMeta does not inspect the descriptors
of a class to see if they contain any abstract methods. It only inspects the
descriptor itself for a True __isabstractmethod__ attribute. This places the
burdon on every descriptor implementation to provide its own support for ABC
compatibility. For example, support for abstract properties was attempted by
adding abstractproperty to the abc module. abstractproperty subclasses the
property builtin (as opposed to the relationship between every other abstract
and concrete class in the python language). Here is the definition of
abstractproperty, in its entirety (modulo docstrings)::
class abstractproperty(property):
__isabstractmethod__ = True
A number of problems manifest with this approach, and I think they all can be
traced to the fact that the abstractedness of a descriptor is currently not
dependent upon the abstractedness of the methods with which it is
composed. The documentation for abstractproperty doesn't suggest using
@abstractmethod::
class C(metaclass=ABCMeta):
def getx(self): ...
def setx(self, value): ...
x = abstractproperty(getx, setx)
which leads to Issue #1: What is abstract about C.x? How does a subclass of C
know whether it needs to override the getter or setter?
Issue #2: The decorator syntax cannot be used to convert an abstract property
into a concrete one. (This relates to Issue #1: how would a descriptor even know
when such a conversion would be appropriate?) Running the following code::
from abc import ABCMeta, abstractmethod, abstractproperty
class AbstractFoo(metaclass=ABCMeta):
@abstractproperty
def bar(self):
return 1
@bar.setter
def bar(self, val):
pass
class ConcreteFoo(AbstractFoo):
@AbstractFoo.bar.getter
def bar(self):
return 1
@bar.setter
def bar(self, val):
pass
foo = ConcreteFoo()
yields::
TypeError: Can't instantiate abstrac
Re: [Python-Dev] The socket HOWTO
On Wed, Jun 8, 2011 at 3:37 AM, Eli Bendersky wrote: > Just be careful not to reproduce http://www.apress.com/9781590593714 :-) > These things tend to get out of hand very quickly. At the level Glyph and Martin are talking about, you're more likely to end up with http://authors.phptr.com/tanenbaumcn4/ :) Cheers, Nick. -- Nick Coghlan | [email protected] | Brisbane, Australia ___ Python-Dev mailing list [email protected] http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] The socket HOWTO
On Tue, Jun 7, 2011 at 1:54 PM, Glyph Lefkowitz wrote: > how is UDP different from TCP? > > The phrase "UDP" never appears in the HOWTO. DGRAM sockets get a brief > mention as "anything else" in the sentence: "... you’ll get better behavior > and performance from a STREAM socket than anything else ...". (To be fair, > I do endorse teaching that "the difference between TCP and UDP is that you > should not use UDP" to anyone not sufficiently advanced to read the relevant > reference documentation themselves.) And if UDP starts sounding tempting due to excessively high latency, these days it's worth looking up the specs for the interplanetary internet instead. Cheers, Nick. -- Nick Coghlan | [email protected] | Brisbane, Australia ___ Python-Dev mailing list [email protected] http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] cpython: Remove some extraneous parentheses and swap the comparison order to
On Wed, Jun 8, 2011 at 7:35 AM, David Malcolm wrote: > After ~12 years of doing this, it comes naturally. I appreciate that > this may come across as weird though :) I actually thought Brett's rationale in the checkin comment was reasonable (if you get in the habit of putting constants on the left, then the classic "'=' instead of '=='" typo is a compiler error instead of a reassignment). Call it a +0 in favour of letting people put constants on the left in C code if they prefer it that way, so long as any given if/elif chain is consistent in the style it uses. Cheers, Nick. -- Nick Coghlan | [email protected] | Brisbane, Australia ___ Python-Dev mailing list [email protected] http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] cpython: Remove some extraneous parentheses and swap the comparison order to
On Wed, Jun 8, 2011 at 7:04 AM, Steven D'Aprano wrote: .. >> Whereas I read it as 'has the value' (or just 'is' ;=). > > Am I the only one who reads == as "equals"? If you are, you are the only one who reads it correctly. Consider >>> a = 2 >>> a == 2.0 True ___ Python-Dev mailing list [email protected] http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] cpython: Remove some extraneous parentheses and swap the comparison order to
On Wed, 08 Jun 2011 21:04:48 +1000, Steven D'Aprano wrote: > Terry Reedy wrote: > > On 6/7/2011 5:35 PM, David Malcolm wrote: > > > >> I know that this style is unpopular, but if it helps, try mentally > >> pronouncing "==" in C as "is the value of". > >> > >> In this example, when I read that line, my mind is thinking: > >> > >> "if 'u' is the value of typecode" > >> > >> After ~12 years of doing this, it comes naturally. I appreciate that > >> this may come across as weird though :) > > > > Whereas I read it as 'has the value' (or just 'is' ;=). > > > Am I the only one who reads == as "equals"? No :) Especially considering that Python actually has an 'is' operator -- R. David Murray http://www.bitdance.com ___ Python-Dev mailing list [email protected] http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Can we improve support for abstract base classes with desciptors
On Thu, Jun 9, 2011 at 1:01 AM, Darren Dale wrote:
[snip excellent analysis of the problem]
I have some suggestions regarding a few details of your current code,
but your basic proposal looks sound to me.
I would tweak __new__ along the following lines though:
def __new__(mcls, name, bases, namespace):
cls = super().__new__(mcls, name, bases, namespace)
# Compute set of abstract method names
# CHANGE 1: refactor descriptor and abstract method scan to
happen in a single pass
def is_descriptor(value):
return (hasattr(value, '__get__') or hasattr(value, '__set__')
or hasattr(value, '__delete__'))
def is_abstract(value):
return getattr(value, "__isabstractmethod__", False)
def get_abstract_names_for_item(item):
name, value = item
if is_abstract(value):
return [name]
elif is_descriptor(value):
# CHANGE 2: Deliberately ignore descriptors on the
descriptor objects
# CHANGE 3: Use new-style string formatting
return ['{}.{}'.format(name, attr) for attr in
dir(value) if is_abstract(getattr(value, attr))]
return []
def get_abstract_names(ns):
names = []
for item in ns.items():
names.extend(get_abstract_names_for_item(item))
return names
abstract_names = get_abstract_names(namespace.items())
for base in bases:
for name in getattr(base, "__abstractmethods__", ()):
# CHANGE 4: Using rpartition better tolerates weird
naming in the metaclass
# (weird naming in descriptors will still blow up in
the earlier search for abstract names)
descr_name, is_descr, attr = name.rpartition('.')
if is_descr:
# base class identified a descriptor abstract method:
descr = getattr(cls, descr_name, None)
val = getattr(descr, attr, None)
else:
val = getattr(cls, name, None)
if val is None or is_abstract(val):
abstract_names.append(name)
cls.__abstractmethods__ = frozenset(abstract_names)
Cheers,
Nick.
--
Nick Coghlan | [email protected] | Brisbane, Australia
___
Python-Dev mailing list
[email protected]
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe:
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] The socket HOWTO
On Tue, Jun 7, 2011 at 10:37 AM, Eli Bendersky wrote: > > Just be careful not to reproduce http://www.apress.com/9781590593714 :-) > These things tend to get out of hand very quickly. You say that like it's a bad thing. The first few chapters of that would make a great replacement for the howto. Geremy Condra ___ Python-Dev mailing list [email protected] http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
[Python-Dev] fatal error callback issue
I'm writing in regards to http://bugs.python.org/issue1195571 I'm embedding Python in my application and ran into a need for this functionality. I wrote a similar patch myself, and was about to submit it. When I searched for similar issues I found that this one has been available since 2005. I'd really like to help get this patch approved and integrated into the python sources. I'm sure many other python embedders have run into this in the past - it's a legitimate concern for any process which is not 100% hosted in the Python world. Thanks. Tom. ___ Python-Dev mailing list [email protected] http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Can we improve support for abstract base classes with desciptors
On Wed, Jun 8, 2011 at 11:55 AM, Nick Coghlan wrote: > On Thu, Jun 9, 2011 at 1:01 AM, Darren Dale wrote: > [snip excellent analysis of the problem] > > I have some suggestions regarding a few details of your current code, > but your basic proposal looks sound to me. > > I would tweak __new__ along the following lines though: [snip] Thank you, I agree. Concerning the following block: > def get_abstract_names(ns): > names = [] > for item in ns.items(): > names.extend(get_abstract_names_for_item(item)) > return names > > abstract_names = get_abstract_names(namespace.items()) That should be "get_abstract_names(namespace)", since ns.items() gets called again in the for loop. I think the get_abstract_names function isn't needed though, since it is only ever called that one time. Any reason not replace the above block with:: abstract_names = [] for item in namespace.items(): abstract_names.extend(get_abstract_names_for_item(item)) > for base in bases: > for name in getattr(base, "__abstractmethods__", ()): > # CHANGE 4: Using rpartition better tolerates weird > naming in the metaclass > # (weird naming in descriptors will still blow up in > the earlier search for abstract names) Could you provide an example of weird naming? Darren ___ Python-Dev mailing list [email protected] http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] [Python-checkins] cpython (2.7): Merge
Le jeudi 09 juin 2011 à 02:30 +0200, brian.curtin a écrit : > http://hg.python.org/cpython/rev/f1509fc75435 > changeset: 70715:f1509fc75435 > branch: 2.7 > parent: 70661:6e7a98cfcfab > user:Brian Curtin > date:Wed Jun 08 19:29:53 2011 -0500 > summary: > Merge FYI this commit has only one parent, it's not a merge. It should have a changelog describing the patch. ... whereas the following commit has two parents, it's a merge: > http://hg.python.org/cpython/rev/567f30527913 > changeset: 70714:567f30527913 > parent: 70712:964d0d65a2a9 > parent: 70713:88e318166eaf > user:Brian Curtin > date:Wed Jun 08 18:43:57 2011 -0500 > summary: > Fix #11583. Changed os.path.isdir to use GetFileAttributes (...) You can use "merge", "Merge 3.2", or other similir changelog. I prefer to use "(Merge 3.2)Fix #11583. Changed os.path._isdir ..." : copy/paste the changelog of the original commit with "(Merge 3.2) " prefix. Victor ___ Python-Dev mailing list [email protected] http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] fatal error callback issue
On 6/8/2011 3:30 PM, Tom Whittock wrote: I'm writing in regards to http://bugs.python.org/issue1195571 I'm embedding Python in my application and ran into a need for this functionality. I wrote a similar patch myself, and was about to submit it. When I searched for similar issues I found that this one has been available since 2005. I'd really like to help get this patch approved and integrated into the python sources. I'm sure many other python embedders have run into this in the past - it's a legitimate concern for any process which is not 100% hosted in the Python world. Add a comment like this to the issue itself. Also review the most recent patch, considering Victor's comments. Is it better than yours? Can you improve it? Can you test it? -- Terry Jan Reedy ___ Python-Dev mailing list [email protected] http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Can we improve support for abstract base classes with desciptors
On Thu, Jun 9, 2011 at 8:51 AM, Darren Dale wrote: > That should be "get_abstract_names(namespace)", since ns.items() gets > called again in the for loop. I think the get_abstract_names function > isn't needed though, since it is only ever called that one time. Any > reason not replace the above block with:: > > abstract_names = [] > for item in namespace.items(): > abstract_names.extend(get_abstract_names_for_item(item)) Nope, inlining that part makes sense. >> for base in bases: >> for name in getattr(base, "__abstractmethods__", ()): >> # CHANGE 4: Using rpartition better tolerates weird >> naming in the metaclass >> # (weird naming in descriptors will still blow up in >> the earlier search for abstract names) > > Could you provide an example of weird naming? >>> class C(object): ... pass ... >>> setattr(C, 'weird.name', staticmethod(int)) >>> c = C() >>> c.weird.name Traceback (most recent call last): File "", line 1, in AttributeError: 'C' object has no attribute 'weird' >>> c.weird.name Traceback (most recent call last): File "", line 1, in AttributeError: 'C' object has no attribute 'weird' >>> getattr(c, 'weird.name')() 0 This is definitely something that could legitimately be dismissed as "well, don't do that then" (particularly since similarly weird names on the descriptors will still break). However, I also prefer the way partition based code reads over split-based code, so I still like the modified version. Full tolerance for weird naming would require storing 2-tuples in __abstractmethods__ which would cause a whole new set of problems and isn't worth the hassle. Cheers, Nick. -- Nick Coghlan | [email protected] | Brisbane, Australia ___ Python-Dev mailing list [email protected] http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] The socket HOWTO
On Wed, Jun 8, 2011 at 21:07, geremy condra wrote: > On Tue, Jun 7, 2011 at 10:37 AM, Eli Bendersky wrote: > > > > Just be careful not to reproduce http://www.apress.com/9781590593714 :-) > > These things tend to get out of hand very quickly. > > You say that like it's a bad thing. The first few chapters of that > would make a great replacement for the howto. > > Not a bad thing at all, and I'm sorry if I made it sound that way. I just meant that it may turn into a *whole book* if too many details are added. I had no intention to criticize this specific book. Frankly I didn't even read it, I just remembered that a book with this title came out recently. Eli ___ Python-Dev mailing list [email protected] http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] cpython (3.2): Fix #11583. Changed os.path.isdir to use GetFileAttributes instead of os.stat.
On 06/09/11 02:00, brian.curtin wrote: > http://hg.python.org/cpython/rev/88e318166eaf > changeset: 70713:88e318166eaf > branch: 3.2 > parent: 70700:0aa3064d1cef > user:Brian Curtin > date:Wed Jun 08 18:17:18 2011 -0500 > summary: > Fix #11583. Changed os.path.isdir to use GetFileAttributes instead of > os.stat. > > By changing to the Windows GetFileAttributes API in nt._isdir we can figure > out if the path is a directory without opening the file via os.stat. This has > the minor benefit of speeding up os.path.isdir by at least 2x for regular > files and 10-15x improvements were seen on symbolic links (which opened the > file multiple times during os.stat). Since os.path.isdir is used in > several places on interpreter startup, we get a minor speedup in startup time. > > files: > Lib/ntpath.py | 13 ++ > Misc/NEWS | 3 ++ > Modules/posixmodule.c | 37 +++ > 3 files changed, 53 insertions(+), 0 deletions(-) > > > diff --git a/Lib/ntpath.py b/Lib/ntpath.py > --- a/Lib/ntpath.py > +++ b/Lib/ntpath.py > @@ -672,3 +672,16 @@ > def sameopenfile(f1, f2): > """Test whether two file objects reference the same file""" > return _getfileinformation(f1) == _getfileinformation(f2) > + > + > +try: > +# The genericpath.isdir implementation uses os.stat and checks the mode > +# attribute to tell whether or not the path is a directory. > +# This is overkill on Windows - just pass the path to GetFileAttributes > +# and check the attribute from there. > +from nt import _isdir > +except ImportError: > +from genericpath import isdir as _isdir > + > +def isdir(path): > +return _isdir(path) Not that it matters, but ISTM that this would be faster as try: from nt import _isdir as isdir except ImportError: pass Georg ___ Python-Dev mailing list [email protected] http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
