Re: [Python-Dev] Explicit Lexical Scoping (pre-PEP?)

2006-07-09 Thread Ka-Ping Yee
On Sun, 9 Jul 2006, Andrew Koenig wrote:
> > Sounds reasonable to me.  If we're talking py3k I'd chuck "global" as a
> > keyword though and replace it with something like "outer".
>
> I must say that I don't like "outer" any more than I like "global."  The
> problem is that in both cases we are selecting the *inner*most definition
> that isn't in the current scope.

That's why "nonlocal" is a better choice in my opinion.


-- ?!ng
___
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] Explicit Lexical Scoping (pre-PEP?)

2006-07-10 Thread Ka-Ping Yee
On Mon, 10 Jul 2006 [EMAIL PROTECTED] wrote:
> I think Talin's got a point though.  It seems hard to find one short English
> word that captures the essence of the desired behavior.  None of the words
> in his list seem strongly suggestive of the meaning to me.  I suspect that
> means one's ultimately as good (or as bad) as the rest.

What's wrong with "nonlocal"?  I don't think i've seen an argument
against that one so far (from Talin or others).


-- ?!ng
___
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] Explicit Lexical Scoping (pre-PEP?)

2006-07-10 Thread Ka-Ping Yee
On 7/10/06, Ka-Ping Yee <[EMAIL PROTECTED]> wrote:
> What's wrong with "nonlocal"?  I don't think i've seen an argument
> against that one so far (from Talin or others).

On Mon, 10 Jul 2006, Jeremy Hylton wrote:
> It's a made-up word.  You won't find it in the dictionary and the
> google define: query sends me to a wikipedia page about quantum
> mechanics.

Two million Google hits for "nonlocal" seems like plenty.
The explanation of "nonlocal" is pretty straightforward --

If the definition of f() contains an assignment to x, then
x is a local variable in f, unless x is declared nonlocal.

> To express this email in the positive form:
> 1. Reserved words should be real words.
> 2. The meaning of the word should be clear.
> 3. "Put statements in positive form."  (Strunk & White)
> 4. The word should sound good.
>
> global meets all of these requirements.

But it's the wrong word.  "Purple" also meets all of these requirements.

I'd rather accurately express the concept in the negative (the
true meaning really is in the negative: "don't make a new binding"),
than choose a simple-sounding word that is essentially a lie.

x = 1

def f(x):
print x

def g():
global x
x = 3
print x

The "x" used in g is not global at all -- it belongs to f.


-- ?!ng
___
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] Explicit Lexical Scoping (pre-PEP?)

2006-07-10 Thread Ka-Ping Yee
On Mon, 10 Jul 2006, Jeremy Hylton wrote:
> The current use of global meets the requirements.  The meaning there
> is clear, because global means global namespace.  If purple were a
> keyword, I wouldn't know what it means.  I was not proposing the use
> of global for some other meaning (and thought I made that clear in the
> remainder of the message).

My apologies.  I misunderstood you -- i thought you were suggesting
it as an alternative to "nonlocal".


-- ?!ng
___
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] Explicit Lexical Scoping (pre-PEP?)

2006-07-12 Thread Ka-Ping Yee
On Thu, 13 Jul 2006, Fredrik Lundh wrote:
> Boris Borcic wrote:
>
> >> note that most examples of this type already work, if the target type is
> >> mutable, and implement the right operations:
> >>
> >>   def counter(num):
> >>   num = mutable_int(num)
> >>   def inc():
> >>   num += 1
> >>   return num
> >>   return inc
[...]
> feel free to replace that += with an .add(1) method call; the point
> wasn't the behaviour of augmented assigment, the point was that that the
> most common use pattern involves *mutation* of the target object.

I don't think that's clear.  In:

a = 1
b = a
a += 1

it doesn't seem common to me that one would expect b to become 2.
Sometimes you want mutation, sometimes you don't.  I don't think
that necessarily follows from whether you are accessing a free
variable.


-- ?!ng
___
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] User's complaints

2006-07-13 Thread Ka-Ping Yee
On Thu, 13 Jul 2006, Wolfgang Langner wrote:
> On 7/13/06, Jeroen Ruigrok van der Werven <[EMAIL PROTECTED]> wrote:
> > Things that struck me as peculiar is the old:
> >
> > if __name__ == "__main__":
> > whatever()
> >
> > This is so out of tune with the rest of python it becomes a nuisance.
>
> It is not beautiful but very useful.
> In Python 3000 we can replace it with:
>
> @main
> def whatever():
> ...
>
> to mark this function as main function if module executed directly.

Why not simply:

def __main__():
...

or even pass in the command-line arguments:

def __main__(*args):
...

Having to 'import sys' to get at the command-line arguments always
seemed awkward to me.  'import sys' feels like it should be a
privileged operation (access to interpreter internals), and getting
the command-line args isn't privileged.


-- ?!ng
___
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] Handling of sys.args (Re: User's complaints)

2006-07-13 Thread Ka-Ping Yee
On Thu, 13 Jul 2006, Greg Ewing wrote:
> Would it help if sys were pre-imported into the builtins?
> Or do you think that args shouldn't live in sys at all?

I feel like the command-line arguments don't really belong in sys,
and i'd rather not have 'sys' pre-imported into the builtins.

I think of 'sys' as the place for sensitive interpreter internals
and the builtins as the place for harmless functions.  They're at
opposite ends of the scale -- 'sys' is the most privileged;
builtins are the least privileged.  From a security point of view,
'import' is the main way to get dangerous new functionality.
I realize 'open' breaks this concept, but it's nice to be able to
say, to a rough approximation, that preventing 'import' gives you
an interpreter that can do computations but isn't a security risk.

These are just my feelings -- i'm not sure how consistent this is
with the original intent of 'sys'.  I think it would be a quite
useful distinction to have, though.

> And while we're on the subject, anyone think it would
> be a good idea to drop the silly feature of having
> the program name as args[0]? You almost *never* want
> to treat it the same way as the rest of the args,
> so the first thing you always do is args[1:].

Starting the args array with the first argument (and putting
the program name somewhere else) seems Pythonic to me.


-- ?!ng
___
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] new security doc using object-capabilities

2006-07-19 Thread Ka-Ping Yee
On Wed, 19 Jul 2006, Brett Cannon wrote:
> I have decided to go with object-capabilities for
> securing interpreters.  I have rewritten my design doc from scratch and
> deleted the old one.  The new doc is named securing_python.txt and can be
> found through the svn web interface at
> http://svn.python.org/view/python/branches/bcannon-sandboxing/securing_python.txt?rev=50717&view=log.

This is amazing news!!  I'm going off to read your document right now.


-- ?!ng
___
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] uuid test suite failing

2006-07-29 Thread Ka-Ping Yee
On Fri, 28 Jul 2006, Neal Norwitz wrote:
> This only fixes 1 of the 2 failures in test_uuid.  The other one is
> due to _unixdll_getnode() failing.  This is because
> _uuid_generate_time is None because we couldn't find it in the uuid
> library.  This is just broken, not sure if it's the code or the test
> though.  We should handle the case if _uuid_generate_time and the
> others are None better.  I don't know what to do in this case.

The design intention is this: each of the various *_getnode() functions
is supposed to work on the platform for which it was written.  For
example, _windll_getnode() is supposed to work on Windows, and will
raise an exception on other platforms; if it raises an exception on
Windows, something is wrong (the code's expectations of the OS are
not met).  When uuid_generate_time is unavailable, _unixdll_getnode()
is supposed to fail.

The getnode() function is just supposed to get an available MAC
address; that's why it catches any exceptions raised by the
*_getnode() functions.


-- ?!ng
___
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] test_uuid

2006-07-29 Thread Ka-Ping Yee
On Sat, 29 Jul 2006, Neal Norwitz wrote:
> I just checked in a change to disable testing 2 uuid functions
> (_ifconfig_get_node and unixdll_getnode) that fail on many platforms.
> Here's the message:
>
> """
> Disable these tests until they are reliable across platforms. These
> problems may mask more important, real problems.
>
> One or both methods are known to fail on: Solaris, OpenBSD, Debian, Ubuntu.
> They pass on Windows and some Linux boxes.
> """

_ifconfig_get_node() should work on all Linuxes.  (Thanks for fixing
it to work on more types of Unix.)

It's okay for unixdll_getnode to fail when the necessary shared library
is not available.

Ideally, test_uuid should serve as a record of which platforms we expect
these routines to work on.  The uuid module as a whole isn't broken if
one of these routines fails; it just means that we don't have complete
platform coverage and/or test_uuid has inaccurate expectations of which
routines work on which platforms.


-- ?!ng
___
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] Rounding float to int directly (Re: struct module and coercing floats to integers)

2006-08-03 Thread Ka-Ping Yee
On Thu, 3 Aug 2006, Greg Ewing wrote:
> The time isn't the main issue. The main issue
> is that almost all the use cases for round()
> involve doing an int() on it afterwards.

That's my experience as well.  In my opinion, the purpose of round()
is most commonly described as "to make an integer".  So it should
yield an integer.

As other comments in this discussion imply, whether you want round()
to return an integer really depends on your intended audience and
their pattern of usage.

It seems to me that for round() to produce an integer is about as
intuitive as for 1/2 to produce 0.5.  That is, if you bring basic
mathematical intuition to the table instead of a background in how
C behaves, then "1/2" suggests one-half and "rounding" suggests
"convert to an integer".  If you have a background in programming
languages and you understand the value of type consistency, then
you would see why dividing integers should yield integers and
rounding floats should yield floats.

Since Python was indeed changed to make 1/2 evaluate to 0.5, that
suggests that it is Pythonic to target the first audience rather
than the second.  And that implies that it would also be Pythonic
to make round() return an int.


-- ?!ng
___
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] uuid module - byte order issue

2006-08-04 Thread Ka-Ping Yee
On Thu, 3 Aug 2006, Oren Tirosh wrote:
> The UUID module uses network byte order, regardless of the platform
> byte order. On little-endian platforms like Windows the ".bytes"
> property of UUID objects is not compatible with the memory layout

RFC 4122 says:

In the absence of explicit application or presentation protocol
specification to the contrary, a UUID is encoded as a 128-bit
object, as follows:

The fields are encoded as 16 octets, with the sizes and order of
the fields defined above, and with each field encoded with the
Most Significant Byte first (known as network byte order).

> Ka-Ping Yee writes* that the Windows UUID generation calls are not RFC
> 4122 compliant and have an illegal version field.
[...]
> If the correct byte order is used the UUIDs generated by Windows XP
> are valid version 4 UUIDs:

I see.  I stand corrected, then.  My interpretation of RFC 4122 would
be that the uuid.py module currently completely implements RFC 4122;
while Windows XP can't be said to violate RFC 4122, supporting this
alternative byte order would be an optional feature.

> The bytes property and bytes argument to the constructor should use
> the platform byte order.

I disagree; i think the main interface to uuid.py should behave
consistently independent of the platform, and should conform to the
default encoding in RFC 4122.  However, we could certainly consider
adding a 'bytes_le' field to support the functionality you describe.

I'll ask Anthony whether adding such a field would be permitted at
this stage of the release process.

> There is another issue with version 1 uuid generation:
> >>> len(set(uuid.uuid1() for i in range(1000)))
> 992
>
> The problem is that the random clock_seq field is only 14 bits long.
> If enough UUIDs are generated within the same system clock tick there
> will be collisions.

The clock field of the UUID has enough resolution to avoid collisions;
the problem you're describing is a limitation of the platform's clock,
not the UUID module.  It doesn't happen on Mac OS X, for example.

> Suggested solution: use the high-resolution of the
> time field (100ns) to generate a monotonically increasing timestamp
> that advances at least by 1 for each call, when time.time() returns
> the same value on subsequent calls.

That sounds like a fine solution to me.  I'll look into it.


-- ?!ng
___
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] uuid module - byte order issue

2006-08-19 Thread Ka-Ping Yee

On Fri, 4 Aug 2006, Oren Tirosh wrote:
> Compatibility with Windows "GUIDs" may be one of the most important
> use cases for the UUID module. It's important to resolve this or users
> will have unpleasant surprises. I did.
[...]
> alternatives:
>
> 1. Default is big endian byte order. Little endian is explicit.
> 2. Default is native byte order. Little endian and big endian are explicit.
> 3. No default. Little endian and big endian are both explicit.

I implemented and committed the first alternative above (as a new
attribute, 'bytes_le'), shortly before the freeze.


-- ?!ng
___
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] new security doc using object-capabilities

2006-09-06 Thread Ka-Ping Yee
Hi Brett,

Here are some comments on your proposal.  Sorry this took so long.
I apologize if any of these comments are out of date (but also look
forward to your answers to some of the questions, as they'll help
me understand some more of the details of your proposal).  Thanks!

> Introduction
> ///
[...]
> Throughout this document several terms are going to be used.  A
> "sandboxed interpreter" is one where the built-in namespace is not the
> same as that of an interpreter whose built-ins were unaltered, which
> is called an "unprotected interpreter".

Is this a definition or an implementation choice?  As in, are you
defining "sandboxed" to mean "with altered built-ins" or just
"restricted in some way", and does the above mean to imply that
altering the built-ins is what triggers other kinds of restrictions
(as it did in Python's old restricted execution mode)?

> A "bare interpreter" is one where the built-in namespace has been
> stripped down the bare minimum needed to run any form of basic Python
> program.  This means that all atomic types (i.e., syntactically
> supported types), ``object``, and the exceptions provided by the
> ``exceptions`` module are considered in the built-in namespace.  There
> have also been no imports executed in the interpreter.

Is a "bare interpreter" just one example of a sandboxed interpreter,
or are all sandboxed interpreters in your design initially bare (i.e.
"sandboxed" = "bare" + zero or more granted authorities)?

> The "security domain" is the boundary at which security is cared
> about.  For this dicussion, it is the interpreter.

It might be clearer to say (if i understand correctly) "Each interpreter
is a separate security domain."

Many interpreters can run within a single operating system process,
right?  Could you say a bit about what sort of concurrency model you
have in mind?  How would this interact (if at all) with use of the
existing threading functionality?

> The "powerbox" is the thing that possesses the ultimate power in the
> system.  In our case it is the Python process.

This could also be the application process, right?

> Rationale
> ///
[...]
> For instance, think of an application that supports a plug-in system
> with Python as the language used for writing plug-ins.  You do not
> want to have to examine every plug-in you download to make sure that
> it does not alter your filesystem if you can help it.  With a proper
> security model and implementation in place this hinderance of having
> to examine all code you execute should be alleviated.

I'm glad to have this use case set out early in the document, so the
reader can keep it in mind as an example while reading about the model.

> Approaches to Security
> ///
>
> There are essentially two types of security: who-I-am
> (permissions-based) security and what-I-have (authority-based)
> security.

As Mark Miller mentioned in another message, your descriptions of
"who-I-am" security and "what-I-have" security make sense, but
they don't correspond to "permission" vs. "authority".  They
correspond to "identity-based" vs. "authority-based" security.

> Difficulties in Python for Object-Capabilities
> //
[...]
> Three key requirements for providing a proper perimeter defence is
> private namespaces, immutable shared state across domains, and
> unforgeable references.

Nice summary.

> Problem of No Private Namespace
> ===
[...]
> The Python language has no such thing as a private namespace.

Don't local scopes count as private namespaces?  It seems clear
that they aren't designed with the intention of being exposed,
unlike other namespaces in Python.

> It also makes providing security at the object level using
> object-capabilities non-existent in pure Python code.

I don't think this is necessarily the case.  No Python code i've
ever seen expects to be able to invade the local scopes of other
functions, so you could use them as private namespaces.  There
are two ways i've seen to invade local scopes:

(a) Use gc.get_referents to get back from a cell object
to its contents.

(b) Compare the cell object to another cell object, thereby
causing __eq__ to be invoked to compare the contents of
the cells.

So you could protect local scopes by prohibiting these or by
simply turning off access to func_closure.  It's clear that hardly
any code depends on these introspection featuresl, so it would be
reasonble to turn them off in a sandboxed interpreter.  (It seems
you would have to turn off some introspection features anyway in
order to have reliable import guards.)

> Problem of Mutable Shared State
> ===
[...]
> Regardless, sharing of state that can be influenced by another
> interpreter is not safe for object-capabilities.

Yup.

> Threat Model
> ///

Re: [Python-Dev] Importing .pyc in -O mode and vice versa

2006-11-07 Thread Ka-Ping Yee
On Mon, 6 Nov 2006, Armin Rigo wrote:
> I know it's a discussion that comes up and dies out regularly.  My two
> cents is that it would be saner to have two separate concepts: cache
> files used internally by the interpreter for speed reasons only, and
> bytecode files that can be shipped and imported.

I like this approach.  Bringing source code and program behaviour closer
together makes debugging easier, and if someone wants to run Python
programs without source code, then EIBTI.


-- ?!ng
___
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] Python in first-year MIT core curriculum

2006-11-18 Thread Ka-Ping Yee
Wow.  Did you catch this news?

http://www-tech.mit.edu/V125/N65/coursevi.html

The first four weeks of C1 will be a lot like the first
four weeks of 6.001, Abelson said. The difference is
that programming will be done in Python and not Scheme.


-- ?!ng

___
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] a feature i'd like to see in python #2: indexing of match objects

2006-12-04 Thread Ka-Ping Yee
On Sun, 3 Dec 2006, Fredrik Lundh wrote:
> Martin v. Löwis wrote:
> > Well, the proposal was to interpret m[i] as m.group(i), for all values
> > of i. I can't see anything confusing with that.
>
> it can quickly become rather confusing if you also interpret m[:] as
> m.groups(), not to mention if you add len() and arbitrary slicing to
> the mix.  what about m[] and m[i,j,k], btw?

I'd say, don't pretend m is a sequence.  Pretend it's a mapping.
Then the conceptual issues go away.


-- ?!ng
___
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] Pydoc Improvements / Rewrite

2007-01-04 Thread Ka-Ping Yee
Hi Ron and Laurent,

I welcome attempts to improve pydoc (especially since I don't have
much time to work on improving it myself).  I definitely agree that
moving to CSS is long overdue, though I would like some input on
the style of the produced pages.

It's probably a good idea to explain how pydoc got to be the way
that it is.  The module boundary between inspect and pydoc is a
pretty clear one, intended to isolate pydoc from future changes
to Python's introspection features (such as attributes on internal
types like frames and functions).

On the other hand, I've often seen the question of why pydoc does
both text and HTML generation instead of generating some intermediate
data structure from which both kinds of output are produced.  The
answer is: I tried it.  The result turned out to be longer than
I expected and needlessly more complicated than what we have now.
It may be that a better job could have been done, but I think there
is a rational basis for why it turned out that way.

The Python objects themselves already are a data structure containing
all of the information we need.  I discovered that translating this
data structure into another data structure and then producing text
or HTML was more work than simply producing text or HTML.  With CSS,
the last step gets even easier and so the intermediate stage becomes
even less necessary.  Also, the intermediate step required me to
essentially invent an API, and I decided that I trusted the stability
of Python's API more than that of some API I invented just for this.

This is not to say that text and HTML generation can't be separated;
it's just a caution against attempting to overgeneralize by creating
an intermediate format.  I'm glad you backed away from XML (or I'd
have warned you that processing the XML would be a lot of extra work).

The inspect module was intended to pull out as much as possible of
the extraction functionality that's shared by the text and HTML
documentation generators.  But pydoc is still big.  At the time I was
proposing pydoc for addition to the standard library, I didn't want
to pollute the top-level module namespace with too many names, so I
tried hard to minimize the number of modules.  And of course it has
grown since then with bits of new functionality and support for new
language features in Python.

But now if a package is being considered, it makes sense to split
out some of the pieces (as you have done), such as the web server,
the search function, and the interactive interpreter help prompt.
It may even enable pydoc to provide search from the interactive help
prompt, which would be a nice feature!  The package could contain
several modules for ease of maintenance, while still providing a
single, convenient command for running pydoc from the Unix prompt.


-- ?!ng
___
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] Pydoc Improvements / Rewrite

2007-01-05 Thread Ka-Ping Yee
On Thu, 4 Jan 2007, Talin wrote:
> One issue that needs to be worked out, however, is the division of
> responsibility between markup processor and output formatter. Does a
> __markup__ plugin do both jobs, or does it just do parsing, and leave
> the formatting of output to the appropriate HTML / text output module?
> How does the HTML output module know how to handle non-standard metadata?
[...]
> I guess the markup processor has to deliver some kind of DOM tree, which
> can be rendered either into text or into HTML. CSS can take over from
> that point on.

If the markup processor is going to deliver a tree, let me just point
out that it would be a pretty major project to define the format of
that tree -- about as large as inventing ReST or any other markup
language, except that the design of such an intermediate format has
to foresee future changes to the input and be flexible enough to target
multiple output formats.  The design would also have to tackle the
question of whether the intermediate format should contain semantic
information (what about cross-references?) and what types of such
information should be allowed (e.g. names of modules, arguments,
exceptions, Python expressions, etc.)


-- ?!ng
___
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] datetime module enhancements

2007-03-09 Thread Ka-Ping Yee
On Sat, 10 Mar 2007, Greg Ewing wrote:
> Collin Winter wrote:
> > Treat dates as if they have a time-part of midnight. This is my preferred
> > solution, and it is already what the datetime module does, for example,
> > when subtracting two dates.
>
> Does it really? Seems to me you can pick any time of day
> to be the representative time and get the same result
> when subtracting two dates, as long as you pick the same
> one for both dates. So it's not really assuming anything
> here.

It certainly gives that appearance:

>>> from datetime import datetime
>>> datetime(2007, 1, 2) - datetime(2007, 1, 1, 0, 0, 0)
datetime.timedelta(1)
>>> str(_)
'1 day, 0:00:00'

The behaviour to the end user exposes the midnight assumption,
regardless whether it's explained by saying the constructor
makes the assumption or the subtraction makes the assumption.


-- ?!ng
___
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] PEP 30XZ: Simplified Parsing

2007-05-02 Thread Ka-Ping Yee
I fully support the removal of implicit string concatenation
(explicit is better than implicit; there's only one way to do it).

I also fully support the removal of backslashes for line continuation
of statements (same reasons).  (I mean this as distinct from line
continuation within a string; that's a separate issue.)


-- ?!ng
___
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] The docs, reloaded

2007-05-19 Thread Ka-Ping Yee
On Sat, 19 May 2007, Georg Brandl wrote:
> For the impatient: the result can be seen at .

This is extremely impressive.  Thank you for this work!

If all the documentation is generated from a base format that is
closer to text (reST instead of LaTeX), that will make it easier
for volunteers to read diffs, make edits, and contribute patches.

I agree that interactivity (online commenting and editing) will
be a huge advantage.

I could imagine this heading in a Wiki-like direction -- where a
particular version is tagged as the official revision shipped
with a particular Python release, but everyone can make edits
online to yield new versions, eventually yielding the revision
that will be released with the next Python release.


-- ?!ng
___
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] The docs, reloaded

2007-05-22 Thread Ka-Ping Yee
On Tue, 22 May 2007, Steve Holden wrote:
> But doesn't *everyone* now know that documentation contributions don't
> have to be marked up? It's certainly been said enough. Maybe that fact
> should be more prominent in the documentation? Then we'll just have to
> worry about getting people to read it ...

I think the issue is instant gratification.  You don't get the
satisfaction of seeing your changes unless you're willing to write
them in LaTeX, and that's a pretty big barrier -- a lot of what
motivates open source volunteers is the sense of fulfillment.

(Hence, by the same nature, Wiki-like editing with instant changes
visible online will probably greatly increase contributions.)


-- ?!ng
___
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] Shorthand for lambda

2005-03-23 Thread Ka-Ping Yee
Hey folks,

I'm sitting over here in the AppleScript talk and Jacob is explaining a
module called 'appscript' that interfaces to the Apple Events system.

What caught my eye was this example:

from appscript import *
ab = app('Address Book')
people = ab.people.filter(its.emails != [])

That last line asks the Address Book to select only entries with
e-mail addresses.  The weird 'its' object comes from the appscript
module -- asking for its properties and using operators causes it
to set up thunks for you.

It dawned on me that you could use this idea to make the whole
filter/lambda experience vastly more pleasant.  I whipped up a quick
implementation:

>>> from placeholder import _
>>> numbers = [5, 9, 56, 34, 1, 24, 37, 89]
>>> filter(_ < 30, numbers)
[5, 9, 1, 24]
>>> map(_ + 10, numbers)
[15, 19, 66, 44, 11, 34, 47, 99]
>>>

Look ma, no lambdas!

I bet someone has already done this before, right?


-- ?!ng
___
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] Shorthand for lambda

2005-03-23 Thread Ka-Ping Yee
On Wed, 23 Mar 2005, Josiah Carlson wrote:
> Paul Moore <[EMAIL PROTECTED]> wrote:
> > I thought about it, but couldn't convince myself that it would work
> > properly in all cases. I was thinking in terms of operator overloading
> > of everything possible - how did you do it?
>
> PyTables allows something very similar for "in-kernel" searches of data,
> but only on a single constraint.  I would imagine that Ka-Ping did it by
> only allowing a single operation per item.

You can do more than one operation, but the usage is still quite limited.
The item placeholder must be the first operand for it to work.

>>> numbers = [3, 8, 4, 1, 2]
>>> filter(_ < 5, numbers)
[3, 4, 1, 2]
>>> map(_ * 5 + 7, numbers)
[10, 15, 11, 8, 9]

I tried implementing __len__, but that doesn't work because Python
enforces a type restriction.

>>> words = 'lovely spam and eggs'.split()
>>> filter(len(_) == 4, words)
Traceback (most recent call last):
  File "", line 1, in ?
TypeError: __len__() should return an int

__getitem__ and __getattr__ mostly work.  However, in order to call a
method on the placeholder you have to add an underscore to distinguish
it from retrieving an attribute.

>>> filter(_.endswith_('s'), words)
['eggs']

You can check out http://zesty.ca/python for the gory details.

As Jeremy wrote, the proper way to do map and filter is to use a
list comprehension, so these are bad examples.  The original
motivation was to provide a way to write lambda expressions for
cases where you aren't doing map or filter.  For that, it works,
but only in limited cases.

I realize this isn't that practical.  It's mainly for your
amusement -- yet another in a long tradition of hacks that use
operator overloading to hijack the Python parser.  (Also a long
tradition of me doing silly things in public.)


-- ?!ng
___
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] Re: Shorthand for lambda

2005-03-23 Thread Ka-Ping Yee
On Wed, 23 Mar 2005, Reinhold Birkenfeld wrote:
> What does you implementation do for this:
>
> >>> somevar = False
> >>> filter(_ and False, numbers)

It fails.  (For the same reason that __len__ doesn't work --
Python insists that __nonzero__ must return an int.)  Though
i must say i have no idea what you are trying to do here.
If you filter on False, you'll always get an empty list.


-- ?!ng
___
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-08 Thread Ka-Ping Yee
On Fri, 8 Apr 2005, Eyal Lotem wrote:
> I would like to experiment with security based on Python references as
> security capabilities.

This is an interesting and worthwhile thought.  Several people
(including myself) have talked about the possibility of doing
this in the past.  I believe the two problems you mention can be
addressed without modifying the Python core.

> * There is no way to create secure proxies because there are no
> private attributes.

Attributes are not private, but local variables are.  If you use
lexical scoping to restrict variable access (as one would in
Scheme, E, etc.) you can create secure proxies.  See below.

> * Lots of Python objects are reachable unnecessarily breaking the
> principle of least privelege (i.e: object.__subclasses__() etc.)

True.  However, Python's restricted execution mode prevents access
to these attributes, allowing you to enforce encapsulation.  (At
least, that is part of the intent of restricted execution mode,
though currently we do not make official guarantees about it.)
Replacing __builtins__ activates restricted execution mode.

Here is a simple facet function.

def facet(target, allowed_attrs):
class Facet:
def __repr__(self):
return '' % (allowed_attrs, target)
def __getattr__(self, name):
if name in allowed_attrs:
return getattr(target, name)
raise NameError(name)
return Facet()

def restrict():
global __builtins__
__builtins__ = __builtins__.__dict__.copy()

# Here's an example.

list = [1, 2, 3]
immutable_facet = facet(list, ['__getitem__', '__len__', '__iter__'])

# Here's another example.

class Counter:
def __init__(self):
self.n = 0

def increment(self):
self.n += 1

def value(self):
return self.n

counter = Counter()
readonly_facet = facet(counter, ['value'])

If i've done this correctly, it should be impossible to alter the
contents of the list or the counter, given only the immutable_facet
or the readonly_facet, after restrict() has been called.

(Try it out and let me know if you can poke holes in it...)

The upshot of all this is that i think you can do secure programming
in Python if you just use a different style.  Unfortunately, this
style is incompatible with the way classes are usually written in
Python, which means you can't safely use much of the standard library,
but i believe the language itself is not fatally flawed.


-- ?!ng
___
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] Re: Security capabilities in Python

2005-04-09 Thread Ka-Ping Yee
On Sat, 9 Apr 2005, Fredrik Lundh wrote:
> Ka-Ping wrote:
> > counter = Counter()
> > readonly_facet = facet(counter, ['value'])
> >
> > If i've done this correctly, it should be impossible to alter the
> > contents of the list or the counter, given only the immutable_facet
> > or the readonly_facet, after restrict() has been called.
>
> I'm probably missing something, but a straightforward reflection
> approach seems to work on my machine:

That's funny.  After i called restrict() Python didn't let me get im_self.

>>> restrict()
>>> readonly_facet.value
>
>>> readonly_facet.value.im_self
Traceback (most recent call last):
  File "", line 1, in ?
RuntimeError: restricted attribute
>>>

It doesn't matter if i make the facet before or after restrict().

>>> restrict()
>>> rf2 = facet(counter, ['value'])
>>> rf2.value
>
>>> rf2.value.im_self
Traceback (most recent call last):
  File "", line 1, in ?
RuntimeError: restricted attribute
>>>

I'm using

Python 2.3 (#1, Sep 13 2003, 00:49:11)
[GCC 3.3 20030304 (Apple Computer, Inc. build 1495)] on darwin


-- ?!ng
___
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-09 Thread Ka-Ping Yee
On Sat, 9 Apr 2005, Jp Calderone wrote:
>   Does using the gc module to bypass this security count?  If so:
>
> [EMAIL PROTECTED]:~$ python -i facet.py
> >>> import gc
> >>> c = readonly_facet.__getattr__.func_closure[1]
> >>> r = gc.get_referents(c)[0]
> >>> r.n = 'hax0r3d'
> >>> readonly_facet.value()
> 'hax0r3d'
> >>>

You can't get func_closure in restricted mode.  (Or at least, i can't,
using the Python included with Mac OS 10.3.8.)

>>> restrict()
>>> readonly_facet.__getattr__.func_closure
Traceback (most recent call last):
  File "", line 1, in ?
RuntimeError: restricted attribute
>>>

Even though this particular example doesn't work in restricted mode,
it's true that the gc module violates capability discipline, and you
would have to forbid its import.  In any real use case, you would have
to restrict imports anyway to prevent access to sys.modules or loading
of arbitrary binaries.

For a version that restricts imports, see:

http://zesty.ca/python/facet.py

Let me know if you figure out how to defeat that.

(This is a fun exercise, but with a potential purpose -- it would be
nice to have a coherent story on this for Python 3000, or maybe even
Python 2.x.)


-- ?!ng
___
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-09 Thread Ka-Ping Yee
On Sat, 9 Apr 2005, Michael Hudson wrote:
> The funniest I know is part of PyPy:
>
> def extract_cell_content(c):
> """Get the value contained in a CPython 'cell', as read through
> the func_closure of a function object."""
> # yuk! this is all I could come up with that works in Python 2.2 too
> class X(object):
> def __eq__(self, other):
> self.other = other
> x = X()
> x_cell, = (lambda: x).func_closure
> x_cell == c
> return x.other

That's pretty amazing.

> It would be unfortunate for PyPy (and IMHO, very un-pythonic) if this
> process became impossible.

Not a problem.  func_closure is already a restricted attribute.

IMHO, the clean way to do this is to provide a built-in function to
get the cell content in a more direct and reliable way, and then
put that in a separate module with other interpreter hacks.

That both makes it easier to do stuff like this, and easier to prevent
it simply by forbidding import of that module.


-- ?!ng
___
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-09 Thread Ka-Ping Yee
On Sat, 9 Apr 2005, James Y Knight wrote:
> You can protect against this, too, but it does show that it's *really*
> hard to get restricting code right...

Good point.  If you can't trust ==, then you're hosed.

> I'm of the opinion that it's not
> really worth it -- you should just use OS protections.

This i disagree with, however.  OS protections are a few orders of
magnitude more heavyweight and vastly more error-prone than using a
language with simple, clear semantics.

Predictable code behaviour is good.


-- ?!ng
___
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-13 Thread Ka-Ping Yee
On Sun, 10 Apr 2005, Eyal Lotem wrote:
> It may be really hard to get it right, unless we are overlooking some simple
> solution.

To "get it right", you at least need to know exactly what your
operators mean.  I messed up because i failed to realize that
'==' can be redefined, and 'in' depends on '==' to work properly.

> What about implementing the facet in C? This could avoid the class of
> problems you have just mentioned.

I don't think that's a good solution.  A facet is just one basic
programming pattern that you can build in a capability system; it
would be silly to have to go back to C every time you wanted to
build some other construct.  A better way would be to start with
capabilities that behave simply and correctly; then you can build
whatever you want.


-- ?!ng
___
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] Check out a new way to read threaded conversations.

2005-04-14 Thread Ka-Ping Yee
I hope you will not mind too much if I ask a small favor.  Sorry
for this off-topic post.

I am working on a new design for displaying online conversations.
(Some of you saw this at PyCon.)  I'm conducting a short survey to
gather some opinions on the current design.

If you have just a few minutes to spare, would you please visit:

http://zesty.ca/threadmap/pydev.cgi

You'll see a new way of looking at this discussion list that you
may find pretty interesting.  I look forward to learning what
you think of it.

I am very grateful for your time and assistance.

(If you reply to this message, please reply to me only -- I don't
want to clutter up python-dev with lots of off-topic messages.)


-- Ping
___
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] anonymous blocks

2005-04-21 Thread Ka-Ping Yee
On Thu, 21 Apr 2005, Guido van Rossum wrote:
> Perhaps it could be even simpler:
>
> [assignment_target '=']* expr ':' suite
>
> This would just be an extension of the regular assignment statement.

It sounds like you are very close to simply translating

expression... function_call(args):
suite

into

expression... function_call(args)(suitefunc)

If i understand what you proposed above, you're using assignment
as a special case to pass arguments to the inner suite, right?  So:

inner_args = function_call(outer_args):
suite

becomes:

def suitefunc(inner_args):
suite
function_call(outer_args)(suitefunc)

?

This could get a little hard to understand if the right-hand side
of the assignment is more complex than a single function call.
I think the meaning would be unambiguous, just non-obvious.  The
only interpretation i see for this:

x = spam('foo') + eggs('bar'):
suite

is this:

def suitefunc(x):
suite
spam('foo') + eggs('bar')(suitefunc)

but that could seem a little too mysterious.  Or you could (in a
later compiler pass) forbid more complex expressions on the RHS.

On another note, would there be any difference between

x = spam():
suite

and

x = spam:
suite

?


-- ?!ng
___
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] anonymous blocks

2005-04-21 Thread Ka-Ping Yee
On Thu, 21 Apr 2005, Guido van Rossum wrote:
> The use cases where the block actually returns a value are probably
> callbacks for things like sort() or map(); I have to admit that I'd
> rather keep lambda for these (and use named functions for longer
> blocks) than introduce an anonymous block syntax that can return
> values!

It seems to me that, in general, Python likes to use keywords for
statements and operators for expressions.

Maybe the reason lambda looks like such a wart is that it uses a
keyword in the middle of an expression.  It also uses the colon
*not* to introduce an indented suite, which is a strange thing to
the Pythonic eye.  This suggests that an operator might fit better.

A possible operator for lambda might be ->.

sort(items, key=x -> x.lower())

Anyway, just a thought.


-- ?!ng
___
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] Re: anonymous blocks

2005-04-25 Thread Ka-Ping Yee
On Mon, 25 Apr 2005, Brett C. wrote:
> It executes the body, calling next() on the argument name on each
> time through until the iteration stops.

There's a little more to it than that.  But on the whole I do support
the goal of finding a simple, short description of what this construct
is intended to do.  If it can be described accurately in a sentence
or two, that's a good sign that the semantics are sufficiently clear
and simple.

> I like "managers" since they are basically managing resources
> most of the time for the user.

No, please let's not call them that.  "Manager" is a very common word
to describe all kinds of classes in object-oriented designs, and it is
so generic as to hardly mean anything.  (Sorry, i don't have a better
alternative at the moment.)


-- ?!ng
___
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] Re: anonymous blocks

2005-04-28 Thread Ka-Ping Yee
On Thu, 28 Apr 2005, Greg Ewing wrote:
> If such an explanation can't be found, I strongly suspect
> that this doesn't correspond to a cohesive enough concept
> to be made into a built-in language feature. If you can't
> give a short, understandable explanation of it, then it's
> probably a bad idea.

In general, i agree with the sentiment of this -- though it's
also okay if there is a way to break the concept down into
concepts that *are* simple enough to have short, understandable
explanations.


-- ?!ng
___
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] PEP 340: syntax suggestion - try opening(filename) as f:

2005-04-29 Thread Ka-Ping Yee
On Fri, 29 Apr 2005, Guido van Rossum wrote:
> The more I think about it the more I like having no keyword at all
> (see other messages).

I hope you'll reconsider this.  I really think introducing a new
statement requires a keyword, for pedagogical reasons as well as
readability and consistency.  Here's my pitch:

All the statements in Python are associated with keywords, except
for assignment, which is simple and extremely common.  I don't
think the block statement is simple enough or common enough for
that; its semantics are much too significant to be flagged only
by a little punctuation mark like a colon.

I can empathize with wanting to avoid a keyword in order to
avoid an endless debate about what the keyword will be.  But
that debate can't be avoided anyway -- we still have to agree
on what to call this thing when talking about it and teaching it.

The keyword gives us a name, a conceptual tag from which to hang
our knowledge and discussions.  Once we have a keyword, there
can be no confusion about what to call the construct.  And if
there is a distinctive keyword, a Python programmer who comes
across this unfamiliar construct will be able to ask someone
"What does this 'spam' keyword mean?" or can search on Google for
"Python spam" to find out what it means.  Without a keyword,
they're out of luck.  Names are power.


-- ?!ng
___
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] Keyword for block statements

2005-04-30 Thread Ka-Ping Yee
On Fri, 29 Apr 2005, Phillip J. Eby wrote:
> At 08:21 PM 4/29/05 -0500, Ka-Ping Yee wrote:
> >All the statements in Python are associated with keywords, except
> >for assignment, which is simple and extremely common.  I don't
> >think the block statement is simple enough or common enough for
> >that; its semantics are much too significant to be flagged only
> >by a little punctuation mark like a colon.
>
> Don't forget the 'as' clause.

It's optional, and you have to skip an arbitrarily long expression
to get to it.

> >if there is a distinctive keyword, a Python programmer who comes
> >across this unfamiliar construct will be able to ask someone
> >"What does this 'spam' keyword mean?" or can search on Google for
> >"Python spam" to find out what it means.  Without a keyword,
> >they're out of luck.  Names are power.
>
> help(synchronized) or help(retry) would doubtless display useful
> information.

The programmer who writes the function used to introduce a block
can hardly be relied upon to explain the language semantics.  We
don't expect the docstring of every class to repeat an explanation
of Python classes, for example.  The language reference manual is
for that; it's a different level of documentation.

> Conversely, try Googling for Python's "for" or "if" keywords,
> and see if you get anything useful -- I didn't.

I tried some of my favourite Python keywords :) and found that the
following searches all successfully turn up information on the
associated kinds of Python statements in the first couple of hits:

python if
python else
python del
python while
python assert
python yield
python break
python continue
python pass
python raise
python try
python finally
python class
python for statement
python return statement
python print statement


-- ?!ng
___
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] PEP 340: Breaking out.

2005-05-04 Thread Ka-Ping Yee
On Wed, 4 May 2005, Shane Hathaway wrote:
> I'd like to suggest a small language enhancement that would fix this
> example.  Allow the break and continue statements to use a keyword,
> either "for" or "while", to state that the code should break out of both
> the block statement and the innermost "for" or "while" statement.  The
> example above would change to:
>
> for name in filenames:
> opening(name) as f:
> if f.read(2) == 0xFEB0:
> break for

This is very elegant.  It works beautifully with "break", though at
first that natural analogs "continue for", "continue while" appear to
conflict with Guido's proposed extension to "continue".

But if we choose the keyword "with" to introduce an anonymous block,
it comes out rather nicely:

continue with 2

That's easier to read than "continue 2", in my opinion.  (If it's not
too cute for you.)

Anyway, i like the general idea of letting the programmer specify
exactly which block to break/continue, instead of leaving it looking
ambiguous.  Explicit is better than implicit, right?


-- ?!ng
___
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] PEP 340 -- loose ends

2005-05-04 Thread Ka-Ping Yee
Reinhold Birkenfeld wrote:
> There is one problem with using no keyword: You cannot use arbitrary
> expressions in the new statement.
[...]
> resource = opening("file.txt")
> resource:
> (...)
>
> The latter would have to be forbidden.

Noam Raphael wrote:
> Can you explain why it would have to be forbidden please?

Reinhold Birkenfeld wrote:
> Well, with it you could create suites with _any_ introducing
> identifier. Consider:
>
> with:
> (...)
>
> synchronized:
> (...)
>
> try:
> (...)
>
> transaction:
> (...)
>
> Do you understand my concern? It would be very, very hard to discern
> these "user-defined statements" from real language constructs.

I think part of the debate is about whether that's good or bad.
I happen to agree with you -- i think a keyword is necessary --
but i believe some people see an advantage in having the flexibility
to make a "real-looking" construct.

As i see it the argument boils down to: Python is not Lisp.

There are good reasons why the language has keywords, why it
distinguishes statements from expressions, uses indentation, and
so on.  All of these properties cause Python programs to be made
of familiar and easily recognizable patterns instead of degenerating
into a homogeneous pile of syntax.


-- ?!ng
___
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] PEP 340: Breaking out.

2005-05-05 Thread Ka-Ping Yee
On Thu, 5 May 2005, Delaney, Timothy C (Timothy) wrote:
> Aahz wrote:
> > My standard workaround is using exceptions, but I'm not sure how that
> > interacts with a block:
> >
> > try:
> > for name in filenames:
> > with opened(name) as f:
> > if f.read(2) == 0xFEB0:
> > raise Found
> > except Found:
> > pass
>
> For any sane block iterator, it will work as expected. However, an evil
> block iterator could suppress the `Found` exception.

I was thinking about more use cases for the block statement,
and one of the ideas was an exception-logging block:

def logged_exceptions(file):
try:
yield
except Exception, value:
file.write(repr(value) + '\n')

block logged_exceptions(file):
do stuff
do stuff
do stuff

...but then i wasn't sure whether this was supposed to be
possible in the proposed scheme.  Currently, generators do not
catch exceptions raised in the code that they yield values to,
because the target of the yield is in a higher stack frame.

This makes sense from a language design perspective, since
there is no try...finally construct lexically wrapping the thing
that raises the exception.  In current Python, for example,
this says 'caught outside generator':

def spam_generator():
try:
yield 'spam'
except ValueError, value:
print 'caught inside generator'

try:
g = spam_generator()
i = g.next()
raise ValueError(5)
except ValueError, value:
print 'caught outside generator'

But now i'm confused.  Tim's words above seem to suggest that
the interior generator could actually catch exceptions raised
outside, by whatever is on the other end of the yield.

So, could a block statement really catch that exception inside?
I think it might be too confusing if it were possible.


-- ?!ng
___
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] PEP 340: Breaking out.

2005-05-05 Thread Ka-Ping Yee
On Fri, 6 May 2005, Nick Coghlan wrote:
> Either way, my latest and greatest version of the non-looping block statement
> semantics can be found here:
> http://mail.python.org/pipermail/python-dev/2005-May/053400.html

My mind is not made up, but i did find this proposal pretty appealing.
I'd love to see it described in a complete PEP as that would make it
easier to compare directly -- in particular, comparing a list of use
cases to the one in PEP 340 would be very valuable to this discussion.


-- ?!ng
___
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] Breaking off Enhanced Iterators PEP from PEP 340

2005-05-06 Thread Ka-Ping Yee
On Fri, 6 May 2005, Guido van Rossum wrote:
> There's one alternative possible (still orthogonal to PEP 340):
> instead of __next__(), we could add an optional argument to the next()
> method, and forget about the next() built-in.

I prefer your original proposal.  I think this is a good time to switch
to next().  If we are going to change the protocol, let's do it right.


-- ?!ng
___
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] Merging PEP 310 and PEP 340-redux?

2005-05-12 Thread Ka-Ping Yee
On Wed, 11 May 2005, Guido van Rossum wrote:
> [Steven Bethard]
> > exc = ()
> > try:
> > try:
> > BLOCK1
> > except:
> > exc = sys.exc_info()
> > finally:
> > stmt_exit(*exc)
> >
> > would this make any of the examples impossible to write?  All you have
> > to do to suppress an exception is to not reraise it in __exit__.
>
> But this use case would contain a trap for the unwary user who is
> writing an __exit__ method -- they have to remember to re-raise an
> exception if it was passed in, but that's easy to forget (and slightly
> tricky since you have to check the arg count or whether the first
> argument is not None).

Then wouldn't it be simplest to separate normal exit from exceptional
exit?  That is, split __exit__ into __except__ and __finally__.  If
__except__ is defined, then it handles the exception, otherwise the
exception is raised normally.

> class locking:
> def __init__(self, lock): self.lock = lock
> def __enter__(self): self.lock.acquire()
> def __exit__(self, *args): self.lock.release()

Having __exit__ take varargs is a signal to me that it mashes together
what really are two different methods.


-- ?!ng
___
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] "with" use case: exception chaining

2005-05-12 Thread Ka-Ping Yee
> - Ka-ping Yee thinks we need separate entry points for the exceptional
>   and the normal termination case.  I disagree; this would end up in
>   unnecessary duplication of code (or boilerplate to equate the two
>   methods) in most cases.  The whole *point* is that finally gets to
>   do its clean-up act regardless of whether an exception is being
>   processed or not.

Okay, let me back up for a second.  My suggestion responded to your
reply to Steve Bethard's example about exception handling.  The point
of the suggestion is that *if* we are going to let "with" do exception
handling, it should be done in a separate method.  I didn't mean to
imply that __finally__ should be skipped.

This brings us back to the question of whether "with" should be able
to handle exceptions.  On this, you wrote:

> For try/finally we have a large body of use cases that just scream for
> abstraction. I'm not convinced that we have the same for try/except.

So let's look at some use cases.  I've thought of two; the first one is
nice and simple, and the second one is messier so i'll discuss it in a
separate message.

Example 1: Exception Chaining.

As has been previously discussed, the information from an exception can
be lost when the handling of the exception runs into a problem.  It is
often helpful to preserve the original reason for the problem.

Suppose, by convention, that the "reason" attribute on exception objects
is designated for this purpose.  The assignment of this attribute can be
conveniently abstracted using a "with" clause as follows:

try:
# ... risky operation ...
except:
with reason(sys.exc_info()):
# ... cleanup ...

The "with reason" construct would be implemented like this:

class reason:
def __init__(self, etype, evalue, etb):
self.reason = etype, evalue, etb

def __except__(self, etype, evalue, etb):
evalue.reason = self.reason
raise etype, evalue, etb

(Other possible names for "reason" might be "cause" or "context".)


-- ?!ng
___
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] "with" use case: replacing a file

2005-05-12 Thread Ka-Ping Yee
Here's another use case to think about.

Example 2: Replacing a File.

Suppose we want to reliably replace a file.  We require that either:

(a) The file is completely replaced with the new contents;
 or (b) the filesystem is unchanged and a meaningful exception is thrown.

We'd like to be able to write this conveniently as:

with replace(filename) as file:
...
file.write(spam)
...
file.write(eggs)
...

To make sure the file is never only partially written, we rely on the
filesystem to rename files atomically, so the basic steps (without
error handling) look like this:

tempname = filename + '.tmp'
file = open(tempname, 'w')
...
file.write(spam)
...
file.close()
os.rename(tempname, filename)

We would like to make sure the temporary file is cleaned up and no
filehandles are left open.  Here's my analysis of all the execution
paths we need to cover:

1. +open +write +close +rename
2. +open +write +close -rename ?remove
3. +open +write -close ?remove
4. +open -write +close ?remove
5. +open -write -close ?remove
6. -open

(In this list, + means success, - means failure, ? means don't care.)

When i add error handling, i get this:

tempname = filename + '.tmp'
file = open(tempname, 'w') # okay to let exceptions escape
problem = None
try:
try:
...
file.write(spam)
...
except:
problem = sys.exc_info()
raise problem
finally:
try:
file.close()
except Exception, exc:
problem, problem.reason = exc, problem
if not problem:
try:
os.rename(tempname, filename)
except Exception, exc:
problem, problem.reason = exc, problem
if problem:
try:
os.remove(tempname)
except Exception, exc:
problem, problem.reason = exc, problem
raise problem

In this case, the implementation of replace() doesn't require a
separate __except__ method:

class replace:
def __init__(self, filename):
self.filename = filename
self.tempname = '%s.%d.%d' % (self.filename, os.getpid(), id(self))

def __enter__(self):
self.file = open(self.tempname, 'w')
return self

def write(self, data):
self.file.write(data)

def __exit__(self, *problem):
try:
self.file.close()
except Exception, exc:
problem, problem.reason = exc, problem
if not problem: # commit
try:
os.rename(tempname, filename)
except Exception, exc:
problem, problem.reason = exc, problem
if problem: # rollback
try:
os.remove(tempname)
except Exception, exc:
problem, problem.reason = exc, problem
raise problem

This is all so intricate i'm not sure if i got it right.  Somebody
let me know if this looks right or not.  (In any case, i look forward
to the day when i can rely on someone else to get it right, and they
only have to write it once!)


-- ?!ng
___
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] "with" use case: exception chaining

2005-05-12 Thread Ka-Ping Yee
On Thu, 12 May 2005, Guido van Rossum wrote:
> [Ka-Ping Yee]
> > Example 1: Exception Chaining.
> >
> > As has been previously discussed, the information from an exception can
> > be lost when the handling of the exception runs into a problem.  It is
> > often helpful to preserve the original reason for the problem.
> [example deleted]
>
> This problem is universal -- every except clause (in theory) can have
> this problem. I'd much rather deal with this in a systematic way in
> the Python VM's exception handling machinery.

That's reasonable.  Unless another use case comes up, i withdraw my
suggestion for a separate __except__ method.

I hope the examples were interesting, anyhow.


-- ?!ng
___
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] Tidier Exceptions

2005-05-12 Thread Ka-Ping Yee
It occurred to me as i was messing around with handling and re-raising
exceptions that tossing around these (type, value, traceback) triples
is irritating and error-prone.

How about just passing around a single value?  All we'd have to do is
put the traceback in value.traceback.

Implementation:

- "raise Class" and "raise Class, string" automatically set
  the .traceback attribute on the new instance of Class.

- "raise instance" automatically sets the .traceback attribute
  on the instance unless it already has one.

The behaviour of "except" and "sys.exc_*" could remain unchanged.
"raise t, v, tb" would eventually be deprecated in favour of "raise v".


-- ?!ng
___
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] Chained Exceptions

2005-05-12 Thread Ka-Ping Yee
Suppose exceptions have an optional "context" attribute, which is
set when the exception is raised in the context of handling another
exception.  Thus:

def a():
try:
raise AError
except:
raise BError

yields an exception which is an instance of BError.  This instance
would have as its "context" attribute an instance of AError.

Or, in a more complex case:

def compute():
try:
1/0
except Exception, exc:
log(exc)

def log(exc):
try:
file = open('error.log')   # oops, forgot 'w'
print >>file, exc
file.close()
except:
display(exc)

def display(exc):
print 'Aaaack!', ex# oops, misspelled 'exc'

Today, this just gives you a NameError about 'ex'.

With the suggested change, you would still get a NameError about 'ex';
its 'context' attribute would show that it occurred while handling an
IOError on error.log; and this IOError would have a 'context' attribute
containing the original ZeroDivisionError that started it all.

What do you think?


-- ?!ng
___
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] Chained Exceptions

2005-05-12 Thread Ka-Ping Yee
On Thu, 12 May 2005, Brett C. wrote:
> Guido van Rossum wrote:
> > Try to come up with a precise specification and we'll talk.
>
> If a new exception is raised (e.g., not a bare 'raise') while a current
> exception is active (e.g., sys.exc_info() would return something other
> than a tuple of None), then the new exception is made the active exception
> and the now old exception is assigned to the new exception's context
> attribute to be the old exception.

Yeah, i think that's basically all there is to it.  I'll go have a peek
at the interpreter to see if i'm forgetting something.


-- ?!ng
___
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] Chained Exceptions

2005-05-12 Thread Ka-Ping Yee
On Thu, 12 May 2005, Guido van Rossum wrote:
> Define "raise". Does that involve a raise statement?

Not necessarily; it could be a raise statement or an inadvertently
triggered exception, such as in the example code i posted.

> What about 1/0?

That counts.

> What if you call a method that executes 1/0?

That counts too.

> What if that method catches that exception?

Did you mean something like this?

def handle():
try:
open('spamspamspam')
except:
catchit()
# point A
...

def catchit():
try:
1/0
except:
pass

Then there's no exception to propagate, so it doesn't matter.
Once we're get to point A, the division by zero is long forgotten.

> What about the StopIteration conceptually
> raised by next() called by the for-loop implementation?

It's "caught" by the for-loop, so to speak, so it never gets out.
Conceptually, the for-loop expands to:

while 1:
try:
item = it.next()
except StopIteration:
break
# body of loop goes here

The 'break' can't possibly cause an exception, so the StopIteration
exception isn't retained.

> I believe there are (at least) two use cases:
>
> (1) I catch some low-level exception (e.g. socket.error) and turn it
> into a high-level exception (e.g. an HTTPRequestFailed exception).
>
> (2) I write some exception handling code and somehow a bug in the
> handler (or an uncooperative environment, e.g. a full disk) causes the
> exception handling code to trip over an exception.
>
> I'm fairly certain (but not 100%) that Ping meant to include both use cases.

Yes, though i did not expect to provide any mechanism for distinguishing
the two cases.  Do you think such a mechanism would be necessary?


-- ?!ng
___
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] Tidier Exceptions

2005-05-12 Thread Ka-Ping Yee
On Thu, 12 May 2005, Brett C. wrote:
> whether bare 'except' statements should go or only catch certain exceptions.

Maybe bare 'except' should be spelled 'except *'.

I don't think it can be removed altogether because sometimes you just
need to be able to do magic, but it can be made a little more explicit.

With the asterisk, it's greppable, and editors can find it or highlight
it.  I like the parallel to 'import *' (frowned upon, but sometimes
useful if you really know what you are doing).


-- ?!ng
___
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] Tidier Exceptions

2005-05-12 Thread Ka-Ping Yee
On Thu, 12 May 2005, Guido van Rossum wrote:
> How is "except:" less greppable?

Duh.  I'm slow today.


-- ?!ng
___
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] Merging PEP 310 and PEP 340-redux?

2005-05-13 Thread Ka-Ping Yee
On Fri, 13 May 2005, Guido van Rossum wrote:
> Straight up-or-down votes in the full senate are appreciated at this point.

I prefer the "PEP 340 redux" version.  Both the flexibility for __enter__
to return a separate object and the ability for __exit__ to react to
exceptions are useful.

> - Today I like the 'do' keyword better; 'with' might confuse folks
> coming from Pascal or VB

I prefer 'with'.  The 'do' keyword sounds "loopy" and doesn't make
grammatical sense.


-- ?!ng
___
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] PEP 343: Resource Composition and Idempotent __exit__

2005-05-14 Thread Ka-Ping Yee
Yikes, this turned out to be rather long.  Here's a summary:

  - The expansion suggested by Shane (moving __enter__ outside the
try-finally) fits the expectation that __exit__ will always be
paired with a successful __enter__.  This "paired-exit" expansion
is fairly intuitive and makes simple resources easy to write,
but they are not very composable.

  - The expansion that Guido currently has in PEP 343 encourages an
implementation style where __exit__ is idempotent.  If we use it,
we should document this fact, since it may seem a little unusual
at first; we should also rename "enter"/"exit" so they do not
mislead programmers into believing that they are paired.  Simple
resources are a little more work to write than with a paired-exit
expansion, but they are easier to compose and reuse.

  - The generator style in PEP 340 is the easiest to compose and
reuse, but its implementation is the most complex to understand.

I lean (but only slightly) toward the second option, because it seems
to be a reasonable compromise.  The increased complexity of writing
resources for PEP 343 over PEP 340 becomes less of an issue if we have
a good do_template function in the standard library; on the other hand,
the use of do_template may complicate debugging.

For idempotent-exit, possible renamings of enter/exit might be
enter/finish, enter/cleanup, enter/finally, start/finally, begin/finally.

*   *   *

Okay.  Here's how i arrived at the above conclusions.  (In the following,
i'll just use "with" for "do/with".)

PEP 343 (rev 1.8) currently expands

with EXPR as VAR:
BLOCK

to this, which i'll call the "idempotent-exit" expansion:

resource = EXPR
exc = (None, None, None)
try:
try:
VAR = resource.__enter__()
BLOCK
except:
exc = sys.exc_info()
raise
finally:
resource.__exit__(*exc)

If there are problems during __enter__, then __enter__ is expected to
record this fact so that __exit__ can clean up.  Since __exit__ is
called regardless of whether __enter__ succeeded, this encourages a
style of writing resources where __exit__ is idempotent.

An alternative, advocated by Shane (and by my first instincts), is this
expansion, which i'll call the "paired-exit" expansion:

resource = EXPR
exc = (None, None, None)
VAR = resource.__enter__()
try:
try:
BLOCK
except:
exc = sys.exc_info()
raise
finally:
resource.__exit__(*exc)

If there are problems during __enter__, __enter__ must clean them up
before propagating an exception, because __exit__ will not be called.

To evaluate these options, we could look at a few scenarios where we're
trying to write a resource wrapper for some lock objects.  Each lock
object has two methods, .acquire() and .release().

Scenario 1. You have two resource objects and you want to acquire both.

Scenario 2. You want a single resource object that acquires two locks.

Scenario 3. Your resource object acquires one of two locks depending
on some runtime condition.


Scenario 1 (Composition by client)
==

The client writes this:

with resource1:
with resource2:
BLOCK

The idempotent-exit expansion would yield this:

exc1 = (None, None, None)
try:
try:
resource1.__enter__()
exc2 = (None, None, None)
try:
try:
resource2.__enter__()
BLOCK
except:
exc2 = sys.exc_info()
raise
finally:
resource2.__exit__(*exc2)
except:
exc1 = sys.exc_info()
raise
finally:
resource1.__exit__(*exc1)

Because __exit__ is always called even if __enter__ fails, the resource
wrapper must record whether __enter__ succeeded:

class ResourceI:
def __init__(self, lock):
self.lock = lock
self.acquired = False

def __enter__(self):
self.lock.acquire()
self.acquired = True

def __exit__(self, *exc):
if self.acquired:
self.lock.release()
self.acquired = False

The paired-exit expansion would yield this:

exc1 = (None, None, None)
resource1.__enter__()
try:
try:
exc2 = (None, None, None)
resource2.__enter__()
try:
try:
BLOCK
except:
exc2 = sys.exc_info()
raise
finally:
resource2.__exit__(*exc2)
except:
exc1 = sys.exc_info()
raise
finally:
resource1.__exit__(*exc1)

In this case the lock can simply be implemented as:

class ResourceP:
def 

Re: [Python-Dev] PEP 343 - Abstract Block Redux

2005-05-15 Thread Ka-Ping Yee
On Sun, 15 May 2005, Shane Hathaway wrote:
> You might add to the PEP the following example, which could really
> improve the process of building GUIs in Python:
>
> class MyFrame(Frame):
> def __init__(self):
> with Panel():
> with VerticalBoxSizer():
> self.text = TextEntry()
> self.ok = Button('Ok')

I don't understand how this would be implemented.  Would a widget
function like 'TextEntry' set the parent of the widget according to
some global 'parent' variable?  If so, how would 'Panel' know that
its parent is supposed to be the 'MyFrame' object?


-- ?!ng
___
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] PEP 343 - Abstract Block Redux

2005-05-15 Thread Ka-Ping Yee
On Sun, 15 May 2005, Guido van Rossum wrote:
> In rev 1.10 I moved the __enter__ call out of the
> try-block again. Having it inside was insane: when __enter__ fails, it
> should do its own cleanup rather than expecting __exit__ to clean up
> after a partial __enter__.

No, it wasn't insane.  You had a good reason for putting it there.

The question is what style of implementation you want to encourage.

If you put __enter__ inside, then you encourage idempotent __exit__,
which makes resource objects easier to reuse.

If you put __enter__ outside, that allows the trivial case to be
written a little more simply, but also makes it hard to reuse.


-- ?!ng
___
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] PEP 344: Exception Chaining and Embedded Tracebacks

2005-05-16 Thread Ka-Ping Yee
This PEP is a concrete proposal for exception chaining, to follow
up on its mention here on Python-Dev last week as well as earlier
discussions in the past year or two.

http://www.python.org/peps/pep-0344.html

I've tried to summarize the applications for chaining mentioned in
these discussions, survey what's available in other languages, and
come up with a precise specification.

PEP 344 proposes three standard attributes on traceback objects:

__context__ for implicit chaining (an unexpected exception
occurred during 'except' or 'finally' processing)

__cause__ for explicit chaining (intentional translation or
augmenting of exceptions, set by "raise EXC from CAUSE")

__traceback__ to point to the traceback

Hope this is useful.  I'd like your feedback.  Thanks!


-- Ping
___
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] PEP 344: Exception Chaining and Embedded Tracebacks

2005-05-16 Thread Ka-Ping Yee
On Mon, 16 May 2005, Aahz wrote:
> I'll comment here in hopes of staving off responses from multiple
> people: I don't think these should be double-underscore attributes.  The
> currently undocumented ``args`` attribute isn't double-underscore, and I
> think that's precedent to be followed.

That isn't the criterion i'm using, though.  Here's my criterion, and
maybe then we can talk about what the right criterion should be:

System attributes are for protocols defined by the language.

(I'm using the term "system attribute" here to mean "an attribute with
a double-underscore name", which i picked up from something Guido
wrote a while back [1].)

For example, __init__, __add__, __file__, __name__, etc. are all
attributes whose meaning is defined by the language itself as opposed
to the Python library.  A good indicator of this is the fact that
their names are hardcoded into the Python VM.  I reasoned that
__cause__, __context__, and __traceback__ should also be system
attributes since their meaning is defined by Python.

Exceptions are just classes; they're intended to be extended in
arbitrary application-specific ways.  It seemed a good idea to leave
that namespace open.


-- ?!ng

[1] http://mail.python.org/pipermail/python-dev/2003-June/036239.html
___
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] Adding content to exception messages

2005-05-19 Thread Ka-Ping Yee
On Thu, 19 May 2005, Nick Coghlan wrote:
> With PEP 344, this could simply be:
>
>try:
>parser.parseFile(file)
>exeption Exception, exception:
>raise type(exception)("Error at line %s in file %s" % (x,y))

Only if we also made all exceptions new-style classes.

That's just a minor nit, though.  The more important question to me is:

Do you care about the difference between a secondary exception that was
raised intentionally (as in your example) and a secondary exception due
to a problem in exception handling?

(For me, the answer is yes.)


-- ?!ng
___
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] PEP 344: Exception Chaining and Embedded Tracebacks

2005-05-20 Thread Ka-Ping Yee
On Mon, 16 May 2005, Guido van Rossum wrote:
> Here's a bunch of commentary:

Thanks.  Sorry it's taken me a couple of days to get back to this.
I think i'm caught up on the mail now.

> You're not giving enough credit to Java, which has the "cause" part
> nailed IMO.

You're right.  I missed that.

In my initial research i was only looking for implicit chaining, and
the only support for that i could find was the proposed @@ in Perl 6.
Later i went back and added explicit chaining, realizing that this
was what some of the interested parties originally wanted (and that
C# had it too).

> In particular, please read and understand the
> comment in ceval.c starting with this line:
>
> /* Implementation notes for set_exc_info() and reset_exc_info():

Got it.

> There's too much text devoted early on to examples.

Okay.  In the next revision of the PEP, i'll rearrange it.

> I don't think the PEP adequately predicts what should happen in this
> example:
>
> def foo():
>   try:
>   1/0  # raises ZeroDivisionError
>   except:
>   bar()
>   raise sys.does_not_exist  # raises AttributeError
>
> def bar():
>   try:
>   1+""  # raises TypeError
>   except TypeError:
>   pass
>
> Intuitively, the AttributeError should have the ZeroDivisionError as
> its __context__, but I think the clearing of the thread's exception
> context when the except clause in bar() is left will drop the
> exception context.

That's true.  I agree that the semantics in the PEP (v1.7) are broken.

> Also, in that same example, according to your specs, the TypeError
> raised by bar() has the ZeroDivisionError raised in foo() as its
> context.  Do we really want this?

I don't think it's absolutely necessary, though it doesn't seem to
hurt.  We agree that if the TypeError makes it up to foo's frame,
it should have the ZeroDivisionError as its __context__, right?

If so, do i understand correctly that you want the __context__ to
depend on where the exception is caught as well as where it is raised?

In your thinking, is this mainly a performance or a cleanliness issue?

Basically i was looking for the simplest description that would
guarantee ending up with all the relevant tracebacks reported in
chronological order.  I thought it would be more complicated if we
had to keep modifying the traceback on the way up, but now that
i've re-learned how tracebacks are constructed, it's moot -- we're
already extending the traceback on the way through each frame.

I have a proposal for the implicit chaining semantics that i'll post
in a separate message so it isn't buried in the middle of this one.

> When chaining exceptions, I think it should be an error if the cause
> is not an exception instance (or None).

That's reasonable.

> Do we really need new syntax to set __cause__?  Java does this without
> syntax by having a standard API initCause() (as well as constructors
> taking a cause as argument; I understand why you don't want to rely on
> that -- neither does Java).  That seems more general because it can be
> used outside the context of a raise statement.

I went back and forth on this.  An earlier version of the PEP actually
proposes a 'setcause' method.  I eventually settled on a few reasons
for the "raise ... from" syntax:

1.  (major) No possibility of method override; no susceptibility
to manipulation of __dict__ or __getattr__; no possibility of
another exception happening while trying to set the cause.

2.  (moderate) There is a clear, distinct idiom for exception
replacement requiring that the cause and effect must be
identified together at the point of raising.

3.  (minor) No method namespace pollution.

4.  (minor) Less typing, less punctuation.

The main thing is that handling exceptions is a delicate matter, so it's
nice to have guarantees that the things you're doing aren't going to
suddenly raise more exceptions.

> Why insert a blank line between chained tracebacks?

Just to make them easier to read.  The last line of each traceback
is important because it identifies the exception type, and that will
be a lot easier to find if it isn't buried in an uninterrupted stream
of lines.

> I might want to add an extra line at the very end (and
> perhaps at each chaining point) warning the user that the exception
> has a chained counterpart that was printed earlier.

How about if the line says how many exceptions there were?  Like:

[This is the last of 5 exceptions; see above for the others.]

> Why should the C level APIs not automatically set __context__?  (There
> may be an obvious reason but it doesn't hurt stating it.)

Because:

(a) you indicated some discomfort with the idea, perhaps because
it would make the interpreter do unnecessary work;
(b) no one seems to be asking for it;
(c) it seems potentially complicated.

However, if we go for the semantics you want, PyErr_Set* wouldn't set
__context__ a

[Python-Dev] PEP 344: Implicit Chaining Semantics

2005-05-20 Thread Ka-Ping Yee
Guido van Rossum wrote:
> try:
> BLOCK
> except EXCEPTION, VAR:
> HANDLER
>
> I'd like to see this translated into
>
> try:
> BLOCK
> except EXCEPTION, VAR:
> __context = VAR
> try:
> HANDLER
> except Exception, __error:
> __error.__context__ = __context
> raise

Eric Nieuwland wrote:
> If I interpret the above translation correctly, then:
>  try:
>  BLOCK1
>  except EXCEPTION1, VAR1:
>  try:
>  BLOCK2
>  except EXCEPTION2, VAR2:
>  HANDLER
>
> with exceptions occuring in BLOCK1, BLOCK2 and HANDLER would result in
> HANDLER's exception with __context__ set to BLOCK1's exception and
> BLOCK2's exception would be lost.

Guido van Rossum wrote:
> But that could easily be fixed by appending the context to the end of
> the chain, right?

That would fix this case, but i have a hard time proving to myself that
the result would include all the tracebacks in chronological order.

Can be back up and see if we can agree on a specification at a semantic
level first?  I've been trying to narrow down exactly what you seem to
intuitively want -- how do you like the following:

   Definition of "context": An exception-raise event X is the context
   for an exception-raise event Y if and only if

   1.  Y occurs after X in the same thread.

   2.  If an 'except' clause catches X, Y occurs before exit from this
   clause and is not caught before exit from this clause.

(I refer to "exception-raise events" to avoid any ambiguity about the
same exception object being raised twice.  Each raise-event corresponds
to at most one catch.)


-- ?!ng
___
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] PEP 344: Explicit vs. Implicit Chaining

2005-05-20 Thread Ka-Ping Yee
Guido van Rossum wrote:
> Do we really need both __context__ and __cause__?

Well, it depends whose needs we're trying to meet.

If we want to satisfy those who have been asking for chaining
of unexpected secondary exceptions, then we have to provide that
on some attribute.

If we also want to provide the facility that Java and C# provide
with initCause/InnerException, then we need a separate attribute
devoted to explicit chaining.  The Java and C# documentation is
clear that the cause/inner exception is to be set only on an
exception that is "caused" or a "direct result" of the primary
exception, which i've taken as a sign that this is an important
distinction.

I wanted to give a shot at making both camps happy.

If the two were unified, we'd still be better off than we are
now, but we should be aware that we would not be providing the
functionality that Java and C# provide.


-- ?!ng
___
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] PEP 344: Implicit Chaining Semantics

2005-05-20 Thread Ka-Ping Yee
On Fri, 20 May 2005, Ka-Ping Yee wrote:
> Can be back up and see if we can agree on a specification at a semantic
> level first?  I've been trying to narrow down exactly what you seem to
> intuitively want -- how do you like the following:
>
>Definition of "context": An exception-raise event X is the context
>for an exception-raise event Y if and only if
>
>1.  Y occurs after X in the same thread.
>
>2.  If an 'except' clause catches X, Y occurs before exit from this
>clause and is not caught before exit from this clause.

Dang.  I forgot to deal with what 'exit' means in the face of 'yield'.

   2.  If an 'except' clause catches X, Y occurs before "exit" from or
   while "inside" this clause, and is not caught before "exit" from
   or while "inside" this clause.

   "Enter" means entering at the beginning or resuming after yield.
   "Exit" means execution of return or yield, jumping out of a block
   via break or continue, or reaching the end of the block.

   "Inside" means entered and not yet exited.


-- ?!ng
___
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] PEP 344: Explicit vs. Implicit Chaining

2005-05-21 Thread Ka-Ping Yee
On Sat, 21 May 2005, James Y Knight wrote:
> On May 20, 2005, at 6:37 PM, Phillip J. Eby wrote:
> > This only helps if you can get to a debugger.  What if you're
> > reading your web server's error log?
>
> Then you're in trouble anyways because you need the contents of some
> local to figure out what's going on, also.

Ever used cgitb?


-- ?!ng
___
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] AST manipulation and source code generation

2005-05-23 Thread Ka-Ping Yee
Would there be any interest in extending the compiler package with tools
for AST transformations and for emitting Python source code from ASTs?

I was experimenting with possible translations for exception chaining
and wanted to run some automated tests, so i started playing around
with the compiler package to do source-to-source transformations.
Then i started working on a way to do template-based substitution of
ASTs and a way to spit source code back out, and i'm wondering if
that might be good for experimenting with future Python features.

(If there's already stuff out there for doing this, let me know --
i don't intend to duplicate existing work.)


-- ?!ng
___
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] Missing PyCon 2006

2006-02-13 Thread Ka-Ping Yee
Hi folks.  I had been planning to attend PyCon this year and was really
looking forward to it, but i need to cancel.  I am sorry that i won't
be getting to see you all in a couple of weeks.

If you know anyone who hasn't yet registered but wants to go, please
contact me -- we can transfer my registration.  Thanks, and sorry for
using python-dev for this.


-- ?!ng
___
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] UUID module

2006-06-09 Thread Ka-Ping Yee
Quite a few people have expressed interest in having UUID
functionality in the standard library, and previously on this
list some suggested possibly using the uuid.py module i wrote:

http://zesty.ca/python/uuid.py

This module provides a UUID class, functions for generating
version 1, 3, 4, and 5 UUIDs, and can convert UUIDs to and from
strings of 32 hex digits and strings of 16 bytes.

The thread of messages posted on python-dev begins here:

http://mail.python.org/pipermail/python-dev/2006-March/062119.html

My reading of this is that there was a pretty good consensus on
the issues with this module that need to be addressed:

(a) UUIDs should be immutable (and usable as dict keys).

(b) The str() of a UUID should not contain curly braces.

(c) The uuid1() function, which generates a version-1 UUID,
uses a very slow method of getting the MAC address.

(d) The retrieved MAC address should be cached.

(e) Tests need to be written.

The big question seems to be item (c); all the other items are easy
to take care of.  Assuming (a), (b), (d), and (e) are done, i see a
few options for how to proceed from there:

1.  Remove the uuid1() function, then put uuid.py in the
standard library so at least we'll have the rest of the
UUID functionality in 2.5b1.  Fill in uuid1() later.

2.  Remove the MAC-address functionality from uuid.py; instead
let the caller give the MAC address as an argument to uuid1().
Put that in the standard library for 2.5b1 and fill in the
function for retrieving the MAC address later.

3.  Add uuid.py to the standard library with its current slow
method of finding the MAC address (parsing the output of
ifconfig or ipconfig), but cache the output so it's only
slow the first time.

4.  Figure out how to use ctypes to retrieve the MAC address.
This would only work on certain platforms, but we could
probably cover the major ones.  On the other hand, it seems
unlikely that this would be fully hammered out before the
code freeze.

5.  Don't include any UUID functionality in 2.5b1; put it off
until 2.6.

What are your thoughts on this?

Thanks!


-- ?!ng
___
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] Pre-PEP: Allow Empty Subscript List Without Parentheses

2006-06-10 Thread Ka-Ping Yee
On Sat, 10 Jun 2006, Greg Ewing wrote:
> I'm having trouble seeing a real use for a 0D array as
> something distinct from a scalar, as opposed to them
> just being an oddity that happens to arise as a side
> effect of the way Numeric/Numpy are implemented.

I think the whole discussion about the concept and meaning of
zero-dimensional arrays is mostly irrelevant to the original
issue.  The original issue is a *syntax* question: should
x[()] be written as x[]?

And from a syntax perspective, it's a bad idea.  x[] is much
more often a typo than an intentional attempt to index a
zero-dimensional array.  The compiler should continue to treat
it as a syntax error.


-- ?!ng
___
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] UUID module

2006-06-10 Thread Ka-Ping Yee
Okay.  I have done as Fredrik suggested:
>  6.  Combine 2 and 3: require the user to pass in a MAC argument
>  to uuid1, but provide a SlowGetMacAddress helper that wraps
>  the existing code.

I agree with Thomas Wouters:
> That sounds like the right thing to do, although I wouldn't call it
> "slow"; just let it be documented as 'might not always work and
> might be inefficient',

The method for getting the node ID is called getnode() and is
documented as possibly slow.  If a hardware address cannot be
obtained, we use a random 48-bit number with the highest bit
set to 1, as recommended by RFC 4122.

I have done as Skip proposed here:
> Or make the MAC address an optional arg to uuid1.  If given, use it.
> If not, use the slow lookup (then cache the result).

I've made the address an optional argument, not a required one,
because i think "Explicit better than implicit" applies to changes
in output.  It makes sense to require an explicit argument if it's
actually going to produce a different result, but i don't think it
is necessary to require an explicit argument just because the
routine might be a bit slow.

Letting the address be an optional argument means that in future,
we can change the implementation of getnode() to make it faster or
more reliable, and users of the module will benefit without having
to change any of their code.

Finally, Phillip brought up PEAK:
> PEAK's uuid module does this such that if win32all is present,
> you get a Windows GUID, or if you have a FreeBSD 5+ or
> NetBSD 2+ kernel you use the local platform uuidgen API.  See e.g.:

...so i looked at PEAK's getnodeid48() routine and borrowed the
Win32 calls from there, with a comment giving attribution to PEAK.

Oh, and there is now a test suite that should cover all the code paths.

This is all posted at http://zesty.ca/python/uuid.py now,
documentation page at http://zesty.ca/python/uuid.html,
tests at http://zesty.ca/python/test_uuid.py .

I'll sleep now (6 am), commit tomorrow unless there are objections.

Thanks for your input, everyone!


-- ?!ng
___
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] UUID module

2006-06-10 Thread Ka-Ping Yee
On Sat, 10 Jun 2006, Mike Brown wrote:
> I have a couple of suggestions for improving that implementation:
>
> 1. You're currently using os.urandom, which can raise a NotImplementedError.
> You should be prepared to fall back on a different PRNG...

The latest version (http://zesty.ca/python/uuid.py) does this.

> 2. random.randrange is a method on a default random.Random instance that,
> although seeded by urandom (if available), may not be the user's preferred
> PRNG.  I recommend making it possible for the user to supply their own
> random.Random instance for use by the module.

I decided not to add more code to do this, because the UUID
constructor is now designed in such a way that it's very simple
to convert your own randomness into a UUID.  If you want to use
another source of randomness, you'd just get 16 random bytes and
then call UUID(bytes=random_stuff, version=4).

That seems simpler to me than adding an extra argument and
requiring a randrange() method on it.


-- ?!ng
___
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] beta1 coming real soon

2006-06-10 Thread Ka-Ping Yee
On Thu, 8 Jun 2006, Neal Norwitz wrote:
> If you plan to make a checkin adding a feature (even a simple one),
> you oughta let people know by responding to this message.  Please get
> the bug fixes in ASAP.  Remember to add tests!

Just to make this appear on this thread: i'm planning to check in
the uuid.py module at http://zesty.ca/python/uuid.py (with tests).


-- ?!ng
___
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] UUID module

2006-06-10 Thread Ka-Ping Yee
Hi Thomas,

> This does not work, for several reasons.
>
> 1. (pythoncom|pywintypes).CreateGuid() return a PyIID instance, which you 
> cannot slice:

You're right.  The PEAK code must have been based on an earlier
version of the CreateGuid() routine.

I've fixed this, and added detection of the UUID version so that
the MAC address will only be picked up if the UUID version is 1.

> (BTW: Why does it first try pywintypes, the pythoncom?)

Because PEAK does this, and i see the CreateGuid routine imported
from both modules in Google searches for code, i assumed that it
used to live in one module and moved to the other.

I've also figured out how to get the MAC address using NetBIOS
calls, and added that to the repertoire of methods.  I've tested
this and it works fast.  I think this may be better than
UuidCreateSequential, because it should work on both Win98 and XP.

The updated version is posted at http://zesty.ca/python/uuid.py .


-- ?!ng
___
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] UUID module

2006-06-10 Thread Ka-Ping Yee
On Sat, 10 Jun 2006, Thomas Heller wrote:
> I have not tested the speed, but extending my snippet to also work
> on 98 should be nearly trivial:
>
> try:
> _func = windll.rpcrt4.UuidCreateSequential
> except AttributeError:
> _func = windll.rpcrt4.UuidCreate
>
> def CreateGuid():
> uuid = UUID()
> if 0 == _func(byref(uuid)):
> return str(buffer(uuid))

Okay.  Thanks for this.  I'll give it a shot.


-- ?!ng
___
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] beta1 coming real soon

2006-06-10 Thread Ka-Ping Yee
On Sat, 10 Jun 2006, Paul Moore wrote:
> Actually, the code uses "ifconfig", which doesn't exist on Windows.
> You want the command "ipconfig /all".

I fixed that before you posted this message. :)


-- ?!ng
___
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] UUID module

2006-06-10 Thread Ka-Ping Yee
On Sat, 10 Jun 2006, Thomas Heller wrote:
> [some nice ctypes code]

Done.  Works like a charm.  Thanks for providing the code!

On Sat, 10 Jun 2006, Phillip J. Eby wrote:
> Also, for Python 2.5, these imports could probably be replaced with a
> ctypes call, though I'm not experienced enough w/ctypes to figure out what
> the call should be.

Happily, we have *the* ctypes guru here, and he's solved the problem
for Windows at least.

> Similarly, for the _uuidgen module, you've not included the C source for
> that module or the setup.py incantations to build it.

Yes, the idea was that even though _uuidgen isn't included with core
Python, users would magically benefit if they installed it (or if they
happen to be using Python in a distribution that includes it); it's
the same idea with the stuff that refers to Win32 extensions.  Is the
presence of _uuidgen sufficiently rare that i should leave out
uuidgen_getnode() for now, then?


-- ?!ng
___
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] UUID module

2006-06-11 Thread Ka-Ping Yee
Thomas Heller wrote:
> I don't know if this is the uuidgen you're talking about, but
> on linux there is libuuid:

Thanks!

Okay, that's in there now.  Have a look at http://zesty.ca/python/uuid.py .

Phillip J. Eby wrote:
> By the way, I'd love to see a uuid.uuid() constructor that simply calls the
> platform-specific default UUID constructor (CoCreateGuid or uuidgen(2)),

I've added code to make uuid1() use uuid_generate_time() if available
and uuid4() use uuid_generate_random() if available.  These functions
are provided on Mac OS X (in libc) and on Linux (in libuuid).  Does
that work for you?

I'm using the Windows UUID generation calls (UuidCreate and
UuidCreateSequential in rpcrt4) only to get the hardware address,
not to make UUIDs, because they yield results that aren't compliant
with RFC 4122.  Even worse, they actually have the variant bits set
to say that they are RFC 4122, but they can have an illegal version
number.  If there are better alternatives on Windows, i'm happy to
use them.


-- ?!ng
___
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] Should hex() yield 'L' suffix for long numbers?

2006-06-11 Thread Ka-Ping Yee
I did this earlier:

>>> hex(9)
'0x9184e729fffL'

and found it a little jarring, because i feel there's been a general
trend toward getting rid of the 'L' suffix in Python.

Literal long integers don't need an L anymore; they're automatically
made into longs if the number is too big.  And while the repr() of
a long retains the L on the end, the str() of a long does not, and
i rather like that.

So i kind of expected that hex() would not include the L either.
I see its main job as just giving me the hex digits (in fact, for
Python 3000 i'd prefer even to drop the '0x' as well), and the L
seems superfluous and distracting.

What do you think?  Is Python 2.5 a reasonable time to drop this L?


-- ?!ng
___
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] UUID module

2006-06-12 Thread Ka-Ping Yee
On Sun, 11 Jun 2006, Giovanni Bajo wrote:
> Some comments on the code:
>
> > for dir in ['', r'c:\windows\system32', r'c:\winnt\system32']:
>
> Can we get rid of these absolute paths? Something like this should suffice:
>
> >>> from ctypes import *
> >>> buf = create_string_buffer(4096)
> >>> windll.kernel32.GetSystemDirectoryA(buf, 4096)
> 17
> >>> buf.value.decode("mbcs")
> u'C:\\WINNT\\system32'

I'd like to, but i don't want to use a method for finding the system
directory that depends on ctypes.  Is there a more general way?

> >  for function in functions:
> >try:
> >_node = function()
> >except:
> >continue
>
> This also hides typos and whatnot.

The intended semantics of getnode() are that it cannot fail.
The individual *_getnode() functions do throw exceptions if
something goes wrong, and so they can be tested individually
on platforms where they are expected to work.


-- ?!ng
___
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] UUID module

2006-06-12 Thread Ka-Ping Yee
On Sun, 11 Jun 2006, Phillip J. Eby wrote:
> At 07:24 PM 6/11/2006 -0500, Ka-Ping Yee wrote:
> >I've added code to make uuid1() use uuid_generate_time() if available
> >and uuid4() use uuid_generate_random() if available.  These functions
> >are provided on Mac OS X (in libc) and on Linux (in libuuid).  Does
> >that work for you?
>
> Sure - but actually my main point was to have a uuid() call you could use
> to just get whatever the platform's preferred form of GUID is, without
> having to pick what *type* you want.

I'm reluctant to do that, because there's a privacy question here.
I think the person using the module should have control over whether
the UUID is going to leak the host ID or not (rather than leaving it
up to whatever the platform prefers or which call the implementor of
uuid.py happened to choose for a given platform).

> Perhaps that isn't feasible, or is a bad idea for some other reason, but my
> main point was to have a call that means "get me a good unique ID".  :)

Couldn't we just recommend uuid.uuid4() for that?


-- ?!ng
___
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] UUID module

2006-06-12 Thread Ka-Ping Yee
On Mon, 12 Jun 2006, Giovanni Bajo wrote:
> GetSystemDirectory() is the official way to find the system directory.

You're right.  I've added a call to GetSystemDirectory, with a fallback
to the usual locations if it doesn't work.

> Another thing that you might do is to drop those absolute system
> directories altogether. After all, ipconfig should always be in the path.

Yup, that's why '' is the first item in the list of directories to try.

> As a last note, you are parsing ipconfig output assuming an English Windows
> installation. My Italian Windows 2000 has localized output.

Thanks for catching this.  I've fixed it in the latest version,
which is now checked in to the trunk.


-- ?!ng
___
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] uuid backward compatibility

2006-06-18 Thread Ka-Ping Yee
On Sun, 18 Jun 2006, George Yoshida wrote:
> uuid.py says in its docstring:
>   This module works with Python 2.3 or higher.
>
> And my question is:
>   Do we plan to make it 2.3 compatible in future releases?
>
> If so, uuid needs to be listed in PEP 291.
> Otherwise, the comment is misleading.

The comment isn't misleading, because the module actually does work
with Python 2.3.  It would only become misleading if it were later
changed to break compatibility with Python 2.3 without updating the
comment.

I intentionally avoided breaking compatibility with Python 2.3 so
that there would be just one current version of uuid.py, both in
the svn repository and available for use with existing installations
of Python, since Python 2.3 is so widely deployed right now.

Anyway, it looks like someone has added this module to the list of
backward-compatible modules in PEP 291.  Regarding whether we want
it to be on that list (i.e. whether or not this backward-compatibility
should be retained as Python moves forward), i'm happy to have it
either way.


-- ?!ng
___
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] Switch statement

2006-06-19 Thread Ka-Ping Yee
On Mon, 19 Jun 2006, Guido van Rossum wrote:
> Um, is this dogma? Wouldn't a switch statement also be a welcome
> addition to the readability? I haven't had the time to follow this
> thread (still catching up on my Google 50%) but I'm not sure I agree
> with the idea that a switch should only exist for speedup.

I feel quite strongly that readability should be the primary motivator
for just about any new syntax.

Choosing an implementation that runs at a reasonable speed is also
worthwhile consideration, but readability is where it starts, IMHO.


-- ?!ng
___
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] uuid backward compatibility

2006-06-19 Thread Ka-Ping Yee
On 6/18/06, "Martin v. Löwis" <[EMAIL PROTECTED]> wrote:
> As for the comment: It apparently *is* misleading, George mistakenly
> took it as a requirement for future changes, rather than a factual
> statement about the present (even though it uses the tense of simple
> present). Anybody breaking 2.3 compatibility will have to remember
> to remove the comment, which he likely won't.

This sentiment is puzzling to me.  It seems you assume that we can trust
future developers to change the code but we can't trust them to update
the documentation.  So we can't have documentation even if it's factually
true just because someone might forget to update it?  Why is the mere
possibility of incorrect documentation in the future more significant
than actual correct documentation in the present?  Couldn't the same
argument be used to support removing all documentation from all code?

If you see a better way to word the comment to reduce the possibility
of misunderstanding, that's cool with me.  I'd just like people who
get their hands on the module to know that they can use it with 2.3.


-- ?!ng
___
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] uuid backward compatibility

2006-06-19 Thread Ka-Ping Yee
On Mon, 19 Jun 2006, Guido van Rossum wrote:
> If you want to encourage people to use your module
> with older versions, the right path is to have a distribution (can be
> very light-weight) on your own website and add it to PyPI

Okay, i've removed the comment and submitted the package to PyPI.


-- ?!ng
___
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] Switch statement

2006-06-20 Thread Ka-Ping Yee

On Mon, 19 Jun 2006, Josiah Carlson wrote:
> I personally don't find switch/case statements to be significantly (if
> at all) easier to read than if/elif/else chains, but that is subjective,
> and I note that Ka-Ping finds switch/case to be significantly easier to
> read.

Uh, i didn't mean to say that.  I said readability should be the primary
motivator for new syntax (in general).  Whether switch/case provides a
significant readability improvement, and how often it turns out to be
useful -- these things depend on the semantics we choose.


-- ?!ng
___
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] Switch statement

2006-06-21 Thread Ka-Ping Yee
On Wed, 21 Jun 2006, Phillip J. Eby wrote:
> Well, EIBTI and all that:
>
>  switch x:
>  case == 1: foo(x)
>  case in S: bar(x)
>
> It even lines up nicely.  :)

Hmm, this is rather nice.  I can imagine possible use cases for

switch x:
case > 3: foo(x)
case is y: spam(x)
case == z: eggs(x)

An interesting use case for which this offers no corresponding
syntax is

case instanceof ClassA: ham(x)

which doesn't work because Python spells a type test as
isinstance(a, b) rather than with an operator.  (I suppose
whether we want it to be an operator might be another
question to think about for Python 3000.)


-- ?!ng
___
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] Switch statement

2006-06-22 Thread Ka-Ping Yee
On Wed, 21 Jun 2006, Guido van Rossum wrote:
> I worry (a bit) about this case:
>
>   y = 12
>   def foo(x, y):
> switch x:
> case y: print "something"
>
> which to the untrained observer (I care about untrained readers much
> more than about untrained writers!) looks like it would print
> something if x equals y, the argument, while in fact it prints
> something if x equals 12.

I am quite concerned about this case too.  I think if Python were
to behave this way, it would be a new pitfall for people learning
the language -- like other pitfalls such as using unbound locals,
mutable default arguments, or the historical non-nested scopes.
I'm not saying the other pitfalls don't have good reasons -- some
are outweighed by other design advantages (unbound locals are a
consequence of having no variable declarations) and some have
since been fixed (like nested scopes).  But i'd be wary of adding
a new pitfall to that list without a very substantial win.

> Me too. I guess I was just pointing out that "just" evaluating it in
> the global scope would not give an error, just like this is valid (but
> confusing):
>
> y = 12
> def foo(y=y):
>   print y
> y = 13
> foo()  # prints 12

I see how frozen-cases and default-arguments could have comparable
semantics, but i do think frozen-cases are more confusing.  In this
default-arguments example, there is at least a hint from the syntax
that we're introducing a new local variable, so there is a landmark
where the reader can hang the mental note that a new thing is being
introduced.  Also, it is easier to see that default arguments are
being fixed at function-definition time because their value
expressions are localized in the source code in the "def" line, a
line that makes sense to be evaluating at definition time.

For frozen-cases, you don't have this kind of landmark, and the bits
that are evaluated at function-definition time are scattered and
mixed with the rest of the function evaluated at function-call time.
That's pretty subtle; i can't think of any other Python construct
off the top of my head that mixes evaluation times like that.  (Yes,
the compiler does optimize literals, but it's done in a way that
doesn't affect semantics.)


-- ?!ng
___
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] Switch statement

2006-06-22 Thread Ka-Ping Yee
On Wed, 21 Jun 2006, Guido van Rossum wrote:
> (Note how I've switched to the switch-for-efficiency camp, since it
> seems better to have clear semantics and a clear reason for the syntax
> to be different from if/elif chains.)

I don't think switch-for-efficiency (at least if efficiency is the
primary design motivator) makes sense without some strong evidence
that the use of if/elif constructs often causes a severe speed problem
in many Python programs.  (Premature optimization and all that.)
Long if/elif chains probably don't occur often enough or slow down
programs enough to invent syntax *just* for speed; and even if they
did, i don't think there's any precedent for a Python statement
invented primarily as a speed optimization.

I'm hoping we can talk more about the question: How can a new statement
help programmers express their intent more clearly?

So far i've seen two possible answers to that question:

1.  The switched-on expression is written and evaluated just once.

2.  The cases could help you unpack things into local variables.

(There was some discussion about unpacking earlier:
http://mail.python.org/pipermail/python-dev/2005-April/052780.html
which petered out, though there may still be the possibility of
designing something quite useful and readable.)

Any others?


-- ?!ng
___
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] Switch statement

2006-06-24 Thread Ka-Ping Yee
On Fri, 23 Jun 2006, Josiah Carlson wrote:
> This is a good thing, because if switch/case ends up functionally
> identical to if/elif/else, then it has no purpose as a construct.

This doesn't make sense as a rule.

Consider:

"If x.y ends up functionally identical to getattr(x, 'y'),
 then it has no purpose as a construct."

"If print x ends up functionally identical to import sys;
 sys.stdout.write(str(x) + '\n'), then it has no purpose as
 a construct."

What matters is not whether it's *functionally* identical.  What
matters is whether it makes more sense to the reader and has a
meaning that is likely to be what the writer wanted.

"Evaluate the switch expression just once" is a semantic win.

"Evaluate the switch expression just once, but throw an exception
if the result is not hashable" is a weaker semantic win.  (How
often is that what the writer is thinking about?)

"Throw an exception at compile time if the cases overlap" is also
a weaker semantic win.  (How often is this an actual mistake that
the writer wants to be caught at compile time?)

"Use the case values computed at compile time, not at runtime" doesn't
seem like much of a win.  (How often will this be what the writer
intended, as opposed to a surprise hiding in the bushes?)


-- ?!ng
___
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] Simple Switch statement

2006-06-25 Thread Ka-Ping Yee
On Sat, 24 Jun 2006, Raymond Hettinger wrote:
> The main points of contention are 1) a non-ambiguous syntax for assigning
> multiple cases to a single block of code, 2) how to compile variables as
> constants in a case statement, and 3) handling overlapping cases.
>
> Here's a simple approach that will provide most of the benefit without
> trying to overdo it:
[...]
> The result of f(x) should be hashable or an exception is raised.
> Cases values must be ints, strings, or tuples of ints or strings.
> No expressions are allowed in cases.

I like this proposal.  It eliminates all of the surprises that have
been hiding in the other switch proposals so far, except for throwing
an exception when the switch expression isn't hashable.  But i can
easily live with that restriction, since the cases are all literals
that must be hashable, so if the switch expression comes out to some
other type then it probably really is an error that should be caught.

I agree with the general feeling that it would be nice to have a bit
more flexibility, but so far i haven't thought of any way to get more
flexibility without more surprises, so until a better idea comes along
i'm happy with this one.


-- ?!ng
___
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] Simple Switch statement

2006-06-25 Thread Ka-Ping Yee
On Sat, 24 Jun 2006, Phillip J. Eby wrote:
> At 03:49 PM 6/24/2006 -0700, Raymond Hettinger wrote:
> >Cases values must be ints, strings, or tuples of ints or strings.
>
> -1.  There is no reason to restrict the types in this fashion.  Even if you
> were trying to ensure marshallability, you could still include unicode and
> longs.

When he said "ints" i assumed that included longs.  The distinction
is so nearly gone by now (from the Python programmer's point of view).

I don't see any particular problem with allowing all basestrings
rather than just 8-bit strings.


-- ?!ng
___
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] Simple Switch statement

2006-06-25 Thread Ka-Ping Yee
On Sun, 25 Jun 2006, Guido van Rossum wrote:
> In your eagerness to
> rule out surprises, you're creating the biggest surprise of all: the
> restriction to literals is certainly a surprise!

I disagree.  Perhaps what we mean by "surprise" is different.  In
Raymond's design, there is a simple rule for what's allowed in a case.
The whole statement can be described in very few words:

Each case is a literal integer, string, or tuple of integers
or strings.  Execution jumps to the first case that matches the
value of the switch expression (or to 'default' if no match).

That's it.  The simpler the rule, the less surprising it is.  It would
take a lot more words to explain the behaviour of something like Nick's
'once'-based proposal.  Here's an attempt:

Each case consists of an arbitrary expression, but the expression
may not refer to any local variables or arguments of the immediately
surrounding function definition.  The value of each case is computed
when the surrounding function definition is compiled.  If any two
cases have the same value, an exception is thrown at compile time.
At runtime, execution jumps to the case whose previously fixed value
matches the value of the switch expression (or to 'default' if no
match).

Not only is that longer to describe, it's also more difficult for a
beginning programmer to understand, since it requires knowing when
different parts of a program are compiled (and what happens if the
same part is compiled more than once).


-- ?!ng
___
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] Simple Switch statementZ

2006-06-25 Thread Ka-Ping Yee
On Mon, 26 Jun 2006, Georg Brandl wrote:
> Raymond Hettinger wrote:
> >five = 5
> >eight = [8]
> >def f(x, six=6):
> >   seven =  7
> >   a = static(five + 4)# this is legal
> >   b = static(six + 4)  # this is illegal
> >   c = static(seven + 4) # this is illegal
> >   d = static(eight + [4]) # this is illegal
>
> Why would the last line be illegal?

I believe Raymond is assuming it would be illegal because it's mutable.
I don't think much has been said about whether static() should be
allowed to yield a mutable value, but if we did allow that, it might
open up an avenue to much confusion.  (I join the chorus of voices that
dislike the name 'static' for this feature.)

Whether or not 'eight + [4]' is allowed in 'static', it certainly
wouldn't be allowed after 'switch' or 'case' since it's unhashable.


-- ?!ng
___
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] Simple Switch statementZ

2006-06-25 Thread Ka-Ping Yee
On Sun, 25 Jun 2006, Guido van Rossum wrote:
> What do you think of Nick C's 'once'?

It's a bit closer to the right meaning... but what about:

def f(x):
def g(y):
return y + once x
return g

Does "once" mean not really once here, but "once for each new function
object that's created for g"?

> Right. But there are all sorts of objects that are compared by object
> identity (e.g. classes, modules, even functions) which may contain
> mutable components but are nevertheless "constant" for the purpose of
> switch or optimization. Let's not confuse this concept of constness
> with immutability.

That's a good point.  We need a concept like "stable for equality"
separate from "constant", since "constant" and "immutable" will mislead
those who are used to the meanings of these words in other languages.


-- ?!ng
___
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] PEP 3103: A Switch/Case Statement

2006-06-26 Thread Ka-Ping Yee
On Mon, 26 Jun 2006, Guido van Rossum wrote:
> I've written a new PEP, summarizing (my reaction to) the recent
> discussion on adding a switch statement. While I have my preferences,
> I'm trying to do various alternatives justice in the descriptions.

Thanks for writing this up!

The section that most draws my attention is "Semantics", and i guess
it isn't a surprise to either of us that you had the most to say
from the perspective you currently support (School II).  :)  Let me
suggest a couple of points to add:

  - School I sees trouble in the approach of pre-freezing a dispatch
dictionary because it places a new and unusual burden on the
programmer to understand exactly what kinds of case values are
allowed to be frozen and when the case values will be frozen.

  - In the School II paragraph you say "Worse, the hash function
might have a bug or a side effect; if we generate code that
believes the hash, a buggy hash might generate an incorrect
match" -- but that is primarily a criticism of the School II
approach, not of the School I approach as you have framed it.
It's School II that mandates that the hash be the truth.

(It looks to me like what you're actually criticizing here is
based on some assumptions about how you think School I might
be implemented, and having taken School I a number of steps
down that (unexplained) road you then see problems with it.)

Also, why is the discussion of School II mostly an argument against
School I?  What about describing the advantages of each school?


-- ?!ng
___
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] PEP 3103: A Switch/Case Statement

2006-06-26 Thread Ka-Ping Yee
On Mon, 26 Jun 2006, Guido van Rossum wrote:
> Can you please edit the PEP yourself to add this? That will be most efficient.

I've done so, and tried to clarify the next line to match (see below).

> With school I, if you want to
> optimize using a hash table (as in PEP 275 Solution 1) you have to
> catch and discard exceptions in hash(), and a bug in hash() can still
> lead this optimization astray

Right.  As written, the problem "a buggy hash might generate an
incorrect match" is not specific to School I; it's a problem with
any approach that is implemented by a hash lookup.  School II is
necessarily implemented this way; School I might or might not be.
So i think the part that says:

the hash function might have a bug or a side effect; if we
generate code that believes the hash, a buggy hash might
generate an incorrect match

doesn't belong there, and i'd like your consent to remove it.
On the other hand, this criticism:

if we generate code that catches errors in the hash to
fall back on an if/elif chain, we might hide genuine bugs

is indeed specific to School I + hashing.

> Right. School I appears just as keen as school II to use hashing to
> optimize things, but isn't prepared to pay the price in semantics;

Ok.  Then there's an inconsistency with the definition of School I:

School I wants to define the switch statement in term of
an equivalent if/elif chain

To clear this up, i've edited the first line of the School II
paragraph, which previously said:

School II sees nothing but trouble in that approach

It seems clear that by "that approach" you meant "trying to achieve
if/elif semantics while using hash optimization" rather than the
more general definition of School I that was given.  I believe
there are a few voices here (and i count myself among them) that
consider the semantics more important than the speed and are in
School I but aren't treating hash optimization as the quintessence
of 'switch', and we shouldn't leave them out.


-- ?!ng
___
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] PEP 3103: A Switch/Case Statement

2006-06-26 Thread Ka-Ping Yee
On Mon, 26 Jun 2006, Guido van Rossum wrote:
> Most school I proponents (perhaps you're the only exception) have
> claimed that optimization is desirable, but added that it would be
> easy to add hash-based optimization. IMO it's not so easy in the light
> of various failure modes of hash(). (A possible solution would be to
> only use hashing if the expression's type is one of a small set of
> trusted builtins, and not a subclass; we can trust int.__hash__,
> str.__hash__ and a few others.)

That's a good idea!  At first glance, it seems like that could lead to
a plausible compromise.


-- ?!ng
___
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] School IIb?

2006-06-26 Thread Ka-Ping Yee
Here's a possible adjustment to the School-II approach that i think
avoids the issues i've been raising, while giving the desired
O(n)-to-O(1) speedup in common situations.  It's basically School-II
dispatch, plus a check:

On compilation, freeze any cases that meet the School-II conditions
and have a trustworthy __hash__ method into a dictionary.  At runtime,
when the dictionary yields a hit, check if the case expression yields
a different value.  If the value has changed, use if/elif processing.

In most cases the case-equality check will be cheap (e.g. an attribute
lookup), but it would allow us to establish for sure that the switch
value really matches the case value when we branch to a particular
case, so we'd not be so vulnerable to __hash__ misbehaving, which
seems to be your main source of discomfort with if/elif semantics.


-- ?!ng
___
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


  1   2   >