[Python-Dev] cProfile with generator throwing

2007-06-08 Thread Eyal Lotem
Hi. It seems that cProfile does not support throwing exceptions into
generators properly, when an external timer routine is used.

The problem is that _lsprof.c: ptrace_enter_call assumes that there
are no exceptions set when it is called, which is not true when the
generator frame is being gen_send_ex'd to send an exception into it
(Maybe you could say that only CallExternalTimer assumes this, but I
am not sure).  This assumption causes its eventual call to
CallExternalTimer to discover that an error is set and assume that it
was caused by its own work (which it wasn't).

I am not sure what the right way to fix this is, so I cannot send a patch.
Here is a minimalist example to reproduce the bug:

>>> import cProfile
>>> import time
>>> p=cProfile.Profile(time.clock)
>>> def f():
...   yield 1
...
>>> p.run("f().throw(Exception())")
Exception exceptions.Exception: Exception() in  ignored
Traceback (most recent call last):
  File "", line 1, in 
  File "/usr/lib/python2.5/cProfile.py", line 135, in run
return self.runctx(cmd, dict, dict)
  File "/usr/lib/python2.5/cProfile.py", line 140, in runctx
exec cmd in globals, locals
  File "", line 1, in 
  File "", line 1, in f
SystemError: error return without exception set
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] Instance variable access and descriptors

2007-06-09 Thread Eyal Lotem
Hi.

I was surprised to find in my profiling that instance variable access
was pretty slow.

I looked through the CPython code involved, and discovered something
that really surprises me.

Python, probably through the valid assumption that most attribute
lookups go to the class, tries to look for the attribute in the class
first, and in the instance, second.

What Python currently does is quite peculiar!
Here's a short description o PyObject_GenericGetAttr:

A. Python looks for a descriptor in the _entire_ mro hierarchy
(len(mro) class/type check and dict lookups).
B. If Python found a descriptor and it has both get and set functions
- it uses it to get the value and returns, skipping the next stage.
C. If Python either did not find a descriptor, or found one that has
no setter, it will try a lookup in the instance dict.
D. If Python failed to find it in the instance, it will use the
descriptor's getter, and if it has no getter it will use the
descriptor itself.


I believe the average costs of A are much higher than of C. Because
there is just 1 instance dict to look through, and it is also
typically smaller than the class dicts (in rare cases of worse-case
timings of hash lookups), while there are len(mro) dicts to look for a
descriptor in.

This means that for simple instance variable lookups, Python is paying
the full mro lookup price!

I believe that this should be changed, so that Python first looks for
the attribute in the instance's dict and only then through the dict's
mro.

This will have the following effects:

A. It will break code that uses instance.__dict__['var'] directly,
when 'var' exists as a property with a __set__ in the class. I believe
this is not significant.
B. It will simplify getattr's semantics. Python should _always_ give
precedence to instance attributes over class ones, rather than have
very weird special-cases (such as a property with a __set__).
C. It will greatly speed up instance variable access, especially when
the class has a large mro.

I think obviously the code breakage is the worst problem. This could
probably be addressed by a transition version in which Python warns
about any instance attributes that existed in the mro as descriptors
as well.

What do you think?
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] Frame zombies

2007-06-09 Thread Eyal Lotem
I was just looking through the code that handles frames (as part of my
current effort to determine how to improve on CPython's performance),
when I noticed the freelist/zombie mechanism for frame allocation
handling.

While the zombie mechanism seems like a nice optimization, I believe
there can be a couple of improvements.

Currently, each code object has a zombie frame that last executed it.
This zombie is reused when that code object is re-executed in a frame.
When a frame is released, it is reassigned as the zombie of the code,
and iff the code object already has a zombie assigned to it, it places
the frame in the freelist.

If I understand correctly, this means, that the "freelist" is actually
only ever used for recursive-call frames that were released.  It also
means that these released frames will be reassigned to other code
objects in the future - in which case they will be reallocated,
perhaps unnecessarily.  "freelist" is just temporary storage for
released recursive calls. A program with no recursions will always
have an empty freelist.

What is bounding the memory consumption of this mechanism is a limit
on the number of frames in the freelist (and the fact that there is a
limited number of code objects, each of which may have an additional
zombie frame).

I believe a better way to implement this mechanism:

A. Replace the co_zombie frame with a co_zombie_freelist.
B. Remove the global freelist.

In other words, have a free list for each code object, rather than
one-per-code-object and a freelist.
This can be memory-bound by limiting the freelist size in each code object.
This can be use a bit more memory if a recursion is called just once -
and then discarded (waste for example 10 frames instead of 1), but can
save a lot of realloc calls when there is more than one recursion used
in the same program.
It is also possible to substantially increase the number of frames
stored per code-object, and then use some kind of more sophisticated
aging mechanism on the zombie freelists to periodically get rid of
unused freelists.  That kind of mechanism would mean that even in the
case of recursive calls, virtually all frame allocs are available from
the freelist.

I also believe this to be somewhat simpler, as there is only one
concept (a zombie freelist) rather than 2 (a zombie code object and a
freelist for recursive calls), and frames are never realloc'd, but
only allocated.

Should I make a patch?
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Instance variable access and descriptors

2007-06-09 Thread Eyal Lotem
I must be missing something, as I really see no reason to keep the
existing semantics other than backwards compatibility (which can be
achieved by introducing a __fastattr__ or such).

Can you explain under which situations or find any example situation
where the existing semantics are desirable?

As for the mro cache - thanks for pointing it out - I think it can
serve as a platform for another idea that in conjunction with psyco,
can possibly speed up CPython very significantly (will create a thread
about this soon).

Please note that speeding up the mro-lookup solves only half of the
problem (if it was solved - which it seems not to have been), the more
important half of the problem remains, allow me to emphasize:

ALL instance attribute accesses look up in both instance and class
dicts, when it could look just in the instance dict. This is made
worse by the fact that the class dict lookup is more expensive (with
or without the mro cache).
Some code that accesses a lot of instance attributes in an inner loop
can easily be sped up by a factor of 2 or more (depending on the size
of the mro).

Eyal

On 6/10/07, Kevin Jacobs <[EMAIL PROTECTED]> <[EMAIL PROTECTED]> wrote:
> I agree with Phillip with regard to the semantics.  They are semantically
> desirable.  However, there is a patch to add a mro cache to speed up these
> sorts of cases on the Python tracker, originally submitted by Armin Rigo.
> He saw ~20% speedups, others see less.  It is currently just sitting there
> with no apparent activity.  So if the overhead of mro lookups is that
> bothersome, it may be well worth your time to review the patch.
>
> URL:
> http://sourceforge.net/tracker/index.php?func=detail&aid=1700288&group_id=5470&atid=305470
>
> -Kevin
>
>
>
> On 6/9/07, Phillip J. Eby <[EMAIL PROTECTED]> wrote:
> >
> > At 12:23 AM 6/10/2007 +0300, Eyal Lotem wrote:
> > >A. It will break code that uses instance.__dict__['var'] directly,
> > >when 'var' exists as a property with a __set__ in the class. I believe
> > >this is not significant.
> > >B. It will simplify getattr's semantics. Python should _always_ give
> > >precedence to instance attributes over class ones, rather than have
> > >very weird special-cases (such as a property with a __set__).
> >
> > Actually, these are features that are both used and desirable; I've
> > been using them both since Python 2.2 (i.e., for many years
> > now).  I'm -1 on removing these features from any version of Python, even
> 3.0.
> >
> >
> > >C. It will greatly speed up instance variable access, especially when
> > >the class has a large mro.
> >
> > ...at the cost of slowing down access to properties and __slots__, by
> > adding an *extra* dictionary lookup there.
> >
> > Note, by the way, that if you want to change attribute lookup
> > semantics, you can always override __getattribute__ and make it work
> > whatever way you like, without forcing everybody else to change *their*
> code.
> >
> > ___
> > Python-Dev mailing list
> > Python-Dev@python.org
> > http://mail.python.org/mailman/listinfo/python-dev
> > Unsubscribe:
> http://mail.python.org/mailman/options/python-dev/jacobs%40bioinformed.com
> >
>
>
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] Fwd: Instance variable access and descriptors

2007-06-09 Thread Eyal Lotem
On 6/10/07, Phillip J. Eby <[EMAIL PROTECTED]> wrote:
> At 12:23 AM 6/10/2007 +0300, Eyal Lotem wrote:
> >A. It will break code that uses instance.__dict__['var'] directly,
> >when 'var' exists as a property with a __set__ in the class. I believe
> >this is not significant.
> >B. It will simplify getattr's semantics. Python should _always_ give
> >precedence to instance attributes over class ones, rather than have
> >very weird special-cases (such as a property with a __set__).
>
> Actually, these are features that are both used and desirable; I've
> been using them both since Python 2.2 (i.e., for many years
> now).  I'm -1 on removing these features from any version of Python, even 3.0.

It is the same feature, actually, two sides of the same coin.
Why do you use self.__dict__['propertyname'] when you can use
self._propertyname?
Why even call the first form, which is both longer and causes
performance problems "a feature"?


> >C. It will greatly speed up instance variable access, especially when
> >the class has a large mro.
>
> ...at the cost of slowing down access to properties and __slots__, by
> adding an *extra* dictionary lookup there.
It will slow down access to properties - but that slowdown is insignificant:
A. The vast majority of lookups are *NOT* of properties. They are the
rare case and should not be the focus of optimization.
B. Property access involves calling Python functions - which is
heavier than a single dict lookup.
C. The dict lookup to find the property in the __mro__ can involve
many dicts (so in those cases adding a single dict lookup is not
heavy).

> Note, by the way, that if you want to change attribute lookup
> semantics, you can always override __getattribute__ and make it work
> whatever way you like, without forcing everybody else to change *their* code.
If I write my own __getattribute__ I lose the performance benefit that
I am after.
I do agree that code shouldn't be broken, that's why a transitional
that requires using __fastlookup__ can be used (Unfortunately, from
__future__ cannot be used as it is not local to a module, but to a
class hierarchy - unless one imports a feature from __future__ into a
class).
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Frame zombies

2007-06-09 Thread Eyal Lotem
The freelist currently serves as a good optimization of a special case
of a recurring recursion.  If the same code object (or one of the same
size) is used for recursive calls repeatedly, the freelist will
realloc-to-same-size (which probably has no serious cost) and thus the
cost of allocating/deallocating frames was averted.

I think that in general, the complexity of a sophisticated and
efficient aging mechanism is not worth it just to optimize recursive
calls. The only question is whether it is truly a memory problem, if
using, say, up-to 50 frames per code object?

Note that _only_ recursions will have more than 1 frame attached.

How many recursions are used and then discarded?
How slow is it to constantly malloc/free frames in a recursion?

My proposal will accelerate the following example:

def f(x, y):
  if 0 == x: return
  f(x-1, y)
def g(x):
  if 0 == x: return
  g(x-1)

while True:
  f(100, 100)
  g(100)

The current implementation will work well with the following:

while True:
  f(100, 100)

But removing freelist altogether will not work well with any type of recursion.

Eyal

On 6/10/07, "Martin v. Löwis" <[EMAIL PROTECTED]> wrote:
> > Should I make a patch?
>
> -1. This could consume quite a lot of memory, and I doubt
> that the speed improvement would be significant. Instead,
> I would check whether performance could be improved by
> just dropping the freelist. Looking at the code, I see
> that it performs a realloc (!) of the frame object if
> the one it found is too small. That surely must be
> expensive, and should be replaced with a free/malloc pair
> instead.
>
> I'd be curious to see whether malloc on today's systems
> is still so slow as to justify a free list. If it is,
> I would propose to create multiple free lists per size
> classes, e.g. for frames with 10, 20, 30, etc. variables,
> rather than having free lists per code object.
>
> Regards,
> Martin
> ___
> Python-Dev mailing list
> Python-Dev@python.org
> http://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe: 
> http://mail.python.org/mailman/options/python-dev/eyal.lotem%40gmail.com
>
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Frame zombies

2007-06-10 Thread Eyal Lotem
On 6/10/07, "Martin v. Löwis" <[EMAIL PROTECTED]> wrote:
> > Note that _only_ recursions will have more than 1 frame attached.
>
> That's not true; in the presence of threads, the same method
> may also be invoked more than one time simultaneously.

Yes, I have missed that, and realized that I missed that myself a bit later.
I guess I can rationalize that with the fact that I myself tend to
avoid threads.

> > But removing freelist altogether will not work well with any type of
> > recursion.
>
> How do you know that? Did you measure the time? On what system?
> What were the results?
>
> Performance optimization without measuring is just unacceptable.

I agree, I may have used the wrong tone above.
Removing the freelist will probably either not have a significant
effect (at worst, its adding very little work of maintaining it), or
improve recursions and functions that tend to be running
simultaniously in multiple threads (as in those cases the realloc will
not actually resize the frame, and mallocs/free will indeed be saved).

But do note my corrected tone (I said "probably" :-) - and anyone is
welcome to try removing it and see if they get a performance benefit.

The fact threading also causes the same code object to be used in
multiple frames makes everything a little less predictable and may
mean that having a larger-than-1 number of frames associated with each
code object may indeed yield a performance benefit.

I am not sure how to benchmark such modifications. Is there any
benchmark that includes threaded use of the same functions in typical
use cases?

> Regards,
> Martin
> ___
> Python-Dev mailing list
> Python-Dev@python.org
> http://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe: 
> http://mail.python.org/mailman/options/python-dev/eyal.lotem%40gmail.com
>
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] Question about dictobject.c:lookdict_string

2007-06-10 Thread Eyal Lotem
My question is specifically regarding the transition back from
lookdict_string (the initial value) to the general lookdict.

Currently, when a string-only dict is trying to look up any
non-string, it reverts back to a general lookdict.

Wouldn't it be better (especially in the more important case of a
string-key-only dict), to revert to the generic lookdict when a
non-string is inserted to the dict, rather than when one is being
searched?

This seems to me as it would shift this (admittedly very slight)
performance cost of a type ptr comparison from the read-access, to
write-access on all dicts (which means insertions of new keys in
non-string-only dicts may pay for another check, or that the lookdict
funcptr will be replaced by two funcptrs so that a different insertion
func on string-only dicts is used  too [was tempted to say vtable
here, but that would add another dereference to lookups]).

It would also have the slight benefit of speeding up non-string
lookups in string-only dicts.

This does not seem like a significant issue, but as I know a lot of
effort went into optimizing dicts, I was wondering if I am missing
something here.
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Question about dictobject.c:lookdict_string

2007-06-12 Thread Eyal Lotem
On 6/11/07, Carl Friedrich Bolz <[EMAIL PROTECTED]> wrote:
> Eyal Lotem wrote:
> > My question is specifically regarding the transition back from
> > lookdict_string (the initial value) to the general lookdict.
> >
> > Currently, when a string-only dict is trying to look up any
> > non-string, it reverts back to a general lookdict.
> >
> > Wouldn't it be better (especially in the more important case of a
> > string-key-only dict), to revert to the generic lookdict when a
> > non-string is inserted to the dict, rather than when one is being
> > searched?
> [...]
> > This does not seem like a significant issue, but as I know a lot of
> > effort went into optimizing dicts, I was wondering if I am missing
> > something here.
>
> Yes, you are: when doing a lookup with a non-string-key, that key could
> be an instance of a class that has __hash__ and __eq__ implementations
> that make the key compare equal to some string that is in the
> dictionary. So you need to change to lookdict, otherwise that lookup
> might fail.
Ah, thanks for clarification.

But doesn't it make sense to only revert that single lookup, and not
modify the function ptr until the dict contains a non-string?

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


[Python-Dev] Cycle collection enhancement idea

2008-06-28 Thread Eyal Lotem
I see why a cycle that has multiple objects with a __del__ method is a problem.

Once you call __del__ on one of the objects, its no longer usable by
the others, and its not clear which order is correct.

My question regards the case where a cycle of objects only has 1
object which has a __del__.

I think a correct strategy to collect the entire cycle is the same one
used on a single object.  On a single object Python uses:
1. Temporarily revive object
2. Call __del__
3. Unrevive object (if(--refcount == 0) then we're done), otherwise it
was resurrected).

We can apply this to the whole cycle:
1. Temporarily revive entire cycle (each of its objects)
2. Call __del__
3. Unrevive the objects of the entire cycle (each of its objects).

Step 1 will allow __del__ to run safely. Since there is only one
__del__ in the cycle, it is not dangerous that its references will
disappear from "under its feet".
(Some code restructuring will probably be necessary, because of
assumptions that are hard-coded into slot_tp_del and subtype_dealloc).

I believe this enhancement is important, because:
A. When using existing code -- you do not control whether its objects
have a __del__. In my experience, a majority of these cases only have
a single __del__-containing object in their cycles.
B. Python's exit cleanup calls __del__ in the wrong order, and
Python's runtime is full of cycles (Each global is a cycle, including
the class objects themselves: class->dict->function->func_globals)).
These cycles very often have only 1 __del__ method.

Some examples of the problem posed by B:
http://www.google.com/search?q=ignored+%22%27NoneType%27+object+has+no+attribute%22+%22__del__+of%22&btnG=Search
Ugly workarounds exist even in the standard library [subprocess]: "def
__del__(self, sys=sys):").

Example:

import os
class RunningFile(object):
filename = '/tmp/running'
def __init__(self):
open(self.filename, 'wb')
def __del__(self):
os.unlink(self.filename)
running_file = RunningFile()

The deller object is in a cycle as described above [as well as the
Deller class itself].  When Python exits, it could call
deller.__del__() and then collect the cycle. But Python does the wrong
thing here, and gets rid of the globals before calling __del__:
Exception exceptions.AttributeError: "'NoneType' object has no
attribute 'unlink'" in > ignored

I believe applying the above enhancement would solve these problems.
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Cycle collection enhancement idea

2008-06-29 Thread Eyal Lotem
On Sun, Jun 29, 2008 at 9:00 PM, "Martin v. Löwis" <[EMAIL PROTECTED]> wrote:
>> As I explained above, it *is* part of a cycle: """including
>> the class objects themselves: class->dict->function->func_globals""".
>
> Ah, right. I must have missed that explanation.
>
>> I know. I assumed Python does not rely on cyclic garbage collectioin
>> for shutdown, because it wouldn't work, as _all_ globals that have
>> *any* instance method will be part of a cycle, and any of them which
>> have a __del__ will not be collected.
>
> No. The mechanism for cleaning modules at shutdown time predates cyclic
> GC, and was not removed because "it wouldn't work".
>
> This specific issue certainly contributes to the fact that it doesn't
> work, but there might be other problems as well (such as extension
> modules holding onto objects participating in cycles).
>
>> I *mentioned* this workaround. What I propose is not a workaround but
>> a solution. You wouldn't need to clean up module globals ad-hoc'ishly,
>> because the cyclic collection would collect your object, even with its
>> __del__.
>
> I don't think it solves the problem. You seem to be assuming that any
> such cycle will contain only a single global object with an __del__.
> However, as modules refer to each other, I very much doubt that is the
> case.
>
>> Please read my entire mail before replying to it. Thanks!
>
> I really, really tried. I read it three times before replying.
>
> However, I found it really, really difficult to follow your writing,
> as it was mixing problem statement and solution, so that I couldn't
> tell what paragraph was about what. English is not my native language,
> complicating communication further. Please accept my apologies.

I apologize for my tone as well, it just seemed frustrating that all
the replies seemed to completely ignore the core point I was trying to
make and claim that the problem I was trying to solve was not a
problem at all, but a behavior I was unaware of...

Mixing another quote from another mail:
> > That would be no worse than what happens now - but its still not
> > perfect (__del__ ordering issues). Also, you would need to temporarily
> > revive the cycles as mentioned above (to avoid accessibility of
> > partially destructed objects).
>
> I don't quite understand what you mean by "revive cycles". There is
> not need to revive any object in a cycle, as all objects are still alive
> (or else they wouldn't be garbage).
By "revive cycles", I mean make sure that they are referenced by an
independent referrer (one that won't go away as part of the __del__
calling process).  This is similar to how the tp_dealloc code
increases the refcount (actually sets it to 1, because it was
certainly 0 when entering the destructor) before calling the __del__
slot.  Without reviving the object before calling its __del__ in the
destructor, and without reviving the objects of a cycle before calling
its __del__'s, the __del__ Pythonic code may be exposed to "dead
objects" (refcount==0).

Consider the cycle:
a.x = b
b.x = a

Lets suppose the a object has a __del__. Lets assume each object in
the cycle has a refcount of 1 (and the cycle should die). Now lets say
this is a's __del__ code:
def __del__(self):
  self.x = None

Running it will set 'b's refcount to 0 and call its destructor, which
will set 'a's refcount to 0 and also call its destructor. But its
__del__ is currently running - so "self" must not have a refcount of
0.  If you only incref on 'a' before calling __del__, then you are
probably alright, as long as there is only one __del__.

> Can you please elaborate? What would such __del__ ordering issues be?

class A(object):
  def __del__(self):
print self.x.attribute

class B(object):
  def __del__(self):
print "B is going down!"
del self.attribute

a = A()
b = B()
a.x = b
b.attribute = 1

If you call b's __del__ first then a's __del__ will fail. If you call
a's __del__ first, then all is well.  Ofcourse you can create true
cyclic dependencies that no order will work, and its pretty clear
there is no way to deduce the right order anyway.  This is what I mean
by "ordering issues".

> There could be a global barricade for calling __del__: you first call
> all __del__s of existing objects, then set the barricade, and then
> start breaking cycles.
> This could even be done with the current approach to module clearing.

Note that the __del__'s themselves may be breaking cycles and
refcounts will go to 0 - unless you temporarily revive (incref) the
entire cycle first.

> I still don't understand what "revive the cycle" means. You will need to
> incref the object for which you call __del__, that's all.

Unless there are multiple __del__'s in the cycle.

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


[Python-Dev] Security capabilities in Python

2005-04-08 Thread Eyal Lotem
I would like to experiment with security based on Python references as
security capabilities.

Unfortunatly, there are several problems that make Python references
invalid as capabilities:

* There is no way to create secure proxies because there are no
private attributes.
* Lots of Python objects are reachable unnecessarily breaking the
principle of least privelege (i.e: object.__subclasses__() etc.)

I was wondering if any such effort has already begun or if there are
other considerations making Python unusable as a capability platform?

(Please cc the reply to my email)
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Security capabilities in Python

2005-04-10 Thread Eyal Lotem
It may be really hard to get it right, unless we are overlooking some simple solution.I disagree that we should "just use OS protections".The
reason I am interested in Pythonic protection is because it is so much
more powerful than OS protections.  The capability model is
much more powerful than the ACL model used by all OS's these days, and
allows for interesting security concepts.What about implementing the facet in C?  This could avoid the class of problems you have just mentioned.On Apr 9, 2005 2:02 PM, James Y Knight <[EMAIL PROTECTED]> wrote:> On Apr 9, 2005, at 5:37 PM, Ka-Ping Yee wrote:> > Let me know if you figure out how to defeat that.> > You can protect against this, too, but it does show that it's *really*> hard to get restricting code right...I'm of the opinion that it's not> really worth it -- you should just use OS protections.> > untrusted_module.py:> > class foostr(str):>   def __eq__(self, other):>return True> > def have_at_it(immutable_facet, readonly_facet):>getattr(immutable_facet, foostr('append'))(5)>print immutable_facet> > James___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] Early PEP draft (For Python 3000?)

2005-10-12 Thread Eyal Lotem
I would like to re-suggest a suggestion I have made in the past, but
with a mild difference, and a narrower scope.

Name: Attribute access for all namespaces

Rationale: globals() access is conceptually the same as setting the
module's attributes but uses a different idiom (access of the dict
directly).  Also, locals() returns a dict, which implies it can affect
the local scope, but quietly ignores changes.  Using attribute access
to access the local/global namespaces just as that is used in instance
namespaces and other modules' namespaces, could reduce the mental
footprint of Python.

Method: All namespace accesses are attribute accesses, and not direct
__dict__ accesses. Thus globals() is replaced by a "module" keyword
(or "magic variable"?) that evaluates to the module object.  Thus,
reading/writing globals in module X, uses getattr/setattr on the
module object, just like doing so in module Y would be.  locals()
would return be replaced by a function that returns the frame object
(or a weaker equivalent of a frame object) of the currently running
function.  This object will represent the local namespace and will
allow attribute getting/setting to read/write attributes. Or it can
disallow attribute setting.

Examples:

   global x ; x = 1
Replaced by:
   module.x = 1

or:

  globals()[x] = 1
Replaced by:
  setattr(module, x, 1)


  locals()['x'] = 1 # Quietly fails!
Replaced by:
  frame.x = 1 # Raises error

  x = locals()[varname]
Replaced by:
  x = getattr(frame, varname)


Advantages:
  - Python becomes more consistent w.r.t namespacing and scopes.
Disadvantages:
  - "module" is already possible by importing one's own module, but that is:
* Confusing and unnecessarily requires naming one's self
redundantly (Making renaming of the module a bit more difficult).
* Not easily possible in a __main__/importable module.
* No equivalent for locals()
  - Automatic script conversion may be difficult in some use cases of
globals()/locals()
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Assignment to __class__ of module? (Autoloading? (Making Queue.Queue easier to use))

2005-10-13 Thread Eyal Lotem
Why not lazily import modules by importing them when they are needed
(i.e inside functions), and not in the top-level module scope?


On 10/13/05, Phillip J. Eby <[EMAIL PROTECTED]> wrote:
> At 04:02 PM 10/13/2005 +0100, Michael Hudson wrote:
> >Greg Ewing <[EMAIL PROTECTED]> writes:
> >
> > > Phillip J. Eby wrote:
> > >> At 01:47 PM 10/13/2005 +1300, Greg Ewing wrote:
> > >>
> > >>> I'm trying to change the __class__ of a newly-imported
> > >>> module to a subclass of types.ModuleType
> > >>
> > >> It happened in Python 2.3, actually.
> > >
> > > Is there a discussion anywhere about the reason this was
> > > done? It would be useful if this capability could be
> > > regained somehow without breaking things.
> >
> >Well, I think it's undesirable that you be able to do this to, e.g.,
> >strings.  Modules are something of a greyer area, I guess.
>
> Actually, it's desirable to be *able* to do it for anything.  But certainly
>
> for otherwise-immutable objects it can lead to aliasing issues.
>
> For mutable objects, it's *very* desirable, and I think the rules added in
> 2.3 might have been overly strict, as they disallow you changing any
> built-in type to a non built-in type, even if the allocator is the
> same.  It seems to me the safety check could perhaps be reduced to just
> checking whether the old and new classes have the same tp_free.  (Apart
> from the layout and other inheritance-related checks, I mean.)
>
> (By the way, for an example use case other than modules, note that somebody
>
> wrote an "observables" package that could detect mutation of lists and
> dictionaries in Python 2.2 using __class__ changes, which then became
> useless as of Python 2.3.)
>
> ___
> Python-Dev mailing list
> Python-Dev@python.org
> http://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe:
> http://mail.python.org/mailman/options/python-dev/eyal.lotem%40gmail.com
>
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] Class decorators vs metaclasses

2005-11-04 Thread Eyal Lotem
I have a few claims, some unrelated, and some built on top of each
other.  I would like to hear your responses as to which are
convincing, which arne't, and why. I think that if these claims are
true, Python 3000 should change quite a bit.

A. Metaclass code is black magic and few understand how it works,
while decorator code is mostly understandable, even by non-gurus.

B. One of Decorators' most powerful features is that they can
mixed-and-matched, which makes them very powerful for many purposes,
while metaclasses are exclusive, and only one can be used.  This is
especially problematic as some classes may assume their subclasses
must use their respective metaclasses.  This means classdecorators are
strictly more powerful than metaclasses, without cumbersome
convertions between metaclass mechanisms and decorator mechanisms.

C. Interesting uses of classdecorators are allowing super-calling
without redundantly specifying the name of your class, or your
superclass.

D. Python seems to be incrementally adding power to the core language
with these features, which is great, but it also causes significant
overlapping of language features, which I believe is something to
avoid when possible.  If metaclasses are replaced with class
decorators, then suddenly inheritence becomes a redundant feature.

E. If inheritence is a redundant feature, it can be removed and an
"inherit" class decorator can be used.  This could also reduce all the
__mro__ clutter from the language along with other complexities, into
alternate implementations of the inherit classdecorator.
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Class decorators vs metaclasses

2005-11-05 Thread Eyal Lotem
On 11/5/05, Alex Martelli <[EMAIL PROTECTED]> wrote:
> On 11/4/05, Eyal Lotem <[EMAIL PROTECTED]> wrote:
> > I have a few claims, some unrelated, and some built on top of each
> > other.  I would like to hear your responses as to which are
> > convincing, which arne't, and why. I think that if these claims are
> > true, Python 3000 should change quite a bit.
> >
> > A. Metaclass code is black magic and few understand how it works,
> > while decorator code is mostly understandable, even by non-gurus.
>
> I disagree.  I've held many presentations and classes on both
> subjects, and while people may INITIALLY feel like metaclasses are
> black magic, as soon as I've explained it the fear dissipates.  It all
> boils down do understanding that:
>
> class Name(Ba,Ses): <>
>
> means
>
> Name = suitable_metaclass('Name', (Ba,Ses), <>)
>
> which isn't any harder than understanding that
>
> @foo(bar)
> def baz(args): ...
>
> means
>
> def baz(args): ...
> baz = foo(bar)(baz)

I disagree again. My experience is that metaclass code is very hard to
understand. Especially when it starts doing non-trivial things, such
as using a base metaclass class that is parametrized by metaclass
attributes in its subclasses.  Lookups of attributes in the base
metaclass methods is mind boggling (is it searching them in the base
metaclass, the subclass, the instance [which is the class]?).  The
same code would be much easier to understand with class decorators.

> > B. One of Decorators' most powerful features is that they can
> > mixed-and-matched, which makes them very powerful for many purposes,
> > while metaclasses are exclusive, and only one can be used.  This is
>
> Wrong.  You can mix as many metaclasses as you wish, as long as
> they're properly coded for multiple inheritance (using super, etc) --
> just inherit from them all.  This is reasonably easy to automate (see
> the last recipe in the 2nd ed of the Python Cookbook), too.

Multiple inheritence is an awful way to mix class fucntionalities
though. Lets take a simpler example.  Most UT frameworks use a
TestCase base class they inherit from to implement setup, tearDown,
and then inherit from it again to implement the test itself.  I argue
this is a weak approach, because then mixing/matching setups is
difficult.  You would argue this is not the case, because of the
ability to multiply-inherit from test cases, but how easy is the
equivalent of:

@with_setup('blah')
@with_other_setup('bleh')
def my_test():
  # the blah setup and bleh other setup are up and usable here,
  # and will be "torn down" at the end of this test

The equivalent of this requires a lot more work and violating DRY. 
Creating a specific function to multiply inherit from TestCases is a
possible solution, but it is much more conceptually complex, and needs
to be reimplemented in the next scenario (Metaclasses for example).

> > especially problematic as some classes may assume their subclasses
> > must use their respective metaclasses.  This means classdecorators are
> > strictly more powerful than metaclasses, without cumbersome
> > convertions between metaclass mechanisms and decorator mechanisms.
>
> The assertion that classdecorators are strictly more powerful than
> custom metaclasses is simply false.  How would you design
> classdecorator XXX so that
>
> @XXX
> class Foo: ...
>
> allows 'print Foo' to emit 'this is beautiful class Foo', for example?
>  the str(Foo) implicit in print calls type(Foo).__str__(Foo), so you
> do need a custom type(Foo) -- which is all that is meant by "a custom
> metaclass"... a custom type whose instances are classes, that's all.

I would argue that this is not such a useful feature, as in that case
you can simply use a factory object instead of a class.  If this
feature remains, that's fine, but the fact it allows for a weak form
of "decoration" of classes should not kill the concept of class
decorators.
The only reason of using metaclasses rather than factory objects, in
my experience, was that references to class objects are considered
different than references to factories (by pickle and deepcopy, and
maybe others) and that can be a useful feature. This feature can be
implemented in more readable means though.

> > C. Interesting uses of classdecorators are allowing super-calling
> > without redundantly specifying the name of your class, or your
> > superclass.
>
> Can you give an example?

@anotherclassdecorator
@supercallerclass
class MyClass(object):
 @supercaller
 def my_method(self, supcaller, x, y, z):
 ...
 result = supcaller.my_method(x, y, z)
 ...

Could be nice to