From tim_one@email.msn.com  Sun Jan  2 05:52:34 2000
From: tim_one@email.msn.com (Tim Peters)
Date: Sun, 2 Jan 2000 00:52:34 -0500
Subject: [Python-Dev] Re: [Distutils] Questions about distutils strategy
In-Reply-To: <199912091617.LAA05742@eric.cnri.reston.va.us>
Message-ID: <000401bf54e5$91587280$1f2d153f@tim>

Briefly backtracking to an old thread:

[Guido]
> ...
> The problem lies in which key is used.  All versions of
> Python 1.5.x (1.5, 1.5.1, 1.5.2) use the same key!  This
> is a main cause of trouble, because it means that different
> versions cannot peacefully live together even if the user
> installs them into different directories -- they will all
> use the registry keys of the last version installed.  This,
> in turn, means that someone who writes a Python application
> that has a dependency on a particular Python version (and
> which application worth distributing doesn't :-) cannot
> trust that if a Python installation is present, it is the
> right one.  But they also cannot simply bundle the standard
> installer for the correct Python version with their program,
> because its installation would overwrite an existing Python
> application, thus breaking some *other* Python apps that
> the user might already have installed.

Right, that's one class of intractable problem under Windows.

*Inside* my workplace, another kind of problem is caused when people try to
make a Python app available over the Windows network.  They stick the Python
they want and its libraries out on the network, with python.exe in the same
directory as the app.  Now some people have highly customized Python setups,
and the network Python picks up "the wrong" site.py etc.  That sucks, and
there appears no sane way to stop it.

Telling internal app distributors they need to invent a unique registry key
and fiddle their python.exe's resources is a non-starter.  Ditto telling
people with highly customized Pythons "don't do that".  Ditto telling anyone
they have to run any sort of installation script just to use a network app
(sometimes they don't even know they're running it! e.g., when it's a
subsystem invoked by another app).

So while everyone is thinking about the hardest possible scenarios, please
give a thought to the dirt simple one too <0.5 wink>:  an app distributor
who knows exactly what they're doing, and for whom *any* magical inference
is simply a barrier to overcome.  The latter can be satisfied by any number
of means, from an envar that says "please don't try to be helpful, *this* is
the directory you look in, and if you don't find stuff there give up" to a
cmdline switch that says the same.  Nothing Windows-specific there -- any OS
with an envar or a cmdline will play along <wink>.

> ...
> I thought a bit about how VB solves this.  I think that when
> you wrap up a VB app in, all the support code (mostly a big
> DLL) is wrapped with it.  When the user runs the installer,
> the DLL is installed (probably in the WINDOWS directory).  If
> a user installs several VB apps built with the same VB
> version, they all attempt to install the exact same DLL; of
> course the installers notice this and optimize it away, keeping
> a reference count.

This is the way most *MS* DLLs work; stuff like the C runtime libraries and
MS database drivers work exactly the same way.  It's rare for pkgs other
than MS's to attempt to use this mechanism, though (the reason is given
below).

> (Ignoring for now the fact that those reference counts don't
> always work!)

?  They work very well, in my experience.  Where they fail is when
installers & uninstallers break the rules.  MS publishes the list of MS DLLs
that are to be treated this way:  an installer "must" use refcounting on the
DLLs in the list.  Alas, some (especially older) installation pkgs don't.
Then the refcounts get screwed up.

That's what makes the mechanism brittle:  "the system" doesn't enforce it,
it relies on universal & intelligent cooperation.  It's very likely that
someone distributing a Python app will neglect (out of ignorance) to bump
the refcount on their Python components, so the refcount will be
artificially low, and a later uninstall of some unrelated pkg that *did*
follow the rules will merrily delete Python.

Gordon and I will repeat this until it sinks in <wink>:  almost everyone
with a successful Windows product ships the non-MS DLLs they rely on and
copies them into their own app directory.  It's simple and it works;
alternatives are complicated and don't work.  Many even ship & copy MS DLLs
(e.g., Scriptics copies its own msvcrt.dll (the MS C runtime) into Tcl's
directories).  Worrying about space consumed by redundant Python components
is a bad case of premature optimization <0.3 wink>.

> ...
> How can we do something similar for Python?

Seriously, short of getting MS to distribute Python and put the Python DLLs
on The List of refcounted resources, we should pursue this line reluctantly
if at all.  MS may have a better scheme in the future, but for now better
safe than sorry.


a-couple-mb-on-a-modern-pc-isn't-worth-the-time-it-took-
    to-read-this<wink>-ly y'rs  - tim




From gstein@lyra.org  Mon Jan  3 02:53:24 2000
From: gstein@lyra.org (Greg Stein)
Date: Sun, 2 Jan 2000 18:53:24 -0800 (PST)
Subject: [Python-Dev] new imputil.py
Message-ID: <Pine.LNX.4.10.10001021838400.412-200000@nebula.lyra.org>

  This message is in MIME format.  The first part should be readable text,
  while the remaining parts are likely unreadable without MIME-aware tools.
  Send mail to mime@docserver.cac.washington.edu for more info.

--1658348780-1657214722-946868004=:412
Content-Type: TEXT/PLAIN; charset=US-ASCII

Happy New Year!

I've attached a new imputil.py to this message. It isn't posted on my page
yet, as I'd like some feedback before declaring this new version viable.

In this imputil, there is an ImportManager class. It gets installed as the
import hook, with the presumption that it is the only import hook
(technically, it could chain, but I've disabled that for now). I think
Python 1.6 should drop the __import__ builtin and move to something like
sys.import_hook (to allow examination and change). Another alternative
would be sys.get_import_hook() and sys.set_import_hook().
[ I don't think we would want a "set" that returned the old version as the
  only way to get the current hook function; we want to be able to easily 
  find the ImportManager instance. ]

The ImportManager knows how to scan sys.path when it needs to find a
top-level module/package (e.g. given a.b.c, the "a" is the top-level; b.c
falls "below" that). sys.path can contain strings which specify a
filesystem directory, or it can contain Importer instances.

The manager also records an ordered list of suffix/importer pairs. The
add_suffix() method is used to append new suffixes, but clients can also
access the .suffixes attribute for fine-grained manipulation/ordering.

There is a new importer called _FilesystemImporter which understands how
to look into a directory for Python modules. It borrows/refers to the
ImportManager's .suffixes attribute, using that to find modules in a
directory. This is also the Importer that gets associated with each
filesystem-based module.

The importers used for suffix-based importing are derived from
SuffixImporter. While a function could be used here, future changes will
be easier if we presume class instances.

The new imputil works fine (use _test_revamp() to switch to the new import
mechanism). Importer subclasses using the old imputil should continue to
work, although I am deprecating the 2-tuple return value for get_code().
get_code() should return None or the 3-tuple form now.

I think I still have a bit more work to do, to enable something like
"import a.b.c" where a.zip is an archive on the path and "b.c" resides in
the archive. Note: it *is* possible to do
sys.path.append(ZipImporter(filename)) and have "a.b.c" in the Zip file.
It would simply be nicer to be able to drop arbitrary .zip files onto the
path and use their basename as the top-level name of a package. Anyhow: I
haven't looked at this scenario yet to find what the new system is missing
(if anything).

As always: feedback is more than appreciated! Especially from people using
imputil today. Did I break anything? Does the new scheme still feel right
to you? etc.

Cheers,
-g

p.s. I'd also like to remove PackageArchiveImporter and PackageArchive.
     They don't seem to add any real value. I might move DirectoryImporter
     and PathImporter to an "examples" file, too.

-- 
Greg Stein, http://www.lyra.org/


--1658348780-1657214722-946868004=:412
Content-Type: TEXT/PLAIN; charset=US-ASCII; name="imputil.py"
Content-Transfer-Encoding: BASE64
Content-ID: <Pine.LNX.4.10.10001021853240.412@nebula.lyra.org>
Content-Description: 
Content-Disposition: attachment; filename="imputil.py"

Iw0KIyBpbXB1dGlsLnB5DQojDQojIFdyaXR0ZW4gYnkgR3JlZyBTdGVpbi4g
UHVibGljIERvbWFpbi4NCiMgTm8gQ29weXJpZ2h0LCBubyBSaWdodHMgUmVz
ZXJ2ZWQsIGFuZCBubyBXYXJyYW50aWVzLg0KIw0KIyBVdGlsaXRpZXMgdG8g
aGVscCBvdXQgd2l0aCBjdXN0b20gaW1wb3J0IG1lY2hhbmlzbXMuDQojDQoj
IEFkZGl0aW9uYWwgbW9kaWZpY2F0aW9ucyB3ZXJlIGNvbnRyaWJlZCBieSBN
YXJjLUFuZHJlIExlbWJ1cmcgYW5kDQojIEdvcmRvbiBNY01pbGxhbi4NCiMN
CiMgVGhpcyBtb2R1bGUgaXMgbWFpbnRhaW5lZCBieSBHcmVnIGFuZCBpcyBh
dmFpbGFibGUgYXQ6DQojICAgIGh0dHA6Ly93d3cubHlyYS5vcmcvZ3JlZy9w
eXRob24vaW1wdXRpbC5weQ0KIw0KIyBTaW5jZSB0aGlzIGlzbid0IGluIHRo
ZSBQeXRob24gZGlzdHJpYnV0aW9uIHlldCwgd2UnbGwgdXNlIHRoZSBDVlMg
SUQNCiMgZm9yIHRyYWNraW5nOg0KIyAgICRJZDogaW1wdXRpbC5weSx2IDEu
OSAyMDAwLzAxLzAzIDAyOjM4OjI5IGdzdGVpbiBFeHAgJA0KIw0KDQojIG5v
dGU6IGF2b2lkIGltcG9ydGluZyBub24tYnVpbHRpbiBtb2R1bGVzDQppbXBv
cnQgaW1wDQppbXBvcnQgc3lzDQppbXBvcnQgc3Ryb3ANCmltcG9ydCBfX2J1
aWx0aW5fXw0KDQojIGZvciB0aGUgRGlyZWN0b3J5SW1wb3J0ZXINCmltcG9y
dCBzdHJ1Y3QNCmltcG9ydCBtYXJzaGFsDQoNCl9TdHJpbmdUeXBlID0gdHlw
ZSgnJykNCl9Nb2R1bGVUeXBlID0gdHlwZShzeXMpDQoNCmNsYXNzIEltcG9y
dE1hbmFnZXI6DQogICJNYW5hZ2UgdGhlIGltcG9ydCBwcm9jZXNzLiINCg0K
ICBkZWYgaW5zdGFsbChzZWxmKToNCiAgICAjIyMgd2FybmluZzogUHl0aG9u
IDEuNiB3aWxsIGhhdmUgYSBkaWZmZXJlbnQgaG9vayBtZWNoYW5pc207IHRo
aXMNCiAgICAjIyMgY29kZSB3aWxsIG5lZWQgdG8gY2hhbmdlLg0KICAgIHNl
bGYuX19jaGFpbl9pbXBvcnQgPSBfX2J1aWx0aW5fXy5fX2ltcG9ydF9fDQog
ICAgc2VsZi5fX2NoYWluX3JlbG9hZCA9IF9fYnVpbHRpbl9fLnJlbG9hZA0K
ICAgIF9fYnVpbHRpbl9fLl9faW1wb3J0X18gPSBzZWxmLl9pbXBvcnRfaG9v
aw0KICAgICMjIyBmaXggdGhpcw0KICAgICNfX2J1aWx0aW5fXy5yZWxvYWQg
PSBOb25lDQogICAgI19fYnVpbHRpbl9fLnJlbG9hZCA9IHNlbGYuX3JlbG9h
ZF9ob29rDQoNCiAgZGVmIGFkZF9zdWZmaXgoc2VsZiwgc3VmZml4LCBpbXBv
cnRlcik6DQogICAgYXNzZXJ0IGlzaW5zdGFuY2UoaW1wb3J0ZXIsIFN1ZmZp
eEltcG9ydGVyKQ0KICAgIHNlbGYuc3VmZml4ZXMuYXBwZW5kKChzdWZmaXgs
IGltcG9ydGVyKSkNCg0KICAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj
IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQog
ICMNCiAgIyBQUklWQVRFIE1FVEhPRFMNCiAgIw0KICBkZWYgX19pbml0X18o
c2VsZik6DQogICAgIyB3ZSdyZSBkZWZpbml0ZWx5IGdvaW5nIHRvIGJlIGlt
cG9ydGluZyBzb21ldGhpbmcgaW4gdGhlIGZ1dHVyZSwNCiAgICAjIHNvIGxl
dCdzIGp1c3QgbG9hZCB0aGUgT1MtcmVsYXRlZCBmYWNpbGl0aWVzLg0KICAg
IGlmIG5vdCBfb3Nfc3RhdDoNCiAgICAgIF9vc19ib290c3RyYXAoKQ0KDQog
ICAgIyBJbml0aWFsaXplIHRoZSBzZXQgb2Ygc3VmZml4ZXMgdGhhdCB3ZSBy
ZWNvZ25pemUgYW5kIGltcG9ydC4NCiAgICAjIFRoZSBkZWZhdWx0IHdpbGwg
aW1wb3J0IGR5bmFtaWMtbG9hZCBtb2R1bGVzIGZpcnN0LCBmb2xsb3dlZCBi
eQ0KICAgICMgLnB5IGZpbGVzIChvciBhIC5weSBmaWxlJ3MgY2FjaGVkIGJ5
dGVjb2RlKQ0KICAgIHNlbGYuc3VmZml4ZXMgPSBbIF0NCiAgICBmb3IgZGVz
YyBpbiBpbXAuZ2V0X3N1ZmZpeGVzKCk6DQogICAgICBpZiBkZXNjWzJdID09
IGltcC5DX0VYVEVOU0lPTjoNCiAgICAgICAgc2VsZi5zdWZmaXhlcy5hcHBl
bmQoKGRlc2NbMF0sIER5bkxvYWRTdWZmaXhJbXBvcnRlcihkZXNjKSkpDQog
ICAgc2VsZi5zdWZmaXhlcy5hcHBlbmQoKCcucHknLCBQeVN1ZmZpeEltcG9y
dGVyKCkpKQ0KDQogICAgIyBUaGlzIGlzIHRoZSBpbXBvcnRlciB0aGF0IHdl
IHVzZSBmb3IgZ3JhYmJpbmcgc3R1ZmYgZnJvbSB0aGUNCiAgICAjIGZpbGVz
eXN0ZW0uIEl0IGRlZmluZXMgb25lIG1vcmUgbWV0aG9kIChpbXBvcnRfZnJv
bV9kaXIpIGZvciBvdXIgdXNlLg0KICAgIHNlbGYuZnNfaW1wID0gX0ZpbGVz
eXN0ZW1JbXBvcnRlcihzZWxmLnN1ZmZpeGVzKQ0KDQogIGRlZiBfaW1wb3J0
X2hvb2soc2VsZiwgZnFuYW1lLCBnbG9iYWxzPU5vbmUsIGxvY2Fscz1Ob25l
LCBmcm9tbGlzdD1Ob25lKToNCiAgICAiIiJQeXRob24gY2FsbHMgdGhpcyBo
b29rIHRvIGxvY2F0ZSBhbmQgaW1wb3J0IGEgbW9kdWxlLiIiIg0KDQogICAg
cGFydHMgPSBzdHJvcC5zcGxpdChmcW5hbWUsICcuJykNCg0KICAgICMgZGV0
ZXJtaW5lIHRoZSBjb250ZXh0IG9mIHRoaXMgaW1wb3J0DQogICAgcGFyZW50
ID0gc2VsZi5fZGV0ZXJtaW5lX2ltcG9ydF9jb250ZXh0KGdsb2JhbHMpDQoN
CiAgICAjIGlmIHRoZXJlIGlzIGEgcGFyZW50LCB0aGVuIGl0cyBpbXBvcnRl
ciBzaG91bGQgbWFuYWdlIHRoaXMgaW1wb3J0DQogICAgaWYgcGFyZW50Og0K
ICAgICAgbW9kdWxlID0gcGFyZW50Ll9faW1wb3J0ZXJfXy5fZG9faW1wb3J0
KHBhcmVudCwgcGFydHMsIGZyb21saXN0KQ0KICAgICAgaWYgbW9kdWxlOg0K
ICAgICAgICByZXR1cm4gbW9kdWxlDQoNCiAgICAjIGhhcyB0aGUgdG9wIG1v
ZHVsZSBhbHJlYWR5IGJlZW4gaW1wb3J0ZWQ/DQogICAgdHJ5Og0KICAgICAg
dG9wX21vZHVsZSA9IHN5cy5tb2R1bGVzW3BhcnRzWzBdXQ0KICAgIGV4Y2Vw
dCBLZXlFcnJvcjoNCg0KICAgICAgIyBsb29rIGZvciB0aGUgdG9wbW9zdCBt
b2R1bGUNCiAgICAgIHRvcF9tb2R1bGUgPSBzZWxmLl9pbXBvcnRfdG9wX21v
ZHVsZShwYXJ0c1swXSkNCiAgICAgIGlmIG5vdCB0b3BfbW9kdWxlOg0KICAg
ICAgICAjIHRoZSB0b3Btb3N0IG1vZHVsZSB3YXNuJ3QgZm91bmQgYXQgYWxs
Lg0KICAgICAgICByYWlzZSBJbXBvcnRFcnJvciwgJ05vIG1vZHVsZSBuYW1l
ZCAnICsgZnFuYW1lDQogICAgICAgIHJldHVybiBzZWxmLl9fY2hhaW5faW1w
b3J0KG5hbWUsIGdsb2JhbHMsIGxvY2FscywgZnJvbWxpc3QpDQoNCiAgICAj
IGZhc3QtcGF0aCBzaW1wbGUgaW1wb3J0cw0KICAgIGlmIGxlbihwYXJ0cykg
PT0gMToNCiAgICAgIGlmIG5vdCBmcm9tbGlzdDoNCiAgICAgICAgcmV0dXJu
IHRvcF9tb2R1bGUNCg0KICAgICAgaWYgbm90IHRvcF9tb2R1bGUuX19kaWN0
X18uZ2V0KCdfX2lzcGtnX18nKToNCiAgICAgICAgIyBfX2lzcGtnX18gaXNu
J3QgZGVmaW5lZCAodGhlIG1vZHVsZSB3YXMgbm90IGltcG9ydGVkIGJ5IHVz
KSwgb3INCiAgICAgICAgIyBpdCBpcyB6ZXJvLg0KICAgICAgICAjDQogICAg
ICAgICMgSW4gdGhlIGZvcm1lciBjYXNlLCB0aGVyZSBpcyBubyB3YXkgdGhh
dCB3ZSBjb3VsZCBpbXBvcnQNCiAgICAgICAgIyBzdWItbW9kdWxlcyB0aGF0
IG9jY3VyIGluIHRoZSBmcm9tbGlzdCAoYnV0IHdlIGNhbid0IHJhaXNlIGFu
DQogICAgICAgICMgZXJyb3IgYmVjYXVzZSBpdCBtYXkganVzdCBiZSBuYW1l
cykgYmVjYXVzZSB3ZSBkb24ndCBrbm93IGhvdw0KICAgICAgICAjIHRvIGRl
YWwgd2l0aCBwYWNrYWdlcyB0aGF0IHdlcmUgaW1wb3J0ZWQgYnkgb3RoZXIg
c3lzdGVtcy4NCiAgICAgICAgIw0KICAgICAgICAjIEluIHRoZSBsYXR0ZXIg
Y2FzZSAoX19pc3BrZ19fID09IDApLCB0aGVyZSBjYW4ndCBiZSBhbnkgc3Vi
LQ0KICAgICAgICAjIG1vZHVsZXMgcHJlc2VudCwgc28gd2UgY2FuIGp1c3Qg
cmV0dXJuLg0KICAgICAgICAjDQogICAgICAgICMgSW4gYm90aCBjYXNlcywg
c2luY2UgbGVuKHBhcnRzKSA9PSAxLCB0aGUgdG9wX21vZHVsZSBpcyBhbHNv
DQogICAgICAgICMgdGhlICJib3R0b20iIHdoaWNoIGlzIHRoZSBkZWZpbmVk
IHJldHVybiB3aGVuIGEgZnJvbWxpc3QgZXhpc3RzLg0KICAgICAgICByZXR1
cm4gdG9wX21vZHVsZQ0KDQogICAgaW1wb3J0ZXIgPSB0b3BfbW9kdWxlLl9f
ZGljdF9fLmdldCgnX19pbXBvcnRlcl9fJykNCiAgICBpZiBpbXBvcnRlcjoN
CiAgICAgIHJldHVybiBpbXBvcnRlci5fZmluaXNoX2ltcG9ydCh0b3BfbW9k
dWxlLCBwYXJ0c1sxOl0sIGZyb21saXN0KQ0KDQogICAgIyBJZiB0aGUgaW1w
b3J0ZXIgZG9lcyBub3QgZXhpc3QsIHRoZW4gd2UgaGF2ZSB0byBiYWlsLiBB
IG1pc3NpbmcgaW1wb3J0ZXINCiAgICAjIG1lYW5zIHRoYXQgc29tZXRoaW5n
IGVsc2UgaW1wb3J0ZWQgdGhlIG1vZHVsZSwgYW5kIHdlIGhhdmUgbm8ga25v
d2xlZGdlDQogICAgIyBvZiBob3cgdG8gZ2V0IHN1Yi1tb2R1bGVzIG91dCBv
ZiB0aGUgdGhpbmcuDQogICAgcmFpc2UgSW1wb3J0RXJyb3IsICdObyBtb2R1
bGUgbmFtZWQgJyArIGZxbmFtZQ0KICAgIHJldHVybiBzZWxmLl9fY2hhaW5f
aW1wb3J0KG5hbWUsIGdsb2JhbHMsIGxvY2FscywgZnJvbWxpc3QpDQoNCiAg
ZGVmIF9kZXRlcm1pbmVfaW1wb3J0X2NvbnRleHQoc2VsZiwgZ2xvYmFscyk6
DQogICAgIiIiUmV0dXJucyB0aGUgY29udGV4dCBpbiB3aGljaCBhIG1vZHVs
ZSBzaG91bGQgYmUgaW1wb3J0ZWQuDQoNCiAgICBUaGUgY29udGV4dCBjb3Vs
ZCBiZSBhIGxvYWRlZCAocGFja2FnZSkgbW9kdWxlIGFuZCB0aGUgaW1wb3J0
ZWQgbW9kdWxlDQogICAgd2lsbCBiZSBsb29rZWQgZm9yIHdpdGhpbiB0aGF0
IHBhY2thZ2UuIFRoZSBjb250ZXh0IGNvdWxkIGFsc28gYmUgTm9uZSwNCiAg
ICBtZWFuaW5nIHRoZXJlIGlzIG5vIGNvbnRleHQgLS0gdGhlIG1vZHVsZSBz
aG91bGQgYmUgbG9va2VkIGZvciBhcyBhDQogICAgInRvcC1sZXZlbCIgbW9k
dWxlLg0KICAgICIiIg0KDQogICAgaWYgbm90IGdsb2JhbHMgb3Igbm90IGds
b2JhbHMuZ2V0KCdfX2ltcG9ydGVyX18nKToNCiAgICAgICMgZ2xvYmFscyBk
b2VzIG5vdCByZWZlciB0byBvbmUgb2Ygb3VyIG1vZHVsZXMgb3IgcGFja2Fn
ZXMuIFRoYXQNCiAgICAgICMgaW1wbGllcyB0aGVyZSBpcyBubyByZWxhdGl2
ZSBpbXBvcnQgY29udGV4dCAoYXMgZmFyIGFzIHdlIGFyZQ0KICAgICAgIyBj
b25jZXJuZWQpLCBhbmQgaXQgc2hvdWxkIGp1c3QgcGljayBpdCBvZmYgdGhl
IHN0YW5kYXJkIHBhdGguDQogICAgICByZXR1cm4gTm9uZQ0KDQogICAgIyBU
aGUgZ2xvYmFscyByZWZlciB0byBhIG1vZHVsZSBvciBwYWNrYWdlIG9mIG91
cnMuIEl0IHdpbGwgZGVmaW5lDQogICAgIyB0aGUgY29udGV4dCBvZiB0aGUg
bmV3IGltcG9ydC4gR2V0IHRoZSBtb2R1bGUvcGFja2FnZSBmcW5hbWUuDQog
ICAgcGFyZW50X2ZxbmFtZSA9IGdsb2JhbHNbJ19fbmFtZV9fJ10NCg0KICAg
ICMgaWYgYSBwYWNrYWdlIGlzIHBlcmZvcm1pbmcgdGhlIGltcG9ydCwgdGhl
biByZXR1cm4gaXRzZWxmIChpbXBvcnRzDQogICAgIyByZWZlciB0byBwa2cg
Y29udGVudHMpDQogICAgaWYgZ2xvYmFsc1snX19pc3BrZ19fJ106DQogICAg
ICBwYXJlbnQgPSBzeXMubW9kdWxlc1twYXJlbnRfZnFuYW1lXQ0KICAgICAg
YXNzZXJ0IGdsb2JhbHMgaXMgcGFyZW50Ll9fZGljdF9fDQogICAgICByZXR1
cm4gcGFyZW50DQoNCiAgICBpID0gc3Ryb3AucmZpbmQocGFyZW50X2ZxbmFt
ZSwgJy4nKQ0KDQogICAgIyBhIG1vZHVsZSBvdXRzaWRlIG9mIGEgcGFja2Fn
ZSBoYXMgbm8gcGFydGljdWxhciBpbXBvcnQgY29udGV4dA0KICAgIGlmIGkg
PT0gLTE6DQogICAgICByZXR1cm4gTm9uZQ0KDQogICAgIyBpZiBhIG1vZHVs
ZSBpbiBhIHBhY2thZ2UgaXMgcGVyZm9ybWluZyB0aGUgaW1wb3J0LCB0aGVu
IHJldHVybiB0aGUNCiAgICAjIHBhY2thZ2UgKGltcG9ydHMgcmVmZXIgdG8g
c2libGluZ3MpDQogICAgcGFyZW50X2ZxbmFtZSA9IHBhcmVudF9mcW5hbWVb
OmldDQogICAgcGFyZW50ID0gc3lzLm1vZHVsZXNbcGFyZW50X2ZxbmFtZV0N
CiAgICBhc3NlcnQgcGFyZW50Ll9fbmFtZV9fID09IHBhcmVudF9mcW5hbWUN
CiAgICByZXR1cm4gcGFyZW50DQoNCiAgZGVmIF9pbXBvcnRfdG9wX21vZHVs
ZShzZWxmLCBuYW1lKToNCiAgICAjIHNjYW4gc3lzLnBhdGggbG9va2luZyBm
b3IgYSBsb2NhdGlvbiBpbiB0aGUgZmlsZXN5c3RlbSB0aGF0IGNvbnRhaW5z
DQogICAgIyB0aGUgbW9kdWxlLCBvciBhbiBJbXBvcnRlciBvYmplY3QgdGhh
dCBjYW4gaW1wb3J0IHRoZSBtb2R1bGUuDQogICAgZm9yIGl0ZW0gaW4gc3lz
LnBhdGg6DQogICAgICBpZiB0eXBlKGl0ZW0pID09IF9TdHJpbmdUeXBlOg0K
ICAgICAgICBtb2R1bGUgPSBzZWxmLmZzX2ltcC5pbXBvcnRfZnJvbV9kaXIo
aXRlbSwgbmFtZSkNCiAgICAgIGVsc2U6DQogICAgICAgIG1vZHVsZSA9IGl0
ZW0uaW1wb3J0X3RvcChuYW1lKQ0KICAgICAgaWYgbW9kdWxlOg0KICAgICAg
ICByZXR1cm4gbW9kdWxlDQogICAgcmV0dXJuIE5vbmUNCg0KICBkZWYgX3Jl
bG9hZF9ob29rKHNlbGYsIG1vZHVsZSk6DQogICAgIlB5dGhvbiBjYWxscyB0
aGlzIGhvb2sgdG8gcmVsb2FkIGEgbW9kdWxlLiINCg0KICAgICMgcmVsb2Fk
aW5nIG9mIGEgbW9kdWxlIG1heSBvciBtYXkgbm90IGJlIHBvc3NpYmxlIChk
ZXBlbmRpbmcgb24gdGhlDQogICAgIyBpbXBvcnRlciksIGJ1dCBhdCBsZWFz
dCB3ZSBjYW4gdmFsaWRhdGUgdGhhdCBpdCdzIG91cnMgdG8gcmVsb2FkDQog
ICAgaW1wb3J0ZXIgPSBtb2R1bGUuX19kaWN0X18uZ2V0KCdfX2ltcG9ydGVy
X18nKQ0KICAgIGlmIG5vdCBpbXBvcnRlcjoNCiAgICAgIHJldHVybiBzZWxm
Ll9fY2hhaW5fcmVsb2FkKG1vZHVsZSkNCg0KICAgICMgb2theS4gaXQgaXMg
dXNpbmcgdGhlIGltcHV0aWwgc3lzdGVtLCBhbmQgd2UgbXVzdCBkZWxlZ2F0
ZSBpdCwgYnV0DQogICAgIyB3ZSBkb24ndCBrbm93IHdoYXQgdG8gZG8gKHll
dCkNCiAgICAjIyMgd2Ugc2hvdWxkIGJsYXN0IHRoZSBtb2R1bGUgZGljdCBh
bmQgZG8gYW5vdGhlciBnZXRfY29kZSgpLiBuZWVkIHRvDQogICAgIyMjIGZs
ZXNoIHRoaXMgb3V0IGFuZCBhZGQgcHJvcGVyIGRvY2NvLi4uDQogICAgcmFp
c2UgU3lzdGVtRXJyb3IsICJyZWxvYWQgbm90IHlldCBpbXBsZW1lbnRlZCIN
Cg0KDQpjbGFzcyBJbXBvcnRlcjoNCiAgIkJhc2UgY2xhc3MgZm9yIHJlcGxh
Y2luZyBzdGFuZGFyZCBpbXBvcnQgZnVuY3Rpb25zLiINCg0KICBkZWYgaW5z
dGFsbChzZWxmKToNCiAgICBzeXMucGF0aC5pbnNlcnQoMCwgc2VsZikNCg0K
ICBkZWYgaW1wb3J0X3RvcChzZWxmLCBuYW1lKToNCiAgICAiSW1wb3J0IGEg
dG9wLWxldmVsIG1vZHVsZS4iDQogICAgcmV0dXJuIHNlbGYuX2ltcG9ydF9v
bmUoTm9uZSwgbmFtZSwgbmFtZSkNCg0KICAjIyMjIyMjIyMjIyMjIyMjIyMj
IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj
IyMjIyMjDQogICMNCiAgIyBQUklWQVRFIE1FVEhPRFMNCiAgIw0KICBkZWYg
X2ZpbmlzaF9pbXBvcnQoc2VsZiwgdG9wLCBwYXJ0cywgZnJvbWxpc3QpOg0K
ICAgICMgaWYgImEuYi5jIiB3YXMgcHJvdmlkZWQsIHRoZW4gbG9hZCB0aGUg
Ii5iLmMiIHBvcnRpb24gZG93biBmcm9tDQogICAgIyBiZWxvdyB0aGUgdG9w
LWxldmVsIG1vZHVsZS4NCiAgICBib3R0b20gPSBzZWxmLl9sb2FkX3RhaWwo
dG9wLCBwYXJ0cykNCg0KICAgICMgaWYgdGhlIGZvcm0gaXMgImltcG9ydCBh
LmIuYyIsIHRoZW4gcmV0dXJuICJhIg0KICAgIGlmIG5vdCBmcm9tbGlzdDoN
CiAgICAgICMgbm8gZnJvbWxpc3Q6IHJldHVybiB0aGUgdG9wIG9mIHRoZSBp
bXBvcnQgdHJlZQ0KICAgICAgcmV0dXJuIHRvcA0KDQogICAgIyB0aGUgdG9w
IG1vZHVsZSB3YXMgaW1wb3J0ZWQgYnkgc2VsZi4NCiAgICAjDQogICAgIyB0
aGlzIG1lYW5zIHRoYXQgdGhlIGJvdHRvbSBtb2R1bGUgd2FzIGFsc28gaW1w
b3J0ZWQgYnkgc2VsZiAoanVzdA0KICAgICMgbm93LCBvciBpbiB0aGUgcGFz
dCBhbmQgd2UgZmV0Y2hlZCBpdCBmcm9tIHN5cy5tb2R1bGVzKS4NCiAgICAj
DQogICAgIyBzaW5jZSB3ZSBpbXBvcnRlZC9oYW5kbGVkIHRoZSBib3R0b20g
bW9kdWxlLCB0aGlzIG1lYW5zIHRoYXQgd2UgY2FuDQogICAgIyBhbHNvIGhh
bmRsZSBpdHMgZnJvbWxpc3QgKGFuZCByZWxpYWJseSB1c2UgX19pc3BrZ19f
KS4NCg0KICAgICMgaWYgdGhlIGJvdHRvbSBub2RlIGlzIGEgcGFja2FnZSwg
dGhlbiAocG90ZW50aWFsbHkpIGltcG9ydCBzb21lIG1vZHVsZXMuDQogICAg
Iw0KICAgICMgbm90ZTogaWYgaXQgaXMgbm90IGEgcGFja2FnZSwgdGhlbiAi
ZnJvbWxpc3QiIHJlZmVycyB0byBuYW1lcyBpbg0KICAgICMgICAgICAgdGhl
IGJvdHRvbSBtb2R1bGUgcmF0aGVyIHRoYW4gbW9kdWxlcy4NCiAgICAjIG5v
dGU6IGZvciBhIG1peCBvZiBuYW1lcyBhbmQgbW9kdWxlcyBpbiB0aGUgZnJv
bWxpc3QsIHdlIHdpbGwNCiAgICAjICAgICAgIGltcG9ydCBhbGwgbW9kdWxl
cyBhbmQgaW5zZXJ0IHRob3NlIGludG8gdGhlIG5hbWVzcGFjZSBvZg0KICAg
ICMgICAgICAgdGhlIHBhY2thZ2UgbW9kdWxlLiBQeXRob24gd2lsbCBwaWNr
IHVwIGFsbCBmcm9tbGlzdCBuYW1lcw0KICAgICMgICAgICAgZnJvbSB0aGUg
Ym90dG9tIChwYWNrYWdlKSBtb2R1bGU7IHNvbWUgd2lsbCBiZSBtb2R1bGVz
IHRoYXQNCiAgICAjICAgICAgIHdlIGltcG9ydGVkIGFuZCBzdG9yZWQgaW4g
dGhlIG5hbWVzcGFjZSwgb3RoZXJzIGFyZSBleHBlY3RlZA0KICAgICMgICAg
ICAgdG8gYmUgcHJlc2VudCBhbHJlYWR5Lg0KICAgIGlmIGJvdHRvbS5fX2lz
cGtnX186DQogICAgICBzZWxmLl9pbXBvcnRfZnJvbWxpc3QoYm90dG9tLCBm
cm9tbGlzdCkNCg0KICAgICMgaWYgdGhlIGZvcm0gaXMgImZyb20gYS5iIGlt
cG9ydCBjLCBkIiB0aGVuIHJldHVybiAiYiINCiAgICByZXR1cm4gYm90dG9t
DQoNCiAgZGVmIF9pbXBvcnRfb25lKHNlbGYsIHBhcmVudCwgbW9kbmFtZSwg
ZnFuYW1lKToNCiAgICAiSW1wb3J0IGEgc2luZ2xlIG1vZHVsZS4iDQoNCiAg
ICAjIGhhcyB0aGUgbW9kdWxlIGFscmVhZHkgYmVlbiBpbXBvcnRlZD8NCiAg
ICB0cnk6DQogICAgICByZXR1cm4gc3lzLm1vZHVsZXNbZnFuYW1lXQ0KICAg
IGV4Y2VwdCBLZXlFcnJvcjoNCiAgICAgIHBhc3MNCg0KICAgICMgbG9hZCB0
aGUgbW9kdWxlJ3MgY29kZSwgb3IgZmV0Y2ggdGhlIG1vZHVsZSBpdHNlbGYN
CiAgICByZXN1bHQgPSBzZWxmLmdldF9jb2RlKHBhcmVudCwgbW9kbmFtZSwg
ZnFuYW1lKQ0KICAgIGlmIHJlc3VsdCBpcyBOb25lOg0KICAgICAgcmV0dXJu
IE5vbmUNCg0KICAgICMjIyBiYWNrd2FyZHMtY29tcGF0DQogICAgaWYgbGVu
KHJlc3VsdCkgPT0gMjoNCiAgICAgIHJlc3VsdCA9IHJlc3VsdCArICh7fSwp
DQoNCiAgICBtb2R1bGUgPSBzZWxmLl9wcm9jZXNzX3Jlc3VsdChyZXN1bHQs
IGZxbmFtZSkNCg0KICAgICMgaW5zZXJ0IHRoZSBtb2R1bGUgaW50byBpdHMg
cGFyZW50DQogICAgaWYgcGFyZW50Og0KICAgICAgc2V0YXR0cihwYXJlbnQs
IG1vZG5hbWUsIG1vZHVsZSkNCiAgICByZXR1cm4gbW9kdWxlDQoNCiAgZGVm
IF9wcm9jZXNzX3Jlc3VsdChzZWxmLCAoaXNwa2csIGNvZGUsIHZhbHVlcyks
IGZxbmFtZSk6DQogICAgIyBkaWQgZ2V0X2NvZGUoKSByZXR1cm4gYW4gYWN0
dWFsIG1vZHVsZT8gKHJhdGhlciB0aGFuIGEgY29kZSBvYmplY3QpDQogICAg
aXNfbW9kdWxlID0gdHlwZShjb2RlKSBpcyBfTW9kdWxlVHlwZQ0KDQogICAg
IyB1c2UgdGhlIHJldHVybmVkIG1vZHVsZSwgb3IgY3JlYXRlIGEgbmV3IG9u
ZSB0byBleGVjIGNvZGUgaW50bw0KICAgIGlmIGlzX21vZHVsZToNCiAgICAg
IG1vZHVsZSA9IGNvZGUNCiAgICBlbHNlOg0KICAgICAgbW9kdWxlID0gaW1w
Lm5ld19tb2R1bGUoZnFuYW1lKQ0KDQogICAgIyMjIHJlY29yZCBwYWNrYWdl
cyBhIGJpdCBkaWZmZXJlbnRseT8/DQogICAgbW9kdWxlLl9faW1wb3J0ZXJf
XyA9IHNlbGYNCiAgICBtb2R1bGUuX19pc3BrZ19fID0gaXNwa2cNCg0KICAg
ICMgaW5zZXJ0IGFkZGl0aW9uYWwgdmFsdWVzIGludG8gdGhlIG1vZHVsZSAo
YmVmb3JlIGV4ZWN1dGluZyB0aGUgY29kZSkNCiAgICBtb2R1bGUuX19kaWN0
X18udXBkYXRlKHZhbHVlcykNCg0KICAgICMgdGhlIG1vZHVsZSBpcyBhbG1v
c3QgcmVhZHkuLi4gbWFrZSBpdCB2aXNpYmxlDQogICAgc3lzLm1vZHVsZXNb
ZnFuYW1lXSA9IG1vZHVsZQ0KDQogICAgIyBleGVjdXRlIHRoZSBjb2RlIHdp
dGhpbiB0aGUgbW9kdWxlJ3MgbmFtZXNwYWNlDQogICAgaWYgbm90IGlzX21v
ZHVsZToNCiAgICAgIGV4ZWMgY29kZSBpbiBtb2R1bGUuX19kaWN0X18NCg0K
ICAgIHJldHVybiBtb2R1bGUNCg0KICBkZWYgX2xvYWRfdGFpbChzZWxmLCBt
LCBwYXJ0cyk6DQogICAgIiIiSW1wb3J0IHRoZSByZXN0IG9mIHRoZSBtb2R1
bGVzLCBkb3duIGZyb20gdGhlIHRvcC1sZXZlbCBtb2R1bGUuDQoNCiAgICBS
ZXR1cm5zIHRoZSBsYXN0IG1vZHVsZSBpbiB0aGUgZG90dGVkIGxpc3Qgb2Yg
bW9kdWxlcy4NCiAgICAiIiINCiAgICBmb3IgcGFydCBpbiBwYXJ0czoNCiAg
ICAgIGZxbmFtZSA9ICIlcy4lcyIgJSAobS5fX25hbWVfXywgcGFydCkNCiAg
ICAgIG0gPSBzZWxmLl9pbXBvcnRfb25lKG0sIHBhcnQsIGZxbmFtZSkNCiAg
ICAgIGlmIG5vdCBtOg0KICAgICAgICByYWlzZSBJbXBvcnRFcnJvciwgIk5v
IG1vZHVsZSBuYW1lZCAiICsgZnFuYW1lDQogICAgcmV0dXJuIG0NCg0KICBk
ZWYgX2ltcG9ydF9mcm9tbGlzdChzZWxmLCBwYWNrYWdlLCBmcm9tbGlzdCk6
DQogICAgJ0ltcG9ydCBhbnkgc3ViLW1vZHVsZXMgaW4gdGhlICJmcm9tIiBs
aXN0LicNCg0KICAgICMgaWYgJyonIGlzIHByZXNlbnQgaW4gdGhlIGZyb21s
aXN0LCB0aGVuIGxvb2sgZm9yIHRoZSAnX19hbGxfXycgdmFyaWFibGUNCiAg
ICAjIHRvIGZpbmQgYWRkaXRpb25hbCBpdGVtcyAobW9kdWxlcykgdG8gaW1w
b3J0Lg0KICAgIGlmICcqJyBpbiBmcm9tbGlzdDoNCiAgICAgIGZyb21saXN0
ID0gbGlzdChmcm9tbGlzdCkgKyBsaXN0KHBhY2thZ2UuX19kaWN0X18uZ2V0
KCdfX2FsbF9fJywgW10pKQ0KDQogICAgZm9yIHN1YiBpbiBmcm9tbGlzdDoN
CiAgICAgICMgaWYgdGhlIG5hbWUgaXMgYWxyZWFkeSBwcmVzZW50LCB0aGVu
IGRvbid0IHRyeSB0byBpbXBvcnQgaXQgKGl0DQogICAgICAjIG1pZ2h0IG5v
dCBiZSBhIG1vZHVsZSEpLg0KICAgICAgaWYgc3ViICE9ICcqJyBhbmQgbm90
IGhhc2F0dHIocGFja2FnZSwgc3ViKToNCiAgICAgICAgc3VibmFtZSA9ICIl
cy4lcyIgJSAocGFja2FnZS5fX25hbWVfXywgc3ViKQ0KICAgICAgICBzdWJt
b2QgPSBzZWxmLl9pbXBvcnRfb25lKHBhY2thZ2UsIHN1Yiwgc3VibmFtZSkN
CiAgICAgICAgaWYgbm90IHN1Ym1vZDoNCiAgICAgICAgICByYWlzZSBJbXBv
cnRFcnJvciwgImNhbm5vdCBpbXBvcnQgbmFtZSAiICsgc3VibmFtZQ0KDQog
IGRlZiBfZG9faW1wb3J0KHNlbGYsIHBhcmVudCwgcGFydHMsIGZyb21saXN0
KToNCiAgICAiIiJBdHRlbXB0IHRvIGltcG9ydCB0aGUgbW9kdWxlIHJlbGF0
aXZlIHRvIHBhcmVudC4NCg0KICAgIFRoaXMgbWV0aG9kIGlzIHVzZWQgd2hl
biB0aGUgaW1wb3J0IGNvbnRleHQgc3BlY2lmaWVzIHRoYXQgPHNlbGY+DQog
ICAgaW1wb3J0ZWQgdGhlIHBhcmVudCBtb2R1bGUuDQogICAgIiIiDQogICAg
dG9wX25hbWUgPSBwYXJ0c1swXQ0KICAgIHRvcF9mcW5hbWUgPSBwYXJlbnQu
X19uYW1lX18gKyAnLicgKyB0b3BfbmFtZQ0KICAgIHRvcF9tb2R1bGUgPSBz
ZWxmLl9pbXBvcnRfb25lKHBhcmVudCwgdG9wX25hbWUsIHRvcF9mcW5hbWUp
DQogICAgaWYgbm90IHRvcF9tb2R1bGU6DQogICAgICAjIHRoaXMgaW1wb3J0
ZXIgYW5kIHBhcmVudCBjb3VsZCBub3QgZmluZCB0aGUgbW9kdWxlIChyZWxh
dGl2ZWx5KQ0KICAgICAgcmV0dXJuIE5vbmUNCg0KICAgIHJldHVybiBzZWxm
Ll9maW5pc2hfaW1wb3J0KHRvcF9tb2R1bGUsIHBhcnRzWzE6XSwgZnJvbWxp
c3QpDQoNCiAgIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj
IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KICAjDQogICMg
TUVUSE9EUyBUTyBPVkVSUklERQ0KICAjDQogIGRlZiBnZXRfY29kZShzZWxm
LCBwYXJlbnQsIG1vZG5hbWUsIGZxbmFtZSk6DQogICAgIiIiRmluZCBhbmQg
cmV0cmlldmUgdGhlIGNvZGUgZm9yIHRoZSBnaXZlbiBtb2R1bGUuDQoNCiAg
ICBwYXJlbnQgc3BlY2lmaWVzIGEgcGFyZW50IG1vZHVsZSB0byBkZWZpbmUg
YSBjb250ZXh0IGZvciBpbXBvcnRpbmcuIEl0DQogICAgbWF5IGJlIE5vbmUs
IGluZGljYXRpbmcgbm8gcGFydGljdWxhciBjb250ZXh0IGZvciB0aGUgc2Vh
cmNoLg0KDQogICAgbW9kbmFtZSBzcGVjaWZpZXMgYSBzaW5nbGUgbW9kdWxl
IChub3QgZG90dGVkKSB3aXRoaW4gdGhlIHBhcmVudC4NCg0KICAgIGZxbmFt
ZSBzcGVjaWZpZXMgdGhlIGZ1bGx5LXF1YWxpZmllZCBtb2R1bGUgbmFtZS4g
VGhpcyBpcyBhIChwb3RlbnRpYWxseSkNCiAgICBkb3R0ZWQgbmFtZSBmcm9t
IHRoZSAicm9vdCIgb2YgdGhlIG1vZHVsZSBuYW1lc3BhY2UgZG93biB0byB0
aGUgbW9kbmFtZS4NCiAgICBJZiB0aGVyZSBpcyBubyBwYXJlbnQsIHRoZW4g
bW9kbmFtZT09ZnFuYW1lLg0KDQogICAgVGhpcyBtZXRob2Qgc2hvdWxkIHJl
dHVybiBOb25lLCBvciBhIDMtdHVwbGUuDQoNCiAgICAqIElmIHRoZSBtb2R1
bGUgd2FzIG5vdCBmb3VuZCwgdGhlbiBOb25lIHNob3VsZCBiZSByZXR1cm5l
ZC4NCg0KICAgICogVGhlIGZpcnN0IGl0ZW0gb2YgdGhlIDItIG9yIDMtdHVw
bGUgc2hvdWxkIGJlIHRoZSBpbnRlZ2VyIDAgb3IgMSwNCiAgICAgIHNwZWNp
Znlpbmcgd2hldGhlciB0aGUgbW9kdWxlIHRoYXQgd2FzIGZvdW5kIGlzIGEg
cGFja2FnZSBvciBub3QuDQoNCiAgICAqIFRoZSBzZWNvbmQgaXRlbSBpcyB0
aGUgY29kZSBvYmplY3QgZm9yIHRoZSBtb2R1bGUgKGl0IHdpbGwgYmUNCiAg
ICAgIGV4ZWN1dGVkIHdpdGhpbiB0aGUgbmV3IG1vZHVsZSdzIG5hbWVzcGFj
ZSkuIFRoaXMgaXRlbSBjYW4gYWxzbw0KICAgICAgYmUgYSBmdWxseS1sb2Fk
ZWQgbW9kdWxlIG9iamVjdCAoZS5nLiBsb2FkZWQgZnJvbSBhIHNoYXJlZCBs
aWIpLg0KDQogICAgKiBUaGUgdGhpcmQgaXRlbSBpcyBhIGRpY3Rpb25hcnkg
b2YgbmFtZS92YWx1ZSBwYWlycyB0aGF0IHdpbGwgYmUNCiAgICAgIGluc2Vy
dGVkIGludG8gbmV3IG1vZHVsZSBiZWZvcmUgdGhlIGNvZGUgb2JqZWN0IGlz
IGV4ZWN1dGVkLiBUaGlzDQogICAgICBpcyBwcm92aWRlZCBpbiBjYXNlIHRo
ZSBtb2R1bGUncyBjb2RlIGV4cGVjdHMgY2VydGFpbiB2YWx1ZXMgKHN1Y2gN
CiAgICAgIGFzIHdoZXJlIHRoZSBtb2R1bGUgd2FzIGZvdW5kKS4gV2hlbiB0
aGUgc2Vjb25kIGl0ZW0gaXMgYSBtb2R1bGUNCiAgICAgIG9iamVjdCwgdGhl
biB0aGVzZSBuYW1lcy92YWx1ZXMgd2lsbCBiZSBpbnNlcnRlZCAqYWZ0ZXIq
IHRoZSBtb2R1bGUNCiAgICAgIGhhcyBiZWVuIGxvYWRlZC9pbml0aWFsaXpl
ZC4NCiAgICAiIiINCiAgICByYWlzZSBSdW50aW1lRXJyb3IsICJnZXRfY29k
ZSBub3QgaW1wbGVtZW50ZWQiDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMj
IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj
IyMjIw0KIw0KIyBTb21lIGhhbmR5IHN0dWZmIGZvciB0aGUgSW1wb3J0ZXJz
DQojDQoNCiMgYnl0ZS1jb21waWxlZCBmaWxlIHN1ZmZpYyBjaGFyYWN0ZXIN
Cl9zdWZmaXhfY2hhciA9IF9fZGVidWdfXyBhbmQgJ2MnIG9yICdvJw0KDQoj
IGJ5dGUtY29tcGlsZWQgZmlsZSBzdWZmaXgNCl9zdWZmaXggPSAnLnB5JyAr
IF9zdWZmaXhfY2hhcg0KDQojIHRoZSBDX0VYVEVOU0lPTiBzdWZmaXhlcw0K
X2Nfc3VmZml4ZXMgPSBmaWx0ZXIobGFtYmRhIHg6IHhbMl0gPT0gaW1wLkNf
RVhURU5TSU9OLCBpbXAuZ2V0X3N1ZmZpeGVzKCkpDQoNCmRlZiBfY29tcGls
ZShwYXRobmFtZSwgdGltZXN0YW1wKToNCiAgIiIiQ29tcGlsZSAoYW5kIGNh
Y2hlKSBhIFB5dGhvbiBzb3VyY2UgZmlsZS4NCg0KICBUaGUgZmlsZSBzcGVj
aWZpZWQgYnkgPHBhdGhuYW1lPiBpcyBjb21waWxlZCB0byBhIGNvZGUgb2Jq
ZWN0IGFuZA0KICByZXR1cm5lZC4NCg0KICBQcmVzdW1pbmcgdGhlIGFwcHJv
cHJpYXRlIHByaXZpbGVnZXMgZXhpc3QsIHRoZSBieXRlY29kZXMgd2lsbCBi
ZQ0KICBzYXZlZCBiYWNrIHRvIHRoZSBmaWxlc3lzdGVtIGZvciBmdXR1cmUg
aW1wb3J0cy4gVGhlIHNvdXJjZSBmaWxlJ3MNCiAgbW9kaWZpY2F0aW9uIHRp
bWVzdGFtcCBtdXN0IGJlIHByb3ZpZGVkIGFzIGEgTG9uZyB2YWx1ZS4NCiAg
IiIiDQogIGNvZGVzdHJpbmcgPSBvcGVuKHBhdGhuYW1lLCAncicpLnJlYWQo
KQ0KICBpZiBjb2Rlc3RyaW5nIGFuZCBjb2Rlc3RyaW5nWy0xXSAhPSAnXG4n
Og0KICAgIGNvZGVzdHJpbmcgPSBjb2Rlc3RyaW5nICsgJ1xuJw0KICBjb2Rl
ID0gX19idWlsdGluX18uY29tcGlsZShjb2Rlc3RyaW5nLCBwYXRobmFtZSwg
J2V4ZWMnKQ0KDQogICMgdHJ5IHRvIGNhY2hlIHRoZSBjb21waWxlZCBjb2Rl
DQogIHRyeToNCiAgICBmID0gb3BlbihwYXRobmFtZSArIF9zdWZmaXhfY2hh
ciwgJ3diJykNCiAgZXhjZXB0IElPRXJyb3I6DQogICAgcGFzcw0KICBlbHNl
Og0KICAgIGYud3JpdGUoJ1wwXDBcMFwwJykNCiAgICBmLndyaXRlKHN0cnVj
dC5wYWNrKCc8SScsIHRpbWVzdGFtcCkpDQogICAgbWFyc2hhbC5kdW1wKGNv
ZGUsIGYpDQogICAgZi5mbHVzaCgpDQogICAgZi5zZWVrKDAsIDApDQogICAg
Zi53cml0ZShpbXAuZ2V0X21hZ2ljKCkpDQogICAgZi5jbG9zZSgpDQoNCiAg
cmV0dXJuIGNvZGUNCg0KX29zX3N0YXQgPSBfb3NfcGF0aF9qb2luID0gTm9u
ZQ0KZGVmIF9vc19ib290c3RyYXAoKToNCiAgIlNldCB1cCAnb3MnIG1vZHVs
ZSByZXBsYWNlbWVudCBmdW5jdGlvbnMgZm9yIHVzZSBkdXJpbmcgaW1wb3J0
IGJvb3RzdHJhcC4iDQoNCiAgbmFtZXMgPSBzeXMuYnVpbHRpbl9tb2R1bGVf
bmFtZXMNCg0KICBqb2luID0gTm9uZQ0KICBpZiAncG9zaXgnIGluIG5hbWVz
Og0KICAgIHNlcCA9ICcvJw0KICAgIGZyb20gcG9zaXggaW1wb3J0IHN0YXQN
CiAgZWxpZiAnbnQnIGluIG5hbWVzOg0KICAgIHNlcCA9ICdcXCcNCiAgICBm
cm9tIG50IGltcG9ydCBzdGF0DQogIGVsaWYgJ2RvcycgaW4gbmFtZXM6DQog
ICAgc2VwID0gJ1xcJw0KICAgIGZyb20gZG9zIGltcG9ydCBzdGF0DQogIGVs
aWYgJ29zMicgaW4gbmFtZXM6DQogICAgc2VwID0gJ1xcJw0KICAgIGZyb20g
b3MyIGltcG9ydCBzdGF0DQogIGVsaWYgJ21hYycgaW4gbmFtZXM6DQogICAg
ZnJvbSBtYWMgaW1wb3J0IHN0YXQNCiAgICBkZWYgam9pbihhLCBiKToNCiAg
ICAgIGlmIGEgPT0gJyc6DQogICAgICAgIHJldHVybiBiDQogICAgICBwYXRo
ID0gcw0KICAgICAgaWYgJzonIG5vdCBpbiBhOg0KICAgICAgICBhID0gJzon
ICsgYQ0KICAgICAgaWYgYVstMTpdIDw+ICc6JzoNCiAgICAgICAgYSA9IGEg
KyAnOicNCiAgICAgIHJldHVybiBhICsgYg0KICBlbHNlOg0KICAgIHJhaXNl
IEltcG9ydEVycm9yLCAnbm8gb3Mgc3BlY2lmaWMgbW9kdWxlIGZvdW5kJw0K
ICANCiAgaWYgam9pbiBpcyBOb25lOg0KICAgIGRlZiBqb2luKGEsIGIsIHNl
cD1zZXApOg0KICAgICAgaWYgYSA9PSAnJzoNCiAgICAgICAgcmV0dXJuIGIN
CiAgICAgIGxhc3RjaGFyID0gYVstMTpdDQogICAgICBpZiBsYXN0Y2hhciA9
PSAnLycgb3IgbGFzdGNoYXIgPT0gc2VwOg0KICAgICAgICByZXR1cm4gYSAr
IGINCiAgICAgIHJldHVybiBhICsgc2VwICsgYg0KDQogIGdsb2JhbCBfb3Nf
c3RhdA0KICBfb3Nfc3RhdCA9IHN0YXQNCg0KICBnbG9iYWwgX29zX3BhdGhf
am9pbg0KICBfb3NfcGF0aF9qb2luID0gam9pbg0KDQpkZWYgX29zX3BhdGhf
aXNkaXIocGF0aG5hbWUpOg0KICAiTG9jYWwgcmVwbGFjZW1lbnQgZm9yIG9z
LnBhdGguaXNkaXIoKS4iDQogIHRyeToNCiAgICBzID0gX29zX3N0YXQocGF0
aG5hbWUpDQogIGV4Y2VwdCBPU0Vycm9yOg0KICAgIHJldHVybiBOb25lDQog
IHJldHVybiAoc1swXSAmIDAxNzAwMDApID09IDAwNDAwMDANCg0KZGVmIF90
aW1lc3RhbXAocGF0aG5hbWUpOg0KICAiUmV0dXJuIHRoZSBmaWxlIG1vZGlm
aWNhdGlvbiB0aW1lIGFzIGEgTG9uZy4iDQogIHRyeToNCiAgICBzID0gX29z
X3N0YXQocGF0aG5hbWUpDQogIGV4Y2VwdCBPU0Vycm9yOg0KICAgIHJldHVy
biBOb25lDQogIHJldHVybiBsb25nKHNbOF0pDQoNCmRlZiBfZnNfaW1wb3J0
KGRpciwgbW9kbmFtZSwgZnFuYW1lKToNCiAgIkZldGNoIGEgbW9kdWxlIGZy
b20gdGhlIGZpbGVzeXN0ZW0uIg0KDQogIHBhdGhuYW1lID0gX29zX3BhdGhf
am9pbihkaXIsIG1vZG5hbWUpDQogIGlmIF9vc19wYXRoX2lzZGlyKHBhdGhu
YW1lKToNCiAgICB2YWx1ZXMgPSB7ICdfX3BrZ2Rpcl9fJyA6IHBhdGhuYW1l
LCAnX19wYXRoX18nIDogWyBwYXRobmFtZSBdIH0NCiAgICBpc3BrZyA9IDEN
CiAgICBwYXRobmFtZSA9IF9vc19wYXRoX2pvaW4ocGF0aG5hbWUsICdfX2lu
aXRfXycpDQogIGVsc2U6DQogICAgdmFsdWVzID0geyB9DQogICAgaXNwa2cg
PSAwDQoNCiAgICAjIGxvb2sgZm9yIGR5bmxvYWQgbW9kdWxlcw0KICAgIGZv
ciBkZXNjIGluIF9jX3N1ZmZpeGVzOg0KICAgICAgZmlsZSA9IHBhdGhuYW1l
ICsgZGVzY1swXQ0KICAgICAgdHJ5Og0KICAgICAgICBmcCA9IG9wZW4oZmls
ZSwgZGVzY1sxXSkNCiAgICAgIGV4Y2VwdCBJT0Vycm9yOg0KICAgICAgICBw
YXNzDQogICAgICBlbHNlOg0KICAgICAgICBtb2R1bGUgPSBpbXAubG9hZF9t
b2R1bGUoZnFuYW1lLCBmcCwgZmlsZSwgZGVzYykNCiAgICAgICAgdmFsdWVz
WydfX2ZpbGVfXyddID0gZmlsZQ0KICAgICAgICByZXR1cm4gMCwgbW9kdWxl
LCB2YWx1ZXMNCg0KICB0X3B5ID0gX3RpbWVzdGFtcChwYXRobmFtZSArICcu
cHknKQ0KICB0X3B5YyA9IF90aW1lc3RhbXAocGF0aG5hbWUgKyBfc3VmZml4
KQ0KICBpZiB0X3B5IGlzIE5vbmUgYW5kIHRfcHljIGlzIE5vbmU6DQogICAg
cmV0dXJuIE5vbmUNCiAgY29kZSA9IE5vbmUNCiAgaWYgdF9weSBpcyBOb25l
IG9yICh0X3B5YyBpcyBub3QgTm9uZSBhbmQgdF9weWMgPj0gdF9weSk6DQog
ICAgZmlsZSA9IHBhdGhuYW1lICsgX3N1ZmZpeA0KICAgIGYgPSBvcGVuKGZp
bGUsICdyYicpDQogICAgaWYgZi5yZWFkKDQpID09IGltcC5nZXRfbWFnaWMo
KToNCiAgICAgIHQgPSBzdHJ1Y3QudW5wYWNrKCc8SScsIGYucmVhZCg0KSlb
MF0NCiAgICAgIGlmIHQgPT0gdF9weToNCiAgICAgICAgY29kZSA9IG1hcnNo
YWwubG9hZChmKQ0KICAgIGYuY2xvc2UoKQ0KICBpZiBjb2RlIGlzIE5vbmU6
DQogICAgZmlsZSA9IHBhdGhuYW1lICsgJy5weScNCiAgICBjb2RlID0gX2Nv
bXBpbGUoZmlsZSwgdF9weSkNCg0KICB2YWx1ZXNbJ19fZmlsZV9fJ10gPSBm
aWxlDQogIHJldHVybiBpc3BrZywgY29kZSwgdmFsdWVzDQoNCg0KIyMjIyMj
IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj
IyMjIyMjIyMjIyMjIyMjIyMjIw0KIw0KIyBTaW1wbGUgZnVuY3Rpb24tYmFz
ZWQgaW1wb3J0ZXINCiMNCmNsYXNzIEZ1bmNJbXBvcnRlcihJbXBvcnRlcik6
DQogICJJbXBvcnRlciBzdWJjbGFzcyB0byB1c2UgYSBzdXBwbGllZCBmdW5j
dGlvbiByYXRoZXIgdGhhbiBtZXRob2Qgb3ZlcnJpZGVzLiINCiAgZGVmIF9f
aW5pdF9fKHNlbGYsIGZ1bmMpOg0KICAgIHNlbGYuZnVuYyA9IGZ1bmMNCiAg
ZGVmIGdldF9jb2RlKHNlbGYsIHBhcmVudCwgbW9kbmFtZSwgZnFuYW1lKToN
CiAgICByZXR1cm4gc2VsZi5mdW5jKHBhcmVudCwgbW9kbmFtZSwgZnFuYW1l
KQ0KDQpkZWYgaW5zdGFsbF93aXRoKGZ1bmMpOg0KICBGdW5jSW1wb3J0ZXIo
ZnVuYykuaW5zdGFsbCgpDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj
IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj
Iw0KIw0KIyBCYXNlIGNsYXNzIGZvciBhcmNoaXZlLWJhc2VkIGltcG9ydGlu
Zw0KIw0KY2xhc3MgUGFja2FnZUFyY2hpdmVJbXBvcnRlcihJbXBvcnRlcik6
DQogICIiIkltcG9ydGVyIHN1YmNsYXNzIHRvIGltcG9ydCBmcm9tIChmaWxl
KSBhcmNoaXZlcy4NCg0KICBUaGlzIEltcG9ydGVyIGhhbmRsZXMgaW1wb3J0
cyBvZiB0aGUgc3R5bGUgPGFyY2hpdmU+LjxzdWJmaWxlPiwgd2hlcmUNCiAg
PGFyY2hpdmU+IGNhbiBiZSBsb2NhdGVkIHVzaW5nIGEgc3ViY2xhc3Mtc3Bl
Y2lmaWMgbWVjaGFuaXNtIGFuZCB0aGUNCiAgPHN1YmZpbGU+IGlzIGZvdW5k
IGluIHRoZSBhcmNoaXZlIHVzaW5nIGEgc3ViY2xhc3Mtc3BlY2lmaWMgbWVj
aGFuaXNtLg0KDQogIFRoaXMgY2xhc3MgZGVmaW5lcyB0d28gaG9va3MgZm9y
IHN1YmNsYXNzZXM6IG9uZSB0byBsb2NhdGUgYW4gYXJjaGl2ZQ0KICAoYW5k
IHBvc3NpYmx5IHJldHVybiBzb21lIGNvbnRleHQgZm9yIGZ1dHVyZSBzdWJm
aWxlIGxvb2t1cHMpLCBhbmQgb25lDQogIHRvIGxvY2F0ZSBzdWJmaWxlcy4N
CiAgIiIiDQoNCiAgZGVmIGdldF9jb2RlKHNlbGYsIHBhcmVudCwgbW9kbmFt
ZSwgZnFuYW1lKToNCiAgICBpZiBwYXJlbnQ6DQogICAgICAjIHRoZSBJbXBv
cnRlci5fZmluaXNoX2ltcG9ydCBsb2dpYyBlbnN1cmVzIHRoYXQgd2UgaGFu
ZGxlIGltcG9ydHMNCiAgICAgICMgdW5kZXIgdGhlIHRvcCBsZXZlbCBtb2R1
bGUgKHBhY2thZ2UgLyBhcmNoaXZlKS4NCiAgICAgIGFzc2VydCBwYXJlbnQu
X19pbXBvcnRlcl9fID09IHNlbGYNCg0KICAgICAgIyBpZiBhIHBhcmVudCAi
cGFja2FnZSIgaXMgcHJvdmlkZWQsIHRoZW4gd2UgYXJlIGltcG9ydGluZyBh
IHN1Yi1maWxlDQogICAgICAjIGZyb20gdGhlIGFyY2hpdmUuDQogICAgICBy
ZXN1bHQgPSBzZWxmLmdldF9zdWJmaWxlKHBhcmVudC5fX2FyY2hpdmVfXywg
bW9kbmFtZSkNCiAgICAgIGlmIHJlc3VsdCBpcyBOb25lOg0KICAgICAgICBy
ZXR1cm4gTm9uZQ0KICAgICAgaWYgdHlwZShyZXN1bHQpID09IHR5cGUoKCkp
Og0KICAgICAgICByZXR1cm4gKDAsKSArIHJlc3VsdA0KICAgICAgcmV0dXJu
IDAsIHJlc3VsdA0KDQogICAgIyBubyBwYXJlbnQgd2FzIHByb3ZpZGVkLCBz
byB0aGUgYXJjaGl2ZSBzaG91bGQgZXhpc3Qgc29tZXdoZXJlIG9uIHRoZQ0K
ICAgICMgZGVmYXVsdCAicGF0aCIuDQogICAgYXJjaGl2ZSA9IHNlbGYuZ2V0
X2FyY2hpdmUobW9kbmFtZSkNCiAgICBpZiBhcmNoaXZlIGlzIE5vbmU6DQog
ICAgICByZXR1cm4gTm9uZQ0KICAgIHJldHVybiAxLCAiIiwgeydfX2FyY2hp
dmVfXyc6YXJjaGl2ZX0NCg0KICBkZWYgZ2V0X2FyY2hpdmUoc2VsZiwgbW9k
bmFtZSk6DQogICAgIiIiR2V0IGFuIGFyY2hpdmUgb2YgbW9kdWxlcy4NCg0K
ICAgIFRoaXMgbWV0aG9kIHNob3VsZCBsb2NhdGUgYW4gYXJjaGl2ZSBhbmQg
cmV0dXJuIGEgdmFsdWUgd2hpY2ggY2FuIGJlDQogICAgdXNlZCBieSBnZXRf
c3ViZmlsZSB0byBsb2FkIG1vZHVsZXMgZnJvbSBpdC4gVGhlIHZhbHVlIG1h
eSBiZSBhIHNpbXBsZQ0KICAgIHBhdGhuYW1lLCBhbiBvcGVuIGZpbGUsIG9y
IGEgY29tcGxleCBvYmplY3QgdGhhdCBjYWNoZXMgaW5mb3JtYXRpb24NCiAg
ICBmb3IgZnV0dXJlIGltcG9ydHMuDQoNCiAgICBSZXR1cm4gTm9uZSBpZiB0
aGUgYXJjaGl2ZSB3YXMgbm90IGZvdW5kLg0KICAgICIiIg0KICAgIHJhaXNl
IFJ1bnRpbWVFcnJvciwgImdldF9hcmNoaXZlIG5vdCBpbXBsZW1lbnRlZCIN
Cg0KICBkZWYgZ2V0X3N1YmZpbGUoc2VsZiwgYXJjaGl2ZSwgbW9kbmFtZSk6
DQogICAgIiIiR2V0IGNvZGUgZnJvbSBhIHN1YmZpbGUgaW4gdGhlIHNwZWNp
ZmllZCBhcmNoaXZlLg0KDQogICAgR2l2ZW4gdGhlIHNwZWNpZmllZCBhcmNo
aXZlIChhcyByZXR1cm5lZCBieSBnZXRfYXJjaGl2ZSgpKSwgbG9jYXRlDQog
ICAgYW5kIHJldHVybiBhIGNvZGUgb2JqZWN0IGZvciB0aGUgc3BlY2lmaWVk
IG1vZHVsZSBuYW1lLg0KDQogICAgQSAyLXR1cGxlIG1heSBiZSByZXR1cm5l
ZCwgY29uc2lzdGluZyBvZiBhIGNvZGUgb2JqZWN0IGFuZCBhIGRpY3QNCiAg
ICBvZiBuYW1lL3ZhbHVlcyB0byBwbGFjZSBpbnRvIHRoZSB0YXJnZXQgbW9k
dWxlLg0KDQogICAgUmV0dXJuIE5vbmUgaWYgdGhlIHN1YmZpbGUgd2FzIG5v
dCBmb3VuZC4NCiAgICAiIiINCiAgICByYWlzZSBSdW50aW1lRXJyb3IsICJn
ZXRfc3ViZmlsZSBub3QgaW1wbGVtZW50ZWQiDQoNCg0KY2xhc3MgUGFja2Fn
ZUFyY2hpdmUoUGFja2FnZUFyY2hpdmVJbXBvcnRlcik6DQogICJQYWNrYWdl
QXJjaGl2ZUltcG9ydGVyIHN1YmNsYXNzIHRoYXQgcmVmZXJzIHRvIGEgc3Bl
Y2lmaWMgYXJjaGl2ZS4iDQoNCiAgZGVmIF9faW5pdF9fKHNlbGYsIG1vZG5h
bWUsIGFyY2hpdmVfcGF0aG5hbWUpOg0KICAgIHNlbGYuX19tb2RuYW1lID0g
bW9kbmFtZQ0KICAgIHNlbGYuX19wYXRoID0gYXJjaGl2ZV9wYXRobmFtZQ0K
DQogIGRlZiBnZXRfYXJjaGl2ZShzZWxmLCBtb2RuYW1lKToNCiAgICBpZiBt
b2RuYW1lID09IHNlbGYuX19tb2RuYW1lOg0KICAgICAgcmV0dXJuIHNlbGYu
X19wYXRoDQogICAgcmV0dXJuIE5vbmUNCg0KICAjIGdldF9zdWJmaWxlIGlz
IHBhc3NlZCB0aGUgZnVsbCBwYXRobmFtZSBvZiB0aGUgYXJjaGl2ZQ0KDQoN
CiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj
IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMNCiMgRW11bGF0ZSB0aGUg
c3RhbmRhcmQgZGlyZWN0b3J5LWJhc2VkIGltcG9ydCBtZWNoYW5pc20NCiMN
CmNsYXNzIERpcmVjdG9yeUltcG9ydGVyKEltcG9ydGVyKToNCiAgIkltcG9y
dGVyIHN1YmNsYXNzIHRvIGVtdWxhdGUgdGhlIHN0YW5kYXJkIGltcG9ydGVy
LiINCg0KICBkZWYgX19pbml0X18oc2VsZiwgZGlyKToNCiAgICBzZWxmLmRp
ciA9IGRpcg0KDQogIGRlZiBnZXRfY29kZShzZWxmLCBwYXJlbnQsIG1vZG5h
bWUsIGZxbmFtZSk6DQogICAgaWYgcGFyZW50Og0KICAgICAgZGlyID0gcGFy
ZW50Ll9fcGtnZGlyX18NCiAgICBlbHNlOg0KICAgICAgZGlyID0gc2VsZi5k
aXINCg0KICAgICMgZGVmZXIgdGhlIGxvYWRpbmcgb2YgT1MtcmVsYXRlZCBm
YWNpbGl0aWVzDQogICAgaWYgbm90IF9vc19zdGF0Og0KICAgICAgX29zX2Jv
b3RzdHJhcCgpDQoNCiAgICAjIFJldHVybiB0aGUgbW9kdWxlIChhbmQgb3Ro
ZXIgaW5mbykgaWYgZm91bmQgaW4gdGhlIHNwZWNpZmllZA0KICAgICMgZGly
ZWN0b3J5LiBPdGhlcndpc2UsIHJldHVybiBOb25lLg0KICAgIHJldHVybiBf
ZnNfaW1wb3J0KGRpciwgbW9kbmFtZSwgZnFuYW1lKQ0KDQogIGRlZiBfX3Jl
cHJfXyhzZWxmKToNCiAgICByZXR1cm4gJzwlcy4lcyBmb3IgIiVzIiBhdCAw
eCV4PicgJSAoc2VsZi5fX2NsYXNzX18uX19tb2R1bGVfXywNCiAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fX2NsYXNz
X18uX19uYW1lX18sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgIHNlbGYuZGlyLA0KICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICBpZChzZWxmKSkNCg0KIyMjIyMjIyMjIyMjIyMj
IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj
IyMjIyMjIyMjIw0KIw0KIyBFbXVsYXRlIHRoZSBzdGFuZGFyZCBwYXRoLXN0
eWxlIGltcG9ydCBtZWNoYW5pc20NCiMNCmNsYXNzIFBhdGhJbXBvcnRlcihJ
bXBvcnRlcik6DQogIGRlZiBfX2luaXRfXyhzZWxmLCBwYXRoPXN5cy5wYXRo
KToNCiAgICBzZWxmLnBhdGggPSBwYXRoDQoNCiAgICAjIHdlJ3JlIGRlZmlu
aXRlbHkgZ29pbmcgdG8gYmUgaW1wb3J0aW5nIHNvbWV0aGluZyBpbiB0aGUg
ZnV0dXJlLA0KICAgICMgc28gbGV0J3MganVzdCBsb2FkIHRoZSBPUy1yZWxh
dGVkIGZhY2lsaXRpZXMuDQogICAgaWYgbm90IF9vc19zdGF0Og0KICAgICAg
X29zX2Jvb3RzdHJhcCgpDQoNCiAgZGVmIGdldF9jb2RlKHNlbGYsIHBhcmVu
dCwgbW9kbmFtZSwgZnFuYW1lKToNCiAgICBpZiBwYXJlbnQ6DQogICAgICAj
IHdlIGFyZSBsb29raW5nIGZvciBhIG1vZHVsZSBpbnNpZGUgb2YgYSBzcGVj
aWZpYyBwYWNrYWdlDQogICAgICByZXR1cm4gX2ZzX2ltcG9ydChwYXJlbnQu
X19wa2dkaXJfXywgbW9kbmFtZSwgZnFuYW1lKQ0KDQogICAgIyBzY2FuIHN5
cy5wYXRoLCBsb29raW5nIGZvciB0aGUgcmVxdWVzdGVkIG1vZHVsZQ0KICAg
IGZvciBkaXIgaW4gc2VsZi5wYXRoOg0KICAgICAgcmVzdWx0ID0gX2ZzX2lt
cG9ydChkaXIsIG1vZG5hbWUsIGZxbmFtZSkNCiAgICAgIGlmIHJlc3VsdDoN
CiAgICAgICAgcmV0dXJuIHJlc3VsdA0KDQogICAgIyBub3QgZm91bmQNCiAg
ICByZXR1cm4gTm9uZQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj
IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMN
CiMNCiMgRW11bGF0ZSB0aGUgaW1wb3J0IG1lY2hhbmlzbSBmb3IgYnVpbHRp
biBhbmQgZnJvemVuIG1vZHVsZXMNCiMNCmNsYXNzIEJ1aWx0aW5JbXBvcnRl
cihJbXBvcnRlcik6DQogIGRlZiBnZXRfY29kZShzZWxmLCBwYXJlbnQsIG1v
ZG5hbWUsIGZxbmFtZSk6DQogICAgaWYgcGFyZW50Og0KICAgICAgIyB0aGVz
ZSBtb2R1bGVzIGRlZmluaXRlbHkgZG8gbm90IG9jY3VyIHdpdGhpbiBhIHBh
Y2thZ2UgY29udGV4dA0KICAgICAgcmV0dXJuIE5vbmUNCg0KICAgICMgbG9v
ayBmb3IgdGhlIG1vZHVsZQ0KICAgIGlmIGltcC5pc19idWlsdGluKG1vZG5h
bWUpOg0KICAgICAgdHlwZSA9IGltcC5DX0JVSUxUSU4NCiAgICBlbGlmIGlt
cC5pc19mcm96ZW4obW9kbmFtZSk6DQogICAgICB0eXBlID0gaW1wLlBZX0ZS
T1pFTg0KICAgIGVsc2U6DQogICAgICAjIG5vdCBmb3VuZA0KICAgICAgcmV0
dXJuIE5vbmUNCg0KICAgICMgZ290IGl0LiBub3cgbG9hZCBhbmQgcmV0dXJu
IGl0Lg0KICAgIG1vZHVsZSA9IGltcC5sb2FkX21vZHVsZShtb2RuYW1lLCBO
b25lLCBtb2RuYW1lLCAoJycsICcnLCB0eXBlKSkNCiAgICByZXR1cm4gMCwg
bW9kdWxlLCB7IH0NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj
IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQoj
DQojIEludGVybmFsIGltcG9ydGVyIHVzZWQgZm9yIGltcG9ydGluZyBmcm9t
IHRoZSBmaWxlc3lzdGVtDQojDQpjbGFzcyBfRmlsZXN5c3RlbUltcG9ydGVy
KEltcG9ydGVyKToNCiAgZGVmIF9faW5pdF9fKHNlbGYsIHN1ZmZpeGVzKToN
CiAgICAjIHRoaXMgbGlzdCBpcyBzaGFyZWQgd2l0aCB0aGUgSW1wb3J0TWFu
YWdlci4NCiAgICBzZWxmLnN1ZmZpeGVzID0gc3VmZml4ZXMNCg0KICBkZWYg
aW1wb3J0X2Zyb21fZGlyKHNlbGYsIGRpciwgZnFuYW1lKToNCiAgICByZXN1
bHQgPSBzZWxmLl9pbXBvcnRfcGF0aG5hbWUoX29zX3BhdGhfam9pbihkaXIs
IGZxbmFtZSksIGZxbmFtZSkNCiAgICBpZiByZXN1bHQ6DQogICAgICByZXR1
cm4gc2VsZi5fcHJvY2Vzc19yZXN1bHQocmVzdWx0LCBmcW5hbWUpDQogICAg
cmV0dXJuIE5vbmUNCg0KICBkZWYgZ2V0X2NvZGUoc2VsZiwgcGFyZW50LCBt
b2RuYW1lLCBmcW5hbWUpOg0KICAgICMgVGhpcyBpbXBvcnRlciBpcyBuZXZl
ciB1c2VkIHdpdGggYW4gZW1wdHkgcGFyZW50LiBJdHMgZXhpc3RlbmNlIGlz
DQogICAgIyBwcml2YXRlIHRvIHRoZSBJbXBvcnRNYW5hZ2VyLiBUaGUgSW1w
b3J0TWFuYWdlciB1c2VzIHRoZQ0KICAgICMgaW1wb3J0X2Zyb21fZGlyKCkg
bWV0aG9kIHRvIGltcG9ydCB0b3AtbGV2ZWwgbW9kdWxlcy9wYWNrYWdlcy4N
CiAgICAjIFRoaXMgbWV0aG9kIGlzIG9ubHkgdXNlZCB3aGVuIHdlIGxvb2sg
Zm9yIGEgbW9kdWxlIHdpdGhpbiBhIHBhY2thZ2UuDQogICAgYXNzZXJ0IHBh
cmVudA0KDQogICAgcmV0dXJuIHNlbGYuX2ltcG9ydF9wYXRobmFtZShfb3Nf
cGF0aF9qb2luKHBhcmVudC5fX3BrZ2Rpcl9fLCBtb2RuYW1lKSwNCiAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZxbmFtZSkNCg0KICBkZWYg
X2ltcG9ydF9wYXRobmFtZShzZWxmLCBwYXRobmFtZSwgZnFuYW1lKToNCiAg
ICBpZiBfb3NfcGF0aF9pc2RpcihwYXRobmFtZSk6DQogICAgICByZXN1bHQg
PSBzZWxmLl9pbXBvcnRfcGF0aG5hbWUoX29zX3BhdGhfam9pbihwYXRobmFt
ZSwgJ19faW5pdF9fJyksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgZnFuYW1lKQ0KICAgICAgaWYgcmVzdWx0Og0KICAgICAgICB2
YWx1ZXMgPSByZXN1bHRbMl0NCiAgICAgICAgdmFsdWVzWydfX3BrZ2Rpcl9f
J10gPSBwYXRobmFtZQ0KICAgICAgICB2YWx1ZXNbJ19fcGF0aF9fJ10gPSBb
IHBhdGhuYW1lIF0NCiAgICAgICAgcmV0dXJuIDEsIHJlc3VsdFsxXSwgdmFs
dWVzDQogICAgICByZXR1cm4gTm9uZQ0KDQogICAgZm9yIHN1ZmZpeCwgaW1w
b3J0ZXIgaW4gc2VsZi5zdWZmaXhlczoNCiAgICAgIGZpbGVuYW1lID0gcGF0
aG5hbWUgKyBzdWZmaXgNCiAgICAgIHRyeToNCiAgICAgICAgZmluZm8gPSBf
b3Nfc3RhdChmaWxlbmFtZSkNCiAgICAgIGV4Y2VwdCBPU0Vycm9yOg0KICAg
ICAgICBwYXNzDQogICAgICBlbHNlOg0KICAgICAgICByZXR1cm4gaW1wb3J0
ZXIuaW1wb3J0X2ZpbGUoZmlsZW5hbWUsIGZpbmZvLCBmcW5hbWUpDQogICAg
cmV0dXJuIE5vbmUNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj
IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIw0K
IyBTVUZGSVgtQkFTRUQgSU1QT1JURVJTDQojDQoNCmNsYXNzIFN1ZmZpeElt
cG9ydGVyOg0KICBkZWYgaW1wb3J0X2ZpbGUoc2VsZiwgZmlsZW5hbWUsIGZp
bmZvLCBmcW5hbWUpOg0KICAgIHJhaXNlIFJ1bnRpbWVFcnJvcg0KDQpjbGFz
cyBQeVN1ZmZpeEltcG9ydGVyKFN1ZmZpeEltcG9ydGVyKToNCiAgZGVmIGlt
cG9ydF9maWxlKHNlbGYsIGZpbGVuYW1lLCBmaW5mbywgZnFuYW1lKToNCiAg
ICBmaWxlID0gZmlsZW5hbWVbOi0zXSArIF9zdWZmaXgNCiAgICB0X3B5ID0g
bG9uZyhmaW5mb1s4XSkNCiAgICB0X3B5YyA9IF90aW1lc3RhbXAoZmlsZSkN
Cg0KICAgIGNvZGUgPSBOb25lDQogICAgaWYgdF9weWMgaXMgbm90IE5vbmUg
YW5kIHRfcHljID49IHRfcHk6DQogICAgICBmID0gb3BlbihmaWxlLCAncmIn
KQ0KICAgICAgaWYgZi5yZWFkKDQpID09IGltcC5nZXRfbWFnaWMoKToNCiAg
ICAgICAgdCA9IHN0cnVjdC51bnBhY2soJzxJJywgZi5yZWFkKDQpKVswXQ0K
ICAgICAgICBpZiB0ID09IHRfcHk6DQogICAgICAgICAgY29kZSA9IG1hcnNo
YWwubG9hZChmKQ0KICAgICAgZi5jbG9zZSgpDQogICAgaWYgY29kZSBpcyBO
b25lOg0KICAgICAgZmlsZSA9IGZpbGVuYW1lDQogICAgICBjb2RlID0gX2Nv
bXBpbGUoZmlsZSwgdF9weSkNCg0KICAgIHJldHVybiAwLCBjb2RlLCB7ICdf
X2ZpbGVfXycgOiBmaWxlIH0NCg0KY2xhc3MgRHluTG9hZFN1ZmZpeEltcG9y
dGVyKFN1ZmZpeEltcG9ydGVyKToNCiAgZGVmIF9faW5pdF9fKHNlbGYsIGRl
c2MpOg0KICAgIHNlbGYuZGVzYyA9IGRlc2MNCg0KICBkZWYgaW1wb3J0X2Zp
bGUoc2VsZiwgZmlsZW5hbWUsIGZpbmZvLCBmcW5hbWUpOg0KICAgIGZwID0g
b3BlbihmaWxlbmFtZSwgc2VsZi5kZXNjWzFdKQ0KICAgIG1vZHVsZSA9IGlt
cC5sb2FkX21vZHVsZShmcW5hbWUsIGZwLCBmaWxlbmFtZSwgc2VsZi5kZXNj
KQ0KICAgIG1vZHVsZS5fX2ZpbGVfXyA9IGZpbGVuYW1lDQogICAgcmV0dXJu
IDAsIG1vZHVsZSwgeyB9DQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj
IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj
Iw0KDQpkZWYgX3Rlc3RfZGlyKCk6DQogICJEZWJ1Zy90ZXN0IGZ1bmN0aW9u
IHRvIGNyZWF0ZSBEaXJlY3RvcnlJbXBvcnRlcnMgZnJvbSBzeXMucGF0aC4i
DQogIHBhdGggPSBzeXMucGF0aFs6XQ0KICBwYXRoLnJldmVyc2UoKQ0KICBm
b3IgZCBpbiBwYXRoOg0KICAgIERpcmVjdG9yeUltcG9ydGVyKGQpLmluc3Rh
bGwoKQ0KDQpkZWYgX3Rlc3RfcmV2YW1wKCk6DQogICJEZWJ1Zy90ZXN0IGZ1
bmN0aW9uIGZvciB0aGUgcmV2YW1wZWQgaW1wb3J0IHN5c3RlbS4iDQogIFBh
dGhJbXBvcnRlcigpLmluc3RhbGwoKQ0KICBCdWlsdGluSW1wb3J0ZXIoKS5p
bnN0YWxsKCkNCg0KZGVmIF9wcmludF9pbXBvcnRlcnMoKToNCiAgaXRlbXMg
PSBzeXMubW9kdWxlcy5pdGVtcygpDQogIGl0ZW1zLnNvcnQoKQ0KICBmb3Ig
bmFtZSwgbW9kdWxlIGluIGl0ZW1zOg0KICAgIGlmIG1vZHVsZToNCiAgICAg
IHByaW50IG5hbWUsIG1vZHVsZS5fX2RpY3RfXy5nZXQoJ19faW1wb3J0ZXJf
XycsICctLSBubyBpbXBvcnRlcicpDQogICAgZWxzZToNCiAgICAgIHByaW50
IG5hbWUsICctLSBub24tZXhpc3RlbnQgbW9kdWxlJw0KDQpkZWYgX3Rlc3Rf
cmV2YW1wKCk6DQogIEltcG9ydE1hbmFnZXIoKS5pbnN0YWxsKCkNCiAgc3lz
LnBhdGguaW5zZXJ0KDAsIEJ1aWx0aW5JbXBvcnRlcigpKQ0KDQojIyMjIyMj
IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj
IyMjIyMjIyMjIyMjIyMjIyMjDQo=
--1658348780-1657214722-946868004=:412--


From mal@lemburg.com  Mon Jan  3 12:28:34 2000
From: mal@lemburg.com (M.-A. Lemburg)
Date: Mon, 03 Jan 2000 13:28:34 +0100
Subject: [Python-Dev] new imputil.py
References: <Pine.LNX.4.10.10001021838400.412-200000@nebula.lyra.org>
Message-ID: <387095F2.2FA64D8E@lemburg.com>

Happy New Year :-)

[new imputil.py]

I tried the new module with the following code:

import imputil,sys

if sys.argv[1] != 'standard':
    print 'Installing imputil...',
    imputil.ImportManager().install()
    sys.path.insert(0, imputil.BuiltinImporter())
    print 'done.'
else:
    print 'Using builtin importer.'

print

print 'Importing standard stuff...',
import string,re,os,sys
print 'done.'

print 'Importing mx Extensions...',
from mx import DateTime,TextTools,ODBC,HTMLTools,UID,URL
print 'done.'

###

The new importer does load everything in the test set
(top level modules, packages, extensions within packages)
without problems on Linux.

Some comments:

· Why is the sys.path.insert(0,imputil.BuiltinImporter()) 
needed in order to get b/w compatibility ?

· Why is there no __path__ aware code in imputil.py (this is
definitely needed in order to make it a drop-in replacement) ?

· Performance is still 50% of the Python builtin importer --
a bummer if you ask me. More aggressive caching is definitely
needed, perhaps even some recoding of methods in C.

· The old chaining code should be moved into a subclass of
its own.

· The code should not import strop directly as this module
will probably go away RSN. Use string methods instead.

· The design of the ImportManager has some minor flaws: the
FS importer should be settable via class attributes, deinstallation
should be possible, a query mechanism to find the importer
used by a certain import would also be nice to be able to
verify correct setup.

· py/pyc/pyo file piping hooks would be nice to allow
imports of signed (and trusted) code and/or encrypted code
(a mixin class for these filters would do the trick).

· Wish list: a distutils importer hooked to a list of standard
package repositories, a module to file location mapper to
speed up file system based imports, 

-- 
Marc-Andre Lemburg
______________________________________________________________________
Y2000:                                             Happy New Century !
Business:                                      http://www.lemburg.com/
Python Pages:                           http://www.lemburg.com/python/



From gstein@lyra.org  Mon Jan  3 13:53:00 2000
From: gstein@lyra.org (Greg Stein)
Date: Mon, 3 Jan 2000 05:53:00 -0800 (PST)
Subject: [Python-Dev] new imputil.py
In-Reply-To: <387095F2.2FA64D8E@lemburg.com>
Message-ID: <Pine.LNX.4.10.10001030529560.412-100000@nebula.lyra.org>

Excellent... thanx for the feedback!

Comments:

On Mon, 3 Jan 2000, M.-A. Lemburg wrote:
>...
> The new importer does load everything in the test set
> (top level modules, packages, extensions within packages)
> without problems on Linux.

Great!

> Some comments:
>=20
> =B7 Why is the sys.path.insert(0,imputil.BuiltinImporter())=20
> needed in order to get b/w compatibility ?

Because I didn't want to build too much knowledge into the ImportManager.
Heck, I think adding sys.path removed some of the design elegence; adding
real knowledge of builtins... well, we'll just not talk about that. :-)

We could certainly do it this way; let's see what Guido says. I'm not
truly adverse to it, but I'd recommend against adding a knowledge of
BuiltinImporter to the ImportManager.

> =B7 Why is there no __path__ aware code in imputil.py (this is
> definitely needed in order to make it a drop-in replacement) ?

Because I don't like __path__ :-)  I don't think it would be too hard to
add, though.

If Guido says we need __path__, then I'll add it. I do believe there was a
poll a while back where he asked whether anybody truly used it. I don't
remember the result and/or Guido's resolution of the matter.

> =B7 Performance is still 50% of the Python builtin importer --
> a bummer if you ask me. More aggressive caching is definitely
> needed, perhaps even some recoding of methods in C.

I'm scared of caching and the possibility for false positives/negatives.

But yes, it is still slower and could use some analysis and/or recoding
*if* the speed is a problem. Slower imports does not necessarily mean they
are "too slow."

> =B7 The old chaining code should be moved into a subclass of
> its own.

Good thought. But really: I'd just rather torch it. This kind of depends
on whether we can get away with saying the ImportManager is *the* gateway
between the interpreter and Python-level import hooks. In other words,
will ImportManager be the *only* Python code to ever be allowed to call
sys.set_import_hook() ? If the ImportManager doesn't have to "play with
other import hooks", then the chaining can be removed altogether.

> =B7 The code should not import strop directly as this module
> will probably go away RSN. Use string methods instead.

Yah. But I'm running this against 1.5.2 :-)

I might be able to do something where the string methods are used if
available, and use the strop module if not.
[ similar to the 'os' bootstrapping that is done ]

Finn Bock emailed me to say that JPython does not have strop, but does
have string methods.

> =B7 The design of the ImportManager has some minor flaws: the
> FS importer should be settable via class attributes,

The class or the object itself? Putting a class in there would be nice, or
possibly passing it to the constructor (with a suitable default).

This is a good idea, though. Please clarify what you'd like to see, and
I'll get it added.

> deinstallation
> should be possible,

Maybe. This is somewhat dependent upon whether it must "play nice."
Deinstallation would be quite easy if we move to a sys.get/set style of
interface, and it wouldn't be an issue to do de-install code.

> a query mechanism to find the importer
> used by a certain import would also be nice to be able to
> verify correct setup.

module.__importer__ provides the importer that was used. This is defined
behavior (the system relies on that being set to deal with packages
properly).

Is this sufficient, or were you looking for something else?

module.__ispkg__ is also set to 0/1 accordingly.

For backwards compat, __file__ and __path__ are also set. The __all__
attribute in an __init__.py file is used for "from package import *".

> =B7 py/pyc/pyo file piping hooks would be nice to allow
> imports of signed (and trusted) code and/or encrypted code
> (a mixin class for these filters would do the trick).

I'd happily accept a base SuffixImporter class for these "pipes". I don't
believe that the ImportManager, Importer, or SuffixImporter base classes
would need any changes, though.

Note that I probably will rearrange the _fs_import() and friends, per
Guido's suggestion to move them into a base class. That may be a step
towards having "pipes" available.

> =B7 Wish list: a distutils importer hooked to a list of standard
> package repositories, a module to file location mapper to
> speed up file system based imports,=20

I'm not sure what the former would do. distutils is still a little
nebulous to me right now.

For a mapper, we can definitely have a custom Importer that knows where
certain modules are found. However, I suspect you're looking for some kind
of a cache, but there isn't a hook to say "I found <foo> at <this>
location" (which would be used to build the mapping).

Suggestions on both of these would be most welcome!

Cheers,
-g

--=20
Greg Stein, http://www.lyra.org/



From gvwilson@nevex.com  Mon Jan  3 14:02:32 2000
From: gvwilson@nevex.com (gvwilson@nevex.com)
Date: Mon, 3 Jan 2000 09:02:32 -0500 (EST)
Subject: [Python-Dev] Software Carpentry: GUI Toolkit?
Message-ID: <Pine.LNX.4.10.10001030852190.20692-100000@akbar.nevex.com>

Hi, folks.  I'm putting together guidelines for submissions to the
Software Carpentry design competition (www.software-carpentry.com), and
would like to know what I should recommend as a Python GUI toolkit.  As I
understand it, the alternatives are:

- Tkinter: the "standard" answer, but many people think it's showing its
  age, and it's an installation and update headaches because of its Tcl
  dependencies.

- some other GUI toolkit: but there's no consensus on which one, and
  documentation is lacking.

- CGI scripts (i.e. all interfaces are web pages): has the virtue of
  simplicity, but could also make some useful interfaces difficult to
  build (e.g. no drag and drop), and would require users to run a server,
  or at least get exec privileges, which can be an installation headache.

If I've missed a good answer, or if there's somewhere else I should look
for a solution, I'd be grateful for a pointer.

Thanks,
Greg




From jim@interet.com  Mon Jan  3 14:31:53 2000
From: jim@interet.com (James C. Ahlstrom)
Date: Mon, 03 Jan 2000 09:31:53 -0500
Subject: [Python-Dev] new imputil.py
References: <Pine.LNX.4.10.10001021838400.412-200000@nebula.lyra.org>
Message-ID: <3870B2D9.31D0D350@interet.com>

Greg Stein wrote:

> I've attached a new imputil.py to this message. It isn't posted on my page

I don't think you should be using "public domain" as a
copyright because you should be protecting the code.
Better to use "all rights transferred to CNRI pursuant
to the Python contribution agreement", or just copyright
it yourself for now.

You didn't incorporate the ZipImporter in
  ftp://ftp.interet.com/pub/importer.py
Is that because you want me to, or doesn't it work?

JimA


From gmcm@hypernet.com  Mon Jan  3 14:38:11 2000
From: gmcm@hypernet.com (Gordon McMillan)
Date: Mon, 3 Jan 2000 09:38:11 -0500
Subject: [Python-Dev] new imputil.py
In-Reply-To: <Pine.LNX.4.10.10001030529560.412-100000@nebula.lyra.org>
References: <387095F2.2FA64D8E@lemburg.com>
Message-ID: <1265213088-25101227@hypernet.com>

Greg Stein wrote:
> On Mon, 3 Jan 2000, M.-A. Lemburg wrote:
[big snip]
> > · Wish list: a distutils importer hooked to a list of standard
> > package repositories, a module to file location mapper to speed
> > up file system based imports, 

> For a mapper, we can definitely have a custom Importer that knows
> where certain modules are found. However, I suspect you're
> looking for some kind of a cache, but there isn't a hook to say
> "I found <foo> at <this> location" (which would be used to build
> the mapping).
> 
> Suggestions on both of these would be most welcome!

Haven't played with the new one yet. But for awhile I've been 
considering a scheme where sys.path[0] has a cache of 
known binary extensions { logicalname: fullpath, ... } and 
sys.path[-1] is the brute force importer.

For standalones, sys.path[0] could be hardcoded. For normal 
installations, sys.path[-1] could inform sys.path[0] when a .so 
/ .dll / .pyd is found. So when a new one is installed, the first 
use will be expensive, but subsequent sessions would import 
it in 1 I/O.

I'd also like to point out that archives *can* be used in a 
development situation. Obviously I wouldn't bother putting a 
module under current development into an archive. But if the 
source is still installed and you haven't mucked with the 
__file__ attribute when you put it in the archive, then 
tracebacks will show you what you need. IDLE doesn't know 
the difference. So for most developers, the standard library 
can be served from an archive with no effect (other than speed).

- Gordon


From gstein@lyra.org  Mon Jan  3 14:57:35 2000
From: gstein@lyra.org (Greg Stein)
Date: Mon, 3 Jan 2000 06:57:35 -0800 (PST)
Subject: [Python-Dev] new imputil.py
In-Reply-To: <3870B2D9.31D0D350@interet.com>
Message-ID: <Pine.LNX.4.10.10001030651260.412-100000@nebula.lyra.org>

On Mon, 3 Jan 2000, James C. Ahlstrom wrote:
> Greg Stein wrote:
> > I've attached a new imputil.py to this message. It isn't posted on my page
> 
> I don't think you should be using "public domain" as a
> copyright because you should be protecting the code.
> Better to use "all rights transferred to CNRI pursuant
> to the Python contribution agreement", or just copyright
> it yourself for now.

Public Domain means there are no copyrights on the code. Anybody can claim
copyright to it. Anybody can start with my version, slap their name and
license on it, and do as they wish. There isn't a way for anybody to
"control" public domain software, so there is no need for protection.

I like to use Public Domain for code that I want to see as broadly used as
possible and/or for short things. There is also a lot that I just don't
care what happens with it. If I don't have a vested interest in something,
then PD is fine.

I wrote imputil as a tool for myself. It isn't something that I feel a
need to keep my name on it -- it works for me, it does what I want, it
doesn't matter what others do it. It does matter than other people *can*
do stuff with it, and PD gives them the most options.

Shades of grey... hard to fully explain in an email... but that's the
general sentiment. I've got a few things under other licenses, but PD
seemed best for imputil.

> You didn't incorporate the ZipImporter in
>   ftp://ftp.interet.com/pub/importer.py
> Is that because you want me to, or doesn't it work?

I had the redesign to do first. When that settles towards something that
Guido is happy with (or he has decided to punt the design altogether),
then I'll integrate the ZipImporter.

Cheers,
-g

-- 
Greg Stein, http://www.lyra.org/



From fdrake@acm.org  Mon Jan  3 20:05:22 2000
From: fdrake@acm.org (Fred L. Drake, Jr.)
Date: Mon, 3 Jan 2000 15:05:22 -0500 (EST)
Subject: [Python-Dev] new imputil.py
In-Reply-To: <1265213088-25101227@hypernet.com>
References: <387095F2.2FA64D8E@lemburg.com>
 <1265213088-25101227@hypernet.com>
Message-ID: <14449.258.374018.919406@weyr.cnri.reston.va.us>

Gordon McMillan writes:
 > I'd also like to point out that archives *can* be used in a 
 > development situation. Obviously I wouldn't bother putting a 
 > module under current development into an archive. But if the 
 > source is still installed and you haven't mucked with the 
 > __file__ attribute when you put it in the archive, then 
 > tracebacks will show you what you need. IDLE doesn't know 
 > the difference. So for most developers, the standard library 
 > can be served from an archive with no effect (other than speed).

  I don't see why we can't just add the source to the archive as well; 
this would allow proper tracebacks even outside the development of the 
library.  Not including sources would cleanly result in the same
situation as we currently see when there's only a .pyc file.
  Am I missing something fundamental?


  -Fred

--
Fred L. Drake, Jr.	  <fdrake at acm.org>
Corporation for National Research Initiatives


From mal@lemburg.com  Mon Jan  3 18:22:02 2000
From: mal@lemburg.com (M.-A. Lemburg)
Date: Mon, 03 Jan 2000 19:22:02 +0100
Subject: [Python-Dev] Better text processing support in py2k?
References: <000901bf53e1$eb4248c0$472d153f@tim>
Message-ID: <3870E8CA.7294B813@lemburg.com>

Tim Peters wrote:
> 
> >> This is why I do complex string processing in Icon <0.9 wink>.
> 
> [MAL]
> > You can have all that extra magic via callable tag objects
> > or callable matching functions. It's not exactly nice to
> > write, but I'm sure that a meta-language could do the
> > conversions for you.
> 
> That wasn't my point:  I do it in Icon because it *is* "exactly nice to
> write", and doesn't require any yet-another meta-language.  It's all
> straightforward, in a way that separate schemes pasted together can never be
> (simply because they *are* "separate schemes pasted together" <wink>).
>
> The point of my Python examples wasn't that they could do something
> mxTextTools can't do, but that they were *Python* examples:  every variation
> I mentioned (or that you're likely to think of) was easy to handle for any
> Python programmer because the "control flow" and "data type" etc aspects
> could be handled exactly the way they always are in *non* pattern-matching
> Python code too, rather than recoded in pattern-scheme-specific different
> ways (e.g., where I had a vanailla "if/break", you set up a special
> exception to tickle the matching engine).
> 
> I'm not attacking mxTextTools, so don't feel compelled to defend it --

Oh, I wasn't defending it -- I know that it is cryptic and sometimes
a pain to use. But given that you don't have to invoke a C compiler
to get a raw speed I find it a rather useful alternative to code
fast utility functions which would otherwise have to be written
in C.

The other reason it exists is simply because I don't like the
recursive style of regexps too much. mxTextTools is simple
and straightforward. Backtracking is still possible, but not
recommended.

> people using regexps in those examples are dead in the water.  mxTextTools
> is very good at what it does; if we have a real disagreement, it's probably
> that I'm less optimistic about the prospects for higher-level wrappers
> (e.g., MikeF's SimpleParse is much slower than "a real" BNF parsing system
> (ARBNFPS), in part because he isn't doing all the optimizations ARBNFPS
> does, but also in part because ARBNFPS uses an underlying engine more
> optimized to its specific task than mxTextTool's more-general engine *can*
> be).  So I don't see mxTextTools as being the answer to everything -- and if
> you hadn't written it, you would agree with that on first glance <wink>.

Oh, I'm sure it *is* the answer to all out problems ;-) ...

def main(*dummy):
    ...

from mx.TextTools import *
tag("",((main, Skip + CallTag, 0),))
 
> > Anyway, I'll keep focussing on the speed aspect of mxTextTools;
> > others can focus on abstractions, so that eventually everybody
> > will be happy :-)
> 
> You and I will be, anyway <wink>.

Happy New Year :-)
-- 
Marc-Andre Lemburg
______________________________________________________________________
Y2000:                                             Happy New Century !
Business:                                      http://www.lemburg.com/
Python Pages:                           http://www.lemburg.com/python/




From mal@lemburg.com  Tue Jan  4 18:36:00 2000
From: mal@lemburg.com (M.-A. Lemburg)
Date: Tue, 04 Jan 2000 19:36:00 +0100
Subject: [Python-Dev] new imputil.py
References: <Pine.LNX.4.10.10001030529560.412-100000@nebula.lyra.org>
Message-ID: <38723D90.D2AE1CA4@lemburg.com>

Greg Stein wrote:
> 
> Comments:
> 
> On Mon, 3 Jan 2000, M.-A. Lemburg wrote:
> >...
> > The new importer does load everything in the test set
> > (top level modules, packages, extensions within packages)
> > without problems on Linux.
> 
> Great!
> 
> > Some comments:
> >
> > · Why is the sys.path.insert(0,imputil.BuiltinImporter())
> > needed in order to get b/w compatibility ?
> 
> Because I didn't want to build too much knowledge into the ImportManager.
> Heck, I think adding sys.path removed some of the design elegence; adding
> real knowledge of builtins... well, we'll just not talk about that. :-)
> 
> We could certainly do it this way; let's see what Guido says. I'm not
> truly adverse to it, but I'd recommend against adding a knowledge of
> BuiltinImporter to the ImportManager.

I was under the impression that the ImportManager should replace
the current implementation. In that light it should of course
provide all the needed techniques per default without the
need to tweak sys.path.

> > · Why is there no __path__ aware code in imputil.py (this is
> > definitely needed in order to make it a drop-in replacement) ?
> 
> Because I don't like __path__ :-)  I don't think it would be too hard to
> add, though.
> 
> If Guido says we need __path__, then I'll add it. I do believe there was a
> poll a while back where he asked whether anybody truly used it. I don't
> remember the result and/or Guido's resolution of the matter.

AFAIK, JimF is using it in Zope. I will use it in the
b/w compatibility package for the soon to be released
mx Extensions packages (instead of using relative imports,
BTW -- can't wait for those to happen).
 
> > · Performance is still 50% of the Python builtin importer --
> > a bummer if you ask me. More aggressive caching is definitely
> > needed, perhaps even some recoding of methods in C.
> 
> I'm scared of caching and the possibility for false positives/negatives.
> 
> But yes, it is still slower and could use some analysis and/or recoding
> *if* the speed is a problem. Slower imports does not necessarily mean they
> are "too slow."

There has been some moaning about the current Python startup
speed, so I guess people already find the existing strategy
too slow.
 
Anyway, put the cache risks into the user's hands and have
them decide whether or not to use them. The important thing
is providing a standard approach to caching which all
importers can use and hook into rather than having three
or four separate cache implementations.

> > · The old chaining code should be moved into a subclass of
> > its own.
> 
> Good thought. But really: I'd just rather torch it. This kind of depends
> on whether we can get away with saying the ImportManager is *the* gateway
> between the interpreter and Python-level import hooks. In other words,
> will ImportManager be the *only* Python code to ever be allowed to call
> sys.set_import_hook() ? If the ImportManager doesn't have to "play with
> other import hooks", then the chaining can be removed altogether.

Hmm, nuking the chains might cause some problems with code
using the old ni.py or other code such as my old ClassModules.py
module which emulates modules using classes (provides all the
cool __getattr__ and __setattr__ features to modules as well).
 
> > · The code should not import strop directly as this module
> > will probably go away RSN. Use string methods instead.
> 
> Yah. But I'm running this against 1.5.2 :-)
> 
> I might be able to do something where the string methods are used if
> available, and use the strop module if not.
> [ similar to the 'os' bootstrapping that is done ]
> 
> Finn Bock emailed me to say that JPython does not have strop, but does
> have string methods.

Since imputil.py targets 1.6 you can safely assume that string
methods are in place.
 
> > · The design of the ImportManager has some minor flaws: the
> > FS importer should be settable via class attributes,
> 
> The class or the object itself? Putting a class in there would be nice, or
> possibly passing it to the constructor (with a suitable default).
> 
> This is a good idea, though. Please clarify what you'd like to see, and
> I'll get it added.

I usually put these things into the class so that subclasses
can easily override the setting.
 
> > deinstallation
> > should be possible,
> 
> Maybe. This is somewhat dependent upon whether it must "play nice."
> Deinstallation would be quite easy if we move to a sys.get/set style of
> interface, and it wouldn't be an issue to do de-install code.

I was thinking mainly of debugging situations where you play
around with new importer code -- its probably not important
for production code.

> > a query mechanism to find the importer
> > used by a certain import would also be nice to be able to
> > verify correct setup.
> 
> module.__importer__ provides the importer that was used. This is defined
> behavior (the system relies on that being set to deal with packages
> properly).
> 
> Is this sufficient, or were you looking for something else?

I was thinking of a situations like:

if <RelativeImporter is not installed>:
   <install RelativeImporter>

or

if <need SignedModuleImporter for modules xyz>:
   raise SystemError,'wrong setup'

Don't know if these queries are possible with the current
flags and attributes.
 
> module.__ispkg__ is also set to 0/1 accordingly.
> 
> For backwards compat, __file__ and __path__ are also set. The __all__
> attribute in an __init__.py file is used for "from package import *".
> 
> > · py/pyc/pyo file piping hooks would be nice to allow
> > imports of signed (and trusted) code and/or encrypted code
> > (a mixin class for these filters would do the trick).
> 
> I'd happily accept a base SuffixImporter class for these "pipes". I don't
> believe that the ImportManager, Importer, or SuffixImporter base classes
> would need any changes, though.
> 
> Note that I probably will rearrange the _fs_import() and friends, per
> Guido's suggestion to move them into a base class. That may be a step
> towards having "pipes" available.

It would be nice to be able to use the concept of stackable streams
as source for byte and source code. For this to work one would have
to make the file reading process a little more abstract by using e.g. a
StreamReader instead (see the current unicode-proposal.txt version).

> > · Wish list: a distutils importer hooked to a list of standard
> > package repositories, a module to file location mapper to
> > speed up file system based imports,
> 
> I'm not sure what the former would do. distutils is still a little
> nebulous to me right now.

Basically it should scan a set of URLs providing access to
package repositories which hold distutils installable package
archives. In case it finds a suitable package it should then
proceed to auto-install it and then continue the normal import
process.

> For a mapper, we can definitely have a custom Importer that knows where
> certain modules are found. However, I suspect you're looking for some kind
> of a cache, but there isn't a hook to say "I found <foo> at <this>
> location" (which would be used to build the mapping).

Right. I would like to see some standard mechanism used
throughout the ImportManager for this. One which all importers
can use and rely on. E.g. it would be nice to have an option
to load the cache from disk upon startup to reduce search times.
All this should be left for the user to configure with the
standard setting being no cache at all (to avoid confusion
and reduce support costs ;-).

-- 
Marc-Andre Lemburg
______________________________________________________________________
Y2000:                                             Happy New Century !
Business:                                      http://www.lemburg.com/
Python Pages:                           http://www.lemburg.com/python/



From bwarsaw@cnri.reston.va.us (Barry A. Warsaw)  Tue Jan  4 21:04:48 2000
From: bwarsaw@cnri.reston.va.us (Barry A. Warsaw) (Barry A. Warsaw)
Date: Tue, 4 Jan 2000 16:04:48 -0500 (EST)
Subject: [Python-Dev] new imputil.py
References: <Pine.LNX.4.10.10001021838400.412-200000@nebula.lyra.org>
Message-ID: <14450.24688.492098.917284@anthem.cnri.reston.va.us>

Happy New Year!

>>>>> "GS" == Greg Stein <gstein@lyra.org> writes:

    GS> I think Python 1.6 should drop the __import__ builtin and move
    GS> to something like sys.import_hook (to allow examination and
    GS> change).

Wait!  You can't remove builtin __import__ without breaking code.
E.g. Mailman uses __import__ quite a bit in its CGI (and other)
harnesses.  Why does __import__ need to be removed?  Why can't it just
just the same mechanism the import statement uses?

    GS> I might be able to do something where the string methods are
    GS> used if available, and use the strop module if not.  [ similar
    GS> to the 'os' bootstrapping that is done ]

    GS> Finn Bock emailed me to say that JPython does not have strop,
    GS> but does have string methods.

Sorry Greg, I haven't had time to look at this stuff at all, so maybe
I'm missing something essential, but if you just continue to use the
string module, you'll be fine for JPython and CPython 1.5.2.  In
CPython 1.5.2, you /will/ actually be using the strop module
under the covers.

In CPython 1.6 and JPython 1.1 you'll be using string methods under
the covers.  Your penalty is one layer of Python function calls.
Never use strop directly though.

>>>>> "MA" == M  <mal@lemburg.com> writes:

    MA> There has been some moaning about the current Python startup
    MA> speed, so I guess people already find the existing strategy
    MA> too slow.
 
Definitely.

-Barry


From gmcm@hypernet.com  Wed Jan  5 03:49:08 2000
From: gmcm@hypernet.com (Gordon McMillan)
Date: Tue, 4 Jan 2000 22:49:08 -0500
Subject: [Python-Dev] new imputil.py
In-Reply-To: <14449.258.374018.919406@weyr.cnri.reston.va.us>
References: <1265213088-25101227@hypernet.com>
Message-ID: <1265079245-1617919@hypernet.com>

Fred L. Drake, Jr.wrote:

> Gordon McMillan writes:
>  > I'd also like to point out that archives *can* be used in a >
>  development situation. Obviously I wouldn't bother putting a >
>  module under current development into an archive. But if the >
>  source is still installed and you haven't mucked with the >
>  __file__ attribute when you put it in the archive, then >
>  tracebacks will show you what you need. IDLE doesn't know > the
>  difference. So for most developers, the standard library > can
>  be served from an archive with no effect (other than speed).
> 
>   I don't see why we can't just add the source to the archive as
>   well; 
> this would allow proper tracebacks even outside the development
> of the library.  Not including sources would cleanly result in
> the same situation as we currently see when there's only a .pyc
> file.
>   Am I missing something fundamental?

Sure you could. Then you could patch IDLE, Pythonwin, etc. 
to open the proper archive and extract the source. Then you 
could patch them (and archive) to update on the fly.

And while you're at it, I'd really like a jacuzzi jet that gets my 
neck and shoulders without having to scrunch into all kinds of 
strange positions.

- Gordon


Return-Path: <owner-python-dev@python.org>
Delivered-To: python-dev@dinsdale.python.org
Received: from python.org (parrot.python.org [132.151.1.90])
	by dinsdale.python.org (Postfix) with ESMTP id A76701CD65
	for <python-dev@dinsdale.python.org>; Fri, 14 Jan 2000 12:39:29 -0500 (EST)
Received: from merlin.codesourcery.com (IDENT:qmailr@[206.168.99.1])
	by python.org (8.9.1a/8.9.1) with SMTP id MAA17463
	for <python-dev@python.org>; Fri, 14 Jan 2000 12:39:29 -0500 (EST)
Received: (qmail 2115 invoked by uid 513); 14 Jan 2000 17:44:23 -0000
Mailing-List: contact publicity-help@software-carpentry.com; run by ezmlm
Delivered-To: mailing list publicity@software-carpentry.com
Received: (qmail 2110 invoked from network); 14 Jan 2000 17:44:19 -0000
Date: Fri, 14 Jan 2000 12:40:13 -0500 (EST)
From: gvwilson@nevex.com
To: publicity@software-carpentry.com
Message-ID: <Pine.LNX.4.10.10001141228191.8785-100001@akbar.nevex.com>
MIME-Version: 1.0
Content-Type: MULTIPART/MIXED; BOUNDARY="168427786-1646135556-947871613=:8785"
Subject: [Python-Dev] ANNOUNCEMENT: Open Source Design Competition
Sender: python-dev-admin@python.org
Errors-To: python-dev-admin@python.org
X-BeenThere: python-dev@python.org
X-Mailman-Version: 1.2 (experimental)
Precedence: bulk
List-Id: Python core developers <python-dev.python.org>

  This message is in MIME format.  The first part should be readable text,
  while the remaining parts are likely unreadable without MIME-aware tools.
  Send mail to mime@docserver.cac.washington.edu for more info.

--168427786-1646135556-947871613=:8785
Content-Type: TEXT/PLAIN; charset=US-ASCII

The Software Carpentry project is pleased to announce the launch of its
first Open Source design competition.  The project's logo is attached, and
details of the competition are included below.

This message is being sent to you because you have expressed an interest
in covering this story, or publicizing this project.  If you have any
questions, or do not wish to receive future notices about Software
Carpentry, please contact:

    Dr. Gregory V. Wilson
    Software Carpentry Project Coordinator
    (416) 593 2428
    gvwilson@software-carpentry.com

Thanks for your interest!

Greg Wilson

----------------------------------------------------------------------
----------------------------------------------------------------------

Los Alamos National Laboratory                     Code Sourcery, LLC

                          Software Carpentry

		    Open Source Design Competition

			 $100,000 in Prizes!

----------------------------------------------------------------------

The Software Carpentry project is pleased to announce its first Open
Source design competition, with prizes totaling $100,000.  Students
and professionals from any country, working individually or in teams,
are invited to submit design outlines for:

* a platform inspection tool to replace autoconf;

* a dependency management tool to replace make;

* an issue tracking system to replace gnats and Bugzilla; and

* a unit and regression testing harness with the functionality of
  XUnit, Expect, and DejaGnu.

Participants may submit separate entries in one or more categories by
March 31, 2000.  Entries must be in English, and no more than 5000
words long; examples are available at http://www.software-carpentry.com.

The competition will be judged by a panel that includes the following
noted software developers, authors, and computational scientists:

    Stephen Adler       Brookhaven National Laboratory
    Frank Alexander     Los Alamos National Laboratory
    Donnie Barnes       Red Hat
    Chris DiBona        VA Linux
    Paul Dubois         Lawrence Livermore National Laboratory
    Andrew Hunt         Pragmatic Programmers, LLC
    Stephen R. Lee      Los Alamos National Laboratory
    Josh MacDonald      University of California, Berkeley
    Brian Marick        Reliable Software Technologies
    Doug Mewhort        Queen's University
    Bruce Perens        co-founder of the Open Source Initiative
    Dave Thomas         Pragmatic Programmers, LLC
    Jon Udell           author of Practical Internet Groupware
    Guido van Rossum    inventor of Python
    Tom Van Vleck       TransIlluminant
    Phil Wadler         Bell Labs
    Scot Wingo          AuctionRover

The best four entries in each category will be awarded $2500, and
invited to submit full designs by June 1, 2000.  The best design in
each category will then receive an additional $7500, while runners-up
will each receive $2500.  Once winning designs have been announced,
$200,000 will be available through open bidding for implementation,
testing, and documentation.

All of the project's work will be Open Source; all tools will be
written in, or scriptable with, Python, and will be required to run on
both Linux and Microsoft Windows NT.

----------------------------------------------------------------------

The Software Carpentry project is sponsored by the Advanced Computing
Laboratory at the U.S. Department of Energy's Los Alamos National
Laboratory (http://www.acl.lanl.gov), and administered by Code 
Sourcery, LLC (http://www.codesourcery.com).  The project's aim
is to encourage adoption of better software development practices by
making software tools easier to use, and by documenting design,
testing, and related activities.  For more information on the project,
or to let us know that you intend to submit a proposal, see
http://www.software-carpentry.com, or mail info@software-carpentry.com.


--168427786-1646135556-947871613=:8785
Content-Type: IMAGE/GIF; name="software-carpentry-logo.gif"
Content-Transfer-Encoding: BASE64
Content-ID: <Pine.LNX.4.10.10001141240130.8785@akbar.nevex.com>
Content-Description: 
Content-Disposition: attachment; filename="software-carpentry-logo.gif"

R0lGODlhLAGhANX/AIACFYU8R2RkZqWlp0pKS+np6tXV1snJyr+/wLW2u+Dh
5srM1Pf4/PT1+e7v877Ax4GDiZygq6Sos4yPl5aZobm7wNrc4aywuXF0efv8
/M7PzywtLJF8U0s4F6mTa76pgXBeQE0+LeDb2M7JxsfAvaCPi7yysJBxb7Ge
nf////7+/v39/fv7+/n5+fj4+Pb29vPz8/Ly8u/v7+3t7ebm5uLi4t3d3dnZ
2dLS0sXFxa6urh4eHg8PDwgICAMDAwAAACwAAAAALAGhAEAG/8CUcEgsGo/I
pHLJbDqf0Kh0Sq1ar9isdsvter/gsFipcjXLQ1aBhtDg3m/NLdN0rZotVpPV
aq7MTH9OLipFOSgxRXZ4dEx5e3pMLJFLGYBLgkxld0yLjpRKj0ktM4VEMgk6
FRcQGBILCrELEwITCRe4uRgEBAICvLwYF6sJEjV9RC4yRjKJRCwzoCkxy0QZ
BdIupUUzL0WkpkMyMEUrMnQ2HOoeHh/u7OocJi8uOiEgNUYzAhsbO/0EMPDb
UKFQDG/WYtjYEKJfCF4gfIEgQCOGtBfOhqiYcUmINmYIh7SQEU4ItSIZohWB
UW3IigLIRM7gJI7csxmNaip5QYNmEv8XNKRV2EBBxYAdDNSETLKChs0lNTRU
OFIBgqkZBZrA6MmEp7QiKOJxaDcihQsDJFCUKAHhBIgOHULEKGmEBoF//XYE
HDhhhYoCLZXIKKADAwQlJ1sgmNBKgEDHkIsy2ZozCQsaHZFcXpoEcJMCMwTb
ALWiRlYiMGx0/BtBQtaiLWxkFDKjhk8WNgKnmGGDZoFYFiwUFPLiBgRftf7S
UGTjqRAZo4mUPj1EYcwUKmhoEABiLAEIE2h15/BWQGsJEnANuFGkQA1QGWjY
zbvBVz8KQqavVE0kO42SL9jAmXu35bYSCnB15wEJNYR2SnRE0FBDSS40196E
RMSWAAUYTHD/zAET2BCOCqbtl5l8ShRwA2dHyHCDc0JQcEEBKsBmgIOh3EAd
Ei48oMABQjQgwQY//CCMQAqkUIOITKh4HRIz3HDJDOCBF94EFGQZwZbopYfL
A/iZpWMnNmQ1UH13IZCGDRgqUVpvS5AIYYqjIQBXBwpyI+USF0TgCwQX3HJB
el12GcFxyGG5I3Y2LIcdBCOscINhBVAAgwpsKlEDDoG1YMANoBSAw464UeBa
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
d8M73tIIAgA7
--168427786-1646135556-947871613=:8785--


From jeremy@cnri.reston.va.us  Mon Jan 17 20:35:37 2000
From: jeremy@cnri.reston.va.us (Jeremy Hylton)
Date: Mon, 17 Jan 2000 15:35:37 -0500 (EST)
Subject: [Python-Dev] developers day session on compilers
Message-ID: <14467.32025.761662.841271@goon.cnri.reston.va.us>

I am championing a Developers' Day session on a Python compiler.
There is a short Web page describing the goals of the session at
http://www.python.org/workshops/2000-01/compiler.html.

I'd appreciate feedback on the content and format of the session.  If
you have ideas for what we should talk about or do, please followup to
me or to the list.

Jeremy



From mal@lemburg.com  Tue Jan 18 22:55:04 2000
From: mal@lemburg.com (M.-A. Lemburg)
Date: Tue, 18 Jan 2000 23:55:04 +0100
Subject: [Python-Dev] Python Tools/
Message-ID: <3884EF48.A6107775@lemburg.com>

I was just looking through the Tools dir of the CVS version
(looking for a tool which autoexpands tabs in Python source
files -- which I didn't find) and found some other useful scripts
along the way.

To my surprise these executable files did not have a .py
extension even though were Python source files. Is this 
intended ? I find that scripts like "world" provide useful
information which would be nice to have in the standard
lib -- with .py extension...

Other tidbits:

I noted that at least in my CVS tree the Tools/ht2html
dir does not include any executable: have I missed something ?

The script Tools/scripts/parseentities.py is not executable
for some reason.

-- 
Marc-Andre Lemburg
______________________________________________________________________
Business:                                      http://www.lemburg.com/
Python Pages:                           http://www.lemburg.com/python/




From guido@CNRI.Reston.VA.US  Wed Jan 19 12:50:05 2000
From: guido@CNRI.Reston.VA.US (Guido van Rossum)
Date: Wed, 19 Jan 2000 07:50:05 -0500
Subject: [Python-Dev] Python Tools/
In-Reply-To: Your message of "Tue, 18 Jan 2000 23:55:04 +0100."
 <3884EF48.A6107775@lemburg.com>
References: <3884EF48.A6107775@lemburg.com>
Message-ID: <200001191250.HAA18786@eric.cnri.reston.va.us>

> I was just looking through the Tools dir of the CVS version
> (looking for a tool which autoexpands tabs in Python source
> files -- which I didn't find) and found some other useful scripts
> along the way.
> 
> To my surprise these executable files did not have a .py
> extension even though were Python source files. Is this 
> intended ? I find that scripts like "world" provide useful
> information which would be nice to have in the standard
> lib -- with .py extension...

I would agree, but that's Barry's creation, so I'll let him answer for
himself.  Any other scripts with the same problem?

> Other tidbits:
> 
> I noted that at least in my CVS tree the Tools/ht2html
> dir does not include any executable: have I missed something ?

Actually, that directory is a ghost and shouldn't have been exported
at all.  (Barry, can you erase it from sweetpea?)

> The script Tools/scripts/parseentities.py is not executable
> for some reason.

Fixed now.

--Guido van Rossum (home page: http://www.python.org/~guido/)


From bwarsaw@cnri.reston.va.us (Barry A. Warsaw)  Wed Jan 19 16:24:41 2000
From: bwarsaw@cnri.reston.va.us (Barry A. Warsaw) (Barry A. Warsaw)
Date: Wed, 19 Jan 2000 11:24:41 -0500 (EST)
Subject: [Python-Dev] Python Tools/
References: <3884EF48.A6107775@lemburg.com>
Message-ID: <14469.58697.116588.501355@anthem.cnri.reston.va.us>

>>>>> "M" == M  <mal@lemburg.com> writes:

    M> To my surprise these executable files did not have a .py
    M> extension even though were Python source files. Is this 
    M> intended ? I find that scripts like "world" provide useful
    M> information which would be nice to have in the standard
    M> lib -- with .py extension...

I hadn't thought about making world a module, but if others agree, I
can play a little CVS magic to move the file to world.py.

    M> I noted that at least in my CVS tree the Tools/ht2html dir does
    M> not include any executable: have I missed something ?

If you do a `cvs up -P' (-P for prune) you'll find that that directory
goes away.  At one point I started to add the ht2html scripts to the
Python tools, but then we decided not to.  Unfortunately, once a
directory's been added to CVS it can never be removed (hence -P).

If you're really interested in the ht2html scripts, which are used to
build the Python.Org and JPython.Org sites (as well as my personal
pages), please see

    http://www.python.org/~bwarsaw/software/pyware.html

-Barry


From bwarsaw@cnri.reston.va.us (Barry A. Warsaw)  Wed Jan 19 17:32:50 2000
From: bwarsaw@cnri.reston.va.us (Barry A. Warsaw) (Barry A. Warsaw)
Date: Wed, 19 Jan 2000 12:32:50 -0500 (EST)
Subject: [Python-Dev] Python Tools/
References: <3884EF48.A6107775@lemburg.com>
 <14469.58697.116588.501355@anthem.cnri.reston.va.us>
Message-ID: <14469.62786.178265.983781@anthem.cnri.reston.va.us>

>>>>> "BAW" == Barry A Warsaw <bwarsaw@cnri.reston.va.us> writes:

    BAW> If you do a `cvs up -P' (-P for prune) you'll find that that
    BAW> directory goes away.  At one point I started to add the
    BAW> ht2html scripts to the Python tools, but then we decided not
    BAW> to.  Unfortunately, once a directory's been added to CVS it
    BAW> can never be removed (hence -P).

I just check this and there is no ht2html directory in Tools anymore.
We probably did remove it after you (MAL) had checked it out.  You can
either ignore the directory, or delete it from your working dirs.  If
cvs complains after deleting it, you may have to manually edit the
CVS/Entries file.  Sorry about that -- we know better now.

-Barry


From gerrit@nl.linux.org  Wed Jan 19 20:14:27 2000
From: gerrit@nl.linux.org (Gerrit Holl)
Date: Wed, 19 Jan 2000 21:14:27 +0100
Subject: [Python-Dev] ''.join in 1.6
Message-ID: <20000119211427.A3755@stopcontact.palga.uucp>

Hello,

I have a question/suggestion about ''.join in Python 1.6.

Suppose I have this list:
l = ["This", "is", "a", "test"]

Currently, I would join it this way into a tab-delimeted string:
s = string.join(l, '\t')

In 1.6, I should do it this way:
'\t'.join(s)

I think it would be better to have that method on the *list*:
s.join('\t')

That's more clear, isn't it?

regards,
Gerrit.

-- 
Please correct any bad English you encounter in my email message!
-----BEGIN GEEK CODE BLOCK----- http://www.geekcode.com
Version: 3.12
GCS dpu s-:-- a14 C++++>$ UL++ P--- L+++ E--- W++ N o? K? w--- !O !M !V PS+ PE?
Y? PGP-- t- 5? X? R- tv- b+(++) DI D+ G++ !e !r !y
-----END GEEK CODE BLOCK-----


From fredrik@pythonware.com  Wed Jan 19 20:43:36 2000
From: fredrik@pythonware.com (Fredrik Lundh)
Date: Wed, 19 Jan 2000 21:43:36 +0100
Subject: [Python-Dev] ''.join in 1.6
References: <20000119211427.A3755@stopcontact.palga.uucp>
Message-ID: <005e01bf62bd$dc8073d0$f29b12c2@secret.pythonware.com>

> In 1.6, I should do it this way:
> '\t'.join(s)
>=20
> I think it would be better to have that method on the *list*:
> s.join('\t')
>=20
> That's more clear, isn't it?

what if "s" is a tuple?  an array?  a user-defined
sequence type?

</F>



From bwarsaw@cnri.reston.va.us (Barry A. Warsaw)  Wed Jan 19 20:36:24 2000
From: bwarsaw@cnri.reston.va.us (Barry A. Warsaw) (Barry A. Warsaw)
Date: Wed, 19 Jan 2000 15:36:24 -0500 (EST)
Subject: [Python-Dev] ''.join in 1.6
References: <20000119211427.A3755@stopcontact.palga.uucp>
Message-ID: <14470.8264.686274.888365@anthem.cnri.reston.va.us>

>>>>> "GH" == Gerrit Holl <gerrit.holl@pobox.com> writes:

    GH> I think it would be better to have that method on the *list*:
    GH> s.join('\t')

    GH> That's more clear, isn't it?

Perhaps, but you want join to work on any sequence don't you?  By
making it a method on string objects, you sort of get that for free
(as opposed to putting it on lists, sequences, and requiring all class
authors to add it as well).

-Barry


From da@ski.org  Wed Jan 19 20:54:03 2000
From: da@ski.org (David Ascher)
Date: Wed, 19 Jan 2000 12:54:03 -0800
Subject: [Python-Dev] ''.join in 1.6
In-Reply-To: <20000119211427.A3755@stopcontact.palga.uucp>
Message-ID: <003b01bf62bf$5191abc0$c355cfc0@ski.org>

Gerrit Holl

> Currently, I would join it this way into a tab-delimeted string:
> s = string.join(l, '\t')
>
> In 1.6, I should do it this way:
> '\t'.join(s)
>
> I think it would be better to have that method on the *list*:
> s.join('\t')
>
> That's more clear, isn't it?

As Tim pointed out when they were discussed, the clearest way to express it
with the new methods is to do:

tab = '\t'

tab.join(s)

Similarly

space = ' '
space.join(s)

etc.

--david ascher



From da@ski.org  Wed Jan 19 22:41:47 2000
From: da@ski.org (David Ascher)
Date: Wed, 19 Jan 2000 14:41:47 -0800
Subject: [Python-Dev] SOAP
Message-ID: <000101bf62ce$5e509e70$c355cfc0@ski.org>

This is a multi-part message in MIME format.

------=_NextPart_000_0002_01BF628B.502D5E70
Content-Type: text/plain;
	charset="iso-8859-1"
Content-Transfer-Encoding: 7bit

Who if anyone is working on SOAP clients and servers for Python?

--david ascher
------=_NextPart_000_0002_01BF628B.502D5E70
Content-Type: text/x-vcard;
	name="David Ascher.vcf"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="David Ascher.vcf"

BEGIN:VCARD
VERSION:2.1
N:Ascher;David
FN:David Ascher
ORG:Smith Kettlewell Eye Research Institute
TEL;WORK;VOICE:415-345-2095
TEL;HOME;VOICE:415-345-2095
TEL;WORK;FAX:415-345-8455
ADR;WORK:;;2318 Fillmore St;San Francisco;CA;94115;US
LABEL;WORK;ENCODING=3DQUOTED-PRINTABLE:2318 Fillmore St=3D0D=3D0ASan =
Francisco, CA 94115=3D0D=3D0AUS
ADR;HOME:;;522A Green St;San Francisco;CA;94133;US
LABEL;HOME;ENCODING=3DQUOTED-PRINTABLE:522A Green St=3D0D=3D0ASan =
Francisco, CA 94133=3D0D=3D0AUS
EMAIL;PREF;INTERNET:da@ski.org
REV:20000107T184849Z
END:VCARD

------=_NextPart_000_0002_01BF628B.502D5E70--



From akuchlin@mems-exchange.org  Thu Jan 20 04:19:33 2000
From: akuchlin@mems-exchange.org (A.M. Kuchling)
Date: Wed, 19 Jan 2000 23:19:33 -0500
Subject: [Python-Dev] Changing existing class instances
Message-ID: <200001200419.XAA01969@mira.erols.com>

Currently, when you replace a class definition with an updated
version, it's really difficult to change existing class instances;
you'd have to essentially sweep every Python object and check if it's
an instance, starting at roots such as __main__ and sys.modules.  This
makes developing code in a long-running process difficult, Zope being
the best example of this.  When you modify a class definition used by
Zope code, you can't update existing instances floating around in
memory.

Over dinner, a friend and I were discussing this, and we thought it
probably isn't difficult to add an extra level of indirection to allow
fixing this.  The only other option we could think of is either the
complete scan of all objects, or inserting a forwarding pointer into
PyClassObjects that points to the replacing class if !NULL, and then
chase pointers when accessing PyInstanceObject->in_class.

A quick hack to implement the extra indirection took about
half an hour.  It does these things:

      * Defines a PyClassHandle type:
struct _PyClassHandle {
  PyClassHandle *next;		/* ptr to next PyClassHandle in linked list */
  PyClassObject *klass;		/* The class object */
} ;

      * The in_class attribute of PyInstanceObject becomes a
        PyClassHandle* instead of a PyClassObject*, and all code 
	such as inst->in_class becomes inst->in_class->klass.

      * As a quick hack to allow changing the class object referenced
        by a handle, I added a .forward( <newclassobject> ) method to
        class objects.  This basically does self.handle->klass =
        <newclassobject>.

The end result is that obj.__class__.forward(newclass) changes obj to
be an instance of newclass, and all other instances of obj.__class__
also mutate to become newclass instances.   

Making this purely automatic seems hard; you'd have to catch things
like 'import ftplib; ftplib.FTP = myclass', which would require
automatically calling ftplib.FTP.forward( myclass ) to make all
existing FTP instances mutate.  Would it be worthwhile to export some
hook for doing this in 1.6?  The cost is adding an extra pointer deref
to all access to PyInstanceObject->in_class.

(This could probably also be added to ExtensionClass, and probably
doesn't need to be added to core Python to help out Zope.  Just a
thought...)

-- 
A.M. Kuchling			http://starship.python.net/crew/amk/
Here the skull of a consumptive child becomes part of a great machine for
calculating the motions of the stars. Here, a yellow bird frets within the
ribcage of an unjust man.
    -- Welcome to Orqwith, in DOOM PATROL #22


From guido@CNRI.Reston.VA.US  Thu Jan 20 04:41:29 2000
From: guido@CNRI.Reston.VA.US (Guido van Rossum)
Date: Wed, 19 Jan 2000 23:41:29 -0500
Subject: [Python-Dev] Changing existing class instances
In-Reply-To: Your message of "Wed, 19 Jan 2000 23:19:33 EST."
 <200001200419.XAA01969@mira.erols.com>
References: <200001200419.XAA01969@mira.erols.com>
Message-ID: <200001200441.XAA20952@eric.cnri.reston.va.us>

> Currently, when you replace a class definition with an updated
> version, it's really difficult to change existing class instances;
> you'd have to essentially sweep every Python object and check if it's
> an instance, starting at roots such as __main__ and sys.modules.  This
> makes developing code in a long-running process difficult, Zope being
> the best example of this.  When you modify a class definition used by
> Zope code, you can't update existing instances floating around in
> memory.

There might be another solution.  When you reload a module, the module
object and its dictionary are reused.

Perhaps class and function objects could similarly be reused?  It
would mean that a class or def statement looks for an existing object
with the same name and type, and overwrites that.  Voila, all
references are automatically updated.

This is more work (e.g. for classes, a new bytecode may have to be
invented because the class creation process must be done differently)
but it's much less of a hack, and I think it would be more reliable.
(Even though it alters borderline semantics a bit.)

(Your extra indirection also slows things down, although I don't know
by how much -- not just the extra memory reference but also less
locality of reference so more cache hits.)

--Guido van Rossum (home page: http://www.python.org/~guido/)


From tim_one@email.msn.com  Thu Jan 20 05:59:51 2000
From: tim_one@email.msn.com (Tim Peters)
Date: Thu, 20 Jan 2000 00:59:51 -0500
Subject: [Python-Dev] Changing existing class instances
In-Reply-To: <200001200441.XAA20952@eric.cnri.reston.va.us>
Message-ID: <000b01bf630b$91a409a0$31a2143f@tim>

[Guido, on Andrew's idea for automagically updating
 classes]

> There might be another solution.  When you reload a module,
> the module object and its dictionary are reused.
>
> Perhaps class and function objects could similarly be
> reused?  It would mean that a class or def statement
> looks for an existing object with the same name and type,
> and overwrites that.  Voila, all references are
> automatically updated.

Too dangerous, I think.  While uncommon in general, I've certainly seen
(even written) functions that e.g. return a contained def or class.  The
intent in such cases is very much to create distinct defs or classes
(despite having the same names).  In this case I assume "the same name"
wouldn't *usually* be found, since the "contained def or class"'s name is
local to the containing function.  But if there ever happened to be a
module-level function or class of the same name, brrrr.

Modules differ because their namespace "search path" consists solely of the
more-global-than-global <wink> sys.modules.

> This is more work (e.g. for classes, a new bytecode may
> have to be invented because the class creation process
> must be done differently) but it's much less of a hack,
> and I think it would be more reliable. (Even though it
> alters borderline semantics a bit.)

How about an explicit function in the "new" module,

    new.update(class_or_def_old, class_or_def_new)

which overwrites old's guts with new's guts (in analogy with dict.update)?
Then no semantics change and you don't need new bytecodes.  In return, a
user who wants to e.g. replace an existing class C would need to do

    oldC = C
    do whatever they do to get the new C
    new.update(oldC, C)

Building on that, a short Python loop could do the magic for every class and
function in a module; and building on *that*, a short "updating import"
function could be written in Python.  View it as providing mechanism instead
of policy <0.9 wink>.

> (Your extra indirection also slows things down, although
> I don't know by how much -- not just the extra memory
> reference but also less locality of reference so more
> cache hits.)

Across the universe of all Python programs on all platforms, weighted by
importance, it was a slowdown of nearly 4.317%.

if-i-had-used-only-one-digit-everyone-would-have-
    known-i-was-making-it-up<wink>-ly y'rs  - tim




From gstein@lyra.org  Thu Jan 20 07:48:29 2000
From: gstein@lyra.org (Greg Stein)
Date: Wed, 19 Jan 2000 23:48:29 -0800 (PST)
Subject: [Python-Dev] Changing existing class instances
In-Reply-To: <000b01bf630b$91a409a0$31a2143f@tim>
Message-ID: <Pine.LNX.4.10.10001192342450.13911-100000@nebula.lyra.org>

Oh man, oh man... I think this is where I get to say something akin to "I
told you so."

:-)

I already described Tim's proposal in my type proposal paper, as a way to
deal with incomplete classes. Essentially, a class object is created
"empty" and is later "updated" with the correct bits. The empty class
allows two classes to refer to each other in the "recursive type"
scenario.

In other words, I definitely would support a new class object behavior
that allows us to update a class' set of bases and dictionary on the fly.
This could then be used to support my solution for the recursive type
scenario (which, in turn, means that we don't have to introduce Yet
Another Namespace into Python to hold type names).

Note: I would agree with Guido, however, on the "look for a class object
with the same name", but with the restriction that the name is only
replaced in the *target* namespace. i.e. a "class Foo" in a function will
only look for Foo in the function's local namespace; it would not
overwrite a class in the global space, nor would it overwrite class
objects returned by a prior invocation of the function.

Cheers,
-g

On Thu, 20 Jan 2000, Tim Peters wrote:
> [Guido, on Andrew's idea for automagically updating
>  classes]
> 
> > There might be another solution.  When you reload a module,
> > the module object and its dictionary are reused.
> >
> > Perhaps class and function objects could similarly be
> > reused?  It would mean that a class or def statement
> > looks for an existing object with the same name and type,
> > and overwrites that.  Voila, all references are
> > automatically updated.
> 
> Too dangerous, I think.  While uncommon in general, I've certainly seen
> (even written) functions that e.g. return a contained def or class.  The
> intent in such cases is very much to create distinct defs or classes
> (despite having the same names).  In this case I assume "the same name"
> wouldn't *usually* be found, since the "contained def or class"'s name is
> local to the containing function.  But if there ever happened to be a
> module-level function or class of the same name, brrrr.
> 
> Modules differ because their namespace "search path" consists solely of the
> more-global-than-global <wink> sys.modules.
> 
> > This is more work (e.g. for classes, a new bytecode may
> > have to be invented because the class creation process
> > must be done differently) but it's much less of a hack,
> > and I think it would be more reliable. (Even though it
> > alters borderline semantics a bit.)
> 
> How about an explicit function in the "new" module,
> 
>     new.update(class_or_def_old, class_or_def_new)
> 
> which overwrites old's guts with new's guts (in analogy with dict.update)?
> Then no semantics change and you don't need new bytecodes.  In return, a
> user who wants to e.g. replace an existing class C would need to do
> 
>     oldC = C
>     do whatever they do to get the new C
>     new.update(oldC, C)
> 
> Building on that, a short Python loop could do the magic for every class and
> function in a module; and building on *that*, a short "updating import"
> function could be written in Python.  View it as providing mechanism instead
> of policy <0.9 wink>.
> 
> > (Your extra indirection also slows things down, although
> > I don't know by how much -- not just the extra memory
> > reference but also less locality of reference so more
> > cache hits.)
> 
> Across the universe of all Python programs on all platforms, weighted by
> importance, it was a slowdown of nearly 4.317%.
> 
> if-i-had-used-only-one-digit-everyone-would-have-
>     known-i-was-making-it-up<wink>-ly y'rs  - tim
> 
> 
> 
> _______________________________________________
> Python-Dev maillist  -  Python-Dev@python.org
> http://www.python.org/mailman/listinfo/python-dev
> 

-- 
Greg Stein, http://www.lyra.org/



From fredrik@pythonware.com  Thu Jan 20 08:06:32 2000
From: fredrik@pythonware.com (Fredrik Lundh)
Date: Thu, 20 Jan 2000 09:06:32 +0100
Subject: [Python-Dev] SOAP
References: <000101bf62ce$5e509e70$c355cfc0@ski.org>
Message-ID: <006901bf631d$449eea50$f29b12c2@secret.pythonware.com>

David Ascher <da@ski.org> wrote:
> Who if anyone is working on SOAP clients and servers for Python?

we are (or rather, we will).  hope to have code
available during (late) Q1.

</F>



From gerrit@nl.linux.org  Thu Jan 20 08:08:01 2000
From: gerrit@nl.linux.org (Gerrit Holl)
Date: Thu, 20 Jan 2000 09:08:01 +0100
Subject: [Python-Dev] ''.join in 1.6
In-Reply-To: <005e01bf62bd$dc8073d0$f29b12c2@secret.pythonware.com>; from fredrik@pythonware.com on Wed, Jan 19, 2000 at 09:43:36PM +0100
References: <20000119211427.A3755@stopcontact.palga.uucp> <005e01bf62bd$dc8073d0$f29b12c2@secret.pythonware.com>
Message-ID: <20000120090801.A903@stopcontact.palga.uucp>

Fredrik Lundh wrote on 948314616:
> > In 1.6, I should do it this way:
> > '\t'.join(s)
> > 
> > I think it would be better to have that method on the *list*:
> > s.join('\t')
> > 
> > That's more clear, isn't it?
> 
> what if "s" is a tuple?  an array?  a user-defined
> sequence type?

I understand. Thanks for your answers.

regards,
Gerrit.

-- 
Please correct any bad English you encounter in my email message!
-----BEGIN GEEK CODE BLOCK----- http://www.geekcode.com
Version: 3.12
GCS dpu s-:-- a14 C++++>$ UL++ P--- L+++ E--- W++ N o? K? w--- !O !M !V PS+ PE?
Y? PGP-- t- 5? X? R- tv- b+(++) DI D+ G++ !e !r !y
-----END GEEK CODE BLOCK-----


From jim@digicool.com  Thu Jan 20 14:06:29 2000
From: jim@digicool.com (Jim Fulton)
Date: Thu, 20 Jan 2000 09:06:29 -0500
Subject: [Python-Dev] Changing existing class instances
References: <200001200419.XAA01969@mira.erols.com>
Message-ID: <38871665.C3B6FFEE@digicool.com>

"A.M. Kuchling" wrote:
> 
> Currently, when you replace a class definition with an updated
> version, it's really difficult to change existing class instances;
> you'd have to essentially sweep every Python object and check if it's
> an instance, starting at roots such as __main__ and sys.modules.  This
> makes developing code in a long-running process difficult, Zope being
> the best example of this.  When you modify a class definition used by
> Zope code, you can't update existing instances floating around in
> memory.

In the case of Zope, if the objects that you care about happen to be 
persistent objects, then it's relatively easy to arrange to get the
objects flushed from memory and reloaded with the new classes.
(There are some subtle issues to deal with, like worrying about 
multiple threads, but in a development environment, you can deal with
these, for example, by limiting the server to one thread.)

Note that this is really only a special case of a much larger problem.

Reloading a module redefines the global variables in a module.
It doesn't update any references to those global references
from other places, such as instances or *other* modules.

For example, imports like:

  from foo import spam

are not updated when foo is reloaded.

Maybe you are expecting too much from reload.

Jim      

--
Jim Fulton           mailto:jim@digicool.com
Technical Director   (888) 344-4332              Python Powered!
Digital Creations    http://www.digicool.com     http://www.python.org

Under US Code Title 47, Sec.227(b)(1)(C), Sec.227(a)(2)(B) This email
address may not be added to any commercial mail list with out my
permission.  Violation of my privacy with advertising or SPAM will
result in a suit for a MINIMUM of $500 damages/incident, $1500 for
repeats.


From jim@digicool.com  Thu Jan 20 14:34:13 2000
From: jim@digicool.com (Jim Fulton)
Date: Thu, 20 Jan 2000 09:34:13 -0500
Subject: Python 2 namespace change? (was Re: [Python-Dev] Changing existing class
 instances)
References: <200001200419.XAA01969@mira.erols.com> <38871665.C3B6FFEE@digicool.com>
Message-ID: <38871CE5.53FB9D68@digicool.com>

Jim Fulton wrote:
> 
> Reloading a module redefines the global variables in a module.
> It doesn't update any references to those global references
> from other places, such as instances or *other* modules.
> 
> For example, imports like:
> 
>   from foo import spam
> 
> are not updated when foo is reloaded.

A change to the way that namespaces are handled 
could make this work and have a number of other benefits, 
like global name usage without namespace lookups.

I've suggested this to Guido in the past.  His 
reasonable response is that this would be too big a 
change for Python 1. Maybe this is something to consider
for Python 2?

The basic idea (borrowed from Smalltalk) is to have a kind 
of dictionary that is a collection of "association" 
objects.  An association object is simply a pairing of a 
name with a value. Association objects can be shared among 
multiple namespaces.  An import like:

  from foo import spam

would copy the association between the name 'foo' and a 
value from module 'spam' into the current module. If foo
is reloaded or if the name is reassigned in spam, the
association is modified and the change is seen in any
namespaces that imported foo.

Similarly if a function uses a global variable:

  spam=1

  def bar():
    global spam
    return spam*2

the compiled function contains the association between
spam and it's value. This means that:

  - When spam is used in the function, it doesn't have to
    be looked up,

  - The function object no longer needs to keep a reference
    to it's globals. This eliminates an annoying circular 
    reference.

(I would not replace existing dictionaries with this new kind.
 I'd have both kinds available.)

I think that this would be a really nice change for Python 2.

Jim

--
Jim Fulton           mailto:jim@digicool.com
Technical Director   (888) 344-4332              Python Powered!
Digital Creations    http://www.digicool.com     http://www.python.org

Under US Code Title 47, Sec.227(b)(1)(C), Sec.227(a)(2)(B) This email
address may not be added to any commercial mail list with out my
permission.  Violation of my privacy with advertising or SPAM will
result in a suit for a MINIMUM of $500 damages/incident, $1500 for
repeats.


From guido@CNRI.Reston.VA.US  Thu Jan 20 15:20:45 2000
From: guido@CNRI.Reston.VA.US (Guido van Rossum)
Date: Thu, 20 Jan 2000 10:20:45 -0500
Subject: [Python-Dev] Changing existing class instances
In-Reply-To: Your message of "Thu, 20 Jan 2000 00:59:51 EST."
 <000b01bf630b$91a409a0$31a2143f@tim>
References: <000b01bf630b$91a409a0$31a2143f@tim>
Message-ID: <200001201520.KAA21137@eric.cnri.reston.va.us>

> From: "Tim Peters" <tim_one@email.msn.com>
> 
> [Guido, on Andrew's idea for automagically updating
>  classes]
> 
> > There might be another solution.  When you reload a module,
> > the module object and its dictionary are reused.
> >
> > Perhaps class and function objects could similarly be
> > reused?  It would mean that a class or def statement
> > looks for an existing object with the same name and type,
> > and overwrites that.  Voila, all references are
> > automatically updated.
> 
> Too dangerous, I think.  While uncommon in general, I've certainly seen
> (even written) functions that e.g. return a contained def or class.  The
> intent in such cases is very much to create distinct defs or classes
> (despite having the same names).  In this case I assume "the same name"
> wouldn't *usually* be found, since the "contained def or class"'s name is
> local to the containing function.  But if there ever happened to be a
> module-level function or class of the same name, brrrr.

Agreed that that would be bad.  But I wouldn't search outer scopes --
I would only look for a class/def that I was about to stomp on.

> Modules differ because their namespace "search path" consists solely of the
> more-global-than-global <wink> sys.modules.

"The search path doesn't enter into it."

> > This is more work (e.g. for classes, a new bytecode may
> > have to be invented because the class creation process
> > must be done differently) but it's much less of a hack,
> > and I think it would be more reliable. (Even though it
> > alters borderline semantics a bit.)
> 
> How about an explicit function in the "new" module,
> 
>     new.update(class_or_def_old, class_or_def_new)
> 
> which overwrites old's guts with new's guts (in analogy with dict.update)?
> Then no semantics change and you don't need new bytecodes.

Only a slight semantics change (which my full proposal would require
too): function objects would become mutable -- their func_code,
func_defaults, func_doc and func_globals fields (and, why not,
func_name too) should be changeable.  If you make all these
assignable, it doesn't even have to be a privileged function.

> In return, a
> user who wants to e.g. replace an existing class C would need to do
> 
>     oldC = C
>     do whatever they do to get the new C
>     new.update(oldC, C)
> 
> Building on that, a short Python loop could do the magic for every class and
> function in a module; and building on *that*, a short "updating import"
> function could be written in Python.  View it as providing mechanism instead
> of policy <0.9 wink>.

That's certainly a reasonable compromise.  Note that the update on a
class should imply an update on its methods, right?

--Guido van Rossum (home page: http://www.python.org/~guido/)


From guido@CNRI.Reston.VA.US  Thu Jan 20 15:45:40 2000
From: guido@CNRI.Reston.VA.US (Guido van Rossum)
Date: Thu, 20 Jan 2000 10:45:40 -0500
Subject: Python 2 namespace change? (was Re: [Python-Dev] Changing existing class instances)
In-Reply-To: Your message of "Thu, 20 Jan 2000 09:34:13 EST."
 <38871CE5.53FB9D68@digicool.com>
References: <200001200419.XAA01969@mira.erols.com> <38871665.C3B6FFEE@digicool.com>
 <38871CE5.53FB9D68@digicool.com>
Message-ID: <200001201545.KAA21304@eric.cnri.reston.va.us>

> I've suggested this to Guido in the past.  His 
> reasonable response is that this would be too big a 
> change for Python 1. Maybe this is something to consider
> for Python 2?

Note: from now on the new name for Python 2 is Python 3000. :-)

> The basic idea (borrowed from Smalltalk) is to have a kind 
> of dictionary that is a collection of "association" 
> objects.  An association object is simply a pairing of a 
> name with a value. Association objects can be shared among 
> multiple namespaces.

I've never liked this very much, mostly because it breaks simplicity:
the idea that a namespace is a mapping from names to values
(e.g. {"limit": 100, "doit": <function...>, ...}) is beautifully
simple, while the idea of inserting an extra level of indirection, no
matter how powerful, is much murkier.

There's also the huge change in semantics, as you point out;
currently,

	from foo import bar

has the same effect (on bar anyway) as

	import foo
	bar = foo.bar		# i.e. copying an object reference
	del foo

while under your proposal it would be more akin to changing all
references to bar to become references to foo.bar.

Of course that's what the moral equivalent of "from ... import ..."
does in most other languages anyway, so we might consider this for
Python 3000; however it would break a considerable amount of old code,
I think.  (Not to mention brain and book breakage. :-)

--Guido van Rossum (home page: http://www.python.org/~guido/)


From guido@CNRI.Reston.VA.US  Thu Jan 20 16:01:38 2000
From: guido@CNRI.Reston.VA.US (Guido van Rossum)
Date: Thu, 20 Jan 2000 11:01:38 -0500
Subject: [Python-Dev] Python 1.6 timing
Message-ID: <200001201601.LAA21359@eric.cnri.reston.va.us>

Andrew let me repost this mail of his to this list.  It's worth a
discussion here (if not in a larger forum).  My responses are at the
bottom.

------- Forwarded Message

Date:    Wed, 19 Jan 2000 20:17:55 -0500
From:    "A.M. Kuchling" <amk1@erols.com>
To:      guido@python.org
Subject: Python 1.6 timing

I thought a bit more about the release schedule for 1.6, and like the
idea of delaying it less and less.  Another bad effect of delaying it
is that not having Unicode in the core handicaps developing XML tools;
we can continue working with wstrop, or integrate MAL's code into the
XML-SIG's CVS tree, but it might mean abandoning the XML processing
field to Perl & Tcl because the tools can't be made fully standard
compliant in time.

Options I can think of:

	1) Delegating some control to a pumpkin holder [...].

	2) Releasing the Unicode+sre modules as separate add-ons to
 	   1.5.  (But would that impose annoying
	   backward-compatibility constraints when they get integrated
	   into 1.6?)

	3) Add Unicode, sre, Distutils, plus other minor things and
           call it 1.5.5, meaning it's not as big a revision as a 1.6
           release, but it's bigger than just another patchlevel of
	   bugfixes.  I don't remember what other features were
	   planned for 1.6; was there anything major, if static typing
	   is left for 2.0?

- -- 
A.M. Kuchling			http://starship.python.net/crew/amk/
Life's too short for chess.
    -- H.J. Byron

------- End of Forwarded Message

There are several other things I can think of now that were planned
for 1.6: revamped import, rich comparisons, revised coercions,
parallel for loop (for i in L; j in M: ...), extended slicing for all
sequences.  I've also been thinking about making classes be types (not
as huge a change as you think, if you don't allow subclassing built-in
types), and adding a built-in array type suitable for use by NumPy.
I've also received a conservative GC patch that seems to be fairly
easy to apply and has some of Tim Peters' blessing.

For 1.5.5 (what happened to 1.5.3 and 1.5.4?), we can have a more
conservative agenda, as suggested by Andrew: Unicode and distutils are
probably the most important things to integrate.  (The import
utilities are not ready for prime time in my opinion; there are too
many issues.)

Anybody care to be the pumpkin?  That would cut the discussion short;
otherwise the problem remains that I can't spend too much time on the
next release unless I get funded for it; what little money I've
received for CP4E I had better spend on getting some CP4E-related
results ASAP, because the next installment of this funding is very
much at stake...

--Guido van Rossum (home page: http://www.python.org/~guido/)
Life's better without braces.
    -- Bruce Eckel


From bwarsaw@cnri.reston.va.us (Barry A. Warsaw)  Thu Jan 20 16:21:30 2000
From: bwarsaw@cnri.reston.va.us (Barry A. Warsaw) (Barry A. Warsaw)
Date: Thu, 20 Jan 2000 11:21:30 -0500 (EST)
Subject: [Python-Dev] Python 1.6 timing
References: <200001201601.LAA21359@eric.cnri.reston.va.us>
Message-ID: <14471.13834.480356.541389@anthem.cnri.reston.va.us>

>>>>> "Guido" == Guido van Rossum <guido@cnri.reston.va.us> writes:

    Guido> There are several other things I can think of now that were
    Guido> planned for 1.6: revamped import, rich comparisons, revised
    Guido> coercions, parallel for loop (for i in L; j in M: ...),
    Guido> extended slicing for all sequences.  I've also been
    Guido> thinking about making classes be types (not as huge a
    Guido> change as you think, if you don't allow subclassing
    Guido> built-in types), and adding a built-in array type suitable
    Guido> for use by NumPy.  I've also received a conservative GC
    Guido> patch that seems to be fairly easy to apply and has some of
    Guido> Tim Peters' blessing.

All very cool things that could easily wait until 1.7.  After all,
what's in a number?  If, as Andrew puts forth, getting a stable Python
release with Unicode is very important for Python's future
positioning, then I say let's go with his more modest list, mainly
Unicode, sre, and Distutils.  We've already got string meths, tons of
library improvements, and sundry other things.  That's a good enough
laundry list for the next release.

From a political standpoint, I'd call the next release 1.6 and not
bother with another installment in 1.5.x series.  And I agree with
Andrew, we should fast track that release as much as possible.  I'm
not sure what the state of the Unicode patches, sre, or Distutils
current is, although I haven't seen any of that stuff checked into the
tree.  My free-time plate is pretty full with JPython and Mailman, but
I'm willing to help where possible.

-Barry


From jim@digicool.com  Thu Jan 20 16:21:33 2000
From: jim@digicool.com (Jim Fulton)
Date: Thu, 20 Jan 2000 11:21:33 -0500
Subject: Version numbering (was Re: [Python-Dev] Python 1.6 timing)
References: <200001201601.LAA21359@eric.cnri.reston.va.us>
Message-ID: <3887360D.C29A9836@digicool.com>

Guido van Rossum wrote:
> 
> Andrew let me repost this mail of his to this list.  It's worth a
> discussion here (if not in a larger forum).  My responses are at the
> bottom.
> 
(snip)
> 
> There are several other things I can think of now that were planned
> for 1.6: revamped import, rich comparisons, revised coercions,
> parallel for loop (for i in L; j in M: ...), extended slicing for all
> sequences.  I've also been thinking about making classes be types (not
> as huge a change as you think, if you don't allow subclassing built-in
> types), and adding a built-in array type suitable for use by NumPy.
> I've also received a conservative GC patch that seems to be fairly
> easy to apply and has some of Tim Peters' blessing.
> 
> For 1.5.5 (what happened to 1.5.3 and 1.5.4?), we can have a more
> conservative agenda, as suggested by Andrew: Unicode and distutils are
> probably the most important things to integrate.  (The import
> utilities are not ready for prime time in my opinion; there are too
> many issues.)

(snip)

What is the basis of the Python numbering scheme?

I thought that there was a notion that:

  - The first part changed with huge, possibly
    backward incompatible, changes,

  - The second part was for new functionality 
    
  - The third part was for bug fixes.

I thought I saw this scheme referenced somewhere and
possibly even attributed to Guido. (?) I think that 
this is a better scheme that what I've seen with 
the 1.5 releases.

Jim

--
Jim Fulton           mailto:jim@digicool.com
Technical Director   (888) 344-4332              Python Powered!
Digital Creations    http://www.digicool.com     http://www.python.org

Under US Code Title 47, Sec.227(b)(1)(C), Sec.227(a)(2)(B) This email
address may not be added to any commercial mail list with out my
permission.  Violation of my privacy with advertising or SPAM will
result in a suit for a MINIMUM of $500 damages/incident, $1500 for
repeats.


From petrilli@amber.org  Thu Jan 20 16:33:52 2000
From: petrilli@amber.org (Christopher Petrilli)
Date: Thu, 20 Jan 2000 11:33:52 -0500
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <14471.13834.480356.541389@anthem.cnri.reston.va.us>; from bwarsaw@cnri.reston.va.us on Thu, Jan 20, 2000 at 11:21:30AM -0500
References: <200001201601.LAA21359@eric.cnri.reston.va.us> <14471.13834.480356.541389@anthem.cnri.reston.va.us>
Message-ID: <20000120113352.A23763@trump.amber.org>

Barry A. Warsaw [bwarsaw@cnri.reston.va.us] wrote:
> All very cool things that could easily wait until 1.7.  After all,
> what's in a number?  If, as Andrew puts forth, getting a stable Python
> release with Unicode is very important for Python's future
> positioning, then I say let's go with his more modest list, mainly
> Unicode, sre, and Distutils.  We've already got string meths, tons of
> library improvements, and sundry other things.  That's a good enough
> laundry list for the next release.

Heck, Python is infinately more conservative in its numbering than 
a lot of projects.  All that was mentioned would normally be enough to
call it 2.0 easily. :-)  Modesty can be counter productive in PR 
business...also there is the issue of having two copies of 1.5.x installed
at the same time, which with Unicode could be a manjor consideraton
for some of us.

For me, numbering has always been (and I try and keep it this way with
Zope):

	X.Y.Z

	X = structural changes, backward incompaibility
	Y = new features
	Z = bug fixes only

Chris
-- 
| Christopher Petrilli
| petrilli@amber.org


From bwarsaw@cnri.reston.va.us (Barry A. Warsaw)  Thu Jan 20 16:30:32 2000
From: bwarsaw@cnri.reston.va.us (Barry A. Warsaw) (Barry A. Warsaw)
Date: Thu, 20 Jan 2000 11:30:32 -0500 (EST)
Subject: [Python-Dev] Python 1.6 timing
References: <200001201601.LAA21359@eric.cnri.reston.va.us>
 <14471.13834.480356.541389@anthem.cnri.reston.va.us>
 <20000120113352.A23763@trump.amber.org>
Message-ID: <14471.14376.9881.702264@anthem.cnri.reston.va.us>

>>>>> "CP" == Christopher Petrilli <petrilli@amber.org> writes:

    CP> For me, numbering has always been (and I try and keep it this
    CP> way with Zope):

    CP> 	X.Y.Z

    | 	X = structural changes, backward incompaibility
    | 	Y = new features
    | 	Z = bug fixes only

I agree.
-Barry


From petrilli@amber.org  Thu Jan 20 16:41:24 2000
From: petrilli@amber.org (Christopher Petrilli)
Date: Thu, 20 Jan 2000 11:41:24 -0500
Subject: [Python-Dev] SOAP
In-Reply-To: <006901bf631d$449eea50$f29b12c2@secret.pythonware.com>; from fredrik@pythonware.com on Thu, Jan 20, 2000 at 09:06:32AM +0100
References: <000101bf62ce$5e509e70$c355cfc0@ski.org> <006901bf631d$449eea50$f29b12c2@secret.pythonware.com>
Message-ID: <20000120114124.B23763@trump.amber.org>

Fredrik Lundh [fredrik@pythonware.com] wrote:
> David Ascher <da@ski.org> wrote:
> > Who if anyone is working on SOAP clients and servers for Python?
> 
> we are (or rather, we will).  hope to have code
> available during (late) Q1.
> 
> </F>

For what it's worth, this is also Zope's strategy.  We are commited to
having full SOAP integration in the system soon (when soon is, is another
queston for the marketing department). :-)   I am pretty sure that it will
be a bi-directional integration.

Chris
-- 
| Christopher Petrilli
| petrilli@amber.org


From akuchlin@mems-exchange.org  Thu Jan 20 16:38:53 2000
From: akuchlin@mems-exchange.org (Andrew M. Kuchling)
Date: Thu, 20 Jan 2000 11:38:53 -0500 (EST)
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <14471.13834.480356.541389@anthem.cnri.reston.va.us>
References: <200001201601.LAA21359@eric.cnri.reston.va.us>
 <14471.13834.480356.541389@anthem.cnri.reston.va.us>
Message-ID: <14471.14877.434886.471929@amarok.cnri.reston.va.us>

Barry A. Warsaw writes:
>    Guido> There are several other things I can think of now that were
>    Guido> planned for 1.6: revamped import, rich comparisons, revised
>    Guido> coercions, parallel for loop (for i in L; j in M: ...),
>    Guido> extended slicing for all sequences.  

I'm not clear on the status of these various things; how many of these
changes are deep ones that need lots of design, or affect massive
amounts of the code base?  For example, revamped import is a tricky
design problem (as we've seen on this list).  Is the spec for rich
comparisons clearly defined at this point?  Something like the
parallel for loop seems like a parser modification combined with a
code-generator modification, with no subtle implications for the rest
of the implementation, and so that seems a simple matter of
programming -- a week or so of effort.  (Maybe I've missed something?)

>    Guido> I've also been
>    Guido> thinking about making classes be types (not as huge a
>    Guido> change as you think, if you don't allow subclassing
>    Guido> built-in types), and adding a built-in array type suitable
>    Guido> for use by NumPy.  I've also received a conservative GC
>    Guido> patch that seems to be fairly easy to apply and has some of
>    Guido> Tim Peters' blessing.

Similarly, does the conservative GC patch splatter changes all over
the place, or is it very localized?  Is adding the NumPy array type
straightforward?  Remember, there would presumably be a couple of 1.6
alphas and betas to shake out bugs.

>From a political standpoint, I'd call the next release 1.6 and not
>bother with another installment in 1.5.x series.  And I agree with

Fair enough; forget about the 1.5.5 suggestion, and call it as 1.6.

>tree.  My free-time plate is pretty full with JPython and Mailman, but
>I'm willing to help where possible.

Ditto.

-- 
A.M. Kuchling			http://starship.python.net/crew/amk/
One trouble with being efficient is that it makes everybody hate you so.
    -- Bob Edwards, the Calgary Eyeopener, March 18, 1916



From jim@digicool.com  Thu Jan 20 16:48:18 2000
From: jim@digicool.com (Jim Fulton)
Date: Thu, 20 Jan 2000 11:48:18 -0500
Subject: Python 2 namespace change? (was Re: [Python-Dev] Changing existing
 class instances)
References: <200001200419.XAA01969@mira.erols.com> <38871665.C3B6FFEE@digicool.com>
 <38871CE5.53FB9D68@digicool.com> <200001201545.KAA21304@eric.cnri.reston.va.us>
Message-ID: <38873C52.29FEAC6D@digicool.com>

Guido van Rossum wrote:
> 
> > I've suggested this to Guido in the past.  His
> > reasonable response is that this would be too big a
> > change for Python 1. Maybe this is something to consider
> > for Python 2?
> 
> Note: from now on the new name for Python 2 is Python 3000. :-)

I like it. 

> > The basic idea (borrowed from Smalltalk) is to have a kind
> > of dictionary that is a collection of "association"
> > objects.  An association object is simply a pairing of a
> > name with a value. Association objects can be shared among
> > multiple namespaces.
> 
> I've never liked this very much, mostly because it breaks simplicity:
> the idea that a namespace is a mapping from names to values
> (e.g. {"limit": 100, "doit": <function...>, ...}) is beautifully
> simple, while the idea of inserting an extra level of indirection, no
> matter how powerful, is much murkier.

How so? It doesn't change the mapping semantics.
 
> There's also the huge change in semantics, as you point out;
> currently,
> 
>         from foo import bar
> 
> has the same effect (on bar anyway) as
> 
>         import foo
>         bar = foo.bar           # i.e. copying an object reference
>         del foo
> 
> while under your proposal it would be more akin to changing all
> references to bar to become references to foo.bar.
> 
> Of course that's what the moral equivalent of "from ... import ..."
> does in most other languages anyway, so we might consider this for
> Python 3000;

Cool. Again, it would also make function global variable access
faster and cleaner in some ways.

> however it would break a considerable amount of old code,
> I think. 

Really? I wonder. I bet it would break alot less old
code that other recent changes.

> (Not to mention brain

It makes my brain feel much better. :)

> and book breakage. :-)

Hey, all of the books will have to be rewritten for Python 3000.

Jim

--
Jim Fulton           mailto:jim@digicool.com
Technical Director   (888) 344-4332              Python Powered!
Digital Creations    http://www.digicool.com     http://www.python.org

Under US Code Title 47, Sec.227(b)(1)(C), Sec.227(a)(2)(B) This email
address may not be added to any commercial mail list with out my
permission.  Violation of my privacy with advertising or SPAM will
result in a suit for a MINIMUM of $500 damages/incident, $1500 for
repeats.


From gstein@lyra.org  Thu Jan 20 17:22:40 2000
From: gstein@lyra.org (Greg Stein)
Date: Thu, 20 Jan 2000 09:22:40 -0800 (PST)
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <200001201601.LAA21359@eric.cnri.reston.va.us>
Message-ID: <Pine.LNX.4.10.10001200907240.13911-100000@nebula.lyra.org>

On Thu, 20 Jan 2000, Guido van Rossum wrote:
>...
> Date:    Wed, 19 Jan 2000 20:17:55 -0500
> From:    "A.M. Kuchling" <amk1@erols.com>
> To:      guido@python.org
> Subject: Python 1.6 timing
> 
> I thought a bit more about the release schedule for 1.6, and like the
> idea of delaying it less and less.  Another bad effect of delaying it
> is that not having Unicode in the core handicaps developing XML tools;
> we can continue working with wstrop, or integrate MAL's code into the
> XML-SIG's CVS tree, but it might mean abandoning the XML processing
> field to Perl & Tcl because the tools can't be made fully standard
> compliant in time.

I agree with Andrew's basic premise.

> Options I can think of:
> 
> 	1) Delegating some control to a pumpkin holder [...].

Seems fine.

> 	2) Releasing the Unicode+sre modules as separate add-ons to
>  	   1.5.  (But would that impose annoying
> 	   backward-compatibility constraints when they get integrated
> 	   into 1.6?)

Icky. :-)

> 	3) Add Unicode, sre, Distutils, plus other minor things and
>            call it 1.5.5, meaning it's not as big a revision as a 1.6
>            release, but it's bigger than just another patchlevel of
> 	   bugfixes.  I don't remember what other features were
> 	   planned for 1.6; was there anything major, if static typing
> 	   is left for 2.0?

Call it 1.6, per the rest of the thread.

>...
> For 1.5.5 (what happened to 1.5.3 and 1.5.4?), we can have a more
> conservative agenda, as suggested by Andrew: Unicode and distutils are
> probably the most important things to integrate.

Unicode: definitely. distutils seems pretty early, but I bet that some key
concepts could be added to 1.6, to make the transition and continued
development easier.

Note that if an announcement were made to the effect of "feature freeze on
February 15; only bug fixes afterwards," that you would get a lot of
people scrambling to submit their pet features. This would be a good way
to light some fires, to see what kinds of things get completed (i.e. we
may think some things aren't ready or are too far out, put that deadline
in and those positions could change...)

> (The import
> utilities are not ready for prime time in my opinion; there are too
> many issues.)

I'm waiting for that review :-)

If you raise issues, then I can knock them down. I don't see all that many
at the moment. But I'm biased :-)

> Anybody care to be the pumpkin?  That would cut the discussion short;
> otherwise the problem remains that I can't spend too much time on the
> next release unless I get funded for it; what little money I've
> received for CP4E I had better spend on getting some CP4E-related
> results ASAP, because the next installment of this funding is very
> much at stake...

I would volunteer for the pumpkin... around April-ish. My plate is rather
full with completing mod_dav and then integrating that into Apache 2.0.
Once the Apache integration begins, then I'd have some more free time.

But this begs the question of: what does the pumpkin-holder mean in the
*Python* world?

If it is collating fixes, producing snapshots, etc, then I'm comfy with
it. If it also contains responsibility for specific kinds of work, then
Fred would probably veto me :-), as I've got an outstanding doc that I owe
him (for about six months now... sigh; maybe I'll bribe MAL to write it; 
he knows the interface :-)).

But stll: what's it mean? How does the pumpkin reduce the Guido-load, yet
still enable the Guido-control?

[ I just had a talk about this with the guys at Inprise, re: InterBase,
  mentioning that the Dictator model works well for Python, but doesn't
  necessarily work well for new projects or commercially-started projects
  due to control/prejudice issues. Python people like it because of the
  resulting simplicity and cleanliness; I doubt we want a pumpkin approach
  that would allow that to go away! ]

Cheers,
-g

-- 
Greg Stein, http://www.lyra.org/



From guido@CNRI.Reston.VA.US  Thu Jan 20 17:20:33 2000
From: guido@CNRI.Reston.VA.US (Guido van Rossum)
Date: Thu, 20 Jan 2000 12:20:33 -0500
Subject: Python 2 namespace change? (was Re: [Python-Dev] Changing existing class instances)
In-Reply-To: Your message of "Thu, 20 Jan 2000 11:48:18 EST."
 <38873C52.29FEAC6D@digicool.com>
References: <200001200419.XAA01969@mira.erols.com> <38871665.C3B6FFEE@digicool.com> <38871CE5.53FB9D68@digicool.com> <200001201545.KAA21304@eric.cnri.reston.va.us>
 <38873C52.29FEAC6D@digicool.com>
Message-ID: <200001201720.MAA21534@eric.cnri.reston.va.us>

[me]
> > I've never liked this very much, mostly because it breaks simplicity:
> > the idea that a namespace is a mapping from names to values
> > (e.g. {"limit": 100, "doit": <function...>, ...}) is beautifully
> > simple, while the idea of inserting an extra level of indirection, no
> > matter how powerful, is much murkier.

[Jim F]
> How so? It doesn't change the mapping semantics.

My assumption is that in your version, the dictionary would contain
special <object binding> objects which then would contain the
referenced objects.  E.g. {"limit": <binding: 100>, "doit": <binding:
<function ...>>}.  Thus, d["limit"] would be that <binding> object,
while previously it would return 100.

> Again, it would also make function global variable access
> faster and cleaner in some ways.

But I have other plans for that (if the optional static typing stuff
ever gets implemented).

> > however it would break a considerable amount of old code,
> > I think. 
> 
> Really? I wonder. I bet it would break alot less old
> code that other recent changes.

Oh?  Name some changes that broke a lot of code?

--Guido van Rossum (home page: http://www.python.org/~guido/)


From jeremy@cnri.reston.va.us  Thu Jan 20 17:36:32 2000
From: jeremy@cnri.reston.va.us (Jeremy Hylton)
Date: Thu, 20 Jan 2000 12:36:32 -0500 (EST)
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <14471.13834.480356.541389@anthem.cnri.reston.va.us>
References: <200001201601.LAA21359@eric.cnri.reston.va.us>
 <14471.13834.480356.541389@anthem.cnri.reston.va.us>
Message-ID: <14471.18336.257653.730100@bitdiddle.cnri.reston.va.us>

>>>>> "BAW" == Barry A Warsaw <bwarsaw@cnri.reston.va.us> writes:
>>>>> "Guido" == Guido van Rossum <guido@cnri.reston.va.us> writes:

  Guido> There are several other things I can think of now that were
  Guido> planned for 1.6: revamped import, rich comparisons, revised
  Guido> coercions, parallel for loop (for i in L; j in M: ...),
  Guido> extended slicing for all sequences.  I've also been thinking
  Guido> about making classes be types (not as huge a change as you
  Guido> think, if you don't allow subclassing built-in types), and
  Guido> adding a built-in array type suitable for use by NumPy.  I've
  Guido> also received a conservative GC patch that seems to be fairly
  Guido> easy to apply and has some of Tim Peters' blessing.

  BAW> All very cool things that could easily wait until 1.7.  After
  BAW> all, what's in a number?  If, as Andrew puts forth, getting a
  BAW> stable Python release with Unicode is very important for
  BAW> Python's future positioning, then I say let's go with his more
  BAW> modest list, mainly Unicode, sre, and Distutils.  We've already
  BAW> got string meths, tons of library improvements, and sundry
  BAW> other things.  That's a good enough laundry list for the next
  BAW> release.

We've had this conversation before, so it'll comes as no surprise that
I agree with you.  Question: If we go with the feature set you've
described, when will those features be ready?  What kind of schedule
could we set for releasing the first alpha?

Jeremy



From guido@CNRI.Reston.VA.US  Thu Jan 20 17:40:51 2000
From: guido@CNRI.Reston.VA.US (Guido van Rossum)
Date: Thu, 20 Jan 2000 12:40:51 -0500
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: Your message of "Thu, 20 Jan 2000 09:22:40 PST."
 <Pine.LNX.4.10.10001200907240.13911-100000@nebula.lyra.org>
References: <Pine.LNX.4.10.10001200907240.13911-100000@nebula.lyra.org>
Message-ID: <200001201740.MAA21608@eric.cnri.reston.va.us>

> Call it 1.6, per the rest of the thread.

OK.  I expect I'll get some complaints from some people who asked when
1.6 would be out (I've generally told them end of 2000); but it sounds
like a 1.7 would be necessary to fulfill the other promises, so it
shouldn't really matter -- it's all a case of relabeling for PR
purposes.

> Unicode: definitely. distutils seems pretty early, but I bet that some key
> concepts could be added to 1.6, to make the transition and continued
> development easier.

The point of adding distutils is that it will allow distribution of
packages without including distutils with each distribution.  Since
distutils was about 200K itself last time I looked, this is important.
I don't believe it would be good to have to say "My FooBar package is
really easy to install.  All you need to do is download and install
distutils, (which by the way is a 200K package that you have to
manually install), and then run "python setup.py" in the FooBar root
directory..."  This would be enough for the average person to run away
screaming.

I think I saw a distribution by AMK that had a setup.py that tried to
use distutils but had a crude fallback if distutils didn't exist;
however that defeats much of the purpose since the package author has
to figure out how to do the fallback.

Large distributions (e.g. NumPy) can afford to squeeze distutils in a
corner of their distribution, but for the average package it wouldn't
be of much use.

In other words, I'm for putting distutils in the next release,
essentially feature-freezing it.  Greg Ward, what do you think of
that?

> Note that if an announcement were made to the effect of "feature freeze on
> February 15; only bug fixes afterwards," that you would get a lot of
> people scrambling to submit their pet features. This would be a good way
> to light some fires, to see what kinds of things get completed (i.e. we
> may think some things aren't ready or are too far out, put that deadline
> in and those positions could change...)

I bet you we couldn't complete the import hooks by that date; I
consider imputil.py as a nice prototype, but the integration with the
C code is still missing.  Also the 50% slowdown is a problem I worry
about for inclusion a production version.  (Plus breakage of everybody
else's code who uses or hacks __import__; e.g. have you tested it with
rexec?)

> > (The import
> > utilities are not ready for prime time in my opinion; there are too
> > many issues.)
> 
> I'm waiting for that review :-)

It was kept up by the need to get the types documents out.

> If you raise issues, then I can knock them down. I don't see all that many
> at the moment. But I'm biased :-)
> 
> > Anybody care to be the pumpkin?  That would cut the discussion short;
> > otherwise the problem remains that I can't spend too much time on the
> > next release unless I get funded for it; what little money I've
> > received for CP4E I had better spend on getting some CP4E-related
> > results ASAP, because the next installment of this funding is very
> > much at stake...
> 
> I would volunteer for the pumpkin... around April-ish. My plate is rather
> full with completing mod_dav and then integrating that into Apache 2.0.
> Once the Apache integration begins, then I'd have some more free time.
> 
> But this begs the question of: what does the pumpkin-holder mean in the
> *Python* world?
> 
> If it is collating fixes, producing snapshots, etc, then I'm comfy with
> it. If it also contains responsibility for specific kinds of work, then
> Fred would probably veto me :-), as I've got an outstanding doc that I owe
> him (for about six months now... sigh; maybe I'll bribe MAL to write it; 
> he knows the interface :-)).
> 
> But stll: what's it mean? How does the pumpkin reduce the Guido-load, yet
> still enable the Guido-control?

Good questions.  I have to say that I feel reluctant to release any
kind of control -- yet at the same time I desperately need help
getting trivial stuff checked in.  One of the most important
time-consuming tasks is quality control: collecting fixes is all well
and good, but I routinely reject fixes that superficially look fine,
because they are subtly broken, or interfere with other plans, or just
because the code looks poorly written.  I also spend a lot of testing
before I check things in; running the standard test suite is a good
safeguard against general breakage, but you really have to play with
the code affected by the change before you can know that it works as
advertised.  My work attitude here means that what gets checked in is
generally rock solid, and that helps Python's reputation; but it is
very costly...

> [ I just had a talk about this with the guys at Inprise, re: InterBase,
>   mentioning that the Dictator model works well for Python, but doesn't
>   necessarily work well for new projects or commercially-started projects
>   due to control/prejudice issues. Python people like it because of the
>   resulting simplicity and cleanliness; I doubt we want a pumpkin approach
>   that would allow that to go away! ]

Agreed, of course.

--Guido van Rossum (home page: http://www.python.org/~guido/)


From da@ski.org  Thu Jan 20 17:57:51 2000
From: da@ski.org (David Ascher)
Date: Thu, 20 Jan 2000 09:57:51 -0800
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <14471.13834.480356.541389@anthem.cnri.reston.va.us>
Message-ID: <000701bf636f$de37c5e0$c355cfc0@ski.org>

[I just got GvR's post on the topic, but I'll send this anyway]

BAW:
> All very cool things that could easily wait until 1.7.  After all,
> what's in a number?

Guido has promised some of those features as being in 1.6 at conferences in
the past, but I agree that string methods for example are a more major
change than I'd expect to see in a 0.0.3-delta version change.

Maybe with a deadline (as Greg suggests) we can integrate some of the
pending patches (I agree with Greg that I at least would have found the time
for a revised patch for rich comparisons if I'd had a deadline -- call me
human =).
Coercion and extended slicing also seem like relatively minor changes,
compared with changing everything to be a class or adding GC!

Regardless, just like Greg, I'd like to know what a pumpkin-holder would
mean in the Python world.

I propose that it be called the Oracle instead.  As in, whoever is Oracle
would get some training with Tim Peters and learn how to channel G__do.  As
a Python user, I'd be most comfortable with such a change if the Oracle just
took over the technical stuff (reviewing patches, CVS checkins, running
tests, corralling help for doc & code, maintaining release notes, building
installers, etc.), but that the important decisions (e.g. whether to add a
feature to the core language) would be checked with G__do first.  We could
call the position "Administrative Assistant", but somehow that doesn't have
the prestige.

A progressive schedule where Guido watches over the Oracle periodically
would probably help build trust in the new mechanism.  The Oracle would be
expected to ask Guido for his opinion with everything at the beginning, and
as a trust builds between Guido and the Oracle and the community and the
mechanism, progressively less.

--david ascher



From gstein@lyra.org  Thu Jan 20 18:30:52 2000
From: gstein@lyra.org (Greg Stein)
Date: Thu, 20 Jan 2000 10:30:52 -0800 (PST)
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <200001201740.MAA21608@eric.cnri.reston.va.us>
Message-ID: <Pine.LNX.4.10.10001200950260.13911-100000@nebula.lyra.org>

On Thu, 20 Jan 2000, Guido van Rossum wrote:
>...
> In other words, I'm for putting distutils in the next release,
> essentially feature-freezing it.  Greg Ward, what do you think of
> that?

Oh, don't get me wrong. I'd like to see it in there for at least all the
reasons you cite. But it seems (to me) that it is still pretty alpha. But
hey: I'm shooting from the peanut gallery; we need GregW's comments.

> > Note that if an announcement were made to the effect of "feature freeze on
> > February 15; only bug fixes afterwards," that you would get a lot of
> > people scrambling to submit their pet features. This would be a good way
> > to light some fires, to see what kinds of things get completed (i.e. we
> > may think some things aren't ready or are too far out, put that deadline
> > in and those positions could change...)
> 
> I bet you we couldn't complete the import hooks by that date; I
> consider imputil.py as a nice prototype, but the integration with the
> C code is still missing.  Also the 50% slowdown is a problem I worry
> about for inclusion a production version.  (Plus breakage of everybody
> else's code who uses or hacks __import__; e.g. have you tested it with
> rexec?)

hehe... if the static typing is to be deferred, then I'll take that bet!

[discussion omitted; too tangental to this thread right now...]

>...
> Good questions.  I have to say that I feel reluctant to release any
> kind of control -- yet at the same time I desperately need help
> getting trivial stuff checked in.

Reading your comments below, we may be able to help.

First, presume that at least one (best would be several) people man the
"front lines" for any/all patches and bug reports. The front line can deal
with the bug reports, mostly by responding with "go away; enter it into
Jitterbug."

Patches fall under several catagories, detailed below:

> One of the most important
> time-consuming tasks is quality control: collecting fixes is all well
> and good, but I routinely reject fixes that superficially look fine,

Conversely, your "lieutenants" (LTs) would filter all ugly-looking
patches.

> because they are subtly broken,

If the LTs didn't catch these, then you could catch them from the checkin
diff email. However, the LTs would reduce the number of broken ones that
you would review.

> or interfere with other plans,

The LTs may know of this, but if not: you'd catch it at checkin time. The
patches would then be backed out, altered, or whatever.

> or just
> because the code looks poorly written.

The LTs would definitely catch this. If the style was *still* not up to
snuff, I'd have to believe it would only be in minor ways that you could
then touch up at your leisure.

> I also spend a lot of testing
> before I check things in;

Done by the LTs.

> running the standard test suite is a good
> safeguard against general breakage,

Ditto.

> but you really have to play with
> the code affected by the change before you can know that it works as
> advertised.

Ditto.

> My work attitude here means that what gets checked in is
> generally rock solid, and that helps Python's reputation; but it is
> very costly...

Based on my responses, I would venture to state that a group of LTs would
manage to keep the Python core rock solid, except for:

1) subtle breakages that require your broader knowledge of Python
2) changes that "go against the plan" (and the LTs were ignorant of it)
3) minor format issues

You would still review checkins, but the number of reviews would drop
since the (obvious) crap has been eliminated. #1 is based on your *broad*
knowledge of Python; I presume the LTs would be your match on various
subsets of Python. By keeping the LTs well-informed, #2 could be nearly
eliminated. #3 isn't that big of a deal, as I think your desired style is
relatively well-known and the LTs would simply endeavor to match existing
style.

You could avoid a lot of testing; you would probably be inclined to do
testing of items that you find dubious, but still this would be a
reduction.

=====

That may be an answer to the checkin problem. How about actual snapshots,
alphas, betas, releases, and accompanying notes/news/readme files? I
presume your LTs could run the alpha and beta aspects, but you would still
issue final releases.

Does your mail volume need to be reduced? (I think this has been asked
before) Specifically, would patches@python.org (and similar targets) need
to be established? (I would think so, as a matter of course, with the
expectation that some patches would still end up with you and need to be
bounced to patches@)

Cheers,
-g

-- 
Greg Stein, http://www.lyra.org/



From klm@digicool.com  Thu Jan 20 18:31:52 2000
From: klm@digicool.com (Ken Manheimer)
Date: Thu, 20 Jan 2000 13:31:52 -0500 (EST)
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <000701bf636f$de37c5e0$c355cfc0@ski.org>
Message-ID: <Pine.LNX.4.10.10001201321300.21609-100000@splat.digicool.com>

I must have missed the historic landmark where "pumpkin" was coined, but i
think i get the gist.  How about "Python Marshall" or "Python Activity
Marshall" (a la the PS_A_)?

Ken

David Ascher wrote:

> [...]
> Regardless, just like Greg, I'd like to know what a pumpkin-holder would
> mean in the Python world.
> 
> I propose that it be called the Oracle instead.  As in, whoever is Oracle
> would get some training with Tim Peters and learn how to channel G__do.  As
> a Python user, I'd be most comfortable with such a change if the Oracle just
> took over the technical stuff (reviewing patches, CVS checkins, running
> tests, corralling help for doc & code, maintaining release notes, building
> installers, etc.), but that the important decisions (e.g. whether to add a
> feature to the core language) would be checked with G__do first.  We could
> call the position "Administrative Assistant", but somehow that doesn't have
> the prestige.
> 
> A progressive schedule where Guido watches over the Oracle periodically
> would probably help build trust in the new mechanism.  The Oracle would be
> expected to ask Guido for his opinion with everything at the beginning, and
> as a trust builds between Guido and the Oracle and the community and the
> mechanism, progressively less.



From gstein@lyra.org  Thu Jan 20 18:42:43 2000
From: gstein@lyra.org (Greg Stein)
Date: Thu, 20 Jan 2000 10:42:43 -0800 (PST)
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <Pine.LNX.4.10.10001201321300.21609-100000@splat.digicool.com>
Message-ID: <Pine.LNX.4.10.10001201039320.13911-100000@nebula.lyra.org>

On Thu, 20 Jan 2000, Ken Manheimer wrote:
> I must have missed the historic landmark where "pumpkin" was coined, but i
> think i get the gist.  How about "Python Marshall" or "Python Activity
> Marshall" (a la the PS_A_)?

The "pumpkin" term comes from Perl-land...

I'm not super clear on the pumpkin-holders's entire job, but I think it is
basically the guy who sees that the version for which he "holds the
pumpkin" is completed and shipped. Not necessarily by himself :-), but as
the overseer (or "release manager" if you will).

The current Perl pumpkin-holder is a guy at ActiveState. I think it
changes for each version.

Cheers,
-g

-- 
Greg Stein, http://www.lyra.org/



From gvwilson@nevex.com  Thu Jan 20 18:51:17 2000
From: gvwilson@nevex.com (gvwilson@nevex.com)
Date: Thu, 20 Jan 2000 13:51:17 -0500 (EST)
Subject: [Python-Dev] Python 1.6 timing (fwd)
Message-ID: <Pine.LNX.4.10.10001201346510.7719-100000@akbar.nevex.com>

Guido> There are several other things I can think of now that were
Guido> planned for 1.6: revamped import, rich comparisons, revised
Guido> coercions, parallel for loop (for i in L; j in M: ...),
Guido> extended slicing for all sequences.  I've also been thinking
Guido> about making classes be types (not as huge a change as you
Guido> think, if you don't allow subclassing built-in types), and
Guido> adding a built-in array type suitable for use by NumPy.  I've
Guido> also received a conservative GC patch that seems to be fairly
Guido> easy to apply and has some of Tim Peters' blessing.

BAW> All very cool things that could easily wait until 1.7.  After
BAW> all, what's in a number?

GVW writes:

I agree on all counts except garbage collection --- I'm half-way through
the second day of the Python class I teach at Los Alamos (the people who
are funding the Python tool design competition), and it's come up a couple
of times.  People want to be able to prototype meshes, throw callbacks
around without worrying about circularity, and some other things that I
don't really understand yet.  There's also a couple of smart guys in the
class who are wondering about CPython vs. JPython ("So this'll be safe in
one version of the language, but not in the other?"), and about marketing
("Help me win a feature comparison against Java in my group...").

There's also been questions about tighter integration of NumPy (e.g.
overloading operators rather than calling 'greater()' to do comparison),
but I think that's a separate discussion...

My $0.02,
Greg



From tismer@tismer.com  Thu Jan 20 19:11:13 2000
From: tismer@tismer.com (Christian Tismer)
Date: Thu, 20 Jan 2000 20:11:13 +0100
Subject: [Python-Dev] Python 1.6 timing (fwd)
References: <Pine.LNX.4.10.10001201346510.7719-100000@akbar.nevex.com>
Message-ID: <38875DD1.B6596@tismer.com>

[garbage collection]

gvwilson@nevex.com wrote:

> I agree on all counts except garbage collection --- I'm half-way through
> the second day of the Python class I teach at Los Alamos (the people who
> are funding the Python tool design competition), and it's come up a couple
> of times.  People want to be able to prototype meshes, throw callbacks
> around without worrying about circularity, and some other things that I
> don't really understand yet.  There's also a couple of smart guys in the
> class who are wondering about CPython vs. JPython ("So this'll be safe in
> one version of the language, but not in the other?"), and about marketing
> ("Help me win a feature comparison against Java in my group...").

Guido once posted some proposal of a hybrid system *with* refcounts
and some additional garbage collection scheme to match circular
things. I believe this is a much better approach than what Java
and therefor also JPython does at the moment.

Although people might argue differently, I'm pretty sure that
reference counting is the stronger concept. By reference counting,
the idea of object ownership can be made explicit. This plays a
central role in the Corba specification for instance, and I made
the same observation when implementing continuations for Stackless
Python. Refcounts are no burden but a virtue.
Even better: Refcounting can lead to many new optimizations if
we pay the cost to make INCREF/DECREF into methods. It has its cost
(about 10 percent less pystones), but massive long-term benefits.

I'm currently in charge to develop a custom version of Python's
builtin types where this concept is used. Everything is refcounted,
but without storing the refcounts in the objects. This is possible
(proven) and will be shown in my next paper.

Conclusion: I vote for a kind of GC that does just what refcounts
cannot do, but please keep with the refcounts.

cheers - chris

-- 
Christian Tismer             :^)   <mailto:tismer@appliedbiometrics.com>
Virtual Photonics GmbH       :     Have a break! Take a ride on Python's
Carnotstr. 6                 :    *Starship* http://starship.python.net
10587 Berlin                 :     PGP key -> http://wwwkeys.pgp.net
PGP Fingerprint       E182 71C7 1A9D 66E9 9D15  D3CC D4D7 93E2 1FAE F6DF
     we're tired of banana software - shipped green, ripens at home


From tim_one@email.msn.com  Thu Jan 20 19:47:01 2000
From: tim_one@email.msn.com (Tim Peters)
Date: Thu, 20 Jan 2000 14:47:01 -0500
Subject: [Python-Dev] Changing existing class instances
In-Reply-To: <200001201520.KAA21137@eric.cnri.reston.va.us>
Message-ID: <000301bf637f$1f1c2d80$b72d153f@tim>

[Tim worries about stomping on unintended classes/defs]

[Guido]
> Agreed that that would be bad.  But I wouldn't search outer
> scopes -- I would only look for a class/def that I was about
> to stomp on.

Maybe I just don't grasp what that means, exactly.  Fair enough, since I'm
not expressing myself clearly either!

Suppose someone does

from Tkinter import *

in my.py, and later in my.py just *happens* to define, at module level,

class Misc:
    blah blah blah

Now Misc was already in my.py's global namespace because Tkinter.py just
happens to export a class of that name too (more by accident than design --
but accidents are what I'm most worried about here).

At the time my.py defines Misc, does Misc count as a class we're "about to
stomp on"?  If so-- & I've assumed so --it would wreak havoc.

But if not, I don't see how this case can be reliably distinguished "by
magic" from the cases where update is desired (if people are doing dynamic
updates to a long-running program, a new version of a class can come from
anywhere, so nothing like original file name or line number can distinguish
correctly either).

>> Modules differ because their namespace "search path"
>> consists solely of the more-global-than-global <wink>
>> sys.modules.

> "The search path doesn't enter into it."

I agree, but am at a loss to describe what's happening in the case above
using other terminology <wink>.  In a sense, you need a system-wide "unique
handle" to support bulletproof updating, and while sys.modules has supplied
that all along for module objects (in the form of the module name), I don't
believe there's anything analogous to key off of for function or class
objects.

>>    [suggesting]
>>    new.update(class_or_def_old, class_or_def_new)

> Only a slight semantics change (which my full proposal
> would require too): function objects would become mutable
> -- their func_code, func_defaults, func_doc and func_globals
> fields (and, why not, func_name too) should be changeable.

Of course I meant "no new semantics" in the sense of "won't cause current
exception-free code to alter behavior in any way".

> If you make all these assignable, it doesn't even have to
> be a privileged function.

I'm all for that!

> [sketching a Python approach to "updating import/reload"
>  building on the hypothetical new.update]

> That's certainly a reasonable compromise.  Note that the
> update on a class should imply an update on its methods,
> right?

Hadn't considered that!  Of course you're right.  So make it a pair of
nested loops <wink>.

so-long-as-it-can-be-written-in-python-it's-easy-ly
    y'rs  - tim




From guido@CNRI.Reston.VA.US  Thu Jan 20 20:02:20 2000
From: guido@CNRI.Reston.VA.US (Guido van Rossum)
Date: Thu, 20 Jan 2000 15:02:20 -0500
Subject: [Python-Dev] Changing existing class instances
In-Reply-To: Your message of "Thu, 20 Jan 2000 14:47:01 EST."
 <000301bf637f$1f1c2d80$b72d153f@tim>
References: <000301bf637f$1f1c2d80$b72d153f@tim>
Message-ID: <200001202002.PAA22435@eric.cnri.reston.va.us>

> [Tim worries about stomping on unintended classes/defs]
> 
> [Guido]
> > Agreed that that would be bad.  But I wouldn't search outer
> > scopes -- I would only look for a class/def that I was about
> > to stomp on.
> 
> Maybe I just don't grasp what that means, exactly.  Fair enough, since I'm
> not expressing myself clearly either!
> 
> Suppose someone does
> 
> from Tkinter import *
> 
> in my.py, and later in my.py just *happens* to define, at module level,
> 
> class Misc:
>     blah blah blah
> 
> Now Misc was already in my.py's global namespace because Tkinter.py just
> happens to export a class of that name too (more by accident than design --
> but accidents are what I'm most worried about here).

For a second I thought you got me there!

> At the time my.py defines Misc, does Misc count as a class we're "about to
> stomp on"?  If so-- & I've assumed so --it would wreak havoc.
> 
> But if not, I don't see how this case can be reliably distinguished "by
> magic" from the cases where update is desired (if people are doing dynamic
> updates to a long-running program, a new version of a class can come from
> anywhere, so nothing like original file name or line number can distinguish
> correctly either).

Fortunately, there's magic available: recently, all classes have a
__module__ attribute that is set to the full name of the module that
defined it (its key in __sys__.modules).

For functions, we would have to invent something similar.

> >> Modules differ because their namespace "search path"
> >> consists solely of the more-global-than-global <wink>
> >> sys.modules.
> 
> > "The search path doesn't enter into it."
> 
> I agree, but am at a loss to describe what's happening in the case above
> using other terminology <wink>.  In a sense, you need a system-wide "unique
> handle" to support bulletproof updating, and while sys.modules has supplied
> that all along for module objects (in the form of the module name), I don't
> believe there's anything analogous to key off of for function or class
> objects.
> 
> >>    [suggesting]
> >>    new.update(class_or_def_old, class_or_def_new)
> 
> > Only a slight semantics change (which my full proposal
> > would require too): function objects would become mutable
> > -- their func_code, func_defaults, func_doc and func_globals
> > fields (and, why not, func_name too) should be changeable.
> 
> Of course I meant "no new semantics" in the sense of "won't cause current
> exception-free code to alter behavior in any way".
> 
> > If you make all these assignable, it doesn't even have to
> > be a privileged function.
> 
> I'm all for that!
> 
> > [sketching a Python approach to "updating import/reload"
> >  building on the hypothetical new.update]
> 
> > That's certainly a reasonable compromise.  Note that the
> > update on a class should imply an update on its methods,
> > right?
> 
> Hadn't considered that!  Of course you're right.  So make it a pair of
> nested loops <wink>.
> 
> so-long-as-it-can-be-written-in-python-it's-easy-ly
>     y'rs  - tim

--Guido van Rossum (home page: http://www.python.org/~guido/)


From guido@CNRI.Reston.VA.US  Thu Jan 20 20:12:58 2000
From: guido@CNRI.Reston.VA.US (Guido van Rossum)
Date: Thu, 20 Jan 2000 15:12:58 -0500
Subject: [Python-Dev] Python 1.6 timing (fwd)
In-Reply-To: Your message of "Thu, 20 Jan 2000 20:11:13 +0100."
 <38875DD1.B6596@tismer.com>
References: <Pine.LNX.4.10.10001201346510.7719-100000@akbar.nevex.com>
 <38875DD1.B6596@tismer.com>
Message-ID: <200001202012.PAA22501@eric.cnri.reston.va.us>

> Conclusion: I vote for a kind of GC that does just what refcounts
> cannot do, but please keep with the refcounts.

The patch that I received and that has Tim's <0.5 blessing> does just
that.  I haven't had the time to understand why it doesn't have his
<1.0 blessing>.

--Guido van Rossum (home page: http://www.python.org/~guido/)


From tim_one@email.msn.com  Thu Jan 20 20:35:44 2000
From: tim_one@email.msn.com (Tim Peters)
Date: Thu, 20 Jan 2000 15:35:44 -0500
Subject: [Python-Dev] Python 1.6 timing (fwd)
In-Reply-To: <200001202012.PAA22501@eric.cnri.reston.va.us>
Message-ID: <000901bf6385$eccfba20$b72d153f@tim>

[Christian]
> Conclusion: I vote for a kind of GC that does just
> what refcounts cannot do, but please keep with the
> refcounts.

[Guido]
> The patch that I received and that has Tim's <0.5
> blessing> does just that. I haven't had the time to
> understand why it doesn't have his <1.0 blessing>.

Primarily because it doesn't reclaim the most common cycles; e.g., cycles
among class instances aren't touched.  This seems easily repairable, but at
an unknown cost (it needs to do the "reachability" transitive closure
business from the set of all "suspicious" objects, and instances are never
considered suspicious now; adding them will certainly cause a lot more
pointer chasing).

Apart from that, the code appears unreasonably expensive as written today,
using e.g. splay trees instead of hash tables to keep track of objects.

The author hasn't said anything more in a bit over two weeks, so I suspect
he's off on other things now.  The technical approach is sound, but even its
inventor (Rafael Lins; Toby Kelsey may have reinvented it on his own,
though) stresses that getting it to run fast is difficult.

needs-work!-ly y'rs  - tim, who hasn't the time to do it




From tismer@tismer.com  Thu Jan 20 20:35:27 2000
From: tismer@tismer.com (Christian Tismer)
Date: Thu, 20 Jan 2000 21:35:27 +0100
Subject: [Python-Dev] Stackless Python 1.0 + Continuations 0.6
Message-ID: <3887718F.82E1B327@tismer.com>

ANNOUNCING:

               Stackless Python 1.0
           A Python Implementation That
             Does Not Use The C Stack

               * plus the real toy *

              Continuation Module 0.6
        Continuations as First Class Objects

What is it?
A plugin-replacement for core Python.
It should run any program which runs under Python 1.5.2 .
But it does not need space on the C stack.

Why did I write it?
Stackless Python was never written before (afaik), since it
was said to be impossible without major rewrites of core Python.
I have proven the controverse: It is easy to write, just hard to think.
About 3 times harder was finally the continuation module.
The whole project took about 6 man months where 80 percent of
the time was thinking and trying. The rest was coding and to
become a reference counting champion :-)

Recent changes:
Version 1.0 has been optimized like hell and is now
3-5 percent faster than Standard Python.

Continuation module is in version 0.6, very stable,
and it allows to save a program's "future" at any
time, in a portable way. Continuations are callable
Python objects with a very small footprint.

Who needs it?
Since the continuations are done, this is no more
only useful for C programmers who want to try certain new
ideas. Everybody who is interested to develop his
own generators, coroutines and tiny threads is
invited to check it out.

Status of the final 1.0:
Pystone works correctly and is 5% faster than standard
Python. Version 0.3 was 10 percent slower.
Continuations work with PythonWin and Idle.

The overall result is now better than expected,
and I'm happy to call this *FINAL*
(until the next version of course:)

Downloadable files can be found at
http://www.tismer.com/research/stackless/

Some older documentation:
http://www.tismer.com/research/stackless/stackless.htm

Some better documentation can be found in my IPC8 paper:
http://www.tismer.com/research/stackless/spc_final.zip
or be read directly as HTML
http://www.tismer.com/research/stackless/spcpaper.htm

Source code and a VC++6.0 build for Windows (340K):
http://www.tismer.com/research/stackless/spc_win32.zip

cheers - chris

== 
Christian Tismer             :^)   <mailto:tismer@appliedbiometrics.com>
Applied Biometrics GmbH      :     Have a break! Take a ride on Python's
Kaiserin-Augusta-Allee 101   :    *Starship* http://starship.python.net
10553 Berlin                 :     PGP key -> http://wwwkeys.pgp.net
PGP Fingerprint       E182 71C7 1A9D 66E9 9D15  D3CC D4D7 93E2 1FAE F6DF
     we're tired of banana software - shipped green, ripens at home

<P><A HREF="http://www.tismer.com/research/stackless/stackless.htm">
Stackless Python 1.0</A>
 - a version of Python 1.5.2 that does not need space on the C
stack.  (20-Jan-00)


From bwarsaw@cnri.reston.va.us (Barry A. Warsaw)  Thu Jan 20 21:12:37 2000
From: bwarsaw@cnri.reston.va.us (Barry A. Warsaw) (Barry A. Warsaw)
Date: Thu, 20 Jan 2000 16:12:37 -0500 (EST)
Subject: [Python-Dev] Python 1.6 timing
References: <Pine.LNX.4.10.10001201321300.21609-100000@splat.digicool.com>
 <Pine.LNX.4.10.10001201039320.13911-100000@nebula.lyra.org>
Message-ID: <14471.31301.504670.201702@anthem.cnri.reston.va.us>

We'd have to rework the CVS arrangement in order to give non-CNRI
employees write access to the tree.  I think I know how I'd go about
this, and it wouldn't be too hard, just a bit time-consuming.  If
that's the way we're going to go, I can start making plans.

-Barry


From guido@CNRI.Reston.VA.US  Thu Jan 20 21:16:39 2000
From: guido@CNRI.Reston.VA.US (Guido van Rossum)
Date: Thu, 20 Jan 2000 16:16:39 -0500
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: Your message of "Thu, 20 Jan 2000 16:12:37 EST."
 <14471.31301.504670.201702@anthem.cnri.reston.va.us>
References: <Pine.LNX.4.10.10001201321300.21609-100000@splat.digicool.com> <Pine.LNX.4.10.10001201039320.13911-100000@nebula.lyra.org>
 <14471.31301.504670.201702@anthem.cnri.reston.va.us>
Message-ID: <200001202116.QAA22943@eric.cnri.reston.va.us>

[Barry]
> We'd have to rework the CVS arrangement in order to give non-CNRI
> employees write access to the tree.  I think I know how I'd go about
> this, and it wouldn't be too hard, just a bit time-consuming.  If
> that's the way we're going to go, I can start making plans.

I think before you make such changes you'd have to talk to Bob (good
luck).

I don't mind applying patches and doing the checkins -- it's the
decision-making that's time-consuming.

--Guido van Rossum (home page: http://www.python.org/~guido/)


From da@ski.org  Thu Jan 20 21:28:24 2000
From: da@ski.org (David Ascher)
Date: Thu, 20 Jan 2000 13:28:24 -0800
Subject: [Python-Dev] Python 1.6 timing (fwd)
In-Reply-To: <Pine.LNX.4.10.10001201346510.7719-100000@akbar.nevex.com>
Message-ID: <001401bf638d$486488f0$c355cfc0@ski.org>

Daddy Warbucks (uh, Greg Wilson =):

> There's also been questions about tighter integration of NumPy (e.g.
> overloading operators rather than calling 'greater()' to do comparison),
> but I think that's a separate discussion...

That's the rich comparison proposal which Guido mentioned.

--david


From bwarsaw@cnri.reston.va.us (Barry A. Warsaw)  Thu Jan 20 21:30:24 2000
From: bwarsaw@cnri.reston.va.us (Barry A. Warsaw) (Barry A. Warsaw)
Date: Thu, 20 Jan 2000 16:30:24 -0500 (EST)
Subject: [Python-Dev] Python 1.6 timing
References: <Pine.LNX.4.10.10001201321300.21609-100000@splat.digicool.com>
 <Pine.LNX.4.10.10001201039320.13911-100000@nebula.lyra.org>
 <14471.31301.504670.201702@anthem.cnri.reston.va.us>
 <200001202116.QAA22943@eric.cnri.reston.va.us>
Message-ID: <14471.32368.730988.252872@anthem.cnri.reston.va.us>

>>>>> "Guido" == Guido van Rossum <guido@cnri.reston.va.us> writes:

    Guido> I think before you make such changes you'd have to talk to
    Guido> Bob (good luck).

Heh.

    Guido> I don't mind applying patches and doing the checkins --
    Guido> it's the decision-making that's time-consuming.

Then maybe the current CVS arrangement is fine (cool with me).

-Barry


From klm@digicool.com  Thu Jan 20 22:08:28 2000
From: klm@digicool.com (Ken Manheimer)
Date: Thu, 20 Jan 2000 17:08:28 -0500 (EST)
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <14471.31301.504670.201702@anthem.cnri.reston.va.us>
Message-ID: <Pine.LNX.4.10.10001201646500.22921-100000@splat.digicool.com>

On Thu, 20 Jan 2000, Barry A. Warsaw wrote:

> We'd have to rework the CVS arrangement in order to give non-CNRI
> employees write access to the tree.  I think I know how I'd go about
> this, and it wouldn't be too hard, just a bit time-consuming.  If
> that's the way we're going to go, I can start making plans.

Though it may be moot if guido's going to continue mediating the checkins,
maybe this would be interesting (if only for barry, to compare
procedures). 

We basically use a captive cvs-":ext:"-over-ssh method, where the captive
.ssh/authorized_keys command is quite succinct:

command="set $SSH_ORIGINAL_COMMAND; shift; exec cvs $@" 1024 35 ...

The shellisms (set/shift/exec cvs $@) lock the user of the qualifying key
into executing a cvs command, and only a cvs command.

Also, for us the checkins are to a public mirror of our CVS repository, so
penetration of the security there doesn't jepordize the master repository
base.  We don't currently have any outsiders checking into our master
repository, and it doesn't seem to me that CVS provides sufficiently
managable discretion for doing that.

Oh, and a disappointment - the account under which cvs conducts the
checkins is the account on the CVS server host, not that of the host where
the checkins are being done.  This means that you can't use a single
account to serve multiple remote users (preventing masquerading quite
reliably by using a separate authorized_key public-key entry for each
remote user).  Therefore we have to have distinct (nailed-down) accounts
for each checkin-privileged person - more management burden.

Ken



From tim_one@email.msn.com  Thu Jan 20 23:53:18 2000
From: tim_one@email.msn.com (Tim Peters)
Date: Thu, 20 Jan 2000 18:53:18 -0500
Subject: [Python-Dev] Python 1.6 timing (fwd)
In-Reply-To: <001401bf638d$486488f0$c355cfc0@ski.org>
Message-ID: <000201bf63a1$8641b1c0$6ea0143f@tim>

[Greg Wilson]
> There's also been questions about tighter integration
> of NumPy (e.g. overloading operators rather than
> calling 'greater()' to do comparison), but I think
? that's a separate discussion...

[David Ascher]
> That's the rich comparison proposal which Guido mentioned.

But there's also been talk about moving (at least) the basic NumPy array
type into the core.  This would be a Good Thing.  Speaking for my employer,
however, only Unicode is an Important Thing <wink>.

As a developer, I have railed against schedule-driven release cycles.
Python tends toward the opposite end of that spectrum, driven by features no
matter how bloody long they take.  Add Unicode to what's already waiting to
go, and that's *good enough* reason for a major release; heck, it's been 9
months & we haven't even had a  1.5.2 bugfix patch.

BTW, do the Perl-Porters have real jobs?

pay-me-to-do-python-releases-and-you'll-get-a-major-new-
    release-every-three-days<wink>-ly y'rs  - tim




From da@ski.org  Fri Jan 21 00:01:45 2000
From: da@ski.org (David Ascher)
Date: Thu, 20 Jan 2000 16:01:45 -0800
Subject: [Python-Dev] Python 1.6 timing (fwd)
In-Reply-To: <000201bf63a1$8641b1c0$6ea0143f@tim>
Message-ID: <002601bf63a2$b4acf9b0$c355cfc0@ski.org>

Tim Peters

> But there's also been talk about moving (at least) the basic NumPy array
> type into the core.  This would be a Good Thing.

IMNSHO, moving the current NumPy array into the core would be a Bad Thing.
Moving a new similar object with cleaned up semantics and better
implementation in would be a Good Thing.  But it won't happen until 1.7 at
the earliest, as the semantics haven't even been agreed on, let alone the
code written.

--david



From da@ski.org  Fri Jan 21 00:07:16 2000
From: da@ski.org (David Ascher)
Date: Thu, 20 Jan 2000 16:07:16 -0800
Subject: [Python-Dev] Conference Schedules
Message-ID: <002701bf63a3$79a15ae0$c355cfc0@ski.org>

This is a multi-part message in MIME format.

------=_NextPart_000_0028_01BF6360.6B7E1AE0
Content-Type: text/plain;
	charset="iso-8859-1"
Content-Transfer-Encoding: 7bit

Given the rush of interesting discussions and progress which occurs in the
two weeks before Python conferences, I propose that we have a bi-weekly
conference.  We'll just have to remember to cancel them at the last minute
except a couple of times a year.

--david ascher

------=_NextPart_000_0028_01BF6360.6B7E1AE0
Content-Type: text/x-vcard;
	name="David Ascher.vcf"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="David Ascher.vcf"

BEGIN:VCARD
VERSION:2.1
N:Ascher;David
FN:David Ascher
ORG:Smith Kettlewell Eye Research Institute
TEL;WORK;VOICE:415-345-2095
TEL;HOME;VOICE:415-345-2095
TEL;WORK;FAX:415-345-8455
ADR;WORK:;;2318 Fillmore St;San Francisco;CA;94115;US
LABEL;WORK;ENCODING=3DQUOTED-PRINTABLE:2318 Fillmore St=3D0D=3D0ASan =
Francisco, CA 94115=3D0D=3D0AUS
ADR;HOME:;;522A Green St;San Francisco;CA;94133;US
LABEL;HOME;ENCODING=3DQUOTED-PRINTABLE:522A Green St=3D0D=3D0ASan =
Francisco, CA 94133=3D0D=3D0AUS
EMAIL;PREF;INTERNET:da@ski.org
REV:20000107T184849Z
END:VCARD

------=_NextPart_000_0028_01BF6360.6B7E1AE0--



From gstein@lyra.org  Fri Jan 21 00:53:59 2000
From: gstein@lyra.org (Greg Stein)
Date: Thu, 20 Jan 2000 16:53:59 -0800 (PST)
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <14471.31301.504670.201702@anthem.cnri.reston.va.us>
Message-ID: <Pine.LNX.4.10.10001201653130.13911-100000@nebula.lyra.org>

On Thu, 20 Jan 2000, Barry A. Warsaw wrote:
> We'd have to rework the CVS arrangement in order to give non-CNRI
> employees write access to the tree.  I think I know how I'd go about
> this, and it wouldn't be too hard, just a bit time-consuming.  If
> that's the way we're going to go, I can start making plans.

Or move the CVS tree off-site.

Cheers,
-g

-- 
Greg Stein, http://www.lyra.org/



From guido@CNRI.Reston.VA.US  Fri Jan 21 01:29:30 2000
From: guido@CNRI.Reston.VA.US (Guido van Rossum)
Date: Thu, 20 Jan 2000 20:29:30 -0500
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: Your message of "Thu, 20 Jan 2000 10:30:52 PST."
 <Pine.LNX.4.10.10001200950260.13911-100000@nebula.lyra.org>
References: <Pine.LNX.4.10.10001200950260.13911-100000@nebula.lyra.org>
Message-ID: <200001210129.UAA28292@eric.cnri.reston.va.us>

(I accidentally mailed this only to Greg; here's a repost of the
relevant parts to the list:)

[me]
> > Good questions.  I have to say that I feel reluctant to release any
> > kind of control -- yet at the same time I desperately need help
> > getting trivial stuff checked in.

[Greg Stein]
> Reading your comments below, we may be able to help.

[...Proposal of lieutenants condensed...]

> Based on my responses, I would venture to state that a group of LTs would
> manage to keep the Python core rock solid, except for:
> 
> 1) subtle breakages that require your broader knowledge of Python
> 2) changes that "go against the plan" (and the LTs were ignorant of it)
> 3) minor format issues
> 
> You would still review checkins, but the number of reviews would drop
> since the (obvious) crap has been eliminated. #1 is based on your *broad*
> knowledge of Python; I presume the LTs would be your match on various
> subsets of Python. By keeping the LTs well-informed, #2 could be nearly
> eliminated. #3 isn't that big of a deal, as I think your desired style is
> relatively well-known and the LTs would simply endeavor to match existing
> style.
> 
> You could avoid a lot of testing; you would probably be inclined to do
> testing of items that you find dubious, but still this would be a
> reduction.
> 
> =====
> 
> That may be an answer to the checkin problem. How about actual snapshots,
> alphas, betas, releases, and accompanying notes/news/readme files? I
> presume your LTs could run the alpha and beta aspects, but you would still
> issue final releases.

There's a lot of work in these (you may have noticed that the release
notes got sloppier as 1.5.2 neared its completion).

I would be happy to have the responsibility to decide to release
without the burden of having to do all the work.

> Does your mail volume need to be reduced? (I think this has been asked
> before) Specifically, would patches@python.org (and similar targets) need
> to be established? (I would think so, as a matter of course, with the
> expectation that some patches would still end up with you and need to be
> bounced to patches@)

It's not the mail volume that bothers me -- I can ignore 100s of
messages a day very quickly.  It's the time it takes to respond to all
of them.


As an experiment, I've collected about 40 messages with suggested
patches in them that I found in my inbox; the oldest are nearly two
years old.

You can access these from this address:

http://www.python.org/~guido/patch/

I would love any help I could get in responding with these, and taking
action in the form of patches.  I propose that if you decide that a
particular patch is worth checking in, you ask the author for the
bugrelease or wetsign disclaimer and let me know that I can check it
in; if changes to the patch are needed, I propose that you negotiate
these with the author first.  (I often ask them to test my version of
a patch when I have style suggestions but don't have access the target
platform or problem it solves.)

--Guido van Rossum (home page: http://www.python.org/~guido/)


From tim_one@email.msn.com  Fri Jan 21 09:38:21 2000
From: tim_one@email.msn.com (Tim Peters)
Date: Fri, 21 Jan 2000 04:38:21 -0500
Subject: [Python-Dev] Changing existing class instances
In-Reply-To: <Pine.LNX.4.10.10001192342450.13911-100000@nebula.lyra.org>
Message-ID: <001801bf63f3$414e0c60$ec2d153f@tim>

[Greg Stein]
> ...
> In other words, I definitely would support a new class
> object behavior that allows us to update a class' set of
> bases and dictionary on the fly.  This could then be used
> to support my solution for the recursive type scenario (which,
> in turn, means that we don't have to introduce Yet Another
> Namespace into Python to hold type names).

Parenthetically, I never grasped the appeal of the parenthetical comment.
Yet Another Namespace for Yet Another Entirely New Purpose seems highly
*desirable* to me!  Trying to overload the current namespace set makes it so
much harder to see that these are compile-time gimmicks, and users need to
be acutely aware of that if they're to use it effectively.  Note that I
understand (& wholly agree with) the need for runtime introspection.

different-things-different-rules-ly y'rs  - tim




From tim_one@email.msn.com  Fri Jan 21 09:38:24 2000
From: tim_one@email.msn.com (Tim Peters)
Date: Fri, 21 Jan 2000 04:38:24 -0500
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <20000120113352.A23763@trump.amber.org>
Message-ID: <001901bf63f3$432404e0$ec2d153f@tim>

[Christopher Petrilli]
> Heck, Python is infinately more conservative in its
> numbering than a lot of projects.  All that was mentioned
> would normally be enough to call it 2.0 easily. :-)  Modesty
> can be counter productive in PR  business...

Indeed, where I work a number of managers met the suggestion to use Python
1.5.x with "what?! we don't want to use software that's barely out of alpha
release -- besides, Perl is already on release 5".  I hear that Guido got
normal American glasses -- time to do normal American hyperinflated version
numbering too.

heck-ms-windows-will-soon-be-at-version-2000<wink>-ly y'rs  - tim




From tim_one@email.msn.com  Fri Jan 21 09:38:26 2000
From: tim_one@email.msn.com (Tim Peters)
Date: Fri, 21 Jan 2000 04:38:26 -0500
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <14471.14877.434886.471929@amarok.cnri.reston.va.us>
Message-ID: <001a01bf63f3$4473b660$ec2d153f@tim>

[Andrew M. Kuchling]
> ...
> Similarly, does the conservative GC patch splatter changes
> all over the place, or is it very localized?

Part of its problem is that it's *too* localized (which was, paradoxically,
I suspect part of its initial quick-eyeball appeal to Guido -- it "looks
like" an amazingly self-contained patch).  For example, all the code to
chase pointers in various types of objects is hiding in a single function,
which does a string of "if type is list then this else if type is tuple then
that ..." tests.  This stuff clearly needs to be distributed across the
object implementations and dispatched to via a new slot in type objects;
there's no code for that now.

I expect it would take a minimum of two weeks (full-time work) to make this
code ready for prime time (but mostly to slash the space and time use -- and
with no certainty of "good enough" in the end).

BTW, "conservative" is a misleading adjective for this approach -- it never
guesses ("guessing on the safe side" whether or not some bit pattern is a
pointer is what "conservative" customarily means in the GC world).

> Is adding the NumPy array type straightforward?

DavidA nixed that one in no uncertain terms!

maybe-hp-will-give-up-unicode-and-we-can-release-tomorrow-ly
    y'rs  - tim




From tim_one@email.msn.com  Fri Jan 21 09:52:13 2000
From: tim_one@email.msn.com (Tim Peters)
Date: Fri, 21 Jan 2000 04:52:13 -0500
Subject: [Python-Dev] Python 1.6 timing (fwd)
In-Reply-To: <Pine.LNX.4.10.10001201346510.7719-100000@akbar.nevex.com>
Message-ID: <001d01bf63f5$318e2600$ec2d153f@tim>

[Greg Wilson]
> ...
> There's also a couple of smart guys in the class who are
> wondering about CPython vs. JPython ("So this'll be safe in
> one version of the language, but not in the other?"),

Greg, people who have been exposed to Fortran (this is LANL, right <wink>?)
can't possibly have a problem with the concept of "not defined by the
standard".  Don't sell these as different *versions* of the language, but as
different implementations.  That's what they are.  The Python *language*
doesn't define anything about the lifetime of objects.  Even when CPython
grows "real GC", thanks to refcounting too you'll still be able to *rely* on
behaviors in CPython you'll see only accidentally in JPython.  You do so at
your own risk, same as e.g. you rely on floating point Fortran x+y+z getting
evaluated "left to right" at your own risk (BTW, x+y+z *is* "left to right"
in Python -- maybe they'll trade that for the lack of GC promises <wink>).




From tim_one@email.msn.com  Fri Jan 21 10:22:51 2000
From: tim_one@email.msn.com (Tim Peters)
Date: Fri, 21 Jan 2000 05:22:51 -0500
Subject: [Python-Dev] Changing existing class instances
In-Reply-To: <200001202002.PAA22435@eric.cnri.reston.va.us>
Message-ID: <001e01bf63f9$79660980$ec2d153f@tim>

[Tim, still worried about stomping on unintended classes/defs]

[example abusing Tkinter.Misc]

> For a second I thought you got me there!

That's twice as long as I thought you'd think that, so I win after all
<wink>.

> Fortunately, there's magic available: recently, all classes
> have a __module__ attribute that is set to the full name
> of the module that defined it (its key in __sys__.modules).
>
> For functions, we would have to invent something similar.

OK!  I didn't know about class.__module__ -- I hope you realize that relying
on your time machine is making you lazy <wink>.

I remain uncomfortable with automagic updating, but not as much so.  Both
kinds of errors still seem possible to me:

1. Automagically updating when it wasn't wanted.

Examples of this are getting harder to come by <wink>.  Off the top of my
head I'm reduced to stuff like this:

>>> adders = []
>>> for i in range(10):
	def adder(y, x=i):
		return y+x
	adders.append(adder)


>>> adders[2](40)
42
>>> adders[9](33)
42
>>>

"That kind of thing" has got to be rare, but can't be non-existent either
(well, isn't -- I've done it).

2. Failing to automagically update when it was wanted.

Implicit in the discussion so far is that long-running systems want to
update code at a granularity no finer than module level.  Is that realistic?
I'm unsure.  It's certainly easy to *imagine* the app running an updater
server thread, accepting new source for functions and classes, and offering
to compile and install the objects.

Under the explicit new.update scheme, such a service needn't bother clients
with communicating the full name of the original module; heck, in a *truly*
long-running app, over time the source tree will change, and classes and
functions will migrate across modules.  That will be a problem for the
explicit scheme too (how does it know *which* "class Misc" to update) -- but
at least it's an explicit problem then, and not a "mysterous failure" of
hidden magic.


I could live with both of those (#1 is more worrisome); but think it easier
all around to give the users some tools and tell them to solve the problems
however they see fit.

or-maybe-we-already-agreed-about-that-ly y'rs  - tim




From gstein@lyra.org  Fri Jan 21 11:08:19 2000
From: gstein@lyra.org (Greg Stein)
Date: Fri, 21 Jan 2000 03:08:19 -0800 (PST)
Subject: [Python-Dev] namespaces (was: Changing existing class instances)
In-Reply-To: <001801bf63f3$414e0c60$ec2d153f@tim>
Message-ID: <Pine.LNX.4.10.10001210254030.13911-100000@nebula.lyra.org>

On Fri, 21 Jan 2000, Tim Peters wrote:
> [Greg Stein]
> > ...
> > In other words, I definitely would support a new class
> > object behavior that allows us to update a class' set of
> > bases and dictionary on the fly.  This could then be used
> > to support my solution for the recursive type scenario (which,
> > in turn, means that we don't have to introduce Yet Another
> > Namespace into Python to hold type names).
> 
> Parenthetically, I never grasped the appeal of the parenthetical comment.
> Yet Another Namespace for Yet Another Entirely New Purpose seems highly
> *desirable* to me!  Trying to overload the current namespace set makes it so
> much harder to see that these are compile-time gimmicks, and users need to
> be acutely aware of that if they're to use it effectively.  Note that I
> understand (& wholly agree with) the need for runtime introspection.

And that is the crux of the issue: I think the names that are assigned to
these classes, interfaces, typedefs, or whatever, can follow the standard
Python semantics and be plopped into the appropriate namespace. There is
no overloading.

The compile-time behavior certainly understands what names have what
types; in this case, if a name is a "typedecl", then it can remember the
*value*, too. When the name is used later, it knows the corresponding
value to use. For instance:

  IntOrString = typedef int|str
  def foo(x: IntOrString):
    ...

In this example, the type-checker knows that IntOrString is a typedecl.
It also knows the *value* of "int|str" so the name IntOrString now has two
items associated with it at type-check time:

   # not "real" syntax, but you get the idea...

   namespace["IntOrString"] = (TypeDeclarator, int|str)

With the above information in hand, the type-checker knows what
IntOrString means in the declaration for foo().

The cool benefit is that the runtime semantics are exactly as you would
expect: a typedecl object is created and assigned to IntOrString. That
object is also associated with the "x" argument in the function object
referred to by the name "foo".

There is no "overloading" of namespaces. We are using Python namespaces
just like they should be, and the type-checker doesn't even have to be all
the smart to track this stuff.

To get back to the recursive class problem, consider the following code:

   decl incomplete class Foo
   decl incomplete class Bar

   class Foo:
     decl a: Bar

   class Bar:
     decl b: Foo

The "decl" statements would create an empty class object and store that
into the "current" namespace. There is no need to shove that off into
another namespace. When the "class Foo" comes along, the class object is
updated with the class definition for Foo.

It is conceivable to remove the need for "decl" if you allow "class" and
"def" to omit the ": suite" portion of their grammar:

  class Foo
  class Bar

  class Foo:
    decl a: Bar
  ...

  def some_function(x: some_type, y: another_type) -> third_type

  ... lots o' code ...

  def some_function(x, y):
    ...

Guido suggested that it may be possible to omit "decl" altogether.
Certainly, it can work for member declarations such as:

  class Foo:
    a: Bar


Anyhow... my point is that a new namespace is not needed. Assuming we want
objects for reflection at runtime, then the above proposal states *how*
those objects are realized at runtime. Further, the type-checker can
easily follow that information and perform the appropriate compile-time
checks.

No New Namespaces!  (lather, rinse, repeat)

Cheers,
-g

-- 
Greg Stein, http://www.lyra.org/



From gstein@lyra.org  Fri Jan 21 11:12:57 2000
From: gstein@lyra.org (Greg Stein)
Date: Fri, 21 Jan 2000 03:12:57 -0800 (PST)
Subject: [Python-Dev] Changing existing class instances
In-Reply-To: <200001202002.PAA22435@eric.cnri.reston.va.us>
Message-ID: <Pine.LNX.4.10.10001210311070.13911-100000@nebula.lyra.org>

On Thu, 20 Jan 2000, Guido van Rossum wrote:
> Tim Peters:
>...
> > At the time my.py defines Misc, does Misc count as a class we're "about to
> > stomp on"?  If so-- & I've assumed so --it would wreak havoc.
> > 
> > But if not, I don't see how this case can be reliably distinguished "by
> > magic" from the cases where update is desired (if people are doing dynamic
> > updates to a long-running program, a new version of a class can come from
> > anywhere, so nothing like original file name or line number can distinguish
> > correctly either).
> 
> Fortunately, there's magic available: recently, all classes have a
> __module__ attribute that is set to the full name of the module that
> defined it (its key in __sys__.modules).
> 
> For functions, we would have to invent something similar.

func.func_globals


__module__ and func_globals can prevent *other* modules from redefining
something accidentally, but it doesn't prevent Badness from within the
module.
[ Tim just posted an example of this: his "def adder()" example... ]

Cheers,
-g

-- 
Greg Stein, http://www.lyra.org/



From bwarsaw@cnri.reston.va.us (Barry A. Warsaw)  Fri Jan 21 14:38:52 2000
From: bwarsaw@cnri.reston.va.us (Barry A. Warsaw) (Barry A. Warsaw)
Date: Fri, 21 Jan 2000 09:38:52 -0500 (EST)
Subject: [Python-Dev] Changing existing class instances
References: <200001202002.PAA22435@eric.cnri.reston.va.us>
 <001e01bf63f9$79660980$ec2d153f@tim>
Message-ID: <14472.28540.765858.16133@anthem.cnri.reston.va.us>

>>>>> "TP" == Tim Peters <tim_one@email.msn.com> writes:

    TP> Under the explicit new.update scheme, such a service needn't
    TP> bother clients with communicating the full name of the
    TP> original module; heck, in a *truly* long-running app, over
    TP> time the source tree will change, and classes and functions
    TP> will migrate across modules.  That will be a problem for the
    TP> explicit scheme too (how does it know *which* "class Misc" to
    TP> update) -- but at least it's an explicit problem then, and not
    TP> a "mysterous failure" of hidden magic.

I completely agree.  I think in general, such long running apps are
rare, and in those cases you probably want to be explicit about when
and how the updates occur anyway.  The one place where automatic
updates would be convenient would be at the interactive prompt, so it
might be nice to add a module that could be imported by PYTHONSTARTUP,
and play hook games to enable automatic updates.

-Barry



From bwarsaw@cnri.reston.va.us (Barry A. Warsaw)  Fri Jan 21 14:39:32 2000
From: bwarsaw@cnri.reston.va.us (Barry A. Warsaw) (Barry A. Warsaw)
Date: Fri, 21 Jan 2000 09:39:32 -0500 (EST)
Subject: [Python-Dev] Python 1.6 timing
References: <14471.31301.504670.201702@anthem.cnri.reston.va.us>
 <Pine.LNX.4.10.10001201653130.13911-100000@nebula.lyra.org>
Message-ID: <14472.28580.945266.658533@anthem.cnri.reston.va.us>

>>>>> "GS" == Greg Stein <gstein@lyra.org> writes:

    GS> Or move the CVS tree off-site.

I don't see what this buys us.
-Barry


From gstein@lyra.org  Fri Jan 21 14:48:40 2000
From: gstein@lyra.org (Greg Stein)
Date: Fri, 21 Jan 2000 06:48:40 -0800 (PST)
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <14472.28580.945266.658533@anthem.cnri.reston.va.us>
Message-ID: <Pine.LNX.4.10.10001210646140.13911-100000@nebula.lyra.org>

On Fri, 21 Jan 2000, Barry A. Warsaw wrote:
> >>>>> "GS" == Greg Stein <gstein@lyra.org> writes:
> 
>     GS> Or move the CVS tree off-site.
> 
> I don't see what this buys us.

I was under the impression that CVS access restrictions are based on CNRI
security policy. If the CVS repository moves elsewhere, then many people
can access it without impact on CNRI's network and security policies.

However, if the external access issue is based on legal reasons (for
example, only CNRI people should alter Python code), then yes: moving the
repository will buy nothing.

Cheers,
-g

-- 
Greg Stein, http://www.lyra.org/



From bwarsaw@python.org  Fri Jan 21 16:08:11 2000
From: bwarsaw@python.org (bwarsaw@python.org)
Date: Fri, 21 Jan 2000 11:08:11 -0500 (EST)
Subject: [Python-Dev] Python 1.6 timing
References: <14472.28580.945266.658533@anthem.cnri.reston.va.us>
 <Pine.LNX.4.10.10001210646140.13911-100000@nebula.lyra.org>
Message-ID: <14472.33899.20409.602096@anthem.cnri.reston.va.us>

>>>>> "GS" == Greg Stein <gstein@lyra.org> writes:

    GS> I was under the impression that CVS access restrictions are
    GS> based on CNRI security policy. If the CVS repository moves
    GS> elsewhere, then many people can access it without impact on
    GS> CNRI's network and security policies.

Well, access to our /internal/ network is of course restricted.  CNRI
employees have write access to the tree by virtue of access to the
filesystem (i.e. by NFS).  My current arrangement for external ssh
mediated access to a writable cvs server on an internal machine is a
hack and not something that I want to perpetuate if more users were
added.

    GS> However, if the external access issue is based on legal
    GS> reasons (for example, only CNRI people should alter Python
    GS> code), then yes: moving the repository will buy nothing.

I'll let Guido comment on policy concerning write access to the Python
CVS tree.  From a technical standpoint, if this is something Guido
wanted to extend to non-CNRI employees, the way to do it would be to
host the primary repository on a CNRI machine outside our firewall,
e.g cvs.python.org.  At that point, we'd be accessing the tree the
same as anybody else.

-Barry


From gstein@lyra.org  Fri Jan 21 16:19:33 2000
From: gstein@lyra.org (Greg Stein)
Date: Fri, 21 Jan 2000 08:19:33 -0800 (PST)
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <14472.33899.20409.602096@anthem.cnri.reston.va.us>
Message-ID: <Pine.LNX.4.10.10001210816440.13911-100000@nebula.lyra.org>

On Fri, 21 Jan 2000 bwarsaw@python.org wrote:
> >>>>> "GS" == Greg Stein <gstein@lyra.org> writes:
>...
> From a technical standpoint, if this is something Guido
> wanted to extend to non-CNRI employees, the way to do it would be to
> host the primary repository on a CNRI machine outside our firewall,
> e.g cvs.python.org.  At that point, we'd be accessing the tree the
> same as anybody else.

Gotcha. Sounds great!

I'm not sure yet that Guido is looking for external people to do checkins
(as opposed to delivering refined patches to him)... So we probably don't
need an assessment from the legal department :-), but if Guido already
knows, then I'd be curious.

thx!
-g

-- 
Greg Stein, http://www.lyra.org/



From paul@prescod.net  Fri Jan 21 16:51:24 2000
From: paul@prescod.net (Paul Prescod)
Date: Fri, 21 Jan 2000 08:51:24 -0800
Subject: [Python-Dev] Re: [Types-sig] namespaces (was: Changing existing class instances)
References: <Pine.LNX.4.10.10001210254030.13911-100000@nebula.lyra.org>
Message-ID: <38888E8C.FE369A86@prescod.net>

Greg Stein wrote:
> Tim Peters:
> > Trying to overload the current namespace set makes it so
> > much harder to see that these are compile-time gimmicks, and users need to
> > be acutely aware of that if they're to use it effectively.  Note that I
> > understand (& wholly agree with) the need for runtime introspection.
> 
> And that is the crux of the issue: I think the names that are assigned to
> these classes, interfaces, typedefs, or whatever, can follow the standard
> Python semantics and be plopped into the appropriate namespace. There is
> no overloading.

This is indeed the crux of the issue. For those that missed it last
time, it became very clear to me that we are working with radically
different design aesthetics when we discussed the idea of having an
optional keyword that said: "this thing is usually handled at compile
time but I want to handle it at runtime. I know what I am doing." 

Greg complained that that would require the programmer to understand too
much what was being done at compile time and what at runtime and what.
>From my point of view this is *exactly* what a programmer *needs* to
know and if we make it too hard for them to know it then we have failed.

> There is no "overloading" of namespaces. We are using Python namespaces
> just like they should be, and the type-checker doesn't even have to be all
> the smart to track this stuff.

There is an overloading of namespaces because we will separately specify
the *compile time semantics* of these names. We need to separately
specify these semantics because we need all compile time type checkers
to behave identically.

Yes, it seems elegant to make type objects seem as if they are "just
like" Python objects. Unfortunately they aren't. Type objects are
evaluated -- and accepted or rejected -- at compile time. Every
programmer needs to understand that and it should be blatantly obvious
in the syntax, just as everything else in Python syntax is blatantly
obvious.

-- 
 Paul Prescod  - ISOGEN Consulting Engineer speaking for himself
Earth will soon support only survivor species -- dandelions, roaches, 
lizards, thistles, crows, rats. Not to mention 10 billion humans.
	- Planet of the Weeds, Harper's Magazine, October 1998



From skaller@maxtal.com.au  Fri Jan 21 21:01:03 2000
From: skaller@maxtal.com.au (skaller)
Date: Sat, 22 Jan 2000 08:01:03 +1100
Subject: [Python-Dev] Re: [Types-sig] namespaces (was: Changing existing class instances)
References: <Pine.LNX.4.10.10001210254030.13911-100000@nebula.lyra.org> <38888E8C.FE369A86@prescod.net>
Message-ID: <3888C90F.BECA3FF6@maxtal.com.au>

Paul Prescod wrote:
 
 
> Yes, it seems elegant to make type objects seem as if they are "just
> like" Python objects. Unfortunately they aren't.

	Yes they are. They even have a type, TypeType.

-- 
John (Max) Skaller, mailto:skaller@maxtal.com.au
10/1 Toxteth Rd Glebe NSW 2037 Australia voice: 61-2-9660-0850
homepage: http://www.maxtal.com.au/~skaller
download: ftp://ftp.cs.usyd.edu/au/jskaller


From tim_one@email.msn.com  Sat Jan 22 23:18:14 2000
From: tim_one@email.msn.com (Tim Peters)
Date: Sat, 22 Jan 2000 18:18:14 -0500
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <000701bf636f$de37c5e0$c355cfc0@ski.org>
Message-ID: <000401bf652e$f5266b60$132d153f@tim>

[David Ascher]
> ...
> Regardless, just like Greg, I'd like to know what a
> pumpkin-holder would mean in the Python world.
>
> I propose that it be called the Oracle instead.  As in,
> whoever is Oracle would get some training with Tim Peters
> and learn how to channel G__do.

I'm afraid that wouldn't work.  The whole secret to channeling Guido in the
*past* was to have been an ABC user:  all you had to do is notice the things
about ABC that you loved and the ones that would drive any sane
*experienced* programmer mad with frustration.  Voila!  Guido's mind is your
mind <wink>.

But the more Python sails into uncharted waters, the less reliable my
Guido-channeling pseudo-skills get.  He is, in Essence, Unfathomable.  Also
indispensable.

> As a Python user, I'd be most comfortable with such a change
> if the Oracle just took over the technical stuff (reviewing
> patches, CVS checkins, running tests, corralling help for
> doc & code, maintaining release notes, building installers,
> etc.), but that the important decisions (e.g. whether to add
> a feature to the core language) would be checked with G__do
> first.

Definitely.  But where do you find someone like that?  It's (or at least
*should* be) several full-time jobs.  Languages like Icon & Scheme do it via
university association (scads of grad student slave labor); REBOL did it by
floating a trendy Internet business plan that actually attracted enough
venture capital to hire about 30 people; Python, unfortunately <wink>, seems
to attract people who already have demanding jobs.

So I see it as an issue of finding warm bodies more than anything else.  In
the absence of funding "real jobs", I really don't see much hope.  Bits &
pieces can be farmed out (e.g., I doubt Guido has had to do any work on the
regular expression code since Andrew arrived), but that's it -- I expect the
past predicts the future quite accurately here.

Certainly much more *could* be "farmed out", but no single volunteer of the
kind Python has attracted so far is going to do a lot on their own month
after month after month.  Even with the best of intentions, their "real
life" will interfere severely more often than not (voice of experience,
there -- and I'd guess it's the same for *all* of us).

if-something-doesn't-change-nothing-will-change<wink>-ly y'rs
    - tim




From tim_one@email.msn.com  Sat Jan 22 23:18:11 2000
From: tim_one@email.msn.com (Tim Peters)
Date: Sat, 22 Jan 2000 18:18:11 -0500
Subject: Python 2 namespace change? (was Re: [Python-Dev] Changing existing class instances)
In-Reply-To: <38871CE5.53FB9D68@digicool.com>
Message-ID: <000301bf652e$f348d1c0$132d153f@tim>

[Jim Fulton]
> ...
> A change to the way that namespaces are handled
> could make this work and have a number of other benefits,
> like global name usage without namespace lookups.
>
> I've suggested this to Guido in the past.  His
> reasonable response is that this would be too big a
> change for Python 1. Maybe this is something to consider
> for Python 2?
>
> The basic idea (borrowed from Smalltalk) is to have a kind
> of dictionary that is a collection of "association"
> objects.  An association object is simply a pairing of a
> name with a value. Association objects can be shared among
> multiple namespaces.

Jim, I've been intrigued by this idea for all the years you've been
suggesting it <wink>, but I've never understood what it is you're proposing!
This is the Python-Dev list, so feel encouraged to present it in concrete
implementation terms instead of ambiguous English.  Or maybe an interface?

interface a_kind_of_dictionary_that_is_a_collection_of_\
              association_objects:
    # ??? beats me ...

Or maybe as a C struct?  For example, is "an association object" a (char*,
PyObject*) pair?

Does this kind of dictionary have keys?  If so, of what type?  What type are
the values?  Best I can make sense of the above, the values are "association
objects", each of which contains a name and a value, and a key is maybe a
duplicate of the name in the association object to which it maps.  "A name"
may or may not be a string -- I can't tell.  Or maybe by "dictionary" you
didn't intend Python's current meaning for that word at all.  I assume "a
value" is a PyObject*.  The whole thrust *appears* to be to get names to map
to a PyObject** instead of PyObject*, but if that's the ticket I don't know
what association objeects have to do with it.

> An import like:
>
>   from foo import spam
>
> would copy the association between the name 'foo' and a
> value from module 'spam' into the current module.

Where does the idea that 'spam' is a *module* here come from?  It doesn't
make sense to me, and I'm so lost I'll spare everyone my further confusions
<wink>.

suspecting-the-last-actually-doesn't-make-any-sense<wink>-ly
    y'rs  - tim




From tim_one@email.msn.com  Sat Jan 22 23:29:45 2000
From: tim_one@email.msn.com (Tim Peters)
Date: Sat, 22 Jan 2000 18:29:45 -0500
Subject: [Python-Dev] Python 1.6 timing (fwd)
In-Reply-To: <38875DD1.B6596@tismer.com>
Message-ID: <000701bf6530$90cc31c0$132d153f@tim>

[hristian Tismer]
> ...
> Even better: Refcounting can lead to many new optimizations
> if we pay the cost to make INCREF/DECREF into methods. It
> has its cost (about 10 percent less pystones), but massive
> long-term benefits.

The GC patch Guido forced <wink> me to look at is based on the observation
that it's impossible to create cyclic trash unless a decref leaves a nonzero
refcount.  So the patch adds a function call to the DECREF macro (if the new
refcount is > 0, the object must be added to the set of "suspicious"
objects; else the object must be removed from that set).

So it roughly adds the cost of a method call to each decref anyway.  You
would think it adds less <wink>, but "the set" now is represented as a splay
tree, so *gobs* of hairy code get executed in either case (splay trees do
mutating rotations even on a lookup).

> ...
> Conclusion: I vote for a kind of GC that does just what
> refcounts cannot do, but please keep with the refcounts.

I like 'em too!

BTW, Toby posted (at least an earlier version of) the patch to c.l.py, if
anyone else wants to dig into it (I may have mentioned before that I'm short
on time <wink>).




From tim_one@email.msn.com  Sun Jan 23 04:59:38 2000
From: tim_one@email.msn.com (Tim Peters)
Date: Sat, 22 Jan 2000 23:59:38 -0500
Subject: [Python-Dev] Changing existing class instances
In-Reply-To: <14472.28540.765858.16133@anthem.cnri.reston.va.us>
Message-ID: <000201bf655e$a6a49b80$732d153f@tim>

[Barry A. Warsaw]
> I completely agree.

That's no fun <wink>.

> I think in general, such long running apps are rare,

By definition, they're non-existent under Windows <0.7 wink>.  But it
depends on which field you're working in.  The closer you get to being part
of a business or consumer service, the more important it gets; e.g., I've
seen serious RFQs for software systems guaranteed to suffer no more than 5
minutes of downtime per *year* (& stiff penalties for failure to meet that).
I've never been on the winning end of such an RFQ, so am not sure what it
takes to meet it.

It's interesting to ponder.  Psion has published a little about the software
techniques they use in their PDAs (my Psion 3a's remarkably capable "Agenda"
app has been running non-stop for a bit over 3 years!).

> and in those cases you probably want to be explicit about when
> and how the updates occur anyway.

My guess is you'd want to be *paranoidly* explicit, leaving nothing to
chance.

> The one place where automatic updates would be convenient would
> be at the interactive prompt, so it might be nice to add a
> module that could be imported by PYTHONSTARTUP, and play hook
> games to enable automatic updates.

Returning the favor, I completely agree.  The single thing people at work
gripe most about is how to do development under IDLE in such a way that
their package-laden systems exhibit the hoped-for changes in response to
editing a module deep in the bowels of the system.  I don't have a *good*
answer to that now; reduced to stuff like writing custom scripts to
selectively clear out sys.modules.

non-stop-ly y'rs  - tim




From bwarsaw@cnri.reston.va.us (Barry A. Warsaw)  Sun Jan 23 15:07:26 2000
From: bwarsaw@cnri.reston.va.us (Barry A. Warsaw) (Barry A. Warsaw)
Date: Sun, 23 Jan 2000 10:07:26 -0500 (EST)
Subject: [Python-Dev] Python 1.6 timing
References: <000701bf636f$de37c5e0$c355cfc0@ski.org>
 <000401bf652e$f5266b60$132d153f@tim>
Message-ID: <14475.6446.336166.192186@anthem.cnri.reston.va.us>

>>>>> "TP" == Tim Peters <tim_one@email.msn.com> writes:

    TP> REBOL did it by floating a trendy Internet business plan that
    TP> actually attracted enough venture capital to hire about 30
    TP> people; Python, unfortunately <wink>, seems to attract people
    TP> who already have demanding jobs.

I think all we have to do is change the name for 1.6 to LinuxPython
2.0, then split off and go IPO.  The more money we lose, the higher
our stock will go and we can use our market cap to hire all those warm
bodies.

-Barry


From jeremy@cnri.reston.va.us  Sun Jan 23 18:54:40 2000
From: jeremy@cnri.reston.va.us (Jeremy Hylton)
Date: Sun, 23 Jan 2000 13:54:40 -0500 (EST)
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <000401bf652e$f5266b60$132d153f@tim>
References: <000701bf636f$de37c5e0$c355cfc0@ski.org>
 <000401bf652e$f5266b60$132d153f@tim>
Message-ID: <14475.20080.508651.261991@bitdiddle.cnri.reston.va.us>

>>>>> "TP" == Tim Peters <tim_one@email.msn.com> writes:

  TP> [David Ascher]
  >> I propose that it be called the Oracle instead.  As in, whoever
  >> is Oracle would get some training with Tim Peters and learn how
  >> to channel G__do.

  TP> I'm afraid that wouldn't work.  The whole secret to channeling
  TP> Guido in the *past* was to have been an ABC user: all you had to
  TP> do is notice the things about ABC that you loved and the ones
  TP> that would drive any sane *experienced* programmer mad with
  TP> frustration.  Voila!  Guido's mind is your mind <wink>.

I have discovered another approach.  CNRI put in a cleam room on the
second floor last year.  I recently discovered a little door behind
some metrology device in a corner of the clean room.  The door opens
onto a tunnel that leads directly into Guido's mind.  Unfortunately,
it won't be of much use for a pumpkin-holder or channeler, because
after about 15 minutes you are deposited on the shoulder of the Dulles
Toll Road.

who-wants-to-be-John-Malkovich-when-they-could-be-Guido-ly y'rs,
Jeremy




From skip@mojam.com (Skip Montanaro)  Wed Jan 26 03:42:06 2000
From: skip@mojam.com (Skip Montanaro) (Skip Montanaro)
Date: Tue, 25 Jan 2000 21:42:06 -0600
Subject: [Python-Dev] Multiple dicts for string interpolation?
Message-ID: <200001260342.VAA10627@beluga.mojam.com>

Every once in awhile I want to perform string interpolation using more than
one dictionary.  One way is to build a dictionary that's a union of multiple 
dictionaries:

    dict = {}
    dict.update(d1)
    dict.update(d2)
    ...
    s = format % dict

Another way is the MultiDict approach that Digital Creations (used to?) use
in their DocumentTemplate module (I can't remember the exact usage any
more):

    dict = MultiDict()
    dict.append(d1)
    dict.append(d2)
    ...
    s = format % dict

A MultiDict object maintains a list of the dicts it's been fed and searches
them in order when __getitem__ is called.

I'd like to propose a third alternative.  How about if the string
interpolation function accepted a tuple of dictionaries directly:

    s = format % (d1, d2)

It would only be used when named interpolation was expected.  I don't think
there would be any conflict with current % operator semantics.

Skip Montanaro | http://www.mojam.com/
skip@mojam.com | http://www.musi-cal.com/
847-971-7098



From guido@CNRI.Reston.VA.US  Wed Jan 26 04:13:28 2000
From: guido@CNRI.Reston.VA.US (Guido van Rossum)
Date: Tue, 25 Jan 2000 23:13:28 -0500
Subject: [Python-Dev] Multiple dicts for string interpolation?
In-Reply-To: Your message of "Tue, 25 Jan 2000 21:42:06 CST."
 <200001260342.VAA10627@beluga.mojam.com>
References: <200001260342.VAA10627@beluga.mojam.com>
Message-ID: <200001260413.XAA02813@eric.cnri.reston.va.us>

> I'd like to propose a third alternative.  How about if the string
> interpolation function accepted a tuple of dictionaries directly:
> 
>     s = format % (d1, d2)
> 
> It would only be used when named interpolation was expected.  I don't think
> there would be any conflict with current % operator semantics.

Gut feeling: it's dangerous to fill up every possible dark corner with
specific semantics that are occasionally useful, because if you go too
far you lose useful redundancy, and you end up with Perl.

Not sure whether this particular suggestion is "going too far."

I think it depends on to what extent this is a common, useful idiom.
Do you have evidence of that?  Examples?

--Guido van Rossum (home page: http://www.python.org/~guido/)


From skip@mojam.com (Skip Montanaro)  Wed Jan 26 04:38:53 2000
From: skip@mojam.com (Skip Montanaro) (Skip Montanaro)
Date: Tue, 25 Jan 2000 22:38:53 -0600 (CST)
Subject: [Python-Dev] Multiple dicts for string interpolation?
In-Reply-To: <200001260413.XAA02813@eric.cnri.reston.va.us>
References: <200001260342.VAA10627@beluga.mojam.com>
 <200001260413.XAA02813@eric.cnri.reston.va.us>
Message-ID: <14478.31325.891846.701373@beluga.mojam.com>

    >> I'd like to propose a third alternative.  How about if the string
    >> interpolation function accepted a tuple of dictionaries directly:
    >> 
    >> s = format % (d1, d2)

    Guido> Gut feeling: it's dangerous to fill up every possible dark corner
    Guido> with specific semantics that are occasionally useful, because if
    Guido> you go too far you lose useful redundancy, and you end up with
    Guido> Perl.

Yeah, I am kind of taking advantage of the fact that the format operator
doesn't happen to use tuples of dicts already, though this seems like a
natural extension of the current semantics.   Currently, you can have

    Style of                Simple form     Complex form
    Interpolation
    -------                 -----------     ------------
    sprintf                 string          tuple of strings
    named                   dict            tuple of dicts

It does complicate the decision making process in the string format routine
a bit.

    Guido> I think it depends on to what extent this is a common, useful
    Guido> idiom.  Do you have evidence of that?  Examples?

Well, the first place I ran into it was in DocumentTemplates a few years
ago.  They used an idiom heavily which may have now been replaced by
acquisition where you'd effectively push and pop value dicts onto a stack as
you entered and exited nested blocks of DTML code.  Their solution was a
special dict-like object.

The example that made the light click for me this evening was having an
object whose class dict stores constants and whose instant dict stores
varying values.  It seemed cleaner to me to do

    obj = Class()
    ...
    s = format % (Class.__dict__, obj.__dict__)

than go through the intermediate step of building a separate dict which
would just get discarded as soon as this bit of string building was
complete.  (I will perform this once for each of several thousand
instances.)

It's not a big deal.  If it seems too obscure the other obvious solutions
are not gruesome.

Skip


From skip@mojam.com (Skip Montanaro)  Wed Jan 26 04:40:20 2000
From: skip@mojam.com (Skip Montanaro) (Skip Montanaro)
Date: Tue, 25 Jan 2000 22:40:20 -0600 (CST)
Subject: [Python-Dev] Multiple dicts for string interpolation?
In-Reply-To: <14478.31325.891846.701373@beluga.mojam.com>
References: <200001260342.VAA10627@beluga.mojam.com>
 <200001260413.XAA02813@eric.cnri.reston.va.us>
 <14478.31325.891846.701373@beluga.mojam.com>
Message-ID: <14478.31412.36960.440988@beluga.mojam.com>

Oh crap...  Of course, the table should have been

    Style of                Simple form     Complex form
    Interpolation
    -------                 -----------     ------------
    sprintf                 string          tuple of strings
    named                   dict            

(empty fourth cell...)

Skip


From klm@digicool.com  Wed Jan 26 05:01:36 2000
From: klm@digicool.com (Ken Manheimer)
Date: Wed, 26 Jan 2000 00:01:36 -0500 (EST)
Subject: [Python-Dev] Multiple dicts for string interpolation?
In-Reply-To: <14478.31325.891846.701373@beluga.mojam.com>
Message-ID: <Pine.LNX.4.10.10001252337510.15410-100000@splat.digicool.com>

On Tue, 25 Jan 2000, Skip Montanaro wrote:

>     Guido> Skip:
>     >> I'd like to propose a third alternative.  How about if the string
>     >> interpolation function accepted a tuple of dictionaries directly:
>     >> 
>     >> s = format % (d1, d2)
> [...]
>     Guido> I think it depends on to what extent this is a common, useful
>     Guido> idiom.  Do you have evidence of that?  Examples?
> 
> Well, the first place I ran into it was in DocumentTemplates a few years
> ago.  They used an idiom heavily which may have now been replaced by
> acquisition where you'd effectively push and pop value dicts onto a stack as
> you entered and exited nested blocks of DTML code.  Their solution was a
> special dict-like object.

Implementation of acquisition basically uses a MultiDict underneath.
Consider acquisition as a cumulative context composed from the containers
of the target of a web request.  (Actually, a distinction is made between
the object containment hierarchy of the target and the successive
components of the path along which the target is reached by the request,
with the containment contexts taking precedence - but that's probably not
important here:-)  Add in incidental things like the server environment
(from which you can get HTTP_REFERER and cookies and so forth).  Each of
the components can be a dictionary or a MultiDict (or a sequence of pairs,
i think), and they're ultimately composed in a MultiDict.

I think another place in zope where multidicts play prominently is in the
security mechanism, where any object can have local roles, and the
ultimate role of a user within a context is composed from the union across
the containment hierarchy.  There probably are lots of other places where
multidicts are used.

Suffice to say that there's a lot of composing of contexts that goes on in
Zope in general, acquistion being a prime example but not the only one,
and multidicts play heavily in many.  I would be surprised if this need to
combine contexts is peculiar to web server, or general server
applications.

> [...]
> It's not a big deal.  If it seems too obscure the other obvious solutions
> are not gruesome.

I suppose we'd be pretty happy to have something like MultiDict as part of
python...

Ken
klm@digicool.com

(Who's the only one left in fredericksburg to speak up, at the moment:-)



From tim_one@email.msn.com  Wed Jan 26 05:39:19 2000
From: tim_one@email.msn.com (Tim Peters)
Date: Wed, 26 Jan 2000 00:39:19 -0500
Subject: [Python-Dev] Multiple dicts for string interpolation?
In-Reply-To: <200001260413.XAA02813@eric.cnri.reston.va.us>
Message-ID: <000101bf67bf$b103e460$592d153f@tim>

[Skip, wants to interpolate multiple dicts via "%",
 suggests passing a tuple of dicts:  format % (d1, d2, ...)]

[Guido]
> ...
> I think it depends on to what extent this is a common, useful
> idiom.  Do you have evidence of that?  Examples?

You yourself raised one last century <wink>:  simply wanting to interpolate
from both locals() and globals().  At the time, the idea of a new dict-like
mapping object (capturing Python's lookup rules) appealed to you.  I still
like that, and note that the apparent need becomes more acute if "deep
nesting" is ever added.

I wasn't aware of the MultiDict approach Skip mentioned, but thought it
looked spot on for the general case!  Skip, is the long-windedness of

    dict = MultiDict()
    dict.append(d1)
    dict.append(d2)
    ...
    s = format % dict

the part you didn't like about that?  If so, how about changing the
constructor to

    def __init__(self, *dicts):
         ...

instead so you could use it as a one-liner

    format % MultiDict(d1, d2, ...)

?  That's exactly the same as the tuple idea, except there's a nice
descriptive word in the middle of it <wink>.




From jack@oratrix.nl  Wed Jan 26 09:56:18 2000
From: jack@oratrix.nl (Jack Jansen)
Date: Wed, 26 Jan 2000 10:56:18 +0100
Subject: [Python-Dev] Multiple dicts for string interpolation?
In-Reply-To: Message by "Tim Peters" <tim_one@email.msn.com> ,
 Wed, 26 Jan 2000 00:39:19 -0500 , <000101bf67bf$b103e460$592d153f@tim>
Message-ID: <20000126095619.DC67D36E440@snelboot.oratrix.nl>

> the part you didn't like about that?  If so, how about changing the
> constructor to
> 
>     def __init__(self, *dicts):
>          ...
> 
> instead so you could use it as a one-liner
> 
>     format % MultiDict(d1, d2, ...)
> 
> ?  That's exactly the same as the tuple idea, except there's a nice
> descriptive word in the middle of it <wink>.

I've always wonderer why dict+dict isn't supported (or possibly dict|dict, if 
the key-collision semantics of + on dict are seen as a problem). Is there a 
good reason for this, or is it just that there are other more important things 
to implement?

This wouldn't be a replacement for all uses of MultiDict, as it would probably 
have to create a new dict to keep semantics in line with those of list+list
--
Jack Jansen             | ++++ stop the execution of Mumia Abu-Jamal ++++
Jack.Jansen@oratrix.com | ++++ if you agree copy these lines to your sig ++++
www.oratrix.nl/~jack    | see http://www.xs4all.nl/~tank/spg-l/sigaction.htm 




From guido@CNRI.Reston.VA.US  Wed Jan 26 12:41:45 2000
From: guido@CNRI.Reston.VA.US (Guido van Rossum)
Date: Wed, 26 Jan 2000 07:41:45 -0500
Subject: [Python-Dev] Multiple dicts for string interpolation?
In-Reply-To: Your message of "Wed, 26 Jan 2000 10:56:18 +0100."
 <20000126095619.DC67D36E440@snelboot.oratrix.nl>
References: <20000126095619.DC67D36E440@snelboot.oratrix.nl>
Message-ID: <200001261241.HAA03001@eric.cnri.reston.va.us>

[Tim]
> >     format % MultiDict(d1, d2, ...)
> > 
> > ?  That's exactly the same as the tuple idea, except there's a nice
> > descriptive word in the middle of it <wink>.

Nice.

[Jack]
> I've always wonderer why dict+dict isn't supported (or possibly
> dict|dict, if the key-collision semantics of + on dict are seen as a
> problem). Is there a good reason for this, or is it just that there
> are other more important things to implement?

The reason is that + (or |) looks symmetrical, but for the key
collisions, one of them has to lose.  We now have dict1.update(dict2),
which is a bit more cumbersome, but makes it much clearer who is the
loser.

--Guido van Rossum (home page: http://www.python.org/~guido/)


From skip@mojam.com (Skip Montanaro)  Wed Jan 26 14:30:09 2000
From: skip@mojam.com (Skip Montanaro) (Skip Montanaro)
Date: Wed, 26 Jan 2000 08:30:09 -0600 (CST)
Subject: [Python-Dev] Multiple dicts for string interpolation?
In-Reply-To: <000101bf67bf$b103e460$592d153f@tim>
References: <200001260413.XAA02813@eric.cnri.reston.va.us>
 <000101bf67bf$b103e460$592d153f@tim>
Message-ID: <14479.1265.213769.810138@beluga.mojam.com>

    Tim> Skip, is the long-windedness of

    Tim>     dict = MultiDict()
    Tim>     dict.append(d1)
    Tim>     dict.append(d2)
    Tim>     ...
    Tim>     s = format % dict

    Tim> the part you didn't like about that?  If so, how about changing the
    Tim> constructor to

    Tim>     def __init__(self, *dicts):
    Tim>          ...

    Tim> instead so you could use it as a one-liner

    Tim>     format % MultiDict(d1, d2, ...)

    Tim> ?  That's exactly the same as the tuple idea, except there's a nice
    Tim> descriptive word in the middle of it <wink>.

The long-windedness was part of it.  The performance hit of composing
dictionaries thousands of times to perform a single format operation was
also a consideration.

Okay, side excursion into the Zope source tree...

What I was calling MultiDict is actually MultiMapping (written in C, BTW).
As a side effect of my Zope install here, I even already have it in sys.path
(go figure!).  And it turns out to work just as Tim surmised:

    >>> d1 = {"a": 1}
    >>> d2 = {"b": 2}
    >>> d = MultiMapping.MultiMapping(d1, d2)
    >>> d["b"]
    2
    >>> d["a"]
    1

Dang!  Turns out Jim Fulton has a time machine also.

I guess the next question is to extend Ken's comment about getting it into
the Python core.  Would that be something possible for 1.6?  I used a Python
version of MultiMapping in an ancient version of DocumentTemplate.  I'm sure
the C version has been around for at least two or three years and would
appear pretty darn stable, since it seems to be at the core of a lot of
Zope's coolness.

Skip


From ping@lfw.org  Thu Jan 27 07:06:01 2000
From: ping@lfw.org (Ka-Ping Yee)
Date: Wed, 26 Jan 2000 23:06:01 -0800 (PST)
Subject: [Python-Dev] Multiple dicts for string interpolation?
In-Reply-To: <14478.31325.891846.701373@beluga.mojam.com>
Message-ID: <Pine.LNX.4.10.10001262237010.2341-100000@skuld.lfw.org>

On Tue, 25 Jan 2000, Skip Montanaro wrote:
> 
>     Guido> I think it depends on to what extent this is a common, useful
>     Guido> idiom.  Do you have evidence of that?  Examples?
> 
> Well, the first place I ran into it was in DocumentTemplates a few years
> ago.  They used an idiom heavily which may have now been replaced by
> acquisition where you'd effectively push and pop value dicts onto a stack as
> you entered and exited nested blocks of DTML code.  Their solution was a
> special dict-like object.

That's really interesting.  I wrote a bunch of Python wrappers for
a UI toolkit a little while ago, and there were two main pieces of
machinery i built to make the toolkit pleasant to use:

    1. a reasonably nice C++ extension class kit (this is where i
       tried overloading operator new for the first time, so it
       would allocate memory that could be freed by PyMem_DEL --
       i don't know if CXX uses the same approach)

    2. a second layer of Python wrapper classes for the extension
       classes that implements extra methods in Python, and maintains
       a hierarchy of default keyword argument values along the
       inheritance hierarchy of widgets

The second of these things involved implementing exactly the kind
of dictionary stack that you mentioned.

The programming idiom for building widgets goes something like:

    defaultstack = {}  # maps class object to list of defaults dictionaries

    class Label(Component):
        defaults = _dict(text="Label", align=LEFT)

    class Button(Label):
        defaults = _dict(text="Button", align=CENTER, shadow=2)

    ...

    w = Window(...)

    Button.push(fg="white", bg="red",
                font="-*-courier-bold-r-normal--14-*-*-*-*-*-*-*")
    a = Button(w, text="one")
    b = Button(w, text="two")
    c = Button(w, text="three")
    Button.pop()

This way you can install some options for a while and make a bunch
of widgets with your defaults, then pop the options and go back to
the previous state.

The layers of dictionaries that get composed in every widget's
__init__ function are (in order of priority):

    1. any non-None keyword arguments to __init__
    2. any non-None values in class.defaults
    3. any non-None values in class.__bases__[0].defaults
    4. any non-None values in class.__bases__[0].__bases__[0].defaults
    etc.

When a new set of defaults is push()ed, the class's current
defaults are saved on the defaultstack for the class, and restored
when pop() gets called.

I don't *know* if this is really the best way to do things, but it
has seemed to work out pretty well in practice.  It makes it more
convenient to deal with all the options you have to throw around
especially when doing UI stuff.

Anyway, i noticed the same sort of thing today while wondering about
using keyword arguments for HTML tag attributes.  (Perhaps HTMLgen
does this sort of thing already -- sorry i haven't looked at it.)
Anyway, the following sort of helper might be useful in general:

    class Default:
        def __init__(self, cl, **defaults):
            self.cl = cl
            self.defaults = defaults

        def __call__(self, *args, **kw):
            for key, value in self.defaults:
                if not kw.has_key(key): kw[key] = value
            return apply(self.cl, args, kw)

Then you could do the same thing as above with:

    MyButton = Default(Button, fg="white", bg="red",
                       font="-*-courier-bold-r-normal--14-*-*-*-*-*-*-*")
    a = MyButton(w, text="one")
    b = MyButton(w, text="two")
    c = MyButton(w, text="three")

This is probably a cleaner way to do things.  I haven't tried it,
but it might be a nice thing to have in Tkinter.
 


-- ?!ng



From ping@lfw.org  Fri Jan 28 04:36:49 2000
From: ping@lfw.org (Ka-Ping Yee)
Date: Thu, 27 Jan 2000 20:36:49 -0800 (PST)
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <14475.20080.508651.261991@bitdiddle.cnri.reston.va.us>
Message-ID: <Pine.LNX.4.10.10001272033300.2341-100000@skuld.lfw.org>

On Sun, 23 Jan 2000, Jeremy Hylton wrote:
> 
> I have discovered another approach.  CNRI put in a cleam room on the
> second floor last year.  I recently discovered a little door behind
> some metrology device in a corner of the clean room.  The door opens
> onto a tunnel that leads directly into Guido's mind.  Unfortunately,
> it won't be of much use for a pumpkin-holder or channeler, because
> after about 15 minutes you are deposited on the shoulder of the Dulles
> Toll Road.

I almost fell out of my chair laughing when i read this.

What do you think would happen if Guido went into the tunnel?  Perhaps
    
    http://www.lfw.org/jminc/Guido/http://www.python.org/

(What you get is a generalization of some earlier silliness... the
description of the original is at http://www.lfw.org/jminc/.)


-- ?!ng



From jim@digicool.com  Fri Jan 28 15:02:12 2000
From: jim@digicool.com (Jim Fulton)
Date: Fri, 28 Jan 2000 10:02:12 -0500
Subject: [Python-Dev] Multiple dicts for string interpolation?
References: <200001260342.VAA10627@beluga.mojam.com>
Message-ID: <3891AF74.1E81D7F8@digicool.com>

Skip Montanaro wrote:
> 
> Every once in awhile I want to perform string interpolation using more than
> one dictionary.  One way is to build a dictionary that's a union of multiple
> dictionaries:
> 
>     dict = {}
>     dict.update(d1)
>     dict.update(d2)
>     ...
>     s = format % dict
> 
> Another way is the MultiDict approach that Digital Creations (used to?) use
> in their DocumentTemplate module (I can't remember the exact usage any
> more):
> 
>     dict = MultiDict()
>     dict.append(d1)
>     dict.append(d2)

Actually, push (and pop). The namspaces are managed as a stack.

>     ...
>     s = format % dict
> 
> A MultiDict object maintains a list of the dicts it's been fed and searches
> them in order when __getitem__ is called.
> 
> I'd like to propose a third alternative.  How about if the string
> interpolation function accepted a tuple of dictionaries directly:
> 
>     s = format % (d1, d2)
> 
> It would only be used when named interpolation was expected.  I don't think
> there would be any conflict with current % operator semantics.

Yes. In the current semantics, you output the two dictionaries.

Try: 

  '%s %s' % ({'hello':'skip'},{})

Jim

--
Jim Fulton           mailto:jim@digicool.com   Python Powered!        
Technical Director   (888) 344-4332            http://www.python.org  
Digital Creations    http://www.digicool.com   http://www.zope.org    

Under US Code Title 47, Sec.227(b)(1)(C), Sec.227(a)(2)(B) This email
address may not be added to any commercial mail list with out my
permission.  Violation of my privacy with advertising or SPAM will
result in a suit for a MINIMUM of $500 damages/incident, $1500 for
repeats.


From jim@digicool.com  Fri Jan 28 15:07:24 2000
From: jim@digicool.com (Jim Fulton)
Date: Fri, 28 Jan 2000 10:07:24 -0500
Subject: [Python-Dev] Multiple dicts for string interpolation?
References: <Pine.LNX.4.10.10001252337510.15410-100000@splat.digicool.com>
Message-ID: <3891B0AC.D39275DF@digicool.com>

Ken Manheimer wrote:
> 
> On Tue, 25 Jan 2000, Skip Montanaro wrote:
> 
> >     Guido> Skip:
> >     >> I'd like to propose a third alternative.  How about if the string
> >     >> interpolation function accepted a tuple of dictionaries directly:
> >     >>
> >     >> s = format % (d1, d2)
> > [...]
> >     Guido> I think it depends on to what extent this is a common, useful
> >     Guido> idiom.  Do you have evidence of that?  Examples?
> >
> > Well, the first place I ran into it was in DocumentTemplates a few years
> > ago.  They used an idiom heavily which may have now been replaced by
> > acquisition where you'd effectively push and pop value dicts onto a stack as
> > you entered and exited nested blocks of DTML code.  Their solution was a
> > special dict-like object.
> 
> Implementation of acquisition basically uses a MultiDict underneath.

No it doesn't.  Acquisition achieves combination of multiple 
namespaces in much the same way that inheritence does (through
delagation).

> Consider acquisition as a cumulative context composed from the containers
> of the target of a web request.  (Actually, a distinction is made between
> the object containment hierarchy of the target and the successive
> components of the path along which the target is reached by the request,
> with the containment contexts taking precedence - but that's probably not
> important here:-)  Add in incidental things like the server environment
> (from which you can get HTTP_REFERER and cookies and so forth).  Each of
> the components can be a dictionary or a MultiDict (or a sequence of pairs,
> i think), and they're ultimately composed in a MultiDict.
> 
> I think another place in zope where multidicts play prominently is in the
> security mechanism, where any object can have local roles, and the
> ultimate role of a user within a context is composed from the union across
> the containment hierarchy.  There probably are lots of other places where
> multidicts are used.

Acquisition plays a role in security, but MultiDicts-like things are 
not used.
 
> Suffice to say that there's a lot of composing of contexts that goes on in
> Zope in general, acquistion being a prime example but not the only one,
> and multidicts play heavily in many.  I would be surprised if this need to
> combine contexts is peculiar to web server, or general server
> applications.
> 
> > [...]
> > It's not a big deal.  If it seems too obscure the other obvious solutions
> > are not gruesome.
> 
> I suppose we'd be pretty happy to have something like MultiDict as part of
> python...

Note that Zope actually uses two separate flavors. The one used most
in Zope (in DocumentTemplate) has very specific hooks to work with
Zope's security machinery.

Jim

--
Jim Fulton           mailto:jim@digicool.com   Python Powered!        
Technical Director   (888) 344-4332            http://www.python.org  
Digital Creations    http://www.digicool.com   http://www.zope.org    

Under US Code Title 47, Sec.227(b)(1)(C), Sec.227(a)(2)(B) This email
address may not be added to any commercial mail list with out my
permission.  Violation of my privacy with advertising or SPAM will
result in a suit for a MINIMUM of $500 damages/incident, $1500 for
repeats.


From jim@digicool.com  Fri Jan 28 15:10:26 2000
From: jim@digicool.com (Jim Fulton)
Date: Fri, 28 Jan 2000 10:10:26 -0500
Subject: [Python-Dev] Multiple dicts for string interpolation?
References: <000101bf67bf$b103e460$592d153f@tim>
Message-ID: <3891B162.554622E2@digicool.com>

Tim Peters wrote:
> 
(snip)
> I wasn't aware of the MultiDict approach Skip mentioned,

See the MultiMapping module in ExtensionClass. You can get the
latest flavor of this in the latest Zope release.

> but thought it
> looked spot on for the general case!  Skip, is the long-windedness of
> 
>     dict = MultiDict()
>     dict.append(d1)
>     dict.append(d2)
>     ...
>     s = format % dict

Note the rather important *stack* sematics of
MultiMappings.  We often push and pop namespaces 
on and off of MultiMappings in use.
 
> the part you didn't like about that?  If so, how about changing the
> constructor to
> 
>     def __init__(self, *dicts):
>          ...
> 
> instead so you could use it as a one-liner
> 
>     format % MultiDict(d1, d2, ...)
> 
> ?  That's exactly the same as the tuple idea, except there's a nice
> descriptive word in the middle of it <wink>.

This is exactly what the current MultiMapping "class" does.

Jim

--
Jim Fulton           mailto:jim@digicool.com   Python Powered!        
Technical Director   (888) 344-4332            http://www.python.org  
Digital Creations    http://www.digicool.com   http://www.zope.org    

Under US Code Title 47, Sec.227(b)(1)(C), Sec.227(a)(2)(B) This email
address may not be added to any commercial mail list with out my
permission.  Violation of my privacy with advertising or SPAM will
result in a suit for a MINIMUM of $500 damages/incident, $1500 for
repeats.


From gward@cnri.reston.va.us  Fri Jan 28 16:39:54 2000
From: gward@cnri.reston.va.us (Greg Ward)
Date: Fri, 28 Jan 2000 11:39:54 -0500
Subject: [Python-Dev] To-do for Distutils 0.2 (and beyond)
Message-ID: <20000128113954.A12965@cnri.reston.va.us>

Hi all --

[oops: I *said* that I was cc'ing this to python-dev when I posted it to
 distutils-sig, but I just plain forgot to.  So here it is again, still
 presumed relevant to python-dev'ers because it directly affects the
 planned Python 1.6 feature set.  Please reply either to me directly or
 to distutils-sig, because that's where the implementation will be done.]

recent developments in the planned release schedule for Python 1.6
(Guido doesn't want to wait for everything planned, but get something
out the door in the next couple of months) are lighting a fire under me
to get a seriously usable version of Distutils ready *really* soon now.
This will be Distutils 0.2; I anticipate that 0.2.x will be included in
Python 1.6, where x is the number of attempts it takes me to get
something reasonably bug-free out the door.

Those if you who were at the Python Conference this past week will have
seen bits and pieces of my "laundry list" of desired features that
should be added to the Distutils at some point in the future.  Given the
shortened schedule, it looks like it's necessary to do some pruning and
concentrate on the essentials to get something in Python 1.6.

So, here is my current laundry list, sorted into a couple of categories:

essential for 0.2 (Python 1.6)
-----------------
* fix the "dist" command (two-phase manifest, better feedback)
  (steal ideas and hopefully code from Gordon Macmillan's installer)
* fix the "install" command (have the right interface and do the right
  thing for installating to non-standard or personal directories) 
* fix some bad nomenclature in the command classes
  (most likely 'options' -> 'user_options', 'set_default_options()' ->
  'initialize_options()', and 'set_final_options()' -> ??? (maybe
  'finalize_options()'?))
* build C libraries (for PIL, and other similar distributions)
* documentation (two small manuals that should become standard Python
  manuals: "Installing Python Modules" and "Developing and Distributing
  Python Modules")
* add a bdist command; should at least be able to generate dumb archives
  of built distributions (eg. a tarball that you unpack from /usr/local,
  or maybe /usr/local/lib/python1.5/site-packages)

desirable for 0.2
-----------------
* "what's installed" database
* dependency checking ("is version 1.3 of foo installed?")
* don't automatically clobber an existing installation -- confirm, or
  require a "force" option, or something
* command to install C headers (assuming more extensions than NumPy need
  to do this)

put off to 0.3 (Python 1.7?)
----------------------------
* JPython support (most importantly, know where to install .py modules
  when run from JPython and be able to build Java extensions for JPython)
* build static Python binary (for shared-library-challenged OSs)
* SWIG support (mainly, know how to run it before building the C
  extension it generates)
* PyFort support (ditto)
* Mac support
* allow overlapping multi-architecture installations (Michel Sanner's
  pet peeve and Guido's nightmare ;-) (this would *not* be the default;
  it would have to be explicitly chosen by brave/cheap/foolhardy
  installers)
* support for archive sites (Parnassus) to pull out meta-info

Anyone feel strongly about moving any of these items around, or
discarding any entirely, or adding anything?  Please let me know by
email; I'll summarize to the list.

Thanks --

       Greg


From jeremy@cnri.reston.va.us  Fri Jan 28 23:52:53 2000
From: jeremy@cnri.reston.va.us (Jeremy Hylton)
Date: Fri, 28 Jan 2000 18:52:53 -0500 (EST)
Subject: [Python-Dev] To-do for Distutils 0.2 (and beyond)
In-Reply-To: <20000128113954.A12965@cnri.reston.va.us>
References: <20000128113954.A12965@cnri.reston.va.us>
Message-ID: <14482.11221.451866.695357@bitdiddle.cnri.reston.va.us>

>>>>> "GW" == Greg Ward <gward@cnri.reston.va.us> writes:

 GW> desirable for 0.2
 GW> -----------------
 GW> * "what's installed" database
 GW> * dependency checking ("is version 1.3 of foo installed?")

These are *not* desirable for version 0.2.  Paul Dubois expressed some
concern about the complexity of these tasks.  I agree completely.  I
think the chances of getting this done correctly in the next month are
slim to none.  Don't waste your time adding the kitchen sink to
distutils :-); just bang on the simple stuff until it's rock solid.

Jeremy




From jim@digicool.com  Sat Jan 29 01:40:22 2000
From: jim@digicool.com (Jim Fulton)
Date: Fri, 28 Jan 2000 20:40:22 -0500
Subject: [Python-Dev] Multiple dicts for string interpolation?
References: <200001260413.XAA02813@eric.cnri.reston.va.us>
 <000101bf67bf$b103e460$592d153f@tim> <14479.1265.213769.810138@beluga.mojam.com>
Message-ID: <38924506.808D34F5@digicool.com>

Skip Montanaro wrote:
> 
(snip)
> I guess the next question is to extend Ken's comment about getting it into
> the Python core.  Would that be something possible for 1.6?  I used a Python
> version of MultiMapping in an ancient version of DocumentTemplate.  I'm sure
> the C version has been around for at least two or three years and would
> appear pretty darn stable,

Yes. I'm sure you'd have to de-ExtensionClass-ify it to get it 
into the core. :)

> since it seems to be at the core of a lot of
> Zope's coolness.

Actually, it isn't, as there is a separate similar thing
(TemplateDict) used in DocumentTemplate.

Jim

--
Jim Fulton           mailto:jim@digicool.com   Python Powered!        
Technical Director   (888) 344-4332            http://www.python.org  
Digital Creations    http://www.digicool.com   http://www.zope.org    

Under US Code Title 47, Sec.227(b)(1)(C), Sec.227(a)(2)(B) This email
address may not be added to any commercial mail list with out my
permission.  Violation of my privacy with advertising or SPAM will
result in a suit for a MINIMUM of $500 damages/incident, $1500 for
repeats.


From guido@CNRI.Reston.VA.US  Sun Jan 30 13:32:18 2000
From: guido@CNRI.Reston.VA.US (Guido van Rossum)
Date: Sun, 30 Jan 2000 08:32:18 -0500
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
Message-ID: <200001301332.IAA12252@eric.cnri.reston.va.us>

Dear developers,

Eric Raymond has sent me the following patch, which adds conditional
expressions to Python.  I'd like to hear opinions on whether this is a
good thing to add to Python, and whether this is the right syntax.

I am a bit skeptical about whether this is sufficiently Pythonic, but
on the other hand there have always been requests for such a feature,
and the existing solutions are ugly:

  a and b or c

only works when you know for sure that b will never be false, and

  (a and [b] or [c])[0] 

is dead ugly...

--Guido van Rossum (home page: http://www.python.org/~guido/)

Subject: Ternary select -- here it is.
From: "Eric S. Raymond" <esr@thyrsus.com>
To: Guido Van Rossum <guido@CNRI.Reston.Va.US>
Date: Sat, 29 Jan 2000 17:40:31 -0500
X-Eric-Conspiracy: There is no conspiracy

Dang, Guido, this was *fun*!

This patch extends the Python interpreter to support the C ternary
operator, and documents the extension in the Reference Manual.  The
implementation is dead simple and robust: it's adapted from the
existing code for if statements, and adds or changes less than 70 lines
of code all told.

Diffs between last version checked in and current workfile(s):

--- Grammar/Grammar	2000/01/28 17:10:18	1.1
+++ Grammar/Grammar	2000/01/29 22:14:05
@@ -61,7 +61,8 @@
 except_clause: 'except' [test [',' test]]
 suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT
 
-test: and_test ('or' and_test)* | lambdef
+test: bool_test ['?' bool_test ':' bool_test]
+bool_test: and_test ('or' and_test)* | lambdef
 and_test: not_test ('and' not_test)*
 not_test: 'not' not_test | comparison
 comparison: expr (comp_op expr)*
--- Include/token.h	2000/01/28 17:38:55	1.1
+++ Include/token.h	2000/01/29 01:27:00
@@ -74,10 +74,11 @@
 #define LEFTSHIFT	34
 #define RIGHTSHIFT	35
 #define DOUBLESTAR	36
+#define QUERY		37
 /* Don't forget to update the table _PyParser_TokenNames in tokenizer.c! */
-#define OP		37
-#define ERRORTOKEN	38
-#define N_TOKENS	39
+#define OP		38
+#define ERRORTOKEN	39
+#define N_TOKENS	34
 
 /* Special definitions for cooperation with parser */
 
--- Modules/parsermodule.c	2000/01/28 18:03:27	1.1
+++ Modules/parsermodule.c	2000/01/29 22:13:45
@@ -945,6 +945,7 @@
 #define	validate_star(ch)	validate_terminal(ch,	    STAR, "*")
 #define	validate_vbar(ch)	validate_terminal(ch,	    VBAR, "|")
 #define validate_doublestar(ch)	validate_terminal(ch, DOUBLESTAR, "**")
+#define validate_query(ch)	validate_terminal(ch,	   QUERY, "?")
 #define validate_dot(ch)	validate_terminal(ch,	     DOT, ".")
 #define	validate_name(ch, str)	validate_terminal(ch,	    NAME, str)
 
@@ -963,7 +964,8 @@
 VALIDATER(exec_stmt);		VALIDATER(compound_stmt);
 VALIDATER(while);		VALIDATER(for);
 VALIDATER(try);			VALIDATER(except_clause);
-VALIDATER(test);		VALIDATER(and_test);
+VALIDATER(test);
+VALIDATER(bool_test);		VALIDATER(and_test);
 VALIDATER(not_test);		VALIDATER(comparison);
 VALIDATER(comp_op);		VALIDATER(expr);
 VALIDATER(xor_expr);		VALIDATER(and_expr);
@@ -1829,12 +1831,34 @@
 }   /* validate_except_clause() */
 
 
+/*  bool_test ( | bool_test ? bool_test )
+ *
+ */
 static int
 validate_test(tree)
     node *tree;
 {
+    if (!validate_ntype(tree, test))
+	return 0;
+    else if (NCH(tree) == 1)
+	return(validate_bool_test(CHILD(tree, 0)));
+    else if (validate_numnodes(tree, 5, "expr"))
+    {
+	return validate_bool_test(CHILD(tree, 0))
+	    && validate_query(CHILD(tree, 1))
+	    && validate_bool_test(CHILD(tree, 2))
+	    && validate_colon(CHILD(tree, 3))
+	    && validate_bool_test(CHILD(tree, 4));
+    }
+}   /* validate_test() */
+
+
+static int
+validate_bool_test(tree)
+    node *tree;
+{
     int nch = NCH(tree);
-    int res = validate_ntype(tree, test) && is_odd(nch);
+    int res = validate_ntype(tree, bool_test) && is_odd(nch);
 
     if (res && (TYPE(CHILD(tree, 0)) == lambdef))
 	res = ((nch == 1)
@@ -1848,7 +1872,7 @@
     }
     return (res);
 
-}   /* validate_test() */
+}   /* validate_bool_test() */
 
 
 static int
--- Parser/tokenizer.c	2000/01/28 17:37:48	1.1
+++ Parser/tokenizer.c	2000/01/29 01:27:26
@@ -99,6 +99,7 @@
 	"LEFTSHIFT",
 	"RIGHTSHIFT",
 	"DOUBLESTAR",
+	"QUERY",
 	/* This table must match the #defines in token.h! */
 	"OP",
 	"<ERRORTOKEN>",
@@ -384,6 +385,7 @@
 	case '}':	return RBRACE;
 	case '^':	return CIRCUMFLEX;
 	case '~':	return TILDE;
+	case '?':	return QUERY;
 	default:	return OP;
 	}
 }
--- Python/compile.c	2000/01/28 23:17:19	1.1
+++ Python/compile.c	2000/01/29 22:19:29
@@ -1698,11 +1698,11 @@
 }
 
 static void
-com_test(c, n)
+com_bool_test(c, n)
 	struct compiling *c;
 	node *n;
 {
-	REQ(n, test); /* and_test ('or' and_test)* | lambdef */
+	REQ(n, bool_test); /* and_test ('or' and_test)* | lambdef */
 	if (NCH(n) == 1 && TYPE(CHILD(n, 0)) == lambdef) {
 		PyObject *v;
 		int i;
@@ -1738,6 +1738,32 @@
 }
 
 static void
+com_test(c, n)
+	struct compiling *c;
+	node *n;
+{
+	int op;
+	REQ(n, test);
+	com_bool_test(c, CHILD(n, 0));
+
+	/* is there a following ternary operator? */
+	/* XXX optimize the compilation when the guard is a constant */
+	if (NCH(n) == 5)
+	{
+	    int anchor1 = 0, anchor2 = 0;
+	    com_addfwref(c, JUMP_IF_FALSE, &anchor2);
+	    com_addbyte(c, POP_TOP);
+	    com_pop(c, 1);
+	    com_node(c, CHILD(n, 2));
+	    com_addfwref(c, JUMP_FORWARD, &anchor1);
+	    com_backpatch(c, anchor2);
+	    com_addbyte(c, POP_TOP);
+	    com_node(c, CHILD(n, 4));
+	    com_backpatch(c, anchor1);
+	}
+}
+
+static void
 com_list(c, n, toplevel)
 	struct compiling *c;
 	node *n;
@@ -2931,6 +2957,9 @@
 		break;
 	case test:
 		com_test(c, n);
+		break;
+	case bool_test:
+		com_bool_test(c, n);
 		break;
 	case and_test:
 		com_and_test(c, n);
--- Doc/ref/ref5.tex	2000/01/29 21:28:13	1.1
+++ Doc/ref/ref5.tex	2000/01/29 22:00:02
@@ -764,7 +764,7 @@
 \section{Boolean operations\label{Booleans}}
 \indexii{Boolean}{operation}
 
-Boolean operations have the lowest priority of all Python operations:
+Boolean operations have the lowest priority of all Python binary operations:
 
 \begin{verbatim}
 expression:     or_test | lambda_form
@@ -832,6 +832,24 @@
 def make_incrementor(increment):
     return lambda x, n=increment: x+n
 \end{verbatim}
+
+\section{Select\label{select}}
+\index{select}
+
+The select operator is a ternary operator with lower priority than
+boolean operations (and thus lower priority than all other binary and
+unary operators).
+
+\begin{verbatim}
+select_expr:    xor_expr | xor_expr "?" xor_expr ":" xor_expr
+\end{verbatim}
+
+If its first operand is nonempty, the value of a select operation is
+its second operand; otherwise the value is the third operand.
+
+(The semantics and precedence level of select are intended to be
+unsurprising to programmers familiar with \C's ternary select
+operator.)
 
 \section{Expression lists\label{exprlists}}
 \indexii{expression}{list}

End of diffs.
-- 
		<a href="http://www.tuxedo.org/~esr">Eric S. Raymond</a>

You know why there's a Second Amendment?  In case the government fails to
follow the first one.
         -- Rush Limbaugh, in a moment of unaccustomed profundity 17 Aug 1993


From jim@digicool.com  Sun Jan 30 13:52:32 2000
From: jim@digicool.com (Jim Fulton)
Date: Sun, 30 Jan 2000 08:52:32 -0500
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
References: <200001301332.IAA12252@eric.cnri.reston.va.us>
Message-ID: <38944220.3177B402@digicool.com>

Guido van Rossum wrote:
> 
> Dear developers,
> 
> Eric Raymond has sent me the following patch, which adds conditional
> expressions to Python.  I'd like to hear opinions on whether this is a
> good thing to add to Python, and whether this is the right syntax.

Yee ha! I think that this is a great idea. 

I'm surprised that using the colon doesn't cause problems.
I'm not a grammer lawyer, and don't care that much. I very 
much would like to see a conditional expression. I wouldn't
object if it was spelled differently than C's.

> I am a bit skeptical about whether this is sufficiently Pythonic, but
> on the other hand there have always been requests for such a feature,
> and the existing solutions are ugly:
> 
>   a and b or c
> 
> only works when you know for sure that b will never be false, and
> 
>   (a and [b] or [c])[0]
> 
> is dead ugly...

Yup.

   (a and (b,) or (c,))[0]

is even worse. ;)

Jim

--
Jim Fulton           mailto:jim@digicool.com
Technical Director   (888) 344-4332              Python Powered!
Digital Creations    http://www.digicool.com     http://www.python.org

Under US Code Title 47, Sec.227(b)(1)(C), Sec.227(a)(2)(B) This email
address may not be added to any commercial mail list with out my
permission.  Violation of my privacy with advertising or SPAM will
result in a suit for a MINIMUM of $500 damages/incident, $1500 for
repeats.


From esr@thyrsus.com  Sun Jan 30 15:59:42 2000
From: esr@thyrsus.com (Eric S. Raymond)
Date: Sun, 30 Jan 2000 10:59:42 -0500
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
In-Reply-To: <38944220.3177B402@digicool.com>; from Jim Fulton on Sun, Jan 30, 2000 at 08:52:32AM -0500
References: <200001301332.IAA12252@eric.cnri.reston.va.us> <38944220.3177B402@digicool.com>
Message-ID: <20000130105941.A10861@thyrsus.com>

Jim Fulton <jim@digicool.com>:
> I'm surprised that using the colon doesn't cause problems.

Pgen doesn't tag this ambiguous.  The LL(1) traversal actually helps
here; by the time you see a colon, you already know whether or not you're
parsing a ternary telect.
-- 
		<a href="http://www.tuxedo.org/~esr">Eric S. Raymond</a>

Don't think of it as `gun control', think of it as `victim
disarmament'. If we make enough laws, we can all be criminals.


From guido@CNRI.Reston.VA.US  Sun Jan 30 16:40:32 2000
From: guido@CNRI.Reston.VA.US (Guido van Rossum)
Date: Sun, 30 Jan 2000 11:40:32 -0500
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
In-Reply-To: Your message of "Sun, 30 Jan 2000 10:59:42 EST."
 <20000130105941.A10861@thyrsus.com>
References: <200001301332.IAA12252@eric.cnri.reston.va.us> <38944220.3177B402@digicool.com>
 <20000130105941.A10861@thyrsus.com>
Message-ID: <200001301640.LAA12598@eric.cnri.reston.va.us>

> Jim Fulton <jim@digicool.com>:
> > I'm surprised that using the colon doesn't cause problems.

[ESR] 
> Pgen doesn't tag this ambiguous.  The LL(1) traversal actually helps
> here; by the time you see a colon, you already know whether or not you're
> parsing a ternary telect.

Interestingly, the very ad-hoc parsing that I described in the
compiling/parsing session on devday would be hit by this...  I was
looking for a colon at nesting level zero.  Serves me right for not
using a real parse :-)

--Guido van Rossum (home page: http://www.python.org/~guido/)


From da@ski.org  Sun Jan 30 18:07:51 2000
From: da@ski.org (David Ascher)
Date: Sun, 30 Jan 2000 10:07:51 -0800
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
References: <200001301332.IAA12252@eric.cnri.reston.va.us> <38944220.3177B402@digicool.com>             <20000130105941.A10861@thyrsus.com>  <200001301640.LAA12598@eric.cnri.reston.va.us>
Message-ID: <004101bf6b4c$ed2ab9b0$0100000a@ski.org>

FWIW, the lack of a ternary select is one of the frequently asked questions
in my Python courses.  It would make TomC happier as well.  I'm not sure the
latter is a feature. =)

On the topic of aesthetics, the C syntax doesn't strike me as the ultimate
in pythonicity but it's not too bad either.  I can't think of an alternative
that doesn't involve a new reserved word.

--david





From gvwilson@nevex.com  Sun Jan 30 20:22:21 2000
From: gvwilson@nevex.com (gvwilson@nevex.com)
Date: Sun, 30 Jan 2000 15:22:21 -0500 (EST)
Subject: [Python-Dev] Eight suggestions for Python books
Message-ID: <Pine.LNX.4.10.10001301519420.3368-100000@akbar.nevex.com>

I realize this is a bit off-topic, but based on discussions with various
publishers over the last couple of years, and on conversations at the
conference last week, I wrote up some notes on books that I think would
help Python succeed, and posted them to comp.lang.python under the heading
"Eight suggestions for Python books".  Some of the books are specificially
about Python, while others try to use Python to fill holes in the
curriculum, and thereby get Python into colleges through the side door (in
the same way that networking and computer graphics texts helped C become
more popular).  Hope it's useful...

Greg



From mal@lemburg.com  Sun Jan 30 21:34:51 2000
From: mal@lemburg.com (M.-A. Lemburg)
Date: Sun, 30 Jan 2000 22:34:51 +0100
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
References: <200001301332.IAA12252@eric.cnri.reston.va.us>
Message-ID: <3894AE7A.BE89D9B4@lemburg.com>

> --- Include/token.h     2000/01/28 17:38:55     1.1
> +++ Include/token.h     2000/01/29 01:27:00
> @@ -74,10 +74,11 @@
>  #define LEFTSHIFT      34
>  #define RIGHTSHIFT     35
>  #define DOUBLESTAR     36
> +#define QUERY          37
>  /* Don't forget to update the table _PyParser_TokenNames in tokenizer.c! */
> -#define OP             37
> -#define ERRORTOKEN     38
> -#define N_TOKENS       39
> +#define OP             38
> +#define ERRORTOKEN     39
> +#define N_TOKENS       34

Shouldn't this read #define N_TOKENS 40 ?!

Apart from that I wouldn't mind having this patch in the core :-)

-- 
Marc-Andre Lemburg
______________________________________________________________________
Business:                                      http://www.lemburg.com/
Python Pages:                           http://www.lemburg.com/python/



From tim_one@email.msn.com  Sun Jan 30 23:25:30 2000
From: tim_one@email.msn.com (Tim Peters)
Date: Sun, 30 Jan 2000 18:25:30 -0500
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
In-Reply-To: <200001301332.IAA12252@eric.cnri.reston.va.us>
Message-ID: <000301bf6b79$4f0c8a60$482d153f@tim>

[Guido van Rossum]
> Eric Raymond has sent me the following patch, which adds conditional
> expressions to Python.  I'd like to hear opinions on whether this
> is a good thing to add to Python,

Marginal; not evil, but of minor utility.

> and whether this is the right syntax.

If and only if you were a C programmer first.  BTW, insert <wink>s where
needed throughout <wink>.

> I am a bit skeptical about whether this is sufficiently Pythonic,
> but on the other hand there have always been requests for such a
> feature,

There have always been requests for the union of all features from all other
languages.

> and the existing solutions are ugly:
>
>   a and b or c
>
> only works when you know for sure that b will never be false,

Too error prone.

> and
>
>   (a and [b] or [c])[0]
>
> is dead ugly...

Well, I'm the guy who invented that one!  The thread that spawned it was
just playfully wondering whether it was *possible* -- and if I didn't solve
it, Majewski would have using even uglier __xxx__ trickery.  I've never used
it in a real program, and shoot people who do.

So there is no reasonable way to spell ?: as a one-liner today, period.  The
question is whether that's "a lack" worth doing something about.  I can live
without it.

Surprised that Jim (Fulton) seems so keen on it:  his cPickle.c uses ?:
exactly once in 4400 lines of C, and in a line that would have been clearer
if C had a max function (or is it min?  it can take a while to
reverse-engineer the intent of a ?:! ... not good when it happens; and I
recall one of the contributed patches that went into 1.5.2 longobject.c,
that had Guido & I both cracking a C manual just to figure out how C would
*parse* a particularly nutso blob of nested ?: thingies).

If this goes in (I'm not deadly opposed, just more opposed than in favor),
I'd like to see "else" used instead of the colon (cond "?" true "else"
false).  The question mark is reasonably mnemonic, but a colon makes no
sense here.

Now let's see whether people really want the functionality or are just
addicted to C syntax <ahem>.

BTW, a number of other changes would be needed to the Lang Ref manual (e.g.,
section 2.6 (Delimeters) explicitly says that "?" isn't used in Python
today, and that its appeareance outside a string literal or comment is "an
unconditional error"; etc).

crabby-old-man-ly y'rs  - tim




From esr@thyrsus.com  Sun Jan 30 23:43:17 2000
From: esr@thyrsus.com (Eric S. Raymond)
Date: Sun, 30 Jan 2000 18:43:17 -0500
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
In-Reply-To: <000301bf6b79$4f0c8a60$482d153f@tim>; from Tim Peters on Sun, Jan 30, 2000 at 06:25:30PM -0500
References: <200001301332.IAA12252@eric.cnri.reston.va.us> <000301bf6b79$4f0c8a60$482d153f@tim>
Message-ID: <20000130184317.A12833@thyrsus.com>

Tim Peters <tim_one@email.msn.com>:
> If this goes in (I'm not deadly opposed, just more opposed than in favor),
> I'd like to see "else" used instead of the colon (cond "?" true "else"
> false).  The question mark is reasonably mnemonic, but a colon makes no
> sense here.

I have to say that I think any ternary syntax that mixes a single-character
operator with a keyword would be intolerably ugly.
 
> Now let's see whether people really want the functionality or are just
> addicted to C syntax <ahem>.

It's not that simple.  People clearly want the functionality; we've
seen ample evidence of that.  Given that, I think the presumption has
to be in favor of using the familiar C syntax rather than an invention
that would necessarily be more obscure.

> BTW, a number of other changes would be needed to the Lang Ref manual (e.g.,
> section 2.6 (Delimeters) explicitly says that "?" isn't used in Python
> today, and that its appeareance outside a string literal or comment is "an
> unconditional error"; etc).

I'm certainly willing to fix that.
-- 
		<a href="http://www.tuxedo.org/~esr">Eric S. Raymond</a>

[The disarming of citizens] has a double effect, it palsies the hand
and brutalizes the mind: a habitual disuse of physical forces totally
destroys the moral [force]; and men lose at once the power of
protecting themselves, and of discerning the cause of their
oppression.
        -- Joel Barlow, "Advice to the Privileged Orders", 1792-93


From dascher@mindspring.com  Mon Jan 31 00:09:39 2000
From: dascher@mindspring.com (David Ascher)
Date: Sun, 30 Jan 2000 16:09:39 -0800
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
References: <200001301332.IAA12252@eric.cnri.reston.va.us> <000301bf6b79$4f0c8a60$482d153f@tim> <20000130184317.A12833@thyrsus.com>
Message-ID: <005c01bf6b7f$7a3a8f60$0100000a@ski.org>

> > Now let's see whether people really want the functionality or are just
> > addicted to C syntax <ahem>.
>
> It's not that simple.  People clearly want the functionality; we've
> seen ample evidence of that.

I personally haven't been stunned by the ample evidence you mention.  While
folks do ask about the ternary select periodically in classes and on the
net, none of my students at least are especially upset when I point out the
readability of:

if a:
      b = c
else:
      b = d

> Given that, I think the presumption has
> to be in favor of using the familiar C syntax rather than an invention
> that would necessarily be more obscure.

The presumption from the language design point of view is to do what's right
regardless of language background, not what's in C -- when Guido remembered
that, he chose 'and' and 'or' over '&&' and '||'.  When Guido forgot that,
he chose integer division =).  While all of the folks on this list are
comfortable with C, I can point out that a (possibly surprisingly) large
proportion of the Python programmers I have taught have never used C or
never felt comfortable with it. If CP4E succeeds, that proportion will grow,
not shrink.

I do think that taking a page from Randy Pausch would be a good idea in this
case.  My guess is that english words would emerge from trying to teach
non-programmers the concept, but I of course don't have data on the topic.
I wonder how high-school teachers teach the hook-colon in C intro classes,
specifically what _words_ they use.  Those words might lead to alternative
syntaxes.

Finally, something at the edge of my brain is trying to combine the logic of
the ternary select (which is clearly related to control flow) and a more
generalized switch statement.  But I'm not seeing anything syntactically
appealing at present.

That said, the hook-colon syntax is appealing from a release management
perspective because it fits within the current set of reserved words and
clearly isn't the hardest concept to teach.

--david



From petrilli@amber.org  Mon Jan 31 00:54:06 2000
From: petrilli@amber.org (Christopher Petrilli)
Date: Sun, 30 Jan 2000 19:54:06 -0500
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
In-Reply-To: <005c01bf6b7f$7a3a8f60$0100000a@ski.org>; from dascher@mindspring.com on Sun, Jan 30, 2000 at 04:09:39PM -0800
References: <200001301332.IAA12252@eric.cnri.reston.va.us> <000301bf6b79$4f0c8a60$482d153f@tim> <20000130184317.A12833@thyrsus.com> <005c01bf6b7f$7a3a8f60$0100000a@ski.org>
Message-ID: <20000130195406.A25682@trump.amber.org>

The question comes from what "problem" you're trying to solve.  The ?: syntax
does not introduce any new "functionality" to the language, nor does it
make it capable of solving problems or requirements that it can not do
at the current time.

The second qustion I'd ask is, who is this aimed at?  It's certainly not
aimed at first-time programmers, as I know from experience that the ?:
is one of the hardest things to teach people in C (after pointers), and
often I leave it out of training when I did it.  It's simply a "shorthand"
not a new functionality.  If its aimed at experienced programmers, I'd 
argue that it's at best "non-pythonic" and at worst a hack, taken from
a language in which it exposes the "macro assembler" approach.

Python is not a language that has been optimized for "minimal typing", it's
much more verbose than most languages, and so that argument shouldn' be
applied.  Perhaps it's for optimization?  That was I believe the original
argument made for it in K&R, in that optimizers in that day were rather
antiquated, wheras today, I believe that any C compiler would get it
right if it were expressed in its full form. (Timbot?)

So, it comes down to a few questions for me:

	Does it solve a new problem?	No
	Is it pythonic?			No
	Does it make it faster?		No

Given Pyton's CP4E goals, and its general place as an easy to use 
language, I'd argue this patch would be counter to all of those goals.

Sorry if I pushed someone's buton, but... I saw a lot of hints at making
Python MUCH more complex, which is counter to why I changed and dropped
many other languags.

Chris
-- 
| Christopher Petrilli
| petrilli@amber.org


From tim_one@email.msn.com  Mon Jan 31 00:44:34 2000
From: tim_one@email.msn.com (Tim Peters)
Date: Sun, 30 Jan 2000 19:44:34 -0500
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
In-Reply-To: <20000130184317.A12833@thyrsus.com>
Message-ID: <000801bf6b84$588c2d60$482d153f@tim>

[Tim, tosses off   cond "?" true "else" false
 in apparent hatred of colons]

[Eric S. Raymond]
> I have to say that I think any ternary syntax that mixes a
> single-character operator with a keyword would be intolerably ugly.

It's certainly not attractive <wink>.  Guido is the Master of Syntax; if he
decides the functionality is Pythonic, he'll dream up a good Pythonic
syntax.  I'll refrain from suggesting  "if" cond "lambda" true "else" false
<wink>.

>> Now let's see whether people really want the functionality or are just
>> addicted to C syntax <ahem>.

> It's not that simple.  People clearly want the functionality; we've
> seen ample evidence of that.

I have not.  Really!  This has been debated for nearly a decade, with no
consensus (the invention of the (a and [b] or [c])[0] atrocity predates
c.l.py!).  *Some* people certainly want ?: (or equivalent) a lot; but others
are equally opposed.  Note that lack of ?: didn't have enough of a
constituency in Andrew Kuchling's eyes either to make his original "Python
Warts" paper, or its revisions:

    http://starship.python.net/crew/amk/python/writing/warts.html

No change ever proposed has failed to attract vocal & persistent supporters,
so it's not as simple as *that* either <0.5 wink>.

> Given that, I think the presumption has to be in favor of using the
> familiar C syntax rather than an invention that would necessarily be
> more obscure.

By count, I'm sure many more languages (from virtually all functional
languages to Icon) use "if cond then true else false" for this purpose;
obscurity is relative to your background.  At least "if x then y else z" is
clear on the face of it (which may betray my background <wink>).  "then" has
no chance of getting into Python1, though.

My core objection is that ?: doesn't "look pretty":  it's not at all
suggestive of what it means, and the effects on precedence and associativity
are unattractive ("see C, copy C" is the only sense there is to it, and
rules for ?: are-- as I noted last time --obscure).  Good syntax counts for
a lot in Python -- which is why it doesn't look like C now.

Get a good syntax, and most of my objections vanish; I don't have a good
syntax to suggest, though.

passing-the-ball-back-to-guido-where-he-always-knew-it-
    would-land<wink>-ly y'rs  - tim




From esr@thyrsus.com  Mon Jan 31 01:07:11 2000
From: esr@thyrsus.com (Eric S. Raymond)
Date: Sun, 30 Jan 2000 20:07:11 -0500
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
In-Reply-To: <20000130195406.A25682@trump.amber.org>; from Christopher Petrilli on Sun, Jan 30, 2000 at 07:54:06PM -0500
References: <200001301332.IAA12252@eric.cnri.reston.va.us> <000301bf6b79$4f0c8a60$482d153f@tim> <20000130184317.A12833@thyrsus.com> <005c01bf6b7f$7a3a8f60$0100000a@ski.org> <20000130195406.A25682@trump.amber.org>
Message-ID: <20000130200711.A13063@thyrsus.com>

Christopher Petrilli <petrilli@amber.org>:
> The question comes from what "problem" you're trying to solve.  The ?: syntax
> does not introduce any new "functionality" to the language, nor does it
> make it capable of solving problems or requirements that it can not do
> at the current time.

Well, in a theoretical sense, you're right.  But then, even troff macros and
INTERCAL are Turing-complete <my-first-attempt-at-a-Tim-Peters-style-wink>.

One of the lessons of Python to this old LISPer is that *notation
matters*.  Theoretically, Python is a subset of Scheme-with-objects
using a vaguely C-like surface notation.  But even I would rather write
a for-loop than the equivalent recursion.  That's why I code in Python
now instead of trying to rescue LISP from its desuetitude.

So while it is *theoretically* true that ?: adds nothing, it is
*practically* true that it enables a large class of idioms that 
can't otherwise be comfortably expressed.  That matters.

Now, you can argue that the complexity ?: adds to language is not paid
for by the additional convenience; I disagree, but that's at least a
defensible argument.  But simply saying it "adds nothing to the
language" is a red herring -- neither do many of the other base
language features.

Why, for example, do we have more than one kind of loop construct?
Unecessary.  Wasteful.  Clearly either "for" or "while" must go.
As an exercise, try editing your complaint so that it refers to 
"for" everywhere it now refers to ?:.  Contemplate the edited
version until you achieve enlightenment ;-).
-- 
		<a href="http://www.tuxedo.org/~esr">Eric S. Raymond</a>

The same applies for other kinds of long-lasting low-level pain. [...]
The body's response to being jabbed, pierced, and cut is to produce
endorphins. [...]  So here's my programme for breaking that cycle of
dependency on Windows: get left arm tattooed with dragon motif, buy a
crate of Jamaican Hot! Pepper Sauce, get nipples pierced.  With any
luck that will produce enough endorphins to make Windows completely
redundant, and I can then upgrade to Linux and get on with things.
	-- Pieter Hintjens


From ping@lfw.org  Mon Jan 31 01:29:43 2000
From: ping@lfw.org (Ka-Ping Yee)
Date: Sun, 30 Jan 2000 19:29:43 -0600 (EST)
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
In-Reply-To: <000301bf6b79$4f0c8a60$482d153f@tim>
Message-ID: <Pine.LNX.4.10.10001301925190.24976-100000@server1.lfw.org>

On Sun, 30 Jan 2000, Tim Peters wrote:
> If this goes in (I'm not deadly opposed, just more opposed than in favor),
> I'd like to see "else" used instead of the colon (cond "?" true "else"
> false).  The question mark is reasonably mnemonic, but a colon makes no
> sense here.

I agree with that sentiment (along the lines of the philosophy that
chose "and" over "&&"), and it seems to me that it makes the most sense
to use words for both:

    a = x > 0 then x else -x

I don't have the time to do it right this second, but i suggest that
a scan through a decent chunk of Python would be useful to find out how
often this construct (in its "and"/"or" incarnation) actually gets used.
I promise to give it a try as soon as i get my notebook battery charged
up again.


-- ?!ng



From tim_one@email.msn.com  Mon Jan 31 02:41:59 2000
From: tim_one@email.msn.com (Tim Peters)
Date: Sun, 30 Jan 2000 21:41:59 -0500
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
In-Reply-To: <20000130195406.A25682@trump.amber.org>
Message-ID: <000201bf6b94$bfabc360$ee2d153f@tim>

[Christopher Petrilli]
> ...
> Python is not a language that has been optimized for "minimal
> typing", it's much more verbose than most languages, and so that
> argument shouldn't be applied.

Concise expression of common concepts is a Good Thing, though, and there's
nothing inherently evil about wanting one of two outcomes <wink>.  My
impression is that the people historically most in favor of ?: ("or
something like it") are also the ones most strongly in favor of embedded
assignment ("or something like it"), and I can't *dismiss* either gripe.
The Python

while 1:
    x = something_or_other()
    if not x:
        break
    consume(x)

idiom is truly grating at first -- more so than the multi-line ?:
alternatives, in my eyes.

> Perhaps it's for optimization?  That was I believe the original
> argument made for it in K&R, in that optimizers in that day were rather
> antiquated, wheras today, I believe that any C compiler would get it
> right if it were expressed in its full form. (Timbot?)

Indeed, a couple weeks ago we tracked down a "mysterious slowdown" of our
core speech recognizer to a particular compiler failing to optimize *unless*
we changed a ?: into a long winded if/else!  There's really nothing you can
say about "any C compiler" -- optimization is much more a black art than
anyone in that business will admit to in public <0.9 wink>.

C was definitely designed with "by hand" optimization in mind, and,
ironically, it's those features (particularly pointer aliasing) that make it
harder for compilers to optimize than is, say, Fortran.

But regardless of origin, ?: stands or falls on its other merits now.
Python's own implementation uses it often enough, and to good effect.  So it
can't be that Guido hates the idea <wink>.  It's just hard to love the
syntax.

> So, it comes down to a few questions for me:
>
> 	Does it solve a new problem?	No
> 	Is it pythonic?			No
> 	Does it make it faster?		No

Would a nice syntax allow clearer expression of some common computations?
Probably yes.  That's the same basis on which, e.g., list.pop and
list.extend and dict.get and 3-argument getattr and ... were adopted.
"Faster" applied to those too, but nobody pushed for 'em on that basis.
Clearer!  That's what really matters.  It's the same argument for list
comprehensions too.

> ...
> Sorry if I pushed someone's buton, but... I saw a lot of hints at making
> Python MUCH more complex, which is counter to why I changed and dropped
> many other languags.

A good antitode to feature panic is reviewing Misc/HISTORY:  Guido's
willingness to entertain suggestions far exceeds his willingness to adopt
them <wink>.

it-would-be-different-if-features-were-just-as-easy-to-
    take-out-ly y'rs  - tim




From tismer@tismer.com  Mon Jan 31 11:46:50 2000
From: tismer@tismer.com (Christian Tismer)
Date: Mon, 31 Jan 2000 12:46:50 +0100
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
References: <Pine.LNX.4.10.10001301925190.24976-100000@server1.lfw.org>
Message-ID: <3895762A.C1706E8@tismer.com>


Ka-Ping Yee wrote:
> 
> On Sun, 30 Jan 2000, Tim Peters wrote:
> > If this goes in (I'm not deadly opposed, just more opposed than in favor),
> > I'd like to see "else" used instead of the colon (cond "?" true "else"
> > false).  The question mark is reasonably mnemonic, but a colon makes no
> > sense here.
> 
> I agree with that sentiment (along the lines of the philosophy that
> chose "and" over "&&"), and it seems to me that it makes the most sense
> to use words for both:
> 
>     a = x > 0 then x else -x

I would favorise this as well instead of using ?: .
Maybe it would make sense to be even more verbose and use an "if"
as well?

       a = if x > 0 then x else -x

       sign = lambda x: if x > 0 then 1 elif x then -1 else 0

ciao - chris

-- 
Christian Tismer             :^)   <mailto:tismer@appliedbiometrics.com>
Applied Biometrics GmbH      :     Have a break! Take a ride on Python's
Düppelstr. 31                :    *Starship* http://starship.python.net
12163 Berlin                 :     PGP key -> http://wwwkeys.pgp.net
PGP Fingerprint       E182 71C7 1A9D 66E9 9D15  D3CC D4D7 93E2 1FAE F6DF
     we're tired of banana software - shipped green, ripens at home


From gward@cnri.reston.va.us  Mon Jan 31 14:15:08 2000
From: gward@cnri.reston.va.us (Greg Ward)
Date: Mon, 31 Jan 2000 09:15:08 -0500
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
In-Reply-To: <Pine.LNX.4.10.10001301925190.24976-100000@server1.lfw.org>; from ping@lfw.org on Sun, Jan 30, 2000 at 07:29:43PM -0600
References: <000301bf6b79$4f0c8a60$482d153f@tim> <Pine.LNX.4.10.10001301925190.24976-100000@server1.lfw.org>
Message-ID: <20000131091507.A17073@cnri.reston.va.us>

On 30 January 2000, Ka-Ping Yee said:
> On Sun, 30 Jan 2000, Tim Peters wrote:
> > If this goes in (I'm not deadly opposed, just more opposed than in favor),
> > I'd like to see "else" used instead of the colon (cond "?" true "else"
> > false).  The question mark is reasonably mnemonic, but a colon makes no
> > sense here.
> 
> I agree with that sentiment (along the lines of the philosophy that
> chose "and" over "&&"), and it seems to me that it makes the most sense
> to use words for both:
> 
>     a = x > 0 then x else -x

Yeah, I agree with Tim: it's a handy feature and I frequently wish I
could do simple conditional assignment without resorting to a full-blown
if/else.  (I think I stumbled across "a and b or c" myself -- either
that or it was suggested by *Learning Python*, but lay dormant in my
subconscious for several months -- which means that I missed the "b must
always be true" subtlety until it bit me.  Ouch.  I avoid that idiom
now.)

BUT the C line-noise syntax is not appropriate.  It's fine in C, and
it's eminently appropriate in Perl -- both languages designed to
minimise wear-and-tear of programmers' keyboards.  But keyboards are
cheap nowadays, so perhaps we can be a bit more profligate with them.

I find Ping's proposed syntax intriguing.  Personally, I've always been
partial to the

    x = if a then b else c

syntax, even though I don't think I've ever used a language that
includes it.  (Oh wait, the toy ALGOL-knockoff that we used in Intro to
Compilers had it, so I *have* written a parser and simplistic code
generator for a language that includes it.  Perhaps that's why I like
it...)

But either of these -- ie. elevate "then" to keywordhood, with or
without "if", and no colons to be seen -- smell like they would play
havoc with Python's grammar.  And they turn a statement keyword "if"
into an expression keyword.  Not being at all familiar with Python's
parser, I should just shut up now, but it feels tricky.

And of course, any proposed syntax changes nowadays have to take JPython
into account.

        Greg


From guido@CNRI.Reston.VA.US  Mon Jan 31 14:36:52 2000
From: guido@CNRI.Reston.VA.US (Guido van Rossum)
Date: Mon, 31 Jan 2000 09:36:52 -0500
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
In-Reply-To: Your message of "Mon, 31 Jan 2000 09:15:08 EST."
 <20000131091507.A17073@cnri.reston.va.us>
References: <000301bf6b79$4f0c8a60$482d153f@tim> <Pine.LNX.4.10.10001301925190.24976-100000@server1.lfw.org>
 <20000131091507.A17073@cnri.reston.va.us>
Message-ID: <200001311436.JAA15213@eric.cnri.reston.va.us>

> I find Ping's proposed syntax intriguing.  Personally, I've always been
> partial to the
> 
>     x = if a then b else c
> 
> syntax, even though I don't think I've ever used a language that
> includes it.  (Oh wait, the toy ALGOL-knockoff that we used in Intro to
> Compilers had it, so I *have* written a parser and simplistic code
> generator for a language that includes it.  Perhaps that's why I like
> it...)

Yes, this was in original Algol 60 and, by magic of a completely
different kind, again in Algol 68 (which was a completely different
language, and the Mount Everest of languages).

> But either of these -- ie. elevate "then" to keywordhood, with or
> without "if", and no colons to be seen -- smell like they would play
> havoc with Python's grammar.  And they turn a statement keyword "if"
> into an expression keyword.  Not being at all familiar with Python's
> parser, I should just shut up now, but it feels tricky.

The solution can be the same as what Algol used: 'if' outside
parentheses is a statement, and inside parentheses is an expression.
It's a bit of a grammar rearrangement, but totally unambiguous.

However, the added keyword means it won't be in 1.6.  The lively
discussion means that Eric's patch will have a hard time getting in
too...

--Guido van Rossum (home page: http://www.python.org/~guido/)


From jim@digicool.com  Mon Jan 31 15:04:45 2000
From: jim@digicool.com (Jim Fulton)
Date: Mon, 31 Jan 2000 10:04:45 -0500
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
References: <200001301332.IAA12252@eric.cnri.reston.va.us> <000301bf6b79$4f0c8a60$482d153f@tim> <20000130184317.A12833@thyrsus.com> <005c01bf6b7f$7a3a8f60$0100000a@ski.org> <20000130195406.A25682@trump.amber.org>
Message-ID: <3895A48D.F69B3DFA@digicool.com>

Christopher Petrilli wrote:
> 
> The question comes from what "problem" you're trying to solve. 

It would allow you to incorporate logic into expressions. 
There are contexts where only expressions are allowed, such as:

  - lambdas

  - DTML expr attributes

in which I'd very much like to incorporate tests.

> The ?: syntax
> does not introduce any new "functionality" to the language,

Yes it does.

> nor does it
> make it capable of solving problems or requirements that it can not do
> at the current time.

Ditto.
 
> The second qustion I'd ask is, who is this aimed at?  It's certainly not
> aimed at first-time programmers, as I know from experience that the ?:
> is one of the hardest things to teach people in C (after pointers),

Hm. I can't agree.

Smalltalk, came out of an essentially CP4E effort
two decades ago at Xerox PARC.  Smalltalk *only* had conditional
expressions. The message:

  [condition] ifTrue: [do something ...]
              ifFalse: [do something else ...]

is an expression in Smalltalk.

> and
> often I leave it out of training when I did it.  It's simply a "shorthand"
> not a new functionality. 

No, it allows testing in expressions.

> If its aimed at experienced programmers, I'd
> argue that it's at best "non-pythonic" and at worst a hack, taken from
> a language in which it exposes the "macro assembler" approach.

I don't agree.

> Python is not a language that has been optimized for "minimal typing",

That's not the issue.

> it's
> much more verbose than most languages, and so that argument shouldn' be
> applied.  Perhaps it's for optimization?  That was I believe the original
> argument made for it in K&R, in that optimizers in that day were rather
> antiquated, wheras today, I believe that any C compiler would get it
> right if it were expressed in its full form. (Timbot?)
> 
> So, it comes down to a few questions for me:
> 
>         Does it solve a new problem?    No

Yes.

>         Is it pythonic?                 No

Pythonicity is relative.

>         Does it make it faster?         No

Who cares?
 
Jim

--
Jim Fulton           mailto:jim@digicool.com   Python Powered!        
Technical Director   (888) 344-4332            http://www.python.org  
Digital Creations    http://www.digicool.com   http://www.zope.org    

Under US Code Title 47, Sec.227(b)(1)(C), Sec.227(a)(2)(B) This email
address may not be added to any commercial mail list with out my
permission.  Violation of my privacy with advertising or SPAM will
result in a suit for a MINIMUM of $500 damages/incident, $1500 for
repeats.


From tismer@tismer.com  Mon Jan 31 15:59:15 2000
From: tismer@tismer.com (Christian Tismer)
Date: Mon, 31 Jan 2000 16:59:15 +0100
Subject: [Python-Dev] Riskless deletion of nested structures
Message-ID: <3895B153.3D2E763D@tismer.com>

This is a multi-part message in MIME format.
--------------D9F780CECED602EF245D7526
Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: 8bit

Howdy,

Please review!

While implementing Stackless Python, a new problem arose:
Nested structures like frame chains and tracebacks can now
easily grow somuch that they cause a stack overflow on deallocation.

To protect lists, tuples, frames, dicts and tracebacks against
this, I wrote a stackless deallocator.
At the moment, everything is done in trashcan.c .
This gives a slight performance loss of 5% for pystone, most probably
due to the double indirection and non-local code reference.
It is yet a hack, since I'm grabbing the tp->dealloc pointers of these
types and replace them by safe versions. This just in order to
try out things quickly. Later I will change this and incorporate
the stack checks into the affected modules, after I got some
feedback on this.

This patch applies to Stackless and standard Python as well:
Deallocation of deeply nested structures will never again cause
a stack overflow.

Installation for the intermediate version:
Insert a line

	_Py_trashcan_install();

at the end of Py_Initialize in pythonrun.c

Please try it and check my code wether there is a better solution.

cheers - chris

-- 
Christian Tismer             :^)   <mailto:tismer@appliedbiometrics.com>
Applied Biometrics GmbH      :     Have a break! Take a ride on Python's
Düppelstr. 31                :    *Starship* http://starship.python.net
12163 Berlin                 :     PGP key -> http://wwwkeys.pgp.net
PGP Fingerprint       E182 71C7 1A9D 66E9 9D15  D3CC D4D7 93E2 1FAE F6DF
     we're tired of banana software - shipped green, ripens at home
--------------D9F780CECED602EF245D7526
Content-Type: application/x-unknown-content-type-cfile;
 name="trashcan.c"
Content-Transfer-Encoding: base64
Content-Disposition: inline;
 filename="trashcan.c"

LyoNCiAgdHJhc2hjYW4NCiAgQ1QgMmswMTMwDQogIG5vbi1yZWN1cnNpdmVseSBkZXN0cm95
IG5lc3RlZCBvYmplY3RzDQoqLw0KDQojaW5jbHVkZSAiUHl0aG9uLmgiDQojaW5jbHVkZSAi
Y29tcGlsZS5oIg0KI2luY2x1ZGUgImZyYW1lb2JqZWN0LmgiDQojaW5jbHVkZSAidHJhY2Vi
YWNrLmgiDQoNCiNpbmNsdWRlICJ0cmFzaGNhbi5oIg0KDQpzdGF0aWMgUHlPYmplY3QgKiBk
ZWxldGVfbGF0ZXIgPSBOVUxMOw0Kc3RhdGljIGludCBkZWxldGVfbmVzdGluZyA9IDA7DQoN
CiNkZWZpbmUgVU5XSU5EX0xFVkVMIDUwDQoNCnZvaWQgc2FmZV9kZWxldGUob2IsIGRlc3Ry
KQ0KCVB5T2JqZWN0ICogb2I7DQoJZGVzdHJ1Y3RvciBkZXN0cjsNCnsNCgkrK2RlbGV0ZV9u
ZXN0aW5nOw0KCWlmIChkZWxldGVfbmVzdGluZyA8IFVOV0lORF9MRVZFTCkgew0KCQlkZXN0
cihvYik7DQoJfQ0KCWVsc2Ugew0KCQlpZiAoIWRlbGV0ZV9sYXRlcikNCgkJCWRlbGV0ZV9s
YXRlciA9IFB5TGlzdF9OZXcoMCk7DQoJCWlmIChkZWxldGVfbGF0ZXIpIHsNCgkJCVB5TGlz
dF9BcHBlbmQoZGVsZXRlX2xhdGVyLCBvYik7DQoJCX0NCgl9DQoJLS1kZWxldGVfbmVzdGlu
ZzsNCgl3aGlsZSAoZGVsZXRlX25lc3RpbmcgPT0gMCAmJiBkZWxldGVfbGF0ZXIpIHsNCgkJ
LyogcGljayB0by1kbyBsaXN0IGFuZCB0cnkgdG8gZXZpY3QgaXQgKi8NCgkJUHlPYmplY3Qg
KiBzaHJlZGRlciA9IGRlbGV0ZV9sYXRlcjsNCgkJZGVsZXRlX2xhdGVyID0gTlVMTDsNCgkJ
KytkZWxldGVfbmVzdGluZzsNCgkJUHlfREVDUkVGKHNocmVkZGVyKTsNCgkJLS1kZWxldGVf
bmVzdGluZzsNCgl9DQp9DQoNCnN0YXRpYyBkZXN0cnVjdG9yIGxpc3RfZGVhbGxvY19vcmln
ID0gTlVMTDsNCg0Kc3RhdGljIHZvaWQgbGlzdF9kZWFsbG9jX3NhZmUob2IpDQoJUHlPYmpl
Y3QgKiBvYjsNCnsNCglzYWZlX2RlbGV0ZShvYiwgbGlzdF9kZWFsbG9jX29yaWcpOw0KfQ0K
DQpzdGF0aWMgZGVzdHJ1Y3RvciB0dXBsZV9kZWFsbG9jX29yaWcgPSBOVUxMOw0KDQpzdGF0
aWMgdm9pZCB0dXBsZV9kZWFsbG9jX3NhZmUob2IpDQoJUHlPYmplY3QgKiBvYjsNCnsNCglz
YWZlX2RlbGV0ZShvYiwgdHVwbGVfZGVhbGxvY19vcmlnKTsNCn0NCg0Kc3RhdGljIGRlc3Ry
dWN0b3IgZGljdF9kZWFsbG9jX29yaWcgPSBOVUxMOw0KDQpzdGF0aWMgdm9pZCBkaWN0X2Rl
YWxsb2Nfc2FmZShvYikNCglQeU9iamVjdCAqIG9iOw0Kew0KCXNhZmVfZGVsZXRlKG9iLCBk
aWN0X2RlYWxsb2Nfb3JpZyk7DQp9DQoNCnN0YXRpYyBkZXN0cnVjdG9yIGZyYW1lX2RlYWxs
b2Nfb3JpZyA9IE5VTEw7DQoNCnN0YXRpYyB2b2lkIGZyYW1lX2RlYWxsb2Nfc2FmZShvYikN
CglQeU9iamVjdCAqIG9iOw0Kew0KCXNhZmVfZGVsZXRlKG9iLCBmcmFtZV9kZWFsbG9jX29y
aWcpOw0KfQ0KDQpzdGF0aWMgZGVzdHJ1Y3RvciB0cmFjZWJhY2tfZGVhbGxvY19vcmlnID0g
TlVMTDsNCg0Kc3RhdGljIHZvaWQgdHJhY2ViYWNrX2RlYWxsb2Nfc2FmZShvYikNCglQeU9i
amVjdCAqIG9iOw0Kew0KCXNhZmVfZGVsZXRlKG9iLCB0cmFjZWJhY2tfZGVhbGxvY19vcmln
KTsNCn0NCg0KDQpzdGF0aWMgaW50IHRyYXNoY2FuX2luc3RhbGxlZCA9IDA7DQoNCnZvaWQg
X1B5X3RyYXNoY2FuX2luc3RhbGwoKQ0Kew0KCWlmICh0cmFzaGNhbl9pbnN0YWxsZWQpIHJl
dHVybjsNCg0KCWxpc3RfZGVhbGxvY19vcmlnID0gUHlMaXN0X1R5cGUudHBfZGVhbGxvYzsN
CglQeUxpc3RfVHlwZS50cF9kZWFsbG9jID0gbGlzdF9kZWFsbG9jX3NhZmU7DQoNCgl0dXBs
ZV9kZWFsbG9jX29yaWcgPSBQeVR1cGxlX1R5cGUudHBfZGVhbGxvYzsNCglQeVR1cGxlX1R5
cGUudHBfZGVhbGxvYyA9IHR1cGxlX2RlYWxsb2Nfc2FmZTsNCg0KCWRpY3RfZGVhbGxvY19v
cmlnID0gUHlEaWN0X1R5cGUudHBfZGVhbGxvYzsNCglQeURpY3RfVHlwZS50cF9kZWFsbG9j
ID0gZGljdF9kZWFsbG9jX3NhZmU7DQoNCglmcmFtZV9kZWFsbG9jX29yaWcgPSBQeUZyYW1l
X1R5cGUudHBfZGVhbGxvYzsNCglQeUZyYW1lX1R5cGUudHBfZGVhbGxvYyA9IGZyYW1lX2Rl
YWxsb2Nfc2FmZTsNCg0KCXRyYWNlYmFja19kZWFsbG9jX29yaWcgPSBQeVRyYWNlQmFja19U
eXBlLnRwX2RlYWxsb2M7DQoJUHlUcmFjZUJhY2tfVHlwZS50cF9kZWFsbG9jID0gdHJhY2Vi
YWNrX2RlYWxsb2Nfc2FmZTsNCg0KCXRyYXNoY2FuX2luc3RhbGxlZCA9IDE7DQp9DQo=
--------------D9F780CECED602EF245D7526
Content-Type: application/x-unknown-content-type-hfile;
 name="trashcan.h"
Content-Transfer-Encoding: base64
Content-Disposition: inline;
 filename="trashcan.h"

I2lmbmRlZiBQeV9UUkFTSENBTl9IDQojZGVmaW5lIFB5X1RSQVNIQ0FOX0gNCiNpZmRlZiBf
X2NwbHVzcGx1cw0KZXh0ZXJuICJDIiB7DQojZW5kaWYNCi8qDQogIHRyYXNoY2FuDQogIENU
IDJrMDEzMA0KICBub24tcmVjdXJzaXZlbHkgZGVzdHJveSBuZXN0ZWQgb2JqZWN0cw0KKi8N
Cg0KRExfSU1QT1JUKHZvaWQpIF9QeV90cmFzaGNhbl9pbnN0YWxsIFB5X1BST1RPKCgpKTsN
Cg0KI2VuZGlmIC8qICFQeV9UUkFTSENBTl9IICov
--------------D9F780CECED602EF245D7526--



From fdrake@acm.org  Mon Jan 31 17:08:11 2000
From: fdrake@acm.org (Fred L. Drake, Jr.)
Date: Mon, 31 Jan 2000 12:08:11 -0500 (EST)
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
In-Reply-To: <Pine.LNX.4.10.10001301925190.24976-100000@server1.lfw.org>
References: <000301bf6b79$4f0c8a60$482d153f@tim>
 <Pine.LNX.4.10.10001301925190.24976-100000@server1.lfw.org>
Message-ID: <14485.49531.600935.643400@weyr.cnri.reston.va.us>

Ka-Ping Yee writes:
 > a scan through a decent chunk of Python would be useful to find out how
 > often this construct (in its "and"/"or" incarnation) actually gets used.

  I'm not sure what the survey provides other than a lower bound.  I
think most Python programmers who want the ?: functionality avoid the
and/or approach because of the ugliness.  I know I do.
  But I'd really like to have the functionality if the syntax is
reasonable!  I could live with something like "if cond then true else
false"; the leading "if" is visually important; without it, you have
to scan over the test expression to find the "then", and that makes it
harder to read.


  -Fred

--
Fred L. Drake, Jr.	  <fdrake at acm.org>
Corporation for National Research Initiatives


From bwarsaw@cnri.reston.va.us (Barry A. Warsaw)  Mon Jan 31 17:33:25 2000
From: bwarsaw@cnri.reston.va.us (Barry A. Warsaw) (Barry A. Warsaw)
Date: Mon, 31 Jan 2000 12:33:25 -0500 (EST)
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
References: <000301bf6b79$4f0c8a60$482d153f@tim>
 <Pine.LNX.4.10.10001301925190.24976-100000@server1.lfw.org>
 <14485.49531.600935.643400@weyr.cnri.reston.va.us>
Message-ID: <14485.51045.97448.830202@anthem.cnri.reston.va.us>

Put me in the camp of "yeah, occasionally I wish I had it, but I can
always hack around it, and the C syntax just blows".  I'm sure if it's
wedgeable into CPython it would also be in JPython, but I dislike ?:
syntax enough to vote strongly against it for CPython 1.6.

A Forth-ish syntax might be more acceptable

    x = y > z if y else z

but come on!  You'll give ordinarily dandruff-free Python programmers
plenty of other reasons to scratch their heads with this one.

head-and-shoulders-above-the-rest-ly y'rs,
-Barry


From gvwilson@nevex.com  Mon Jan 31 17:44:53 2000
From: gvwilson@nevex.com (gvwilson@nevex.com)
Date: Mon, 31 Jan 2000 12:44:53 -0500 (EST)
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
In-Reply-To: <3895A48D.F69B3DFA@digicool.com>
Message-ID: <Pine.LNX.4.10.10001311239400.11154-100000@akbar.nevex.com>

> It (?:) would allow you to incorporate logic into expressions. 
> There are contexts where only expressions are allowed, such as:
>   - lambdas
>   - DTML expr attributes
> in which I'd very much like to incorporate tests.

Don't know much about DTML, but believe that being able to put
conditionals in lambdas would make the latter much more useful.

> > The ?: syntax
> > does not introduce any new "functionality" to the language,
> Yes it does.

Is anything possible with ?: that's impossible without? No --- Python is
Turing-equivalent before and after the change.

Is anything easier with ?: --- yes.

Does this make up for the added complexity?  Dunno (see below).

> > The second qustion I'd ask is, who is this aimed at?  It's certainly not
> > aimed at first-time programmers, as I know from experience that the ?:
> > is one of the hardest things to teach people in C (after pointers),
> Hm. I can't agree.

Strongly agree with the first author --- IME, ?: is very hard to teach.

Greg



From klm@digicool.com  Mon Jan 31 17:58:07 2000
From: klm@digicool.com (Ken Manheimer)
Date: Mon, 31 Jan 2000 12:58:07 -0500 (EST)
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
In-Reply-To: <14485.49531.600935.643400@weyr.cnri.reston.va.us>
Message-ID: <Pine.LNX.4.10.10001311236250.11106-100000@splat.digicool.com>

On Mon, 31 Jan 2000, Fred L. Drake, Jr. wrote:

> Ka-Ping Yee writes:
>  > a scan through a decent chunk of Python would be useful to find out how
>  > often this construct (in its "and"/"or" incarnation) actually gets used.
> 
>   I'm not sure what the survey provides other than a lower bound.  I
> think most Python programmers who want the ?: functionality avoid the
> and/or approach because of the ugliness.  I know I do.

Good point.  Just because the workaround is bad doesn't mean the thing
being worked-around is unimportant...

I should weigh in to say that i have really really wanted, in particular,
the ability to have a condition on the right hand side of an assignement.
IIR, on some occasions it seemed less clear to have to use separate
statements for what was essentially a single assignment that just, eg,
differed by a single term.  I wanted (want) some reasonable way to express
the condition in an expression.  I can see how this compactness could lead
to regex-style convolution of expressions, but that could be avoided by
providing a not-too-terse syntax.

(I should admit that may have succumbed to the (a and (b,) or (c,))[0]
grotesquerie at some point!  Not sure.  Wish i could recall what might
have justified succumbing - the mere fact that i may have, without
compelling justification, might-should disqualify my judgement on the
matter, ay?  Hey, maybe i didn't, i was just imagining it - now am i not a
sterling judge?-)

Ken
klm@digicool.com



From tismer@tismer.com  Mon Jan 31 19:55:36 2000
From: tismer@tismer.com (Christian Tismer)
Date: Mon, 31 Jan 2000 20:55:36 +0100
Subject: [Python-Dev] Ann: Stackless Python 1.02
Message-ID: <3895E8B8.995CA560@tismer.com>

Stackless Python is a Python without C stack usage.
It allows for all kinds of non-local control flow.
For info see http://www.tismer.com/research/stackless/

Update for Stackless Python V. 1.02:

- passes all standard tests
- should work with Zope now (try...finally was incorrect)
- has a smart object destructor for really deeply nested stuff

The "5 percent speedup" is no longer there currently, since
the smart object destructor needs to be optimized into
the objects. It is not done in this test phase but will come.

Please visit the Stackless Python homepage at

http://www.tismer.com/research/stackless/

Fact sheet, links to documentation, source and
binaries can be found there.

cheers - chris

<P><A HREF="http://www.tismer.com/research/stackless/">Stackless
Python 1.02 + Continuations 0.6</A> - a version of Python 1.5.2 that
does not need space on the C stack, and first-class callable
continuation objects for Python.  (31-Jan-2000)

Christian Tismer
Mission Impossible 5oftware Team


From hon2559@orgio.net  Sun Jan  9 01:50:35 2000
From: hon2559@orgio.net (=?ks_c_5601-1987?B?wMy757j0KDI0bWFsbCk=?=)
Date: Sun, 09 Jan 2000 10:50:35 +0900
Subject: [Python-Dev] =?ks_c_5601-1987?B?IsDMu+citbUgx8+w7SAiwaS89rHiIrW1ILnesO0uLi4gW7GksO1d?=
Message-ID: <E16Ciyf-0007ql-00@mail.python.org>

This is a multi-part message in MIME format.

------=_NextPart_000_0107_01C0F09A.93A50C00
Content-Type: text/plain;
	charset="ks_c_5601-1987"
Content-Transfer-Encoding: base64

VW50aXRsZWQgRG9jdW1lbnRBOmFjdGl2ZSB7CUNPTE9SOiAjMDAwMDAwOyBGT05ULVNJWkU6
IDEycHg7IFRFWFQtREVDT1JBVElPTjogbm9uZSB9QTpsaW5rIHsgCUNPTE9SOiAjMDAwMDAw
OyBGT05ULVNJWkU6IDEycHg7IFRFWFQtREVDT1JBVElPTjogbm9uZSB9QTp2aXNpdGVkIHsJ
Q09MT1I6ICMwMDAwMDA7IEZPTlQtU0laRTogMTJweDsgVEVYVC1ERUNPUkFUSU9OOiBub25l
IH1BOmhvdmVyIHsJQ09MT1I6ICMwMDAwMDA7IEZPTlQtU0laRTogMTJweDsgVEVYVC1ERUNP
UkFUSU9OOiBub25lIH1URCB7CUZPTlQtU0laRTogMTJweDsgZm9udC1mYWNlOiCxvLiyIH0g
ICAgICAgICAgICAgICAgICAgv8K288DOILDovuDAuyDHz73FILDtsLS60LXpv6Gw1CC5q7fh
waaw+MfPtMIgvK268b26t84gQS9TILnfu/29wyDAzLvnvvfDvLChIMOlwNPAuyDIuMfHx9K2
pyAgtb++58itwOe/obytIMPWsO0gMTAwMLi4v/ix7sH2ILmwx7C56LvzwLsgx9ggteW4rrTC
ILytuvG9usDUtM+02SAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICDAzLvn
uKYgx9/AuLTPIMH9tenAzLimIMfPseQgx9i+37DatMK1pS4uLr3DsKO1tSAgvviw7SDA2r3F
tbUgvviw7S4uLg0KIMPiwOW/5LiutMIguvG9zrytIL72tc61tSC+yLOqsO0sDQogxKPBpL72
uLa1tSDAzMGoILj4x9G02SDHz73DsO0uLi4NCiANCiDAzMGoILDGwaTHz8H2ILi2vLy/5C4g
ICAgICAgICAgICAgICAgICAgICAgICAgDQq79SC6uLHdwNq4rr+hvK3AxyDD4rnfILH6sv3H
z7DUIL3DwNvHz7y8v+QhIQ0KIMH9vsjAxyCxuLyusbi8riC5rcC6ILanuKYguLuy+8fPsNQg
w7O4rsfYILXluLO0z7TZLg0KIA0KIFvAzLvnw7u80iwgwNTB1sO7vNIsILDFwdbDu7zSXQ0K
ICAgICAgICAgICAgICAgICAgICAgICAgICANCsDMu+e1+7fOISEgv6G+7sTBILX7t84hIQ0K
IA0KIL+hvu7EwSDAzMD8vK268b26IMDMwaggwPy5rrChv80gx9SysiDHz73KvcO/5C4NCiAg
ICAgICAgICAgICAgICAgICAgICAgICAgDQqw7bC0tNTAxyC8scXDu+fH17+hIL7LuMKw1CDA
zLvnvcMgud+7/cfSILz2IMDWtMIgxeu9xcDMwPwgILytuvG9urimILTrx+DH2CC15biutMIg
vK268b26IMDUtM+02S4NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIL7Is+fHz7y8
v+Q/ILTrx9G5zrG5ILTrx6UgwM7FzbPdwMy75yDAzLvnuPQgICh3d3cuMjRtYWxsLmNvLmty
KSDA1LTPtNkuDQogx+O29CC++MDMILjewM/AuyC6uLO7IMHLvNvH1bTPtNkuILHNx8/AxyC4
3sDPwLogwKUgvK3HziDB3yC+y7DUILXIILDNwMy45yANCiDBpLq4IMXrvcW6ziCxx7DtILvn
x9e/oSDAx7DFIFuxpLDtXbfOIMelvcO1yCDIq7q4uN7AzyDA1LTPtNkuDQogDQogwK/AzcfR
IMGkuri287DtILv9sKK1x77uILq4s7uzqiC60sbtwLsgteW3yLTZuOkgvPa9xbDFus64piAg
tK23r8HWvLy/5C4uDQogtNm9xSC6uLO7wfYgvsqw2r3AtM+02S4NCiA=

------=_NextPart_000_0107_01C0F09A.93A50C00
Content-Type: text/html;
	charset="ks_c_5601-1987"
Content-Transfer-Encoding: base64

PGh0bWw+DQo8aGVhZD4NCjx0aXRsZT5VbnRpdGxlZCBEb2N1bWVudDwvdGl0bGU+DQo8bWV0
YSBodHRwLWVxdWl2PSJDb250ZW50LVR5cGUiIGNvbnRlbnQ9InRleHQvaHRtbDsgY2hhcnNl
dD1ldWMta3IiPg0KPFNUWUxFIHR5cGU9dGV4dC9jc3M+DQpBOmFjdGl2ZSB7DQoJQ09MT1I6
ICMwMDAwMDA7IEZPTlQtU0laRTogMTJweDsgVEVYVC1ERUNPUkFUSU9OOiBub25lDQogICAg
ICAgIH0NCkE6bGluayB7IA0KCUNPTE9SOiAjMDAwMDAwOyBGT05ULVNJWkU6IDEycHg7IFRF
WFQtREVDT1JBVElPTjogbm9uZQ0KICAgICAgIH0NCkE6dmlzaXRlZCB7DQoJQ09MT1I6ICMw
MDAwMDA7IEZPTlQtU0laRTogMTJweDsgVEVYVC1ERUNPUkFUSU9OOiBub25lDQogICAgICAg
IH0NCkE6aG92ZXIgew0KCUNPTE9SOiAjMDAwMDAwOyBGT05ULVNJWkU6IDEycHg7IFRFWFQt
REVDT1JBVElPTjogbm9uZQ0KICAgICAgICB9DQpURCB7DQoJRk9OVC1TSVpFOiAxMnB4OyBm
b250LWZhY2U6ILG8uLINCiAgIH0NCjwvc3R5bGU+DQo8L2hlYWQ+DQoNCjxib2R5IGJnY29s
b3I9IiNGRkZGRkYiIHRleHQ9IiMwMDAwMDAiIGxlZnRtYXJnaW49IjAiIHRvcG1hcmdpbj0i
MCIgbWFyZ2lud2lkdGg9IjAiIG1hcmdpbmhlaWdodD0iMCI+DQo8dGFibGUgd2lkdGg9IjYw
MCIgYm9yZGVyPSIwIiBjZWxsc3BhY2luZz0iMCIgY2VsbHBhZGRpbmc9IjAiIGFsaWduPSJj
ZW50ZXIiPg0KICA8dHI+DQogICAgPHRkPjxhIGhyZWY9Imh0dHA6Ly93d3cuMjRtYWxsLmNv
LmtyL21haW4uYXNwP29ra2luZD1tYWlsIiB0YXJnZXQ9Im5ldyI+PGltZyBzcmM9Imh0dHA6
Ly93d3cuMjRtYWxsLmNvLmtyL21haWwvaW1nL2VtYWlsXzEuZ2lmIiB3aWR0aD0iNjAwIiBo
ZWlnaHQ9IjUwIiBuYW1lPSJzZXJ2aWNlIiBib3JkZXI9IjAiPjwvYT48L3RkPg0KICA8L3Ry
Pg0KICA8dHI+DQogICAgPHRkPjxhIGhyZWY9Imh0dHA6Ly93d3cuMjRtYWxsLmNvLmtyL21h
aW4uYXNwP29ra2luZD1tYWlsIiB0YXJnZXQ9Im5ldyI+PGltZyBzcmM9Imh0dHA6Ly93d3cu
MjRtYWxsLmNvLmtyL21haWwvaW1nL2VtYWlsXzIuZ2lmIiB3aWR0aD0iNjAwIiBoZWlnaHQ9
IjE2MiIgYm9yZGVyPSIwIiBuYW1lPSJzZXJ2aWNlIj48L2E+PC90ZD4NCiAgPC90cj4NCiAg
PHRyPg0KICAgIDx0ZCBiYWNrZ3JvdW5kPSJodHRwOi8vd3d3LjI0bWFsbC5jby5rci9tYWls
L2ltZy9lbWFpbF8zLmdpZiIgaGVpZ2h0PSI2MSI+DQogICAgICA8dGFibGUgd2lkdGg9IjU5
MCIgYm9yZGVyPSIwIiBjZWxsc3BhY2luZz0iMCIgY2VsbHBhZGRpbmc9IjAiIGhlaWdodD0i
NjEiPg0KICAgICAgICA8dHI+IA0KICAgICAgICAgIDx0ZCB3aWR0aD0iMTEwIj4mbmJzcDs8
L3RkPg0KICAgICAgICAgIDx0ZCB3aWR0aD0iNDgwIiBoZWlnaHQ9IjI1Ij4mbmJzcDs8L3Rk
Pg0KICAgICAgICA8L3RyPg0KICAgICAgICA8dHI+IA0KICAgICAgICAgIDx0ZCB3aWR0aD0i
MTEwIj4mbmJzcDs8L3RkPg0KICAgICAgICAgIDx0ZCB3aWR0aD0iNDgwIj6/wrbzwM4gsOi+
4MC7IMfPvcUgsO2wtLrQtem/obDUILmrt+HBprD4x8+0wiC8rbrxvbq3ziBBL1Mgud+7/b3D
IMDMu+e+98O8sKEgw6XA08C7IMi4x8fH0ranIA0KICAgICAgICAgICAgtb++58itwOe/obyt
IMPWsO0gMTAwMLi4v/ix7sH2ILmwx7C56LvzwLsgx9ggteW4rrTCILytuvG9usDUtM+02SA8
L3RkPg0KICAgICAgICA8L3RyPg0KICAgICAgPC90YWJsZT4NCiAgICA8L3RkPg0KICA8L3Ry
Pg0KICA8dHI+DQogICAgPHRkPg0KICAgICAgPHRhYmxlIHdpZHRoPSI2MDAiIGJvcmRlcj0i
MCIgY2VsbHNwYWNpbmc9IjAiIGNlbGxwYWRkaW5nPSIwIj4NCiAgICAgICAgPHRyPiANCiAg
ICAgICAgICA8dGQgd2lkdGg9IjQiIGJhY2tncm91bmQ9Imh0dHA6Ly93d3cuMjRtYWxsLmNv
LmtyL21haWwvaW1nL2VtYWlsX2xlZnQuZ2lmIj48L3RkPg0KICAgICAgICAgIDx0ZCB3aWR0
aD0iNTkxIj4gDQogICAgICAgICAgICA8dGFibGUgd2lkdGg9IjU5MSIgYm9yZGVyPSIwIiBj
ZWxsc3BhY2luZz0iMCIgY2VsbHBhZGRpbmc9IjAiPg0KICAgICAgICAgICAgICA8dHI+DQog
ICAgICAgICAgICAgICAgPHRkIGNvbHNwYW49IjMiIGhlaWdodD0iMTAiPjwvdGQ+DQogICAg
ICAgICAgICAgIDwvdHI+DQogICAgICAgICAgICAgIDx0ciBhbGlnbj0iY2VudGVyIj4gDQog
ICAgICAgICAgICAgICAgPHRkIGNvbHNwYW49IjMiIGhlaWdodD0iMjAiPiZuYnNwOzxpbWcg
c3JjPSJodHRwOi8vd3d3LjI0bWFsbC5jby5rci9tYWlsL2ltZy9lbWFpbF90aXRsZS5naWYi
IHdpZHRoPSI0MDAiIGhlaWdodD0iMjIiPjwvdGQ+DQogICAgICAgICAgICAgIDwvdHI+DQog
ICAgICAgICAgICAgIDx0cj4gDQogICAgICAgICAgICAgICAgPHRkIGNvbHNwYW49IjMiIGhl
aWdodD0iMTAiPjwvdGQ+DQogICAgICAgICAgICAgIDwvdHI+DQogICAgICAgICAgICAgIDx0
cj4gDQogICAgICAgICAgICAgICAgPHRkIHdpZHRoPSIxMzEiPjxhIGhyZWY9Imh0dHA6Ly93
d3cuMjRtYWxsLmNvLmtyL21lbnVfYWRkaXRpb24vaG9tZS9kZWZhdWx0LmFzcD9PS2tpbmQ9
bWFpbCIgdGFyZ2V0PSJuZXciPjxpbWcgc3JjPSJodHRwOi8vd3d3LjI0bWFsbC5jby5rci9t
YWlsL2ltZy9lbWFpbF9sXzIuZ2lmIiB3aWR0aD0iMTMxIiBoZWlnaHQ9Ijk1IiBib3JkZXI9
IjAiIG5hbWU9InNlcnZpY2UiPjwvYT48L3RkPg0KICAgICAgICAgICAgICAgIDx0ZCB3aWR0
aD0iNDYwIiBjb2xzcGFuPSIyIj4gDQogICAgICAgICAgICAgICAgICA8dGFibGUgd2lkdGg9
IjQ2MCIgYm9yZGVyPSIwIiBjZWxsc3BhY2luZz0iMCIgY2VsbHBhZGRpbmc9IjAiPg0KICAg
ICAgICAgICAgICAgICAgICA8dHI+IA0KICAgICAgICAgICAgICAgICAgICAgIDx0ZCBjb2xz
cGFuPSIyIiBoZWlnaHQ9IjIzIj48aW1nIHNyYz0iaHR0cDovL3d3dy4yNG1hbGwuY28ua3Iv
bWFpbC9pbWcvZW1haWxfdHh0XzEuZ2lmIiB3aWR0aD0iMjQxIiBoZWlnaHQ9IjIyIj48L3Rk
Pg0KICAgICAgICAgICAgICAgICAgICA8L3RyPg0KICAgICAgICAgICAgICAgICAgICA8dHI+
IA0KICAgICAgICAgICAgICAgICAgICAgIDx0ZCBoZWlnaHQ9IjUiIHdpZHRoPSIyMCI+PC90
ZD4NCiAgICAgICAgICAgICAgICAgICAgICA8dGQgaGVpZ2h0PSI1IiB3aWR0aD0iNDQwIj48
L3RkPg0KICAgICAgICAgICAgICAgICAgICA8L3RyPg0KICAgICAgICAgICAgICAgICAgICA8
dHI+IA0KICAgICAgICAgICAgICAgICAgICAgIDx0ZCB3aWR0aD0iMjAiPiZuYnNwOzwvdGQ+
DQogICAgICAgICAgICAgICAgICAgICAgPHRkIHdpZHRoPSI0NDAiPjxmb250IGNvbG9yPSIj
MzMzMzMzIj7AzLvnuKYgx9/AuLTPIMH9tenAzLimIMfPseQgx9i+37DatMK1pS4uLr3DsKO1
tSANCiAgICAgICAgICAgICAgICAgICAgICAgIL74sO0gwNq9xbW1IL74sO0uLi48YnI+DQog
ICAgICAgICAgICAgICAgICAgICAgICDD4sDlv+S4rrTCILrxvc68rSC+9rXOtbUgvsizqrDt
LDxicj4NCiAgICAgICAgICAgICAgICAgICAgICAgIMSjwaS+9ri2tbUgwMzBqCC4+MfRtNkg
x8+9w7DtLi4uPGJyPg0KICAgICAgICAgICAgICAgICAgICAgICAgPGJyPg0KICAgICAgICAg
ICAgICAgICAgICAgICAgwMzBqCCwxsGkx8/B9iC4try8v+QuPC9mb250PjwvdGQ+DQogICAg
ICAgICAgICAgICAgICAgIDwvdHI+DQogICAgICAgICAgICAgICAgICA8L3RhYmxlPg0KICAg
ICAgICAgICAgICAgIDwvdGQ+DQogICAgICAgICAgICAgIDwvdHI+DQogICAgICAgICAgICAg
IDx0cj4gDQogICAgICAgICAgICAgICAgPHRkIHdpZHRoPSIxMzEiPjxpbWcgc3JjPSJodHRw
Oi8vd3d3LjI0bWFsbC5jby5rci9tYWlsL2ltZy9lbWFpbF9sXzMuZ2lmIiB3aWR0aD0iMTMx
IiBoZWlnaHQ9IjE4Ij48L3RkPg0KICAgICAgICAgICAgICAgIDx0ZCB3aWR0aD0iNDYwIiBj
b2xzcGFuPSIyIj4mbmJzcDs8L3RkPg0KICAgICAgICAgICAgICA8L3RyPg0KICAgICAgICAg
ICAgICA8dHI+IA0KICAgICAgICAgICAgICAgIDx0ZCB3aWR0aD0iMTMxIj48YSBocmVmPSJo
dHRwOi8vd3d3LjI0bWFsbC5jby5rci9tZW51X2FkZGl0aW9uL2NsZWFuL2RlZmF1bHQuYXNw
P29ra2luZD1tYWlsIiB0YXJnZXQ9Im5ldyI+PGltZyBzcmM9Imh0dHA6Ly93d3cuMjRtYWxs
LmNvLmtyL21haWwvaW1nL2VtYWlsX2xfNC5naWYiIHdpZHRoPSIxMzEiIGhlaWdodD0iOTYi
IGJvcmRlcj0iMCIgbmFtZT0ic2VydmljZSI+PC9hPjwvdGQ+DQogICAgICAgICAgICAgICAg
PHRkIHdpZHRoPSI0NjAiIHZhbGlnbj0idG9wIiBjb2xzcGFuPSIyIj4gDQogICAgICAgICAg
ICAgICAgICA8dGFibGUgd2lkdGg9IjQ2MCIgYm9yZGVyPSIwIiBjZWxsc3BhY2luZz0iMCIg
Y2VsbHBhZGRpbmc9IjAiPg0KICAgICAgICAgICAgICAgICAgICA8dHI+IA0KICAgICAgICAg
ICAgICAgICAgICAgIDx0ZCBjb2xzcGFuPSIyIiBoZWlnaHQ9IjIzIj48aW1nIHNyYz0iaHR0
cDovL3d3dy4yNG1hbGwuY28ua3IvbWFpbC9pbWcvZW1haWxfdHh0XzIuZ2lmIiB3aWR0aD0i
MjQxIiBoZWlnaHQ9IjIyIj48L3RkPg0KICAgICAgICAgICAgICAgICAgICA8L3RyPg0KICAg
ICAgICAgICAgICAgICAgICA8dHI+IA0KICAgICAgICAgICAgICAgICAgICAgIDx0ZCBoZWln
aHQ9IjUiIHdpZHRoPSIyMCI+PC90ZD4NCiAgICAgICAgICAgICAgICAgICAgICA8dGQgaGVp
Z2h0PSI1IiB3aWR0aD0iNDQwIj48L3RkPg0KICAgICAgICAgICAgICAgICAgICA8L3RyPg0K
ICAgICAgICAgICAgICAgICAgICA8dHI+IA0KICAgICAgICAgICAgICAgICAgICAgIDx0ZCB3
aWR0aD0iMjAiPiZuYnNwOzwvdGQ+DQogICAgICAgICAgICAgICAgICAgICAgPHRkIHdpZHRo
PSI0NDAiPiANCiAgICAgICAgICAgICAgICAgICAgICAgIDxwPjxmb250IGNvbG9yPSIjMzMz
MzMzIj679SC6uLHdwNq4rr+hvK3AxyDD4rnfILH6sv3Hz7DUIL3DwNvHz7y8v+QhITxicj4N
CiAgICAgICAgICAgICAgICAgICAgICAgICAgwf2+yMDHILG4vK6xuLyuILmtwLogtqe4piC4
u7L7x8+w1CDDs7iux9ggteW4s7TPtNkuPGJyPg0KICAgICAgICAgICAgICAgICAgICAgICAg
ICA8YnI+DQogICAgICAgICAgICAgICAgICAgICAgICAgIFvAzLvnw7u80iwgwNTB1sO7vNIs
ILDFwdbDu7zSXTwvZm9udD48L3A+DQogICAgICAgICAgICAgICAgICAgICAgPC90ZD4NCiAg
ICAgICAgICAgICAgICAgICAgPC90cj4NCiAgICAgICAgICAgICAgICAgIDwvdGFibGU+DQog
ICAgICAgICAgICAgICAgPC90ZD4NCiAgICAgICAgICAgICAgPC90cj4NCiAgICAgICAgICAg
ICAgPHRyPiANCiAgICAgICAgICAgICAgICA8dGQgd2lkdGg9IjEzMSI+PGltZyBzcmM9Imh0
dHA6Ly93d3cuMjRtYWxsLmNvLmtyL21haWwvaW1nL2VtYWlsX2xfNS5naWYiIHdpZHRoPSIx
MzEiIGhlaWdodD0iMTkiPjwvdGQ+DQogICAgICAgICAgICAgICAgPHRkIHdpZHRoPSI0NjAi
IGNvbHNwYW49IjIiPiZuYnNwOzwvdGQ+DQogICAgICAgICAgICAgIDwvdHI+DQogICAgICAg
ICAgICAgIDx0cj4gDQogICAgICAgICAgICAgICAgPHRkIHdpZHRoPSIxMzEiPjxhIGhyZWY9
Imh0dHA6Ly93d3cuMjRtYWxsLmNvLmtyL21lbnVfYWRkaXRpb24vYWlyY29uL2RlZmF1bHQu
YXNwP29ra2luZD1tYWlsIiB0YXJnZXQ9Im5ldyI+PGltZyBzcmM9Imh0dHA6Ly93d3cuMjRt
YWxsLmNvLmtyL21haWwvaW1nL2VtYWlsX2xfNi5naWYiIHdpZHRoPSIxMzEiIGhlaWdodD0i
OTciIGJvcmRlcj0iMCIgbmFtZT0ic2VydmljZSI+PC9hPjwvdGQ+DQogICAgICAgICAgICAg
ICAgPHRkIHdpZHRoPSI0NjAiIHZhbGlnbj0idG9wIiBjb2xzcGFuPSIyIj4gDQogICAgICAg
ICAgICAgICAgICA8dGFibGUgd2lkdGg9IjQ2MCIgYm9yZGVyPSIwIiBjZWxsc3BhY2luZz0i
MCIgY2VsbHBhZGRpbmc9IjAiPg0KICAgICAgICAgICAgICAgICAgICA8dHI+IA0KICAgICAg
ICAgICAgICAgICAgICAgIDx0ZCBjb2xzcGFuPSIyIiBoZWlnaHQ9IjIzIj48aW1nIHNyYz0i
aHR0cDovL3d3dy4yNG1hbGwuY28ua3IvbWFpbC9pbWcvZW1haWxfdHh0XzMuZ2lmIiB3aWR0
aD0iMzAwIiBoZWlnaHQ9IjIyIj48L3RkPg0KICAgICAgICAgICAgICAgICAgICA8L3RyPg0K
ICAgICAgICAgICAgICAgICAgICA8dHI+IA0KICAgICAgICAgICAgICAgICAgICAgIDx0ZCBo
ZWlnaHQ9IjUiIHdpZHRoPSIyMCI+PC90ZD4NCiAgICAgICAgICAgICAgICAgICAgICA8dGQg
aGVpZ2h0PSI1IiB3aWR0aD0iNDQwIj48L3RkPg0KICAgICAgICAgICAgICAgICAgICA8L3Ry
Pg0KICAgICAgICAgICAgICAgICAgICA8dHI+IA0KICAgICAgICAgICAgICAgICAgICAgIDx0
ZCB3aWR0aD0iMjAiPiZuYnNwOzwvdGQ+DQogICAgICAgICAgICAgICAgICAgICAgPHRkIHdp
ZHRoPSI0NDAiPiANCiAgICAgICAgICAgICAgICAgICAgICAgIDxwPjxmb250IGNvbG9yPSIj
MzMzMzMzIj7AzLvntfu3ziEhIL+hvu7EwSC1+7fOISE8YnI+DQogICAgICAgICAgICAgICAg
ICAgICAgICAgIDxicj4NCiAgICAgICAgICAgICAgICAgICAgICAgICAgv6G+7sTBIMDMwPy8
rbrxvbogwMzBqCDA/LmusKG/zSDH1LKyIMfPvcq9w7/kLjwvZm9udD48L3A+DQogICAgICAg
ICAgICAgICAgICAgICAgPC90ZD4NCiAgICAgICAgICAgICAgICAgICAgPC90cj4NCiAgICAg
ICAgICAgICAgICAgIDwvdGFibGU+DQogICAgICAgICAgICAgICAgPC90ZD4NCiAgICAgICAg
ICAgICAgPC90cj4NCiAgICAgICAgICAgICAgPHRyPiANCiAgICAgICAgICAgICAgICA8dGQg
d2lkdGg9IjEzMSI+PGltZyBzcmM9Imh0dHA6Ly93d3cuMjRtYWxsLmNvLmtyL21haWwvaW1n
L2VtYWlsX2xfNy5naWYiIHdpZHRoPSIxMzEiIGhlaWdodD0iMTgiPjwvdGQ+DQogICAgICAg
ICAgICAgICAgPHRkIHdpZHRoPSI0NjAiIGNvbHNwYW49IjIiPiZuYnNwOzwvdGQ+DQogICAg
ICAgICAgICAgIDwvdHI+DQogICAgICAgICAgICAgIDx0cj4gDQogICAgICAgICAgICAgICAg
PHRkIHdpZHRoPSIxMzEiPjxhIGhyZWY9Imh0dHA6Ly93d3cuMjRtYWxsLmNvLmtyL21lbnVf
YWRkaXRpb24vbGluZS9kZWZhdWx0LmFzcD9va2tpbmQ9bWFpbCIgdGFyZ2V0PSJuZXciPjxp
bWcgc3JjPSJodHRwOi8vd3d3LjI0bWFsbC5jby5rci9tYWlsL2ltZy9lbWFpbF9sXzguZ2lm
IiB3aWR0aD0iMTMxIiBoZWlnaHQ9Ijk2IiBib3JkZXI9IjAiIG5hbWU9InNlcnZpY2UiPjwv
YT48L3RkPg0KICAgICAgICAgICAgICAgIDx0ZCB3aWR0aD0iNDYwIiB2YWxpZ249InRvcCIg
Y29sc3Bhbj0iMiI+IA0KICAgICAgICAgICAgICAgICAgPHRhYmxlIHdpZHRoPSI0NjAiIGJv
cmRlcj0iMCIgY2VsbHNwYWNpbmc9IjAiIGNlbGxwYWRkaW5nPSIwIj4NCiAgICAgICAgICAg
ICAgICAgICAgPHRyPiANCiAgICAgICAgICAgICAgICAgICAgICA8dGQgY29sc3Bhbj0iMiIg
aGVpZ2h0PSIyMyI+PGltZyBzcmM9Imh0dHA6Ly93d3cuMjRtYWxsLmNvLmtyL21haWwvaW1n
L2VtYWlsX3R4dF80LmdpZiIgd2lkdGg9IjMwMCIgaGVpZ2h0PSIyMiI+PC90ZD4NCiAgICAg
ICAgICAgICAgICAgICAgPC90cj4NCiAgICAgICAgICAgICAgICAgICAgPHRyPiANCiAgICAg
ICAgICAgICAgICAgICAgICA8dGQgaGVpZ2h0PSI1IiB3aWR0aD0iMjAiPjwvdGQ+DQogICAg
ICAgICAgICAgICAgICAgICAgPHRkIGhlaWdodD0iNSIgd2lkdGg9IjQ0MCI+PC90ZD4NCiAg
ICAgICAgICAgICAgICAgICAgPC90cj4NCiAgICAgICAgICAgICAgICAgICAgPHRyPiANCiAg
ICAgICAgICAgICAgICAgICAgICA8dGQgd2lkdGg9IjIwIj4mbmJzcDs8L3RkPg0KICAgICAg
ICAgICAgICAgICAgICAgIDx0ZCB3aWR0aD0iNDQwIj4gDQogICAgICAgICAgICAgICAgICAg
ICAgICA8cD48Zm9udCBjb2xvcj0iIzMzMzMzMyI+sO2wtLTUwMcgvLHFw7vnx9e/oSC+y7jC
sNQgwMy7573DILnfu/3H0iC89iDA1rTCIMXrvcXAzMD8IA0KICAgICAgICAgICAgICAgICAg
ICAgICAgICC8rbrxvbq4piC068fgx9ggteW4rrTCILytuvG9uiDA1LTPtNkuPC9mb250Pjwv
cD4NCiAgICAgICAgICAgICAgICAgICAgICA8L3RkPg0KICAgICAgICAgICAgICAgICAgICA8
L3RyPg0KICAgICAgICAgICAgICAgICAgPC90YWJsZT4NCiAgICAgICAgICAgICAgICA8L3Rk
Pg0KICAgICAgICAgICAgICA8L3RyPg0KICAgICAgICAgICAgICA8dHI+IA0KICAgICAgICAg
ICAgICAgIDx0ZCB3aWR0aD0iMTMxIiBoZWlnaHQ9IjgwIiBiYWNrZ3JvdW5kPSJodHRwOi8v
d3d3LjI0bWFsbC5jby5rci9tYWlsL2ltZy9lbWFpbF9sXzkuZ2lmIj4mbmJzcDs8L3RkPg0K
ICAgICAgICAgICAgICAgIDx0ZCB3aWR0aD0iMjUwIiBhbGlnbj0icmlnaHQiIGhlaWdodD0i
ODAiPjxhIGhyZWY9Imh0dHA6Ly93d3cuMjRtYWxsLmNvLmtyL21haW4uYXNwP29ra2luZD1t
YWlsIiBvbmZvY3VzID0ndGhpcy5ibHVyKCknIHRhcmdldD0ibmV3Ij48aW1nIHNyYz0iaHR0
cDovL3d3dy4yNG1hbGwuY28ua3IvbWFpbC9pbWcvZW1haWxfcmVxLmdpZiIgd2lkdGg9IjE0
NiIgaGVpZ2h0PSI3NCIgYm9yZGVyPSIwIj48L2E+PC90ZD4NCiAgICAgICAgICAgICAgICA8
dGQgd2lkdGg9IjIxMCI+Jm5ic3A7PC90ZD4NCiAgICAgICAgICAgICAgPC90cj4NCiAgICAg
ICAgICAgICAgPHRyPiANCiAgICAgICAgICAgICAgICA8dGQgd2lkdGg9IjEzMSIgYmFja2dy
b3VuZD0iaHR0cDovL3d3dy4yNG1hbGwuY28ua3IvbWFpbC9pbWcvZW1haWxfbF85LmdpZiI+
Jm5ic3A7PC90ZD4NCiAgICAgICAgICAgICAgICA8dGQgd2lkdGg9IjQ2MCIgY29sc3Bhbj0i
MiI+Jm5ic3A7PC90ZD4NCiAgICAgICAgICAgICAgPC90cj4NCiAgICAgICAgICAgIDwvdGFi
bGU+DQogICAgICAgICAgPC90ZD4NCiAgICAgICAgICA8dGQgd2lkdGg9IjUiIGJhY2tncm91
bmQ9Imh0dHA6Ly93d3cuMjRtYWxsLmNvLmtyL21haWwvaW1nL2VtYWlsX3JpZ2h0LmdpZiI+
PC90ZD4NCiAgICAgICAgPC90cj4NCiAgICAgIDwvdGFibGU+DQogICAgPC90ZD4NCiAgPC90
cj4NCiAgPHRyPg0KICAgIDx0ZD48aW1nIHNyYz0iaHR0cDovL3d3dy4yNG1hbGwuY28ua3Iv
bWFpbC9pbWcvZW1haWxfYnRtLmdpZiIgd2lkdGg9IjYwMCIgaGVpZ2h0PSI0NSI+PC90ZD4N
CiAgPC90cj4NCjwvdGFibGU+DQo8dHI+DQogIDx0ZCBhbGlnbj0iY2VudGVyIiB3aWR0aD0i
NTkyIj4gDQogICAgPHAgYWxpZ249ImNlbnRlciI+IDxmb250IGNvbG9yPSIjMDAwMDAwIiBz
aXplPSIyIj6+yLPnx8+8vL/kPyC068fRuc6xuSC068elIMDOxc2z3cDMu+cgPGEgaHJlZj0i
aHR0cDovL3d3dy4yNG1hbGwuY28ua3IvbWFpbi5hc3A/b2traW5kPW1haWwiPsDMu+e49CAN
CiAgICAgICh3d3cuMjRtYWxsLmNvLmtyKTwvYT4gwNS0z7TZLjxicj4NCiAgICAgIMfjtvQg
vvjAzCC43sDPwLsgurizuyDBy7zbx9W0z7TZLiCxzcfPwMcguN7Az8C6IMClILytx84gwd8g
vsuw1CC1yCCwzcDMuOcgPGJyPg0KICAgICAgwaS6uCDF673Fus4gscew7SC758fXv6EgwMew
xSBbsaSw7V23ziDHpb3DtcggyKu6uLjewM8gwNS0z7TZLjxicj4NCiAgICAgIDxicj4NCiAg
ICAgIMCvwM3H0SDBpLq4tvOw7SC7/bCitce+7iC6uLO7s6ogutLG7cC7ILXlt8i02bjpIDxB
IGhyZWY9Im1haWx0bzpob24yNTU5QG9yZ2lvLm5ldD9zdWJqZWN0Pbz2vcWwxbrOJmFtcDti
b2R5PbjewM+89r3FwLsgsMW6zsfVtM+02SI+PGZvbnQgY29sb3I9IiNGRjAwMDAiPjxiPrz2
vcWwxbrOPC9iPjwvZm9udD48L2E+uKYgDQogICAgICC0rbevwda8vL/kLi48L2ZvbnQ+PC9w
Pg0KICAgIDxwIGFsaWduPSJjZW50ZXIiPjxmb250IGNvbG9yPSIjMDAwMDAwIiBzaXplPSIy
Ij4gtNm9xSC6uLO7wfYgvsqw2r3AtM+02S48L2ZvbnQ+PC9wPg0KICA8L3RkPg0KPC90cj4N
CjwvQk9EWT4NCjwvSFRNTD4=

------=_NextPart_000_0107_01C0F09A.93A50C00--



From tim_one at email.msn.com  Sun Jan  2 06:52:34 2000
From: tim_one at email.msn.com (Tim Peters)
Date: Sun, 2 Jan 2000 00:52:34 -0500
Subject: [Python-Dev] Re: [Distutils] Questions about distutils strategy
In-Reply-To: <199912091617.LAA05742@eric.cnri.reston.va.us>
Message-ID: <000401bf54e5$91587280$1f2d153f@tim>

Briefly backtracking to an old thread:

[Guido]
> ...
> The problem lies in which key is used.  All versions of
> Python 1.5.x (1.5, 1.5.1, 1.5.2) use the same key!  This
> is a main cause of trouble, because it means that different
> versions cannot peacefully live together even if the user
> installs them into different directories -- they will all
> use the registry keys of the last version installed.  This,
> in turn, means that someone who writes a Python application
> that has a dependency on a particular Python version (and
> which application worth distributing doesn't :-) cannot
> trust that if a Python installation is present, it is the
> right one.  But they also cannot simply bundle the standard
> installer for the correct Python version with their program,
> because its installation would overwrite an existing Python
> application, thus breaking some *other* Python apps that
> the user might already have installed.

Right, that's one class of intractable problem under Windows.

*Inside* my workplace, another kind of problem is caused when people try to
make a Python app available over the Windows network.  They stick the Python
they want and its libraries out on the network, with python.exe in the same
directory as the app.  Now some people have highly customized Python setups,
and the network Python picks up "the wrong" site.py etc.  That sucks, and
there appears no sane way to stop it.

Telling internal app distributors they need to invent a unique registry key
and fiddle their python.exe's resources is a non-starter.  Ditto telling
people with highly customized Pythons "don't do that".  Ditto telling anyone
they have to run any sort of installation script just to use a network app
(sometimes they don't even know they're running it! e.g., when it's a
subsystem invoked by another app).

So while everyone is thinking about the hardest possible scenarios, please
give a thought to the dirt simple one too <0.5 wink>:  an app distributor
who knows exactly what they're doing, and for whom *any* magical inference
is simply a barrier to overcome.  The latter can be satisfied by any number
of means, from an envar that says "please don't try to be helpful, *this* is
the directory you look in, and if you don't find stuff there give up" to a
cmdline switch that says the same.  Nothing Windows-specific there -- any OS
with an envar or a cmdline will play along <wink>.

> ...
> I thought a bit about how VB solves this.  I think that when
> you wrap up a VB app in, all the support code (mostly a big
> DLL) is wrapped with it.  When the user runs the installer,
> the DLL is installed (probably in the WINDOWS directory).  If
> a user installs several VB apps built with the same VB
> version, they all attempt to install the exact same DLL; of
> course the installers notice this and optimize it away, keeping
> a reference count.

This is the way most *MS* DLLs work; stuff like the C runtime libraries and
MS database drivers work exactly the same way.  It's rare for pkgs other
than MS's to attempt to use this mechanism, though (the reason is given
below).

> (Ignoring for now the fact that those reference counts don't
> always work!)

?  They work very well, in my experience.  Where they fail is when
installers & uninstallers break the rules.  MS publishes the list of MS DLLs
that are to be treated this way:  an installer "must" use refcounting on the
DLLs in the list.  Alas, some (especially older) installation pkgs don't.
Then the refcounts get screwed up.

That's what makes the mechanism brittle:  "the system" doesn't enforce it,
it relies on universal & intelligent cooperation.  It's very likely that
someone distributing a Python app will neglect (out of ignorance) to bump
the refcount on their Python components, so the refcount will be
artificially low, and a later uninstall of some unrelated pkg that *did*
follow the rules will merrily delete Python.

Gordon and I will repeat this until it sinks in <wink>:  almost everyone
with a successful Windows product ships the non-MS DLLs they rely on and
copies them into their own app directory.  It's simple and it works;
alternatives are complicated and don't work.  Many even ship & copy MS DLLs
(e.g., Scriptics copies its own msvcrt.dll (the MS C runtime) into Tcl's
directories).  Worrying about space consumed by redundant Python components
is a bad case of premature optimization <0.3 wink>.

> ...
> How can we do something similar for Python?

Seriously, short of getting MS to distribute Python and put the Python DLLs
on The List of refcounted resources, we should pursue this line reluctantly
if at all.  MS may have a better scheme in the future, but for now better
safe than sorry.


a-couple-mb-on-a-modern-pc-isn't-worth-the-time-it-took-
    to-read-this<wink>-ly y'rs  - tim





From gstein at lyra.org  Mon Jan  3 03:53:24 2000
From: gstein at lyra.org (Greg Stein)
Date: Sun, 2 Jan 2000 18:53:24 -0800 (PST)
Subject: [Python-Dev] new imputil.py
Message-ID: <Pine.LNX.4.10.10001021838400.412-200000@nebula.lyra.org>

Happy New Year!

I've attached a new imputil.py to this message. It isn't posted on my page
yet, as I'd like some feedback before declaring this new version viable.

In this imputil, there is an ImportManager class. It gets installed as the
import hook, with the presumption that it is the only import hook
(technically, it could chain, but I've disabled that for now). I think
Python 1.6 should drop the __import__ builtin and move to something like
sys.import_hook (to allow examination and change). Another alternative
would be sys.get_import_hook() and sys.set_import_hook().
[ I don't think we would want a "set" that returned the old version as the
  only way to get the current hook function; we want to be able to easily 
  find the ImportManager instance. ]

The ImportManager knows how to scan sys.path when it needs to find a
top-level module/package (e.g. given a.b.c, the "a" is the top-level; b.c
falls "below" that). sys.path can contain strings which specify a
filesystem directory, or it can contain Importer instances.

The manager also records an ordered list of suffix/importer pairs. The
add_suffix() method is used to append new suffixes, but clients can also
access the .suffixes attribute for fine-grained manipulation/ordering.

There is a new importer called _FilesystemImporter which understands how
to look into a directory for Python modules. It borrows/refers to the
ImportManager's .suffixes attribute, using that to find modules in a
directory. This is also the Importer that gets associated with each
filesystem-based module.

The importers used for suffix-based importing are derived from
SuffixImporter. While a function could be used here, future changes will
be easier if we presume class instances.

The new imputil works fine (use _test_revamp() to switch to the new import
mechanism). Importer subclasses using the old imputil should continue to
work, although I am deprecating the 2-tuple return value for get_code().
get_code() should return None or the 3-tuple form now.

I think I still have a bit more work to do, to enable something like
"import a.b.c" where a.zip is an archive on the path and "b.c" resides in
the archive. Note: it *is* possible to do
sys.path.append(ZipImporter(filename)) and have "a.b.c" in the Zip file.
It would simply be nicer to be able to drop arbitrary .zip files onto the
path and use their basename as the top-level name of a package. Anyhow: I
haven't looked at this scenario yet to find what the new system is missing
(if anything).

As always: feedback is more than appreciated! Especially from people using
imputil today. Did I break anything? Does the new scheme still feel right
to you? etc.

Cheers,
-g

p.s. I'd also like to remove PackageArchiveImporter and PackageArchive.
     They don't seem to add any real value. I might move DirectoryImporter
     and PathImporter to an "examples" file, too.

-- 
Greg Stein, http://www.lyra.org/

-------------- next part --------------
#
# imputil.py
#
# Written by Greg Stein. Public Domain.
# No Copyright, no Rights Reserved, and no Warranties.
#
# Utilities to help out with custom import mechanisms.
#
# Additional modifications were contribed by Marc-Andre Lemburg and
# Gordon McMillan.
#
# This module is maintained by Greg and is available at:
#    http://www.lyra.org/greg/python/imputil.py
#
# Since this isn't in the Python distribution yet, we'll use the CVS ID
# for tracking:
#   $Id: imputil.py,v 1.9 2000/01/03 02:38:29 gstein Exp $
#

# note: avoid importing non-builtin modules
import imp
import sys
import strop
import __builtin__

# for the DirectoryImporter
import struct
import marshal

_StringType = type('')
_ModuleType = type(sys)

class ImportManager:
  "Manage the import process."

  def install(self):
    ### warning: Python 1.6 will have a different hook mechanism; this
    ### code will need to change.
    self.__chain_import = __builtin__.__import__
    self.__chain_reload = __builtin__.reload
    __builtin__.__import__ = self._import_hook
    ### fix this
    #__builtin__.reload = None
    #__builtin__.reload = self._reload_hook

  def add_suffix(self, suffix, importer):
    assert isinstance(importer, SuffixImporter)
    self.suffixes.append((suffix, importer))

  ######################################################################
  #
  # PRIVATE METHODS
  #
  def __init__(self):
    # we're definitely going to be importing something in the future,
    # so let's just load the OS-related facilities.
    if not _os_stat:
      _os_bootstrap()

    # Initialize the set of suffixes that we recognize and import.
    # The default will import dynamic-load modules first, followed by
    # .py files (or a .py file's cached bytecode)
    self.suffixes = [ ]
    for desc in imp.get_suffixes():
      if desc[2] == imp.C_EXTENSION:
        self.suffixes.append((desc[0], DynLoadSuffixImporter(desc)))
    self.suffixes.append(('.py', PySuffixImporter()))

    # This is the importer that we use for grabbing stuff from the
    # filesystem. It defines one more method (import_from_dir) for our use.
    self.fs_imp = _FilesystemImporter(self.suffixes)

  def _import_hook(self, fqname, globals=None, locals=None, fromlist=None):
    """Python calls this hook to locate and import a module."""

    parts = strop.split(fqname, '.')

    # determine the context of this import
    parent = self._determine_import_context(globals)

    # if there is a parent, then its importer should manage this import
    if parent:
      module = parent.__importer__._do_import(parent, parts, fromlist)
      if module:
        return module

    # has the top module already been imported?
    try:
      top_module = sys.modules[parts[0]]
    except KeyError:

      # look for the topmost module
      top_module = self._import_top_module(parts[0])
      if not top_module:
        # the topmost module wasn't found at all.
        raise ImportError, 'No module named ' + fqname
        return self.__chain_import(name, globals, locals, fromlist)

    # fast-path simple imports
    if len(parts) == 1:
      if not fromlist:
        return top_module

      if not top_module.__dict__.get('__ispkg__'):
        # __ispkg__ isn't defined (the module was not imported by us), or
        # it is zero.
        #
        # In the former case, there is no way that we could import
        # sub-modules that occur in the fromlist (but we can't raise an
        # error because it may just be names) because we don't know how
        # to deal with packages that were imported by other systems.
        #
        # In the latter case (__ispkg__ == 0), there can't be any sub-
        # modules present, so we can just return.
        #
        # In both cases, since len(parts) == 1, the top_module is also
        # the "bottom" which is the defined return when a fromlist exists.
        return top_module

    importer = top_module.__dict__.get('__importer__')
    if importer:
      return importer._finish_import(top_module, parts[1:], fromlist)

    # If the importer does not exist, then we have to bail. A missing importer
    # means that something else imported the module, and we have no knowledge
    # of how to get sub-modules out of the thing.
    raise ImportError, 'No module named ' + fqname
    return self.__chain_import(name, globals, locals, fromlist)

  def _determine_import_context(self, globals):
    """Returns the context in which a module should be imported.

    The context could be a loaded (package) module and the imported module
    will be looked for within that package. The context could also be None,
    meaning there is no context -- the module should be looked for as a
    "top-level" module.
    """

    if not globals or not globals.get('__importer__'):
      # globals does not refer to one of our modules or packages. That
      # implies there is no relative import context (as far as we are
      # concerned), and it should just pick it off the standard path.
      return None

    # The globals refer to a module or package of ours. It will define
    # the context of the new import. Get the module/package fqname.
    parent_fqname = globals['__name__']

    # if a package is performing the import, then return itself (imports
    # refer to pkg contents)
    if globals['__ispkg__']:
      parent = sys.modules[parent_fqname]
      assert globals is parent.__dict__
      return parent

    i = strop.rfind(parent_fqname, '.')

    # a module outside of a package has no particular import context
    if i == -1:
      return None

    # if a module in a package is performing the import, then return the
    # package (imports refer to siblings)
    parent_fqname = parent_fqname[:i]
    parent = sys.modules[parent_fqname]
    assert parent.__name__ == parent_fqname
    return parent

  def _import_top_module(self, name):
    # scan sys.path looking for a location in the filesystem that contains
    # the module, or an Importer object that can import the module.
    for item in sys.path:
      if type(item) == _StringType:
        module = self.fs_imp.import_from_dir(item, name)
      else:
        module = item.import_top(name)
      if module:
        return module
    return None

  def _reload_hook(self, module):
    "Python calls this hook to reload a module."

    # reloading of a module may or may not be possible (depending on the
    # importer), but at least we can validate that it's ours to reload
    importer = module.__dict__.get('__importer__')
    if not importer:
      return self.__chain_reload(module)

    # okay. it is using the imputil system, and we must delegate it, but
    # we don't know what to do (yet)
    ### we should blast the module dict and do another get_code(). need to
    ### flesh this out and add proper docco...
    raise SystemError, "reload not yet implemented"


class Importer:
  "Base class for replacing standard import functions."

  def install(self):
    sys.path.insert(0, self)

  def import_top(self, name):
    "Import a top-level module."
    return self._import_one(None, name, name)

  ######################################################################
  #
  # PRIVATE METHODS
  #
  def _finish_import(self, top, parts, fromlist):
    # if "a.b.c" was provided, then load the ".b.c" portion down from
    # below the top-level module.
    bottom = self._load_tail(top, parts)

    # if the form is "import a.b.c", then return "a"
    if not fromlist:
      # no fromlist: return the top of the import tree
      return top

    # the top module was imported by self.
    #
    # this means that the bottom module was also imported by self (just
    # now, or in the past and we fetched it from sys.modules).
    #
    # since we imported/handled the bottom module, this means that we can
    # also handle its fromlist (and reliably use __ispkg__).

    # if the bottom node is a package, then (potentially) import some modules.
    #
    # note: if it is not a package, then "fromlist" refers to names in
    #       the bottom module rather than modules.
    # note: for a mix of names and modules in the fromlist, we will
    #       import all modules and insert those into the namespace of
    #       the package module. Python will pick up all fromlist names
    #       from the bottom (package) module; some will be modules that
    #       we imported and stored in the namespace, others are expected
    #       to be present already.
    if bottom.__ispkg__:
      self._import_fromlist(bottom, fromlist)

    # if the form is "from a.b import c, d" then return "b"
    return bottom

  def _import_one(self, parent, modname, fqname):
    "Import a single module."

    # has the module already been imported?
    try:
      return sys.modules[fqname]
    except KeyError:
      pass

    # load the module's code, or fetch the module itself
    result = self.get_code(parent, modname, fqname)
    if result is None:
      return None

    ### backwards-compat
    if len(result) == 2:
      result = result + ({},)

    module = self._process_result(result, fqname)

    # insert the module into its parent
    if parent:
      setattr(parent, modname, module)
    return module

  def _process_result(self, (ispkg, code, values), fqname):
    # did get_code() return an actual module? (rather than a code object)
    is_module = type(code) is _ModuleType

    # use the returned module, or create a new one to exec code into
    if is_module:
      module = code
    else:
      module = imp.new_module(fqname)

    ### record packages a bit differently??
    module.__importer__ = self
    module.__ispkg__ = ispkg

    # insert additional values into the module (before executing the code)
    module.__dict__.update(values)

    # the module is almost ready... make it visible
    sys.modules[fqname] = module

    # execute the code within the module's namespace
    if not is_module:
      exec code in module.__dict__

    return module

  def _load_tail(self, m, parts):
    """Import the rest of the modules, down from the top-level module.

    Returns the last module in the dotted list of modules.
    """
    for part in parts:
      fqname = "%s.%s" % (m.__name__, part)
      m = self._import_one(m, part, fqname)
      if not m:
        raise ImportError, "No module named " + fqname
    return m

  def _import_fromlist(self, package, fromlist):
    'Import any sub-modules in the "from" list.'

    # if '*' is present in the fromlist, then look for the '__all__' variable
    # to find additional items (modules) to import.
    if '*' in fromlist:
      fromlist = list(fromlist) + list(package.__dict__.get('__all__', []))

    for sub in fromlist:
      # if the name is already present, then don't try to import it (it
      # might not be a module!).
      if sub != '*' and not hasattr(package, sub):
        subname = "%s.%s" % (package.__name__, sub)
        submod = self._import_one(package, sub, subname)
        if not submod:
          raise ImportError, "cannot import name " + subname

  def _do_import(self, parent, parts, fromlist):
    """Attempt to import the module relative to parent.

    This method is used when the import context specifies that <self>
    imported the parent module.
    """
    top_name = parts[0]
    top_fqname = parent.__name__ + '.' + top_name
    top_module = self._import_one(parent, top_name, top_fqname)
    if not top_module:
      # this importer and parent could not find the module (relatively)
      return None

    return self._finish_import(top_module, parts[1:], fromlist)

  ######################################################################
  #
  # METHODS TO OVERRIDE
  #
  def get_code(self, parent, modname, fqname):
    """Find and retrieve the code for the given module.

    parent specifies a parent module to define a context for importing. It
    may be None, indicating no particular context for the search.

    modname specifies a single module (not dotted) within the parent.

    fqname specifies the fully-qualified module name. This is a (potentially)
    dotted name from the "root" of the module namespace down to the modname.
    If there is no parent, then modname==fqname.

    This method should return None, or a 3-tuple.

    * If the module was not found, then None should be returned.

    * The first item of the 2- or 3-tuple should be the integer 0 or 1,
      specifying whether the module that was found is a package or not.

    * The second item is the code object for the module (it will be
      executed within the new module's namespace). This item can also
      be a fully-loaded module object (e.g. loaded from a shared lib).

    * The third item is a dictionary of name/value pairs that will be
      inserted into new module before the code object is executed. This
      is provided in case the module's code expects certain values (such
      as where the module was found). When the second item is a module
      object, then these names/values will be inserted *after* the module
      has been loaded/initialized.
    """
    raise RuntimeError, "get_code not implemented"


######################################################################
#
# Some handy stuff for the Importers
#

# byte-compiled file suffic character
_suffix_char = __debug__ and 'c' or 'o'

# byte-compiled file suffix
_suffix = '.py' + _suffix_char

# the C_EXTENSION suffixes
_c_suffixes = filter(lambda x: x[2] == imp.C_EXTENSION, imp.get_suffixes())

def _compile(pathname, timestamp):
  """Compile (and cache) a Python source file.

  The file specified by <pathname> is compiled to a code object and
  returned.

  Presuming the appropriate privileges exist, the bytecodes will be
  saved back to the filesystem for future imports. The source file's
  modification timestamp must be provided as a Long value.
  """
  codestring = open(pathname, 'r').read()
  if codestring and codestring[-1] != '\n':
    codestring = codestring + '\n'
  code = __builtin__.compile(codestring, pathname, 'exec')

  # try to cache the compiled code
  try:
    f = open(pathname + _suffix_char, 'wb')
  except IOError:
    pass
  else:
    f.write('\0\0\0\0')
    f.write(struct.pack('<I', timestamp))
    marshal.dump(code, f)
    f.flush()
    f.seek(0, 0)
    f.write(imp.get_magic())
    f.close()

  return code

_os_stat = _os_path_join = None
def _os_bootstrap():
  "Set up 'os' module replacement functions for use during import bootstrap."

  names = sys.builtin_module_names

  join = None
  if 'posix' in names:
    sep = '/'
    from posix import stat
  elif 'nt' in names:
    sep = '\\'
    from nt import stat
  elif 'dos' in names:
    sep = '\\'
    from dos import stat
  elif 'os2' in names:
    sep = '\\'
    from os2 import stat
  elif 'mac' in names:
    from mac import stat
    def join(a, b):
      if a == '':
        return b
      path = s
      if ':' not in a:
        a = ':' + a
      if a[-1:] <> ':':
        a = a + ':'
      return a + b
  else:
    raise ImportError, 'no os specific module found'
  
  if join is None:
    def join(a, b, sep=sep):
      if a == '':
        return b
      lastchar = a[-1:]
      if lastchar == '/' or lastchar == sep:
        return a + b
      return a + sep + b

  global _os_stat
  _os_stat = stat

  global _os_path_join
  _os_path_join = join

def _os_path_isdir(pathname):
  "Local replacement for os.path.isdir()."
  try:
    s = _os_stat(pathname)
  except OSError:
    return None
  return (s[0] & 0170000) == 0040000

def _timestamp(pathname):
  "Return the file modification time as a Long."
  try:
    s = _os_stat(pathname)
  except OSError:
    return None
  return long(s[8])

def _fs_import(dir, modname, fqname):
  "Fetch a module from the filesystem."

  pathname = _os_path_join(dir, modname)
  if _os_path_isdir(pathname):
    values = { '__pkgdir__' : pathname, '__path__' : [ pathname ] }
    ispkg = 1
    pathname = _os_path_join(pathname, '__init__')
  else:
    values = { }
    ispkg = 0

    # look for dynload modules
    for desc in _c_suffixes:
      file = pathname + desc[0]
      try:
        fp = open(file, desc[1])
      except IOError:
        pass
      else:
        module = imp.load_module(fqname, fp, file, desc)
        values['__file__'] = file
        return 0, module, values

  t_py = _timestamp(pathname + '.py')
  t_pyc = _timestamp(pathname + _suffix)
  if t_py is None and t_pyc is None:
    return None
  code = None
  if t_py is None or (t_pyc is not None and t_pyc >= t_py):
    file = pathname + _suffix
    f = open(file, 'rb')
    if f.read(4) == imp.get_magic():
      t = struct.unpack('<I', f.read(4))[0]
      if t == t_py:
        code = marshal.load(f)
    f.close()
  if code is None:
    file = pathname + '.py'
    code = _compile(file, t_py)

  values['__file__'] = file
  return ispkg, code, values


######################################################################
#
# Simple function-based importer
#
class FuncImporter(Importer):
  "Importer subclass to use a supplied function rather than method overrides."
  def __init__(self, func):
    self.func = func
  def get_code(self, parent, modname, fqname):
    return self.func(parent, modname, fqname)

def install_with(func):
  FuncImporter(func).install()


######################################################################
#
# Base class for archive-based importing
#
class PackageArchiveImporter(Importer):
  """Importer subclass to import from (file) archives.

  This Importer handles imports of the style <archive>.<subfile>, where
  <archive> can be located using a subclass-specific mechanism and the
  <subfile> is found in the archive using a subclass-specific mechanism.

  This class defines two hooks for subclasses: one to locate an archive
  (and possibly return some context for future subfile lookups), and one
  to locate subfiles.
  """

  def get_code(self, parent, modname, fqname):
    if parent:
      # the Importer._finish_import logic ensures that we handle imports
      # under the top level module (package / archive).
      assert parent.__importer__ == self

      # if a parent "package" is provided, then we are importing a sub-file
      # from the archive.
      result = self.get_subfile(parent.__archive__, modname)
      if result is None:
        return None
      if type(result) == type(()):
        return (0,) + result
      return 0, result

    # no parent was provided, so the archive should exist somewhere on the
    # default "path".
    archive = self.get_archive(modname)
    if archive is None:
      return None
    return 1, "", {'__archive__':archive}

  def get_archive(self, modname):
    """Get an archive of modules.

    This method should locate an archive and return a value which can be
    used by get_subfile to load modules from it. The value may be a simple
    pathname, an open file, or a complex object that caches information
    for future imports.

    Return None if the archive was not found.
    """
    raise RuntimeError, "get_archive not implemented"

  def get_subfile(self, archive, modname):
    """Get code from a subfile in the specified archive.

    Given the specified archive (as returned by get_archive()), locate
    and return a code object for the specified module name.

    A 2-tuple may be returned, consisting of a code object and a dict
    of name/values to place into the target module.

    Return None if the subfile was not found.
    """
    raise RuntimeError, "get_subfile not implemented"


class PackageArchive(PackageArchiveImporter):
  "PackageArchiveImporter subclass that refers to a specific archive."

  def __init__(self, modname, archive_pathname):
    self.__modname = modname
    self.__path = archive_pathname

  def get_archive(self, modname):
    if modname == self.__modname:
      return self.__path
    return None

  # get_subfile is passed the full pathname of the archive


######################################################################
#
# Emulate the standard directory-based import mechanism
#
class DirectoryImporter(Importer):
  "Importer subclass to emulate the standard importer."

  def __init__(self, dir):
    self.dir = dir

  def get_code(self, parent, modname, fqname):
    if parent:
      dir = parent.__pkgdir__
    else:
      dir = self.dir

    # defer the loading of OS-related facilities
    if not _os_stat:
      _os_bootstrap()

    # Return the module (and other info) if found in the specified
    # directory. Otherwise, return None.
    return _fs_import(dir, modname, fqname)

  def __repr__(self):
    return '<%s.%s for "%s" at 0x%x>' % (self.__class__.__module__,
                                         self.__class__.__name__,
                                         self.dir,
                                         id(self))

######################################################################
#
# Emulate the standard path-style import mechanism
#
class PathImporter(Importer):
  def __init__(self, path=sys.path):
    self.path = path

    # we're definitely going to be importing something in the future,
    # so let's just load the OS-related facilities.
    if not _os_stat:
      _os_bootstrap()

  def get_code(self, parent, modname, fqname):
    if parent:
      # we are looking for a module inside of a specific package
      return _fs_import(parent.__pkgdir__, modname, fqname)

    # scan sys.path, looking for the requested module
    for dir in self.path:
      result = _fs_import(dir, modname, fqname)
      if result:
        return result

    # not found
    return None


######################################################################
#
# Emulate the import mechanism for builtin and frozen modules
#
class BuiltinImporter(Importer):
  def get_code(self, parent, modname, fqname):
    if parent:
      # these modules definitely do not occur within a package context
      return None

    # look for the module
    if imp.is_builtin(modname):
      type = imp.C_BUILTIN
    elif imp.is_frozen(modname):
      type = imp.PY_FROZEN
    else:
      # not found
      return None

    # got it. now load and return it.
    module = imp.load_module(modname, None, modname, ('', '', type))
    return 0, module, { }


######################################################################
#
# Internal importer used for importing from the filesystem
#
class _FilesystemImporter(Importer):
  def __init__(self, suffixes):
    # this list is shared with the ImportManager.
    self.suffixes = suffixes

  def import_from_dir(self, dir, fqname):
    result = self._import_pathname(_os_path_join(dir, fqname), fqname)
    if result:
      return self._process_result(result, fqname)
    return None

  def get_code(self, parent, modname, fqname):
    # This importer is never used with an empty parent. Its existence is
    # private to the ImportManager. The ImportManager uses the
    # import_from_dir() method to import top-level modules/packages.
    # This method is only used when we look for a module within a package.
    assert parent

    return self._import_pathname(_os_path_join(parent.__pkgdir__, modname),
                                 fqname)

  def _import_pathname(self, pathname, fqname):
    if _os_path_isdir(pathname):
      result = self._import_pathname(_os_path_join(pathname, '__init__'),
                                     fqname)
      if result:
        values = result[2]
        values['__pkgdir__'] = pathname
        values['__path__'] = [ pathname ]
        return 1, result[1], values
      return None

    for suffix, importer in self.suffixes:
      filename = pathname + suffix
      try:
        finfo = _os_stat(filename)
      except OSError:
        pass
      else:
        return importer.import_file(filename, finfo, fqname)
    return None

######################################################################
#
# SUFFIX-BASED IMPORTERS
#

class SuffixImporter:
  def import_file(self, filename, finfo, fqname):
    raise RuntimeError

class PySuffixImporter(SuffixImporter):
  def import_file(self, filename, finfo, fqname):
    file = filename[:-3] + _suffix
    t_py = long(finfo[8])
    t_pyc = _timestamp(file)

    code = None
    if t_pyc is not None and t_pyc >= t_py:
      f = open(file, 'rb')
      if f.read(4) == imp.get_magic():
        t = struct.unpack('<I', f.read(4))[0]
        if t == t_py:
          code = marshal.load(f)
      f.close()
    if code is None:
      file = filename
      code = _compile(file, t_py)

    return 0, code, { '__file__' : file }

class DynLoadSuffixImporter(SuffixImporter):
  def __init__(self, desc):
    self.desc = desc

  def import_file(self, filename, finfo, fqname):
    fp = open(filename, self.desc[1])
    module = imp.load_module(fqname, fp, filename, self.desc)
    module.__file__ = filename
    return 0, module, { }


######################################################################

def _test_dir():
  "Debug/test function to create DirectoryImporters from sys.path."
  path = sys.path[:]
  path.reverse()
  for d in path:
    DirectoryImporter(d).install()

def _test_revamp():
  "Debug/test function for the revamped import system."
  PathImporter().install()
  BuiltinImporter().install()

def _print_importers():
  items = sys.modules.items()
  items.sort()
  for name, module in items:
    if module:
      print name, module.__dict__.get('__importer__', '-- no importer')
    else:
      print name, '-- non-existent module'

def _test_revamp():
  ImportManager().install()
  sys.path.insert(0, BuiltinImporter())

######################################################################

From mal at lemburg.com  Mon Jan  3 13:28:34 2000
From: mal at lemburg.com (M.-A. Lemburg)
Date: Mon, 03 Jan 2000 13:28:34 +0100
Subject: [Python-Dev] new imputil.py
References: <Pine.LNX.4.10.10001021838400.412-200000@nebula.lyra.org>
Message-ID: <387095F2.2FA64D8E@lemburg.com>

Happy New Year :-)

[new imputil.py]

I tried the new module with the following code:

import imputil,sys

if sys.argv[1] != 'standard':
    print 'Installing imputil...',
    imputil.ImportManager().install()
    sys.path.insert(0, imputil.BuiltinImporter())
    print 'done.'
else:
    print 'Using builtin importer.'

print

print 'Importing standard stuff...',
import string,re,os,sys
print 'done.'

print 'Importing mx Extensions...',
from mx import DateTime,TextTools,ODBC,HTMLTools,UID,URL
print 'done.'

###

The new importer does load everything in the test set
(top level modules, packages, extensions within packages)
without problems on Linux.

Some comments:

? Why is the sys.path.insert(0,imputil.BuiltinImporter()) 
needed in order to get b/w compatibility ?

? Why is there no __path__ aware code in imputil.py (this is
definitely needed in order to make it a drop-in replacement) ?

? Performance is still 50% of the Python builtin importer --
a bummer if you ask me. More aggressive caching is definitely
needed, perhaps even some recoding of methods in C.

? The old chaining code should be moved into a subclass of
its own.

? The code should not import strop directly as this module
will probably go away RSN. Use string methods instead.

? The design of the ImportManager has some minor flaws: the
FS importer should be settable via class attributes, deinstallation
should be possible, a query mechanism to find the importer
used by a certain import would also be nice to be able to
verify correct setup.

? py/pyc/pyo file piping hooks would be nice to allow
imports of signed (and trusted) code and/or encrypted code
(a mixin class for these filters would do the trick).

? Wish list: a distutils importer hooked to a list of standard
package repositories, a module to file location mapper to
speed up file system based imports, 

-- 
Marc-Andre Lemburg
______________________________________________________________________
Y2000:                                             Happy New Century !
Business:                                      http://www.lemburg.com/
Python Pages:                           http://www.lemburg.com/python/




From gstein at lyra.org  Mon Jan  3 14:53:00 2000
From: gstein at lyra.org (Greg Stein)
Date: Mon, 3 Jan 2000 05:53:00 -0800 (PST)
Subject: [Python-Dev] new imputil.py
In-Reply-To: <387095F2.2FA64D8E@lemburg.com>
Message-ID: <Pine.LNX.4.10.10001030529560.412-100000@nebula.lyra.org>

Excellent... thanx for the feedback!

Comments:

On Mon, 3 Jan 2000, M.-A. Lemburg wrote:
>...
> The new importer does load everything in the test set
> (top level modules, packages, extensions within packages)
> without problems on Linux.

Great!

> Some comments:
> 
> ? Why is the sys.path.insert(0,imputil.BuiltinImporter()) 
> needed in order to get b/w compatibility ?

Because I didn't want to build too much knowledge into the ImportManager.
Heck, I think adding sys.path removed some of the design elegence; adding
real knowledge of builtins... well, we'll just not talk about that. :-)

We could certainly do it this way; let's see what Guido says. I'm not
truly adverse to it, but I'd recommend against adding a knowledge of
BuiltinImporter to the ImportManager.

> ? Why is there no __path__ aware code in imputil.py (this is
> definitely needed in order to make it a drop-in replacement) ?

Because I don't like __path__ :-)  I don't think it would be too hard to
add, though.

If Guido says we need __path__, then I'll add it. I do believe there was a
poll a while back where he asked whether anybody truly used it. I don't
remember the result and/or Guido's resolution of the matter.

> ? Performance is still 50% of the Python builtin importer --
> a bummer if you ask me. More aggressive caching is definitely
> needed, perhaps even some recoding of methods in C.

I'm scared of caching and the possibility for false positives/negatives.

But yes, it is still slower and could use some analysis and/or recoding
*if* the speed is a problem. Slower imports does not necessarily mean they
are "too slow."

> ? The old chaining code should be moved into a subclass of
> its own.

Good thought. But really: I'd just rather torch it. This kind of depends
on whether we can get away with saying the ImportManager is *the* gateway
between the interpreter and Python-level import hooks. In other words,
will ImportManager be the *only* Python code to ever be allowed to call
sys.set_import_hook() ? If the ImportManager doesn't have to "play with
other import hooks", then the chaining can be removed altogether.

> ? The code should not import strop directly as this module
> will probably go away RSN. Use string methods instead.

Yah. But I'm running this against 1.5.2 :-)

I might be able to do something where the string methods are used if
available, and use the strop module if not.
[ similar to the 'os' bootstrapping that is done ]

Finn Bock emailed me to say that JPython does not have strop, but does
have string methods.

> ? The design of the ImportManager has some minor flaws: the
> FS importer should be settable via class attributes,

The class or the object itself? Putting a class in there would be nice, or
possibly passing it to the constructor (with a suitable default).

This is a good idea, though. Please clarify what you'd like to see, and
I'll get it added.

> deinstallation
> should be possible,

Maybe. This is somewhat dependent upon whether it must "play nice."
Deinstallation would be quite easy if we move to a sys.get/set style of
interface, and it wouldn't be an issue to do de-install code.

> a query mechanism to find the importer
> used by a certain import would also be nice to be able to
> verify correct setup.

module.__importer__ provides the importer that was used. This is defined
behavior (the system relies on that being set to deal with packages
properly).

Is this sufficient, or were you looking for something else?

module.__ispkg__ is also set to 0/1 accordingly.

For backwards compat, __file__ and __path__ are also set. The __all__
attribute in an __init__.py file is used for "from package import *".

> ? py/pyc/pyo file piping hooks would be nice to allow
> imports of signed (and trusted) code and/or encrypted code
> (a mixin class for these filters would do the trick).

I'd happily accept a base SuffixImporter class for these "pipes". I don't
believe that the ImportManager, Importer, or SuffixImporter base classes
would need any changes, though.

Note that I probably will rearrange the _fs_import() and friends, per
Guido's suggestion to move them into a base class. That may be a step
towards having "pipes" available.

> ? Wish list: a distutils importer hooked to a list of standard
> package repositories, a module to file location mapper to
> speed up file system based imports, 

I'm not sure what the former would do. distutils is still a little
nebulous to me right now.

For a mapper, we can definitely have a custom Importer that knows where
certain modules are found. However, I suspect you're looking for some kind
of a cache, but there isn't a hook to say "I found <foo> at <this>
location" (which would be used to build the mapping).

Suggestions on both of these would be most welcome!

Cheers,
-g

-- 
Greg Stein, http://www.lyra.org/




From gvwilson at nevex.com  Mon Jan  3 15:02:32 2000
From: gvwilson at nevex.com (gvwilson at nevex.com)
Date: Mon, 3 Jan 2000 09:02:32 -0500 (EST)
Subject: [Python-Dev] Software Carpentry: GUI Toolkit?
Message-ID: <Pine.LNX.4.10.10001030852190.20692-100000@akbar.nevex.com>

Hi, folks.  I'm putting together guidelines for submissions to the
Software Carpentry design competition (www.software-carpentry.com), and
would like to know what I should recommend as a Python GUI toolkit.  As I
understand it, the alternatives are:

- Tkinter: the "standard" answer, but many people think it's showing its
  age, and it's an installation and update headaches because of its Tcl
  dependencies.

- some other GUI toolkit: but there's no consensus on which one, and
  documentation is lacking.

- CGI scripts (i.e. all interfaces are web pages): has the virtue of
  simplicity, but could also make some useful interfaces difficult to
  build (e.g. no drag and drop), and would require users to run a server,
  or at least get exec privileges, which can be an installation headache.

If I've missed a good answer, or if there's somewhere else I should look
for a solution, I'd be grateful for a pointer.

Thanks,
Greg





From jim at interet.com  Mon Jan  3 15:31:53 2000
From: jim at interet.com (James C. Ahlstrom)
Date: Mon, 03 Jan 2000 09:31:53 -0500
Subject: [Python-Dev] new imputil.py
References: <Pine.LNX.4.10.10001021838400.412-200000@nebula.lyra.org>
Message-ID: <3870B2D9.31D0D350@interet.com>

Greg Stein wrote:

> I've attached a new imputil.py to this message. It isn't posted on my page

I don't think you should be using "public domain" as a
copyright because you should be protecting the code.
Better to use "all rights transferred to CNRI pursuant
to the Python contribution agreement", or just copyright
it yourself for now.

You didn't incorporate the ZipImporter in
  ftp://ftp.interet.com/pub/importer.py
Is that because you want me to, or doesn't it work?

JimA



From gmcm at hypernet.com  Mon Jan  3 15:38:11 2000
From: gmcm at hypernet.com (Gordon McMillan)
Date: Mon, 3 Jan 2000 09:38:11 -0500
Subject: [Python-Dev] new imputil.py
In-Reply-To: <Pine.LNX.4.10.10001030529560.412-100000@nebula.lyra.org>
References: <387095F2.2FA64D8E@lemburg.com>
Message-ID: <1265213088-25101227@hypernet.com>

Greg Stein wrote:
> On Mon, 3 Jan 2000, M.-A. Lemburg wrote:
[big snip]
> > ? Wish list: a distutils importer hooked to a list of standard
> > package repositories, a module to file location mapper to speed
> > up file system based imports, 

> For a mapper, we can definitely have a custom Importer that knows
> where certain modules are found. However, I suspect you're
> looking for some kind of a cache, but there isn't a hook to say
> "I found <foo> at <this> location" (which would be used to build
> the mapping).
> 
> Suggestions on both of these would be most welcome!

Haven't played with the new one yet. But for awhile I've been 
considering a scheme where sys.path[0] has a cache of 
known binary extensions { logicalname: fullpath, ... } and 
sys.path[-1] is the brute force importer.

For standalones, sys.path[0] could be hardcoded. For normal 
installations, sys.path[-1] could inform sys.path[0] when a .so 
/ .dll / .pyd is found. So when a new one is installed, the first 
use will be expensive, but subsequent sessions would import 
it in 1 I/O.

I'd also like to point out that archives *can* be used in a 
development situation. Obviously I wouldn't bother putting a 
module under current development into an archive. But if the 
source is still installed and you haven't mucked with the 
__file__ attribute when you put it in the archive, then 
tracebacks will show you what you need. IDLE doesn't know 
the difference. So for most developers, the standard library 
can be served from an archive with no effect (other than speed).

- Gordon



From gstein at lyra.org  Mon Jan  3 15:57:35 2000
From: gstein at lyra.org (Greg Stein)
Date: Mon, 3 Jan 2000 06:57:35 -0800 (PST)
Subject: [Python-Dev] new imputil.py
In-Reply-To: <3870B2D9.31D0D350@interet.com>
Message-ID: <Pine.LNX.4.10.10001030651260.412-100000@nebula.lyra.org>

On Mon, 3 Jan 2000, James C. Ahlstrom wrote:
> Greg Stein wrote:
> > I've attached a new imputil.py to this message. It isn't posted on my page
> 
> I don't think you should be using "public domain" as a
> copyright because you should be protecting the code.
> Better to use "all rights transferred to CNRI pursuant
> to the Python contribution agreement", or just copyright
> it yourself for now.

Public Domain means there are no copyrights on the code. Anybody can claim
copyright to it. Anybody can start with my version, slap their name and
license on it, and do as they wish. There isn't a way for anybody to
"control" public domain software, so there is no need for protection.

I like to use Public Domain for code that I want to see as broadly used as
possible and/or for short things. There is also a lot that I just don't
care what happens with it. If I don't have a vested interest in something,
then PD is fine.

I wrote imputil as a tool for myself. It isn't something that I feel a
need to keep my name on it -- it works for me, it does what I want, it
doesn't matter what others do it. It does matter than other people *can*
do stuff with it, and PD gives them the most options.

Shades of grey... hard to fully explain in an email... but that's the
general sentiment. I've got a few things under other licenses, but PD
seemed best for imputil.

> You didn't incorporate the ZipImporter in
>   ftp://ftp.interet.com/pub/importer.py
> Is that because you want me to, or doesn't it work?

I had the redesign to do first. When that settles towards something that
Guido is happy with (or he has decided to punt the design altogether),
then I'll integrate the ZipImporter.

Cheers,
-g

-- 
Greg Stein, http://www.lyra.org/




From fdrake at acm.org  Mon Jan  3 21:05:22 2000
From: fdrake at acm.org (Fred L. Drake, Jr.)
Date: Mon, 3 Jan 2000 15:05:22 -0500 (EST)
Subject: [Python-Dev] new imputil.py
In-Reply-To: <1265213088-25101227@hypernet.com>
References: <387095F2.2FA64D8E@lemburg.com>
	<1265213088-25101227@hypernet.com>
Message-ID: <14449.258.374018.919406@weyr.cnri.reston.va.us>

Gordon McMillan writes:
 > I'd also like to point out that archives *can* be used in a 
 > development situation. Obviously I wouldn't bother putting a 
 > module under current development into an archive. But if the 
 > source is still installed and you haven't mucked with the 
 > __file__ attribute when you put it in the archive, then 
 > tracebacks will show you what you need. IDLE doesn't know 
 > the difference. So for most developers, the standard library 
 > can be served from an archive with no effect (other than speed).

  I don't see why we can't just add the source to the archive as well; 
this would allow proper tracebacks even outside the development of the 
library.  Not including sources would cleanly result in the same
situation as we currently see when there's only a .pyc file.
  Am I missing something fundamental?


  -Fred

--
Fred L. Drake, Jr.	  <fdrake at acm.org>
Corporation for National Research Initiatives



From mal at lemburg.com  Mon Jan  3 19:22:02 2000
From: mal at lemburg.com (M.-A. Lemburg)
Date: Mon, 03 Jan 2000 19:22:02 +0100
Subject: [Python-Dev] Better text processing support in py2k?
References: <000901bf53e1$eb4248c0$472d153f@tim>
Message-ID: <3870E8CA.7294B813@lemburg.com>

Tim Peters wrote:
> 
> >> This is why I do complex string processing in Icon <0.9 wink>.
> 
> [MAL]
> > You can have all that extra magic via callable tag objects
> > or callable matching functions. It's not exactly nice to
> > write, but I'm sure that a meta-language could do the
> > conversions for you.
> 
> That wasn't my point:  I do it in Icon because it *is* "exactly nice to
> write", and doesn't require any yet-another meta-language.  It's all
> straightforward, in a way that separate schemes pasted together can never be
> (simply because they *are* "separate schemes pasted together" <wink>).
>
> The point of my Python examples wasn't that they could do something
> mxTextTools can't do, but that they were *Python* examples:  every variation
> I mentioned (or that you're likely to think of) was easy to handle for any
> Python programmer because the "control flow" and "data type" etc aspects
> could be handled exactly the way they always are in *non* pattern-matching
> Python code too, rather than recoded in pattern-scheme-specific different
> ways (e.g., where I had a vanailla "if/break", you set up a special
> exception to tickle the matching engine).
> 
> I'm not attacking mxTextTools, so don't feel compelled to defend it --

Oh, I wasn't defending it -- I know that it is cryptic and sometimes
a pain to use. But given that you don't have to invoke a C compiler
to get a raw speed I find it a rather useful alternative to code
fast utility functions which would otherwise have to be written
in C.

The other reason it exists is simply because I don't like the
recursive style of regexps too much. mxTextTools is simple
and straightforward. Backtracking is still possible, but not
recommended.

> people using regexps in those examples are dead in the water.  mxTextTools
> is very good at what it does; if we have a real disagreement, it's probably
> that I'm less optimistic about the prospects for higher-level wrappers
> (e.g., MikeF's SimpleParse is much slower than "a real" BNF parsing system
> (ARBNFPS), in part because he isn't doing all the optimizations ARBNFPS
> does, but also in part because ARBNFPS uses an underlying engine more
> optimized to its specific task than mxTextTool's more-general engine *can*
> be).  So I don't see mxTextTools as being the answer to everything -- and if
> you hadn't written it, you would agree with that on first glance <wink>.

Oh, I'm sure it *is* the answer to all out problems ;-) ...

def main(*dummy):
    ...

from mx.TextTools import *
tag("",((main, Skip + CallTag, 0),))
 
> > Anyway, I'll keep focussing on the speed aspect of mxTextTools;
> > others can focus on abstractions, so that eventually everybody
> > will be happy :-)
> 
> You and I will be, anyway <wink>.

Happy New Year :-)
-- 
Marc-Andre Lemburg
______________________________________________________________________
Y2000:                                             Happy New Century !
Business:                                      http://www.lemburg.com/
Python Pages:                           http://www.lemburg.com/python/





From mal at lemburg.com  Tue Jan  4 19:36:00 2000
From: mal at lemburg.com (M.-A. Lemburg)
Date: Tue, 04 Jan 2000 19:36:00 +0100
Subject: [Python-Dev] new imputil.py
References: <Pine.LNX.4.10.10001030529560.412-100000@nebula.lyra.org>
Message-ID: <38723D90.D2AE1CA4@lemburg.com>

Greg Stein wrote:
> 
> Comments:
> 
> On Mon, 3 Jan 2000, M.-A. Lemburg wrote:
> >...
> > The new importer does load everything in the test set
> > (top level modules, packages, extensions within packages)
> > without problems on Linux.
> 
> Great!
> 
> > Some comments:
> >
> > ? Why is the sys.path.insert(0,imputil.BuiltinImporter())
> > needed in order to get b/w compatibility ?
> 
> Because I didn't want to build too much knowledge into the ImportManager.
> Heck, I think adding sys.path removed some of the design elegence; adding
> real knowledge of builtins... well, we'll just not talk about that. :-)
> 
> We could certainly do it this way; let's see what Guido says. I'm not
> truly adverse to it, but I'd recommend against adding a knowledge of
> BuiltinImporter to the ImportManager.

I was under the impression that the ImportManager should replace
the current implementation. In that light it should of course
provide all the needed techniques per default without the
need to tweak sys.path.

> > ? Why is there no __path__ aware code in imputil.py (this is
> > definitely needed in order to make it a drop-in replacement) ?
> 
> Because I don't like __path__ :-)  I don't think it would be too hard to
> add, though.
> 
> If Guido says we need __path__, then I'll add it. I do believe there was a
> poll a while back where he asked whether anybody truly used it. I don't
> remember the result and/or Guido's resolution of the matter.

AFAIK, JimF is using it in Zope. I will use it in the
b/w compatibility package for the soon to be released
mx Extensions packages (instead of using relative imports,
BTW -- can't wait for those to happen).
 
> > ? Performance is still 50% of the Python builtin importer --
> > a bummer if you ask me. More aggressive caching is definitely
> > needed, perhaps even some recoding of methods in C.
> 
> I'm scared of caching and the possibility for false positives/negatives.
> 
> But yes, it is still slower and could use some analysis and/or recoding
> *if* the speed is a problem. Slower imports does not necessarily mean they
> are "too slow."

There has been some moaning about the current Python startup
speed, so I guess people already find the existing strategy
too slow.
 
Anyway, put the cache risks into the user's hands and have
them decide whether or not to use them. The important thing
is providing a standard approach to caching which all
importers can use and hook into rather than having three
or four separate cache implementations.

> > ? The old chaining code should be moved into a subclass of
> > its own.
> 
> Good thought. But really: I'd just rather torch it. This kind of depends
> on whether we can get away with saying the ImportManager is *the* gateway
> between the interpreter and Python-level import hooks. In other words,
> will ImportManager be the *only* Python code to ever be allowed to call
> sys.set_import_hook() ? If the ImportManager doesn't have to "play with
> other import hooks", then the chaining can be removed altogether.

Hmm, nuking the chains might cause some problems with code
using the old ni.py or other code such as my old ClassModules.py
module which emulates modules using classes (provides all the
cool __getattr__ and __setattr__ features to modules as well).
 
> > ? The code should not import strop directly as this module
> > will probably go away RSN. Use string methods instead.
> 
> Yah. But I'm running this against 1.5.2 :-)
> 
> I might be able to do something where the string methods are used if
> available, and use the strop module if not.
> [ similar to the 'os' bootstrapping that is done ]
> 
> Finn Bock emailed me to say that JPython does not have strop, but does
> have string methods.

Since imputil.py targets 1.6 you can safely assume that string
methods are in place.
 
> > ? The design of the ImportManager has some minor flaws: the
> > FS importer should be settable via class attributes,
> 
> The class or the object itself? Putting a class in there would be nice, or
> possibly passing it to the constructor (with a suitable default).
> 
> This is a good idea, though. Please clarify what you'd like to see, and
> I'll get it added.

I usually put these things into the class so that subclasses
can easily override the setting.
 
> > deinstallation
> > should be possible,
> 
> Maybe. This is somewhat dependent upon whether it must "play nice."
> Deinstallation would be quite easy if we move to a sys.get/set style of
> interface, and it wouldn't be an issue to do de-install code.

I was thinking mainly of debugging situations where you play
around with new importer code -- its probably not important
for production code.

> > a query mechanism to find the importer
> > used by a certain import would also be nice to be able to
> > verify correct setup.
> 
> module.__importer__ provides the importer that was used. This is defined
> behavior (the system relies on that being set to deal with packages
> properly).
> 
> Is this sufficient, or were you looking for something else?

I was thinking of a situations like:

if <RelativeImporter is not installed>:
   <install RelativeImporter>

or

if <need SignedModuleImporter for modules xyz>:
   raise SystemError,'wrong setup'

Don't know if these queries are possible with the current
flags and attributes.
 
> module.__ispkg__ is also set to 0/1 accordingly.
> 
> For backwards compat, __file__ and __path__ are also set. The __all__
> attribute in an __init__.py file is used for "from package import *".
> 
> > ? py/pyc/pyo file piping hooks would be nice to allow
> > imports of signed (and trusted) code and/or encrypted code
> > (a mixin class for these filters would do the trick).
> 
> I'd happily accept a base SuffixImporter class for these "pipes". I don't
> believe that the ImportManager, Importer, or SuffixImporter base classes
> would need any changes, though.
> 
> Note that I probably will rearrange the _fs_import() and friends, per
> Guido's suggestion to move them into a base class. That may be a step
> towards having "pipes" available.

It would be nice to be able to use the concept of stackable streams
as source for byte and source code. For this to work one would have
to make the file reading process a little more abstract by using e.g. a
StreamReader instead (see the current unicode-proposal.txt version).

> > ? Wish list: a distutils importer hooked to a list of standard
> > package repositories, a module to file location mapper to
> > speed up file system based imports,
> 
> I'm not sure what the former would do. distutils is still a little
> nebulous to me right now.

Basically it should scan a set of URLs providing access to
package repositories which hold distutils installable package
archives. In case it finds a suitable package it should then
proceed to auto-install it and then continue the normal import
process.

> For a mapper, we can definitely have a custom Importer that knows where
> certain modules are found. However, I suspect you're looking for some kind
> of a cache, but there isn't a hook to say "I found <foo> at <this>
> location" (which would be used to build the mapping).

Right. I would like to see some standard mechanism used
throughout the ImportManager for this. One which all importers
can use and rely on. E.g. it would be nice to have an option
to load the cache from disk upon startup to reduce search times.
All this should be left for the user to configure with the
standard setting being no cache at all (to avoid confusion
and reduce support costs ;-).

-- 
Marc-Andre Lemburg
______________________________________________________________________
Y2000:                                             Happy New Century !
Business:                                      http://www.lemburg.com/
Python Pages:                           http://www.lemburg.com/python/




From bwarsaw at cnri.reston.va.us  Tue Jan  4 22:04:48 2000
From: bwarsaw at cnri.reston.va.us (Barry A. Warsaw)
Date: Tue, 4 Jan 2000 16:04:48 -0500 (EST)
Subject: [Python-Dev] new imputil.py
References: <Pine.LNX.4.10.10001021838400.412-200000@nebula.lyra.org>
Message-ID: <14450.24688.492098.917284@anthem.cnri.reston.va.us>

Happy New Year!

>>>>> "GS" == Greg Stein <gstein at lyra.org> writes:

    GS> I think Python 1.6 should drop the __import__ builtin and move
    GS> to something like sys.import_hook (to allow examination and
    GS> change).

Wait!  You can't remove builtin __import__ without breaking code.
E.g. Mailman uses __import__ quite a bit in its CGI (and other)
harnesses.  Why does __import__ need to be removed?  Why can't it just
just the same mechanism the import statement uses?

    GS> I might be able to do something where the string methods are
    GS> used if available, and use the strop module if not.  [ similar
    GS> to the 'os' bootstrapping that is done ]

    GS> Finn Bock emailed me to say that JPython does not have strop,
    GS> but does have string methods.

Sorry Greg, I haven't had time to look at this stuff at all, so maybe
I'm missing something essential, but if you just continue to use the
string module, you'll be fine for JPython and CPython 1.5.2.  In
CPython 1.5.2, you /will/ actually be using the strop module
under the covers.

In CPython 1.6 and JPython 1.1 you'll be using string methods under
the covers.  Your penalty is one layer of Python function calls.
Never use strop directly though.

>>>>> "MA" == M  <mal at lemburg.com> writes:

    MA> There has been some moaning about the current Python startup
    MA> speed, so I guess people already find the existing strategy
    MA> too slow.
 
Definitely.

-Barry



From gmcm at hypernet.com  Wed Jan  5 04:49:08 2000
From: gmcm at hypernet.com (Gordon McMillan)
Date: Tue, 4 Jan 2000 22:49:08 -0500
Subject: [Python-Dev] new imputil.py
In-Reply-To: <14449.258.374018.919406@weyr.cnri.reston.va.us>
References: <1265213088-25101227@hypernet.com>
Message-ID: <1265079245-1617919@hypernet.com>

Fred L. Drake, Jr.wrote:

> Gordon McMillan writes:
>  > I'd also like to point out that archives *can* be used in a >
>  development situation. Obviously I wouldn't bother putting a >
>  module under current development into an archive. But if the >
>  source is still installed and you haven't mucked with the >
>  __file__ attribute when you put it in the archive, then >
>  tracebacks will show you what you need. IDLE doesn't know > the
>  difference. So for most developers, the standard library > can
>  be served from an archive with no effect (other than speed).
> 
>   I don't see why we can't just add the source to the archive as
>   well; 
> this would allow proper tracebacks even outside the development
> of the library.  Not including sources would cleanly result in
> the same situation as we currently see when there's only a .pyc
> file.
>   Am I missing something fundamental?

Sure you could. Then you could patch IDLE, Pythonwin, etc. 
to open the proper archive and extract the source. Then you 
could patch them (and archive) to update on the fly.

And while you're at it, I'd really like a jacuzzi jet that gets my 
neck and shoulders without having to scrunch into all kinds of 
strange positions.

- Gordon


Return-Path: <owner-python-dev at python.org>
Delivered-To: python-dev at dinsdale.python.org
Received: from python.org (parrot.python.org [132.151.1.90])
	by dinsdale.python.org (Postfix) with ESMTP id A76701CD65
	for <python-dev at dinsdale.python.org>; Fri, 14 Jan 2000 12:39:29 -0500 (EST)
Received: from merlin.codesourcery.com (IDENT:qmailr@[206.168.99.1])
	by python.org (8.9.1a/8.9.1) with SMTP id MAA17463
	for <python-dev at python.org>; Fri, 14 Jan 2000 12:39:29 -0500 (EST)
Received: (qmail 2115 invoked by uid 513); 14 Jan 2000 17:44:23 -0000
Mailing-List: contact publicity-help at software-carpentry.com; run by ezmlm
Delivered-To: mailing list publicity at software-carpentry.com
Received: (qmail 2110 invoked from network); 14 Jan 2000 17:44:19 -0000
Date: Fri, 14 Jan 2000 12:40:13 -0500 (EST)
From: gvwilson at nevex.com
To: publicity at software-carpentry.com
Message-ID: <Pine.LNX.4.10.10001141228191.8785-100001 at akbar.nevex.com>
MIME-Version: 1.0
Content-Type: MULTIPART/MIXED; BOUNDARY="168427786-1646135556-947871613=:8785"
Subject: [Python-Dev] ANNOUNCEMENT: Open Source Design Competition
Sender: python-dev-admin at python.org
Errors-To: python-dev-admin at python.org
X-BeenThere: python-dev at python.org
X-Mailman-Version: 1.2 (experimental)
Precedence: bulk
List-Id: Python core developers <python-dev.python.org>

  This message is in MIME format.  The first part should be readable text,
  while the remaining parts are likely unreadable without MIME-aware tools.
  Send mail to mime at docserver.cac.washington.edu for more info.

--168427786-1646135556-947871613=:8785
Content-Type: TEXT/PLAIN; charset=US-ASCII

The Software Carpentry project is pleased to announce the launch of its
first Open Source design competition.  The project's logo is attached, and
details of the competition are included below.

This message is being sent to you because you have expressed an interest
in covering this story, or publicizing this project.  If you have any
questions, or do not wish to receive future notices about Software
Carpentry, please contact:

    Dr. Gregory V. Wilson
    Software Carpentry Project Coordinator
    (416) 593 2428
    gvwilson at software-carpentry.com

Thanks for your interest!

Greg Wilson

----------------------------------------------------------------------
----------------------------------------------------------------------

Los Alamos National Laboratory                     Code Sourcery, LLC

                          Software Carpentry

		    Open Source Design Competition

			 $100,000 in Prizes!

----------------------------------------------------------------------

The Software Carpentry project is pleased to announce its first Open
Source design competition, with prizes totaling $100,000.  Students
and professionals from any country, working individually or in teams,
are invited to submit design outlines for:

* a platform inspection tool to replace autoconf;

* a dependency management tool to replace make;

* an issue tracking system to replace gnats and Bugzilla; and

* a unit and regression testing harness with the functionality of
  XUnit, Expect, and DejaGnu.

Participants may submit separate entries in one or more categories by
March 31, 2000.  Entries must be in English, and no more than 5000
words long; examples are available at http://www.software-carpentry.com.

The competition will be judged by a panel that includes the following
noted software developers, authors, and computational scientists:

    Stephen Adler       Brookhaven National Laboratory
    Frank Alexander     Los Alamos National Laboratory
    Donnie Barnes       Red Hat
    Chris DiBona        VA Linux
    Paul Dubois         Lawrence Livermore National Laboratory
    Andrew Hunt         Pragmatic Programmers, LLC
    Stephen R. Lee      Los Alamos National Laboratory
    Josh MacDonald      University of California, Berkeley
    Brian Marick        Reliable Software Technologies
    Doug Mewhort        Queen's University
    Bruce Perens        co-founder of the Open Source Initiative
    Dave Thomas         Pragmatic Programmers, LLC
    Jon Udell           author of Practical Internet Groupware
    Guido van Rossum    inventor of Python
    Tom Van Vleck       TransIlluminant
    Phil Wadler         Bell Labs
    Scot Wingo          AuctionRover

The best four entries in each category will be awarded $2500, and
invited to submit full designs by June 1, 2000.  The best design in
each category will then receive an additional $7500, while runners-up
will each receive $2500.  Once winning designs have been announced,
$200,000 will be available through open bidding for implementation,
testing, and documentation.

All of the project's work will be Open Source; all tools will be
written in, or scriptable with, Python, and will be required to run on
both Linux and Microsoft Windows NT.

----------------------------------------------------------------------

The Software Carpentry project is sponsored by the Advanced Computing
Laboratory at the U.S. Department of Energy's Los Alamos National
Laboratory (http://www.acl.lanl.gov), and administered by Code 
Sourcery, LLC (http://www.codesourcery.com).  The project's aim
is to encourage adoption of better software development practices by
making software tools easier to use, and by documenting design,
testing, and related activities.  For more information on the project,
or to let us know that you intend to submit a proposal, see
http://www.software-carpentry.com, or mail info at software-carpentry.com.


--168427786-1646135556-947871613=:8785
Content-Type: IMAGE/GIF; name="software-carpentry-logo.gif"
Content-Transfer-Encoding: BASE64
Content-ID: <Pine.LNX.4.10.10001141240130.8785 at akbar.nevex.com>
Content-Description: 
Content-Disposition: attachment; filename="software-carpentry-logo.gif"

R0lGODlhLAGhANX/AIACFYU8R2RkZqWlp0pKS+np6tXV1snJyr+/wLW2u+Dh
5srM1Pf4/PT1+e7v877Ax4GDiZygq6Sos4yPl5aZobm7wNrc4aywuXF0efv8
/M7PzywtLJF8U0s4F6mTa76pgXBeQE0+LeDb2M7JxsfAvaCPi7yysJBxb7Ge
nf////7+/v39/fv7+/n5+fj4+Pb29vPz8/Ly8u/v7+3t7ebm5uLi4t3d3dnZ
2dLS0sXFxa6urh4eHg8PDwgICAMDAwAAACwAAAAALAGhAEAG/8CUcEgsGo/I
pHLJbDqf0Kh0Sq1ar9isdsvter/gsFipcjXLQ1aBhtDg3m/NLdN0rZotVpPV
aq7MTH9OLipFOSgxRXZ4dEx5e3pMLJFLGYBLgkxld0yLjpRKj0ktM4VEMgk6
FRcQGBILCrELEwITCRe4uRgEBAICvLwYF6sJEjV9RC4yRjKJRCwzoCkxy0QZ
BdIupUUzL0WkpkMyMEUrMnQ2HOoeHh/u7OocJi8uOiEgNUYzAhsbO/0EMPDb
UKFQDG/WYtjYEKJfCF4gfIEgQCOGtBfOhqiYcUmINmYIh7SQEU4ItSIZohWB
UW3IigLIRM7gJI7csxmNaip5QYNmEv8XNKRV2EBBxYAdDNSETLKChs0lNTRU
OFIBgqkZBZrA6MmEp7QiKOJxaDcihQsDJFCUKAHhBIgOHULEKGmEBoF//XYE
HDhhhYoCLZXIKKADAwQlJ1sgmNBKgEDHkIsy2ZozCQsaHZFcXpoEcJMCMwTb
ALWiRlYiMGx0/BtBQtaiLWxkFDKjhk8WNgKnmGGDZoFYFiwUFPLiBgRftf7S
UGTjqRAZo4mUPj1EYcwUKmhoEABiLAEIE2h15/BWQGsJEnANuFGkQA1QGWjY
zbvBVz8KQqavVE0kO42SL9jAmXu35bYSCnB15wEJNYR2SnRE0FBDSS40196E
RMSWAAUYTHD/zAET2BCOCqbtl5l8ShRwA2dHyHCDc0JQcEEBKsBmgIOh3EAd
Ei48oMABQjQgwQY//CCMQAqkUIOITKh4HRIz3HDJDOCBF94EFGQZwZbopYfL
A/iZpWMnNmQ1UH13IZCGDRgqUVpvS5AIYYqjIQBXBwpyI+USF0TgCwQX3HJB
el12GcFxyGG5I3Y2LIcdBCOscINhBVAAgwpsKlEDDoG1YMANoBSAw464UeBa
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
d8M73tIIAgA7
--168427786-1646135556-947871613=:8785--



From jeremy at cnri.reston.va.us  Mon Jan 17 21:35:37 2000
From: jeremy at cnri.reston.va.us (Jeremy Hylton)
Date: Mon, 17 Jan 2000 15:35:37 -0500 (EST)
Subject: [Python-Dev] developers day session on compilers
Message-ID: <14467.32025.761662.841271@goon.cnri.reston.va.us>

I am championing a Developers' Day session on a Python compiler.
There is a short Web page describing the goals of the session at
http://www.python.org/workshops/2000-01/compiler.html.

I'd appreciate feedback on the content and format of the session.  If
you have ideas for what we should talk about or do, please followup to
me or to the list.

Jeremy




From mal at lemburg.com  Tue Jan 18 23:55:04 2000
From: mal at lemburg.com (M.-A. Lemburg)
Date: Tue, 18 Jan 2000 23:55:04 +0100
Subject: [Python-Dev] Python Tools/
Message-ID: <3884EF48.A6107775@lemburg.com>

I was just looking through the Tools dir of the CVS version
(looking for a tool which autoexpands tabs in Python source
files -- which I didn't find) and found some other useful scripts
along the way.

To my surprise these executable files did not have a .py
extension even though were Python source files. Is this 
intended ? I find that scripts like "world" provide useful
information which would be nice to have in the standard
lib -- with .py extension...

Other tidbits:

I noted that at least in my CVS tree the Tools/ht2html
dir does not include any executable: have I missed something ?

The script Tools/scripts/parseentities.py is not executable
for some reason.

-- 
Marc-Andre Lemburg
______________________________________________________________________
Business:                                      http://www.lemburg.com/
Python Pages:                           http://www.lemburg.com/python/





From guido at CNRI.Reston.VA.US  Wed Jan 19 13:50:05 2000
From: guido at CNRI.Reston.VA.US (Guido van Rossum)
Date: Wed, 19 Jan 2000 07:50:05 -0500
Subject: [Python-Dev] Python Tools/
In-Reply-To: Your message of "Tue, 18 Jan 2000 23:55:04 +0100."
             <3884EF48.A6107775@lemburg.com> 
References: <3884EF48.A6107775@lemburg.com> 
Message-ID: <200001191250.HAA18786@eric.cnri.reston.va.us>

> I was just looking through the Tools dir of the CVS version
> (looking for a tool which autoexpands tabs in Python source
> files -- which I didn't find) and found some other useful scripts
> along the way.
> 
> To my surprise these executable files did not have a .py
> extension even though were Python source files. Is this 
> intended ? I find that scripts like "world" provide useful
> information which would be nice to have in the standard
> lib -- with .py extension...

I would agree, but that's Barry's creation, so I'll let him answer for
himself.  Any other scripts with the same problem?

> Other tidbits:
> 
> I noted that at least in my CVS tree the Tools/ht2html
> dir does not include any executable: have I missed something ?

Actually, that directory is a ghost and shouldn't have been exported
at all.  (Barry, can you erase it from sweetpea?)

> The script Tools/scripts/parseentities.py is not executable
> for some reason.

Fixed now.

--Guido van Rossum (home page: http://www.python.org/~guido/)



From bwarsaw at cnri.reston.va.us  Wed Jan 19 17:24:41 2000
From: bwarsaw at cnri.reston.va.us (Barry A. Warsaw)
Date: Wed, 19 Jan 2000 11:24:41 -0500 (EST)
Subject: [Python-Dev] Python Tools/
References: <3884EF48.A6107775@lemburg.com>
Message-ID: <14469.58697.116588.501355@anthem.cnri.reston.va.us>

>>>>> "M" == M  <mal at lemburg.com> writes:

    M> To my surprise these executable files did not have a .py
    M> extension even though were Python source files. Is this 
    M> intended ? I find that scripts like "world" provide useful
    M> information which would be nice to have in the standard
    M> lib -- with .py extension...

I hadn't thought about making world a module, but if others agree, I
can play a little CVS magic to move the file to world.py.

    M> I noted that at least in my CVS tree the Tools/ht2html dir does
    M> not include any executable: have I missed something ?

If you do a `cvs up -P' (-P for prune) you'll find that that directory
goes away.  At one point I started to add the ht2html scripts to the
Python tools, but then we decided not to.  Unfortunately, once a
directory's been added to CVS it can never be removed (hence -P).

If you're really interested in the ht2html scripts, which are used to
build the Python.Org and JPython.Org sites (as well as my personal
pages), please see

    http://www.python.org/~bwarsaw/software/pyware.html

-Barry



From bwarsaw at cnri.reston.va.us  Wed Jan 19 18:32:50 2000
From: bwarsaw at cnri.reston.va.us (Barry A. Warsaw)
Date: Wed, 19 Jan 2000 12:32:50 -0500 (EST)
Subject: [Python-Dev] Python Tools/
References: <3884EF48.A6107775@lemburg.com>
	<14469.58697.116588.501355@anthem.cnri.reston.va.us>
Message-ID: <14469.62786.178265.983781@anthem.cnri.reston.va.us>

>>>>> "BAW" == Barry A Warsaw <bwarsaw at cnri.reston.va.us> writes:

    BAW> If you do a `cvs up -P' (-P for prune) you'll find that that
    BAW> directory goes away.  At one point I started to add the
    BAW> ht2html scripts to the Python tools, but then we decided not
    BAW> to.  Unfortunately, once a directory's been added to CVS it
    BAW> can never be removed (hence -P).

I just check this and there is no ht2html directory in Tools anymore.
We probably did remove it after you (MAL) had checked it out.  You can
either ignore the directory, or delete it from your working dirs.  If
cvs complains after deleting it, you may have to manually edit the
CVS/Entries file.  Sorry about that -- we know better now.

-Barry



From gerrit.holl at pobox.com  Wed Jan 19 21:14:27 2000
From: gerrit.holl at pobox.com (Gerrit Holl)
Date: Wed, 19 Jan 2000 21:14:27 +0100
Subject: [Python-Dev] ''.join in 1.6
Message-ID: <20000119211427.A3755@stopcontact.palga.uucp>

Hello,

I have a question/suggestion about ''.join in Python 1.6.

Suppose I have this list:
l = ["This", "is", "a", "test"]

Currently, I would join it this way into a tab-delimeted string:
s = string.join(l, '\t')

In 1.6, I should do it this way:
'\t'.join(s)

I think it would be better to have that method on the *list*:
s.join('\t')

That's more clear, isn't it?

regards,
Gerrit.

-- 
Please correct any bad English you encounter in my email message!
-----BEGIN GEEK CODE BLOCK----- http://www.geekcode.com
Version: 3.12
GCS dpu s-:-- a14 C++++>$ UL++ P--- L+++ E--- W++ N o? K? w--- !O !M !V PS+ PE?
Y? PGP-- t- 5? X? R- tv- b+(++) DI D+ G++ !e !r !y
-----END GEEK CODE BLOCK-----



From fredrik at pythonware.com  Wed Jan 19 21:43:36 2000
From: fredrik at pythonware.com (Fredrik Lundh)
Date: Wed, 19 Jan 2000 21:43:36 +0100
Subject: [Python-Dev] ''.join in 1.6
References: <20000119211427.A3755@stopcontact.palga.uucp>
Message-ID: <005e01bf62bd$dc8073d0$f29b12c2@secret.pythonware.com>

> In 1.6, I should do it this way:
> '\t'.join(s)
> 
> I think it would be better to have that method on the *list*:
> s.join('\t')
> 
> That's more clear, isn't it?

what if "s" is a tuple?  an array?  a user-defined
sequence type?

</F>




From bwarsaw at cnri.reston.va.us  Wed Jan 19 21:36:24 2000
From: bwarsaw at cnri.reston.va.us (Barry A. Warsaw)
Date: Wed, 19 Jan 2000 15:36:24 -0500 (EST)
Subject: [Python-Dev] ''.join in 1.6
References: <20000119211427.A3755@stopcontact.palga.uucp>
Message-ID: <14470.8264.686274.888365@anthem.cnri.reston.va.us>

>>>>> "GH" == Gerrit Holl <gerrit.holl at pobox.com> writes:

    GH> I think it would be better to have that method on the *list*:
    GH> s.join('\t')

    GH> That's more clear, isn't it?

Perhaps, but you want join to work on any sequence don't you?  By
making it a method on string objects, you sort of get that for free
(as opposed to putting it on lists, sequences, and requiring all class
authors to add it as well).

-Barry



From da at ski.org  Wed Jan 19 21:54:03 2000
From: da at ski.org (David Ascher)
Date: Wed, 19 Jan 2000 12:54:03 -0800
Subject: [Python-Dev] ''.join in 1.6
In-Reply-To: <20000119211427.A3755@stopcontact.palga.uucp>
Message-ID: <003b01bf62bf$5191abc0$c355cfc0@ski.org>

Gerrit Holl

> Currently, I would join it this way into a tab-delimeted string:
> s = string.join(l, '\t')
>
> In 1.6, I should do it this way:
> '\t'.join(s)
>
> I think it would be better to have that method on the *list*:
> s.join('\t')
>
> That's more clear, isn't it?

As Tim pointed out when they were discussed, the clearest way to express it
with the new methods is to do:

tab = '\t'

tab.join(s)

Similarly

space = ' '
space.join(s)

etc.

--david ascher




From da at ski.org  Wed Jan 19 23:41:47 2000
From: da at ski.org (David Ascher)
Date: Wed, 19 Jan 2000 14:41:47 -0800
Subject: [Python-Dev] SOAP
Message-ID: <000101bf62ce$5e509e70$c355cfc0@ski.org>

Who if anyone is working on SOAP clients and servers for Python?

--david ascher
-------------- next part --------------
A non-text attachment was scrubbed...
Name: David Ascher.vcf
Type: text/x-vcard
Size: 527 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/python-dev/attachments/20000119/2e2d3203/attachment.vcf>

From amk1 at erols.com  Thu Jan 20 05:19:33 2000
From: amk1 at erols.com (A.M. Kuchling)
Date: Wed, 19 Jan 2000 23:19:33 -0500
Subject: [Python-Dev] Changing existing class instances
Message-ID: <200001200419.XAA01969@mira.erols.com>

Currently, when you replace a class definition with an updated
version, it's really difficult to change existing class instances;
you'd have to essentially sweep every Python object and check if it's
an instance, starting at roots such as __main__ and sys.modules.  This
makes developing code in a long-running process difficult, Zope being
the best example of this.  When you modify a class definition used by
Zope code, you can't update existing instances floating around in
memory.

Over dinner, a friend and I were discussing this, and we thought it
probably isn't difficult to add an extra level of indirection to allow
fixing this.  The only other option we could think of is either the
complete scan of all objects, or inserting a forwarding pointer into
PyClassObjects that points to the replacing class if !NULL, and then
chase pointers when accessing PyInstanceObject->in_class.

A quick hack to implement the extra indirection took about
half an hour.  It does these things:

      * Defines a PyClassHandle type:
struct _PyClassHandle {
  PyClassHandle *next;		/* ptr to next PyClassHandle in linked list */
  PyClassObject *klass;		/* The class object */
} ;

      * The in_class attribute of PyInstanceObject becomes a
        PyClassHandle* instead of a PyClassObject*, and all code 
	such as inst->in_class becomes inst->in_class->klass.

      * As a quick hack to allow changing the class object referenced
        by a handle, I added a .forward( <newclassobject> ) method to
        class objects.  This basically does self.handle->klass =
        <newclassobject>.

The end result is that obj.__class__.forward(newclass) changes obj to
be an instance of newclass, and all other instances of obj.__class__
also mutate to become newclass instances.   

Making this purely automatic seems hard; you'd have to catch things
like 'import ftplib; ftplib.FTP = myclass', which would require
automatically calling ftplib.FTP.forward( myclass ) to make all
existing FTP instances mutate.  Would it be worthwhile to export some
hook for doing this in 1.6?  The cost is adding an extra pointer deref
to all access to PyInstanceObject->in_class.

(This could probably also be added to ExtensionClass, and probably
doesn't need to be added to core Python to help out Zope.  Just a
thought...)

-- 
A.M. Kuchling			http://starship.python.net/crew/amk/
Here the skull of a consumptive child becomes part of a great machine for
calculating the motions of the stars. Here, a yellow bird frets within the
ribcage of an unjust man.
    -- Welcome to Orqwith, in DOOM PATROL #22



From guido at CNRI.Reston.VA.US  Thu Jan 20 05:41:29 2000
From: guido at CNRI.Reston.VA.US (Guido van Rossum)
Date: Wed, 19 Jan 2000 23:41:29 -0500
Subject: [Python-Dev] Changing existing class instances
In-Reply-To: Your message of "Wed, 19 Jan 2000 23:19:33 EST."
             <200001200419.XAA01969@mira.erols.com> 
References: <200001200419.XAA01969@mira.erols.com> 
Message-ID: <200001200441.XAA20952@eric.cnri.reston.va.us>

> Currently, when you replace a class definition with an updated
> version, it's really difficult to change existing class instances;
> you'd have to essentially sweep every Python object and check if it's
> an instance, starting at roots such as __main__ and sys.modules.  This
> makes developing code in a long-running process difficult, Zope being
> the best example of this.  When you modify a class definition used by
> Zope code, you can't update existing instances floating around in
> memory.

There might be another solution.  When you reload a module, the module
object and its dictionary are reused.

Perhaps class and function objects could similarly be reused?  It
would mean that a class or def statement looks for an existing object
with the same name and type, and overwrites that.  Voila, all
references are automatically updated.

This is more work (e.g. for classes, a new bytecode may have to be
invented because the class creation process must be done differently)
but it's much less of a hack, and I think it would be more reliable.
(Even though it alters borderline semantics a bit.)

(Your extra indirection also slows things down, although I don't know
by how much -- not just the extra memory reference but also less
locality of reference so more cache hits.)

--Guido van Rossum (home page: http://www.python.org/~guido/)



From tim_one at email.msn.com  Thu Jan 20 06:59:51 2000
From: tim_one at email.msn.com (Tim Peters)
Date: Thu, 20 Jan 2000 00:59:51 -0500
Subject: [Python-Dev] Changing existing class instances
In-Reply-To: <200001200441.XAA20952@eric.cnri.reston.va.us>
Message-ID: <000b01bf630b$91a409a0$31a2143f@tim>

[Guido, on Andrew's idea for automagically updating
 classes]

> There might be another solution.  When you reload a module,
> the module object and its dictionary are reused.
>
> Perhaps class and function objects could similarly be
> reused?  It would mean that a class or def statement
> looks for an existing object with the same name and type,
> and overwrites that.  Voila, all references are
> automatically updated.

Too dangerous, I think.  While uncommon in general, I've certainly seen
(even written) functions that e.g. return a contained def or class.  The
intent in such cases is very much to create distinct defs or classes
(despite having the same names).  In this case I assume "the same name"
wouldn't *usually* be found, since the "contained def or class"'s name is
local to the containing function.  But if there ever happened to be a
module-level function or class of the same name, brrrr.

Modules differ because their namespace "search path" consists solely of the
more-global-than-global <wink> sys.modules.

> This is more work (e.g. for classes, a new bytecode may
> have to be invented because the class creation process
> must be done differently) but it's much less of a hack,
> and I think it would be more reliable. (Even though it
> alters borderline semantics a bit.)

How about an explicit function in the "new" module,

    new.update(class_or_def_old, class_or_def_new)

which overwrites old's guts with new's guts (in analogy with dict.update)?
Then no semantics change and you don't need new bytecodes.  In return, a
user who wants to e.g. replace an existing class C would need to do

    oldC = C
    do whatever they do to get the new C
    new.update(oldC, C)

Building on that, a short Python loop could do the magic for every class and
function in a module; and building on *that*, a short "updating import"
function could be written in Python.  View it as providing mechanism instead
of policy <0.9 wink>.

> (Your extra indirection also slows things down, although
> I don't know by how much -- not just the extra memory
> reference but also less locality of reference so more
> cache hits.)

Across the universe of all Python programs on all platforms, weighted by
importance, it was a slowdown of nearly 4.317%.

if-i-had-used-only-one-digit-everyone-would-have-
    known-i-was-making-it-up<wink>-ly y'rs  - tim





From gstein at lyra.org  Thu Jan 20 08:48:29 2000
From: gstein at lyra.org (Greg Stein)
Date: Wed, 19 Jan 2000 23:48:29 -0800 (PST)
Subject: [Python-Dev] Changing existing class instances
In-Reply-To: <000b01bf630b$91a409a0$31a2143f@tim>
Message-ID: <Pine.LNX.4.10.10001192342450.13911-100000@nebula.lyra.org>

Oh man, oh man... I think this is where I get to say something akin to "I
told you so."

:-)

I already described Tim's proposal in my type proposal paper, as a way to
deal with incomplete classes. Essentially, a class object is created
"empty" and is later "updated" with the correct bits. The empty class
allows two classes to refer to each other in the "recursive type"
scenario.

In other words, I definitely would support a new class object behavior
that allows us to update a class' set of bases and dictionary on the fly.
This could then be used to support my solution for the recursive type
scenario (which, in turn, means that we don't have to introduce Yet
Another Namespace into Python to hold type names).

Note: I would agree with Guido, however, on the "look for a class object
with the same name", but with the restriction that the name is only
replaced in the *target* namespace. i.e. a "class Foo" in a function will
only look for Foo in the function's local namespace; it would not
overwrite a class in the global space, nor would it overwrite class
objects returned by a prior invocation of the function.

Cheers,
-g

On Thu, 20 Jan 2000, Tim Peters wrote:
> [Guido, on Andrew's idea for automagically updating
>  classes]
> 
> > There might be another solution.  When you reload a module,
> > the module object and its dictionary are reused.
> >
> > Perhaps class and function objects could similarly be
> > reused?  It would mean that a class or def statement
> > looks for an existing object with the same name and type,
> > and overwrites that.  Voila, all references are
> > automatically updated.
> 
> Too dangerous, I think.  While uncommon in general, I've certainly seen
> (even written) functions that e.g. return a contained def or class.  The
> intent in such cases is very much to create distinct defs or classes
> (despite having the same names).  In this case I assume "the same name"
> wouldn't *usually* be found, since the "contained def or class"'s name is
> local to the containing function.  But if there ever happened to be a
> module-level function or class of the same name, brrrr.
> 
> Modules differ because their namespace "search path" consists solely of the
> more-global-than-global <wink> sys.modules.
> 
> > This is more work (e.g. for classes, a new bytecode may
> > have to be invented because the class creation process
> > must be done differently) but it's much less of a hack,
> > and I think it would be more reliable. (Even though it
> > alters borderline semantics a bit.)
> 
> How about an explicit function in the "new" module,
> 
>     new.update(class_or_def_old, class_or_def_new)
> 
> which overwrites old's guts with new's guts (in analogy with dict.update)?
> Then no semantics change and you don't need new bytecodes.  In return, a
> user who wants to e.g. replace an existing class C would need to do
> 
>     oldC = C
>     do whatever they do to get the new C
>     new.update(oldC, C)
> 
> Building on that, a short Python loop could do the magic for every class and
> function in a module; and building on *that*, a short "updating import"
> function could be written in Python.  View it as providing mechanism instead
> of policy <0.9 wink>.
> 
> > (Your extra indirection also slows things down, although
> > I don't know by how much -- not just the extra memory
> > reference but also less locality of reference so more
> > cache hits.)
> 
> Across the universe of all Python programs on all platforms, weighted by
> importance, it was a slowdown of nearly 4.317%.
> 
> if-i-had-used-only-one-digit-everyone-would-have-
>     known-i-was-making-it-up<wink>-ly y'rs  - tim
> 
> 
> 
> _______________________________________________
> Python-Dev maillist  -  Python-Dev at python.org
> http://www.python.org/mailman/listinfo/python-dev
> 

-- 
Greg Stein, http://www.lyra.org/




From fredrik at pythonware.com  Thu Jan 20 09:06:32 2000
From: fredrik at pythonware.com (Fredrik Lundh)
Date: Thu, 20 Jan 2000 09:06:32 +0100
Subject: [Python-Dev] SOAP
References: <000101bf62ce$5e509e70$c355cfc0@ski.org>
Message-ID: <006901bf631d$449eea50$f29b12c2@secret.pythonware.com>

David Ascher <da at ski.org> wrote:
> Who if anyone is working on SOAP clients and servers for Python?

we are (or rather, we will).  hope to have code
available during (late) Q1.

</F>




From gerrit.holl at pobox.com  Thu Jan 20 09:08:01 2000
From: gerrit.holl at pobox.com (Gerrit Holl)
Date: Thu, 20 Jan 2000 09:08:01 +0100
Subject: [Python-Dev] ''.join in 1.6
In-Reply-To: <005e01bf62bd$dc8073d0$f29b12c2@secret.pythonware.com>; from fredrik@pythonware.com on Wed, Jan 19, 2000 at 09:43:36PM +0100
References: <20000119211427.A3755@stopcontact.palga.uucp> <005e01bf62bd$dc8073d0$f29b12c2@secret.pythonware.com>
Message-ID: <20000120090801.A903@stopcontact.palga.uucp>

Fredrik Lundh wrote on 948314616:
> > In 1.6, I should do it this way:
> > '\t'.join(s)
> > 
> > I think it would be better to have that method on the *list*:
> > s.join('\t')
> > 
> > That's more clear, isn't it?
> 
> what if "s" is a tuple?  an array?  a user-defined
> sequence type?

I understand. Thanks for your answers.

regards,
Gerrit.

-- 
Please correct any bad English you encounter in my email message!
-----BEGIN GEEK CODE BLOCK----- http://www.geekcode.com
Version: 3.12
GCS dpu s-:-- a14 C++++>$ UL++ P--- L+++ E--- W++ N o? K? w--- !O !M !V PS+ PE?
Y? PGP-- t- 5? X? R- tv- b+(++) DI D+ G++ !e !r !y
-----END GEEK CODE BLOCK-----



From jim at digicool.com  Thu Jan 20 15:06:29 2000
From: jim at digicool.com (Jim Fulton)
Date: Thu, 20 Jan 2000 09:06:29 -0500
Subject: [Python-Dev] Changing existing class instances
References: <200001200419.XAA01969@mira.erols.com>
Message-ID: <38871665.C3B6FFEE@digicool.com>

"A.M. Kuchling" wrote:
> 
> Currently, when you replace a class definition with an updated
> version, it's really difficult to change existing class instances;
> you'd have to essentially sweep every Python object and check if it's
> an instance, starting at roots such as __main__ and sys.modules.  This
> makes developing code in a long-running process difficult, Zope being
> the best example of this.  When you modify a class definition used by
> Zope code, you can't update existing instances floating around in
> memory.

In the case of Zope, if the objects that you care about happen to be 
persistent objects, then it's relatively easy to arrange to get the
objects flushed from memory and reloaded with the new classes.
(There are some subtle issues to deal with, like worrying about 
multiple threads, but in a development environment, you can deal with
these, for example, by limiting the server to one thread.)

Note that this is really only a special case of a much larger problem.

Reloading a module redefines the global variables in a module.
It doesn't update any references to those global references
from other places, such as instances or *other* modules.

For example, imports like:

  from foo import spam

are not updated when foo is reloaded.

Maybe you are expecting too much from reload.

Jim      

--
Jim Fulton           mailto:jim at digicool.com
Technical Director   (888) 344-4332              Python Powered!
Digital Creations    http://www.digicool.com     http://www.python.org

Under US Code Title 47, Sec.227(b)(1)(C), Sec.227(a)(2)(B) This email
address may not be added to any commercial mail list with out my
permission.  Violation of my privacy with advertising or SPAM will
result in a suit for a MINIMUM of $500 damages/incident, $1500 for
repeats.



From jim at digicool.com  Thu Jan 20 15:34:13 2000
From: jim at digicool.com (Jim Fulton)
Date: Thu, 20 Jan 2000 09:34:13 -0500
Subject: Python 2 namespace change? (was Re: [Python-Dev] Changing existing class 
 instances)
References: <200001200419.XAA01969@mira.erols.com> <38871665.C3B6FFEE@digicool.com>
Message-ID: <38871CE5.53FB9D68@digicool.com>

Jim Fulton wrote:
> 
> Reloading a module redefines the global variables in a module.
> It doesn't update any references to those global references
> from other places, such as instances or *other* modules.
> 
> For example, imports like:
> 
>   from foo import spam
> 
> are not updated when foo is reloaded.

A change to the way that namespaces are handled 
could make this work and have a number of other benefits, 
like global name usage without namespace lookups.

I've suggested this to Guido in the past.  His 
reasonable response is that this would be too big a 
change for Python 1. Maybe this is something to consider
for Python 2?

The basic idea (borrowed from Smalltalk) is to have a kind 
of dictionary that is a collection of "association" 
objects.  An association object is simply a pairing of a 
name with a value. Association objects can be shared among 
multiple namespaces.  An import like:

  from foo import spam

would copy the association between the name 'foo' and a 
value from module 'spam' into the current module. If foo
is reloaded or if the name is reassigned in spam, the
association is modified and the change is seen in any
namespaces that imported foo.

Similarly if a function uses a global variable:

  spam=1

  def bar():
    global spam
    return spam*2

the compiled function contains the association between
spam and it's value. This means that:

  - When spam is used in the function, it doesn't have to
    be looked up,

  - The function object no longer needs to keep a reference
    to it's globals. This eliminates an annoying circular 
    reference.

(I would not replace existing dictionaries with this new kind.
 I'd have both kinds available.)

I think that this would be a really nice change for Python 2.

Jim

--
Jim Fulton           mailto:jim at digicool.com
Technical Director   (888) 344-4332              Python Powered!
Digital Creations    http://www.digicool.com     http://www.python.org

Under US Code Title 47, Sec.227(b)(1)(C), Sec.227(a)(2)(B) This email
address may not be added to any commercial mail list with out my
permission.  Violation of my privacy with advertising or SPAM will
result in a suit for a MINIMUM of $500 damages/incident, $1500 for
repeats.



From guido at CNRI.Reston.VA.US  Thu Jan 20 16:20:45 2000
From: guido at CNRI.Reston.VA.US (Guido van Rossum)
Date: Thu, 20 Jan 2000 10:20:45 -0500
Subject: [Python-Dev] Changing existing class instances
In-Reply-To: Your message of "Thu, 20 Jan 2000 00:59:51 EST."
             <000b01bf630b$91a409a0$31a2143f@tim> 
References: <000b01bf630b$91a409a0$31a2143f@tim> 
Message-ID: <200001201520.KAA21137@eric.cnri.reston.va.us>

> From: "Tim Peters" <tim_one at email.msn.com>
> 
> [Guido, on Andrew's idea for automagically updating
>  classes]
> 
> > There might be another solution.  When you reload a module,
> > the module object and its dictionary are reused.
> >
> > Perhaps class and function objects could similarly be
> > reused?  It would mean that a class or def statement
> > looks for an existing object with the same name and type,
> > and overwrites that.  Voila, all references are
> > automatically updated.
> 
> Too dangerous, I think.  While uncommon in general, I've certainly seen
> (even written) functions that e.g. return a contained def or class.  The
> intent in such cases is very much to create distinct defs or classes
> (despite having the same names).  In this case I assume "the same name"
> wouldn't *usually* be found, since the "contained def or class"'s name is
> local to the containing function.  But if there ever happened to be a
> module-level function or class of the same name, brrrr.

Agreed that that would be bad.  But I wouldn't search outer scopes --
I would only look for a class/def that I was about to stomp on.

> Modules differ because their namespace "search path" consists solely of the
> more-global-than-global <wink> sys.modules.

"The search path doesn't enter into it."

> > This is more work (e.g. for classes, a new bytecode may
> > have to be invented because the class creation process
> > must be done differently) but it's much less of a hack,
> > and I think it would be more reliable. (Even though it
> > alters borderline semantics a bit.)
> 
> How about an explicit function in the "new" module,
> 
>     new.update(class_or_def_old, class_or_def_new)
> 
> which overwrites old's guts with new's guts (in analogy with dict.update)?
> Then no semantics change and you don't need new bytecodes.

Only a slight semantics change (which my full proposal would require
too): function objects would become mutable -- their func_code,
func_defaults, func_doc and func_globals fields (and, why not,
func_name too) should be changeable.  If you make all these
assignable, it doesn't even have to be a privileged function.

> In return, a
> user who wants to e.g. replace an existing class C would need to do
> 
>     oldC = C
>     do whatever they do to get the new C
>     new.update(oldC, C)
> 
> Building on that, a short Python loop could do the magic for every class and
> function in a module; and building on *that*, a short "updating import"
> function could be written in Python.  View it as providing mechanism instead
> of policy <0.9 wink>.

That's certainly a reasonable compromise.  Note that the update on a
class should imply an update on its methods, right?

--Guido van Rossum (home page: http://www.python.org/~guido/)



From guido at CNRI.Reston.VA.US  Thu Jan 20 16:45:40 2000
From: guido at CNRI.Reston.VA.US (Guido van Rossum)
Date: Thu, 20 Jan 2000 10:45:40 -0500
Subject: Python 2 namespace change? (was Re: [Python-Dev] Changing existing class instances)
In-Reply-To: Your message of "Thu, 20 Jan 2000 09:34:13 EST."
             <38871CE5.53FB9D68@digicool.com> 
References: <200001200419.XAA01969@mira.erols.com> <38871665.C3B6FFEE@digicool.com>  
            <38871CE5.53FB9D68@digicool.com> 
Message-ID: <200001201545.KAA21304@eric.cnri.reston.va.us>

> I've suggested this to Guido in the past.  His 
> reasonable response is that this would be too big a 
> change for Python 1. Maybe this is something to consider
> for Python 2?

Note: from now on the new name for Python 2 is Python 3000. :-)

> The basic idea (borrowed from Smalltalk) is to have a kind 
> of dictionary that is a collection of "association" 
> objects.  An association object is simply a pairing of a 
> name with a value. Association objects can be shared among 
> multiple namespaces.

I've never liked this very much, mostly because it breaks simplicity:
the idea that a namespace is a mapping from names to values
(e.g. {"limit": 100, "doit": <function...>, ...}) is beautifully
simple, while the idea of inserting an extra level of indirection, no
matter how powerful, is much murkier.

There's also the huge change in semantics, as you point out;
currently,

	from foo import bar

has the same effect (on bar anyway) as

	import foo
	bar = foo.bar		# i.e. copying an object reference
	del foo

while under your proposal it would be more akin to changing all
references to bar to become references to foo.bar.

Of course that's what the moral equivalent of "from ... import ..."
does in most other languages anyway, so we might consider this for
Python 3000; however it would break a considerable amount of old code,
I think.  (Not to mention brain and book breakage. :-)

--Guido van Rossum (home page: http://www.python.org/~guido/)



From guido at CNRI.Reston.VA.US  Thu Jan 20 17:01:38 2000
From: guido at CNRI.Reston.VA.US (Guido van Rossum)
Date: Thu, 20 Jan 2000 11:01:38 -0500
Subject: [Python-Dev] Python 1.6 timing
Message-ID: <200001201601.LAA21359@eric.cnri.reston.va.us>

Andrew let me repost this mail of his to this list.  It's worth a
discussion here (if not in a larger forum).  My responses are at the
bottom.

------- Forwarded Message

Date:    Wed, 19 Jan 2000 20:17:55 -0500
From:    "A.M. Kuchling" <amk1 at erols.com>
To:      guido at python.org
Subject: Python 1.6 timing

I thought a bit more about the release schedule for 1.6, and like the
idea of delaying it less and less.  Another bad effect of delaying it
is that not having Unicode in the core handicaps developing XML tools;
we can continue working with wstrop, or integrate MAL's code into the
XML-SIG's CVS tree, but it might mean abandoning the XML processing
field to Perl & Tcl because the tools can't be made fully standard
compliant in time.

Options I can think of:

	1) Delegating some control to a pumpkin holder [...].

	2) Releasing the Unicode+sre modules as separate add-ons to
 	   1.5.  (But would that impose annoying
	   backward-compatibility constraints when they get integrated
	   into 1.6?)

	3) Add Unicode, sre, Distutils, plus other minor things and
           call it 1.5.5, meaning it's not as big a revision as a 1.6
           release, but it's bigger than just another patchlevel of
	   bugfixes.  I don't remember what other features were
	   planned for 1.6; was there anything major, if static typing
	   is left for 2.0?

- -- 
A.M. Kuchling			http://starship.python.net/crew/amk/
Life's too short for chess.
    -- H.J. Byron

------- End of Forwarded Message

There are several other things I can think of now that were planned
for 1.6: revamped import, rich comparisons, revised coercions,
parallel for loop (for i in L; j in M: ...), extended slicing for all
sequences.  I've also been thinking about making classes be types (not
as huge a change as you think, if you don't allow subclassing built-in
types), and adding a built-in array type suitable for use by NumPy.
I've also received a conservative GC patch that seems to be fairly
easy to apply and has some of Tim Peters' blessing.

For 1.5.5 (what happened to 1.5.3 and 1.5.4?), we can have a more
conservative agenda, as suggested by Andrew: Unicode and distutils are
probably the most important things to integrate.  (The import
utilities are not ready for prime time in my opinion; there are too
many issues.)

Anybody care to be the pumpkin?  That would cut the discussion short;
otherwise the problem remains that I can't spend too much time on the
next release unless I get funded for it; what little money I've
received for CP4E I had better spend on getting some CP4E-related
results ASAP, because the next installment of this funding is very
much at stake...

--Guido van Rossum (home page: http://www.python.org/~guido/)
Life's better without braces.
    -- Bruce Eckel



From bwarsaw at cnri.reston.va.us  Thu Jan 20 17:21:30 2000
From: bwarsaw at cnri.reston.va.us (Barry A. Warsaw)
Date: Thu, 20 Jan 2000 11:21:30 -0500 (EST)
Subject: [Python-Dev] Python 1.6 timing
References: <200001201601.LAA21359@eric.cnri.reston.va.us>
Message-ID: <14471.13834.480356.541389@anthem.cnri.reston.va.us>

>>>>> "Guido" == Guido van Rossum <guido at cnri.reston.va.us> writes:

    Guido> There are several other things I can think of now that were
    Guido> planned for 1.6: revamped import, rich comparisons, revised
    Guido> coercions, parallel for loop (for i in L; j in M: ...),
    Guido> extended slicing for all sequences.  I've also been
    Guido> thinking about making classes be types (not as huge a
    Guido> change as you think, if you don't allow subclassing
    Guido> built-in types), and adding a built-in array type suitable
    Guido> for use by NumPy.  I've also received a conservative GC
    Guido> patch that seems to be fairly easy to apply and has some of
    Guido> Tim Peters' blessing.

All very cool things that could easily wait until 1.7.  After all,
what's in a number?  If, as Andrew puts forth, getting a stable Python
release with Unicode is very important for Python's future
positioning, then I say let's go with his more modest list, mainly
Unicode, sre, and Distutils.  We've already got string meths, tons of
library improvements, and sundry other things.  That's a good enough
laundry list for the next release.


From jim at digicool.com  Thu Jan 20 17:21:33 2000
From: jim at digicool.com (Jim Fulton)
Date: Thu, 20 Jan 2000 11:21:33 -0500
Subject: Version numbering (was Re: [Python-Dev] Python 1.6 timing)
References: <200001201601.LAA21359@eric.cnri.reston.va.us>
Message-ID: <3887360D.C29A9836@digicool.com>

Guido van Rossum wrote:
> 
> Andrew let me repost this mail of his to this list.  It's worth a
> discussion here (if not in a larger forum).  My responses are at the
> bottom.
> 
(snip)
> 
> There are several other things I can think of now that were planned
> for 1.6: revamped import, rich comparisons, revised coercions,
> parallel for loop (for i in L; j in M: ...), extended slicing for all
> sequences.  I've also been thinking about making classes be types (not
> as huge a change as you think, if you don't allow subclassing built-in
> types), and adding a built-in array type suitable for use by NumPy.
> I've also received a conservative GC patch that seems to be fairly
> easy to apply and has some of Tim Peters' blessing.
> 
> For 1.5.5 (what happened to 1.5.3 and 1.5.4?), we can have a more
> conservative agenda, as suggested by Andrew: Unicode and distutils are
> probably the most important things to integrate.  (The import
> utilities are not ready for prime time in my opinion; there are too
> many issues.)

(snip)

What is the basis of the Python numbering scheme?

I thought that there was a notion that:

  - The first part changed with huge, possibly
    backward incompatible, changes,

  - The second part was for new functionality 
    
  - The third part was for bug fixes.

I thought I saw this scheme referenced somewhere and
possibly even attributed to Guido. (?) I think that 
this is a better scheme that what I've seen with 
the 1.5 releases.

Jim

--
Jim Fulton           mailto:jim at digicool.com
Technical Director   (888) 344-4332              Python Powered!
Digital Creations    http://www.digicool.com     http://www.python.org

Under US Code Title 47, Sec.227(b)(1)(C), Sec.227(a)(2)(B) This email
address may not be added to any commercial mail list with out my
permission.  Violation of my privacy with advertising or SPAM will
result in a suit for a MINIMUM of $500 damages/incident, $1500 for
repeats.



From petrilli at amber.org  Thu Jan 20 17:33:52 2000
From: petrilli at amber.org (Christopher Petrilli)
Date: Thu, 20 Jan 2000 11:33:52 -0500
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <14471.13834.480356.541389@anthem.cnri.reston.va.us>; from bwarsaw@cnri.reston.va.us on Thu, Jan 20, 2000 at 11:21:30AM -0500
References: <200001201601.LAA21359@eric.cnri.reston.va.us> <14471.13834.480356.541389@anthem.cnri.reston.va.us>
Message-ID: <20000120113352.A23763@trump.amber.org>

Barry A. Warsaw [bwarsaw at cnri.reston.va.us] wrote:
> All very cool things that could easily wait until 1.7.  After all,
> what's in a number?  If, as Andrew puts forth, getting a stable Python
> release with Unicode is very important for Python's future
> positioning, then I say let's go with his more modest list, mainly
> Unicode, sre, and Distutils.  We've already got string meths, tons of
> library improvements, and sundry other things.  That's a good enough
> laundry list for the next release.

Heck, Python is infinately more conservative in its numbering than 
a lot of projects.  All that was mentioned would normally be enough to
call it 2.0 easily. :-)  Modesty can be counter productive in PR 
business...also there is the issue of having two copies of 1.5.x installed
at the same time, which with Unicode could be a manjor consideraton
for some of us.

For me, numbering has always been (and I try and keep it this way with
Zope):

	X.Y.Z

	X = structural changes, backward incompaibility
	Y = new features
	Z = bug fixes only

Chris
-- 
| Christopher Petrilli
| petrilli at amber.org



From bwarsaw at cnri.reston.va.us  Thu Jan 20 17:30:32 2000
From: bwarsaw at cnri.reston.va.us (Barry A. Warsaw)
Date: Thu, 20 Jan 2000 11:30:32 -0500 (EST)
Subject: [Python-Dev] Python 1.6 timing
References: <200001201601.LAA21359@eric.cnri.reston.va.us>
	<14471.13834.480356.541389@anthem.cnri.reston.va.us>
	<20000120113352.A23763@trump.amber.org>
Message-ID: <14471.14376.9881.702264@anthem.cnri.reston.va.us>

>>>>> "CP" == Christopher Petrilli <petrilli at amber.org> writes:

    CP> For me, numbering has always been (and I try and keep it this
    CP> way with Zope):

    CP> 	X.Y.Z

    | 	X = structural changes, backward incompaibility
    | 	Y = new features
    | 	Z = bug fixes only

I agree.
-Barry



From petrilli at amber.org  Thu Jan 20 17:41:24 2000
From: petrilli at amber.org (Christopher Petrilli)
Date: Thu, 20 Jan 2000 11:41:24 -0500
Subject: [Python-Dev] SOAP
In-Reply-To: <006901bf631d$449eea50$f29b12c2@secret.pythonware.com>; from fredrik@pythonware.com on Thu, Jan 20, 2000 at 09:06:32AM +0100
References: <000101bf62ce$5e509e70$c355cfc0@ski.org> <006901bf631d$449eea50$f29b12c2@secret.pythonware.com>
Message-ID: <20000120114124.B23763@trump.amber.org>

Fredrik Lundh [fredrik at pythonware.com] wrote:
> David Ascher <da at ski.org> wrote:
> > Who if anyone is working on SOAP clients and servers for Python?
> 
> we are (or rather, we will).  hope to have code
> available during (late) Q1.
> 
> </F>

For what it's worth, this is also Zope's strategy.  We are commited to
having full SOAP integration in the system soon (when soon is, is another
queston for the marketing department). :-)   I am pretty sure that it will
be a bi-directional integration.

Chris
-- 
| Christopher Petrilli
| petrilli at amber.org



From akuchlin at mems-exchange.org  Thu Jan 20 17:38:53 2000
From: akuchlin at mems-exchange.org (Andrew M. Kuchling)
Date: Thu, 20 Jan 2000 11:38:53 -0500 (EST)
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <14471.13834.480356.541389@anthem.cnri.reston.va.us>
References: <200001201601.LAA21359@eric.cnri.reston.va.us>
	<14471.13834.480356.541389@anthem.cnri.reston.va.us>
Message-ID: <14471.14877.434886.471929@amarok.cnri.reston.va.us>

Barry A. Warsaw writes:
>    Guido> There are several other things I can think of now that were
>    Guido> planned for 1.6: revamped import, rich comparisons, revised
>    Guido> coercions, parallel for loop (for i in L; j in M: ...),
>    Guido> extended slicing for all sequences.  

I'm not clear on the status of these various things; how many of these
changes are deep ones that need lots of design, or affect massive
amounts of the code base?  For example, revamped import is a tricky
design problem (as we've seen on this list).  Is the spec for rich
comparisons clearly defined at this point?  Something like the
parallel for loop seems like a parser modification combined with a
code-generator modification, with no subtle implications for the rest
of the implementation, and so that seems a simple matter of
programming -- a week or so of effort.  (Maybe I've missed something?)

>    Guido> I've also been
>    Guido> thinking about making classes be types (not as huge a
>    Guido> change as you think, if you don't allow subclassing
>    Guido> built-in types), and adding a built-in array type suitable
>    Guido> for use by NumPy.  I've also received a conservative GC
>    Guido> patch that seems to be fairly easy to apply and has some of
>    Guido> Tim Peters' blessing.

Similarly, does the conservative GC patch splatter changes all over
the place, or is it very localized?  Is adding the NumPy array type
straightforward?  Remember, there would presumably be a couple of 1.6
alphas and betas to shake out bugs.

>From a political standpoint, I'd call the next release 1.6 and not
>bother with another installment in 1.5.x series.  And I agree with

Fair enough; forget about the 1.5.5 suggestion, and call it as 1.6.

>tree.  My free-time plate is pretty full with JPython and Mailman, but
>I'm willing to help where possible.

Ditto.

-- 
A.M. Kuchling			http://starship.python.net/crew/amk/
One trouble with being efficient is that it makes everybody hate you so.
    -- Bob Edwards, the Calgary Eyeopener, March 18, 1916




From jim at digicool.com  Thu Jan 20 17:48:18 2000
From: jim at digicool.com (Jim Fulton)
Date: Thu, 20 Jan 2000 11:48:18 -0500
Subject: Python 2 namespace change? (was Re: [Python-Dev] Changing existing 
 class instances)
References: <200001200419.XAA01969@mira.erols.com> <38871665.C3B6FFEE@digicool.com>  
	            <38871CE5.53FB9D68@digicool.com> <200001201545.KAA21304@eric.cnri.reston.va.us>
Message-ID: <38873C52.29FEAC6D@digicool.com>

Guido van Rossum wrote:
> 
> > I've suggested this to Guido in the past.  His
> > reasonable response is that this would be too big a
> > change for Python 1. Maybe this is something to consider
> > for Python 2?
> 
> Note: from now on the new name for Python 2 is Python 3000. :-)

I like it. 

> > The basic idea (borrowed from Smalltalk) is to have a kind
> > of dictionary that is a collection of "association"
> > objects.  An association object is simply a pairing of a
> > name with a value. Association objects can be shared among
> > multiple namespaces.
> 
> I've never liked this very much, mostly because it breaks simplicity:
> the idea that a namespace is a mapping from names to values
> (e.g. {"limit": 100, "doit": <function...>, ...}) is beautifully
> simple, while the idea of inserting an extra level of indirection, no
> matter how powerful, is much murkier.

How so? It doesn't change the mapping semantics.
 
> There's also the huge change in semantics, as you point out;
> currently,
> 
>         from foo import bar
> 
> has the same effect (on bar anyway) as
> 
>         import foo
>         bar = foo.bar           # i.e. copying an object reference
>         del foo
> 
> while under your proposal it would be more akin to changing all
> references to bar to become references to foo.bar.
> 
> Of course that's what the moral equivalent of "from ... import ..."
> does in most other languages anyway, so we might consider this for
> Python 3000;

Cool. Again, it would also make function global variable access
faster and cleaner in some ways.

> however it would break a considerable amount of old code,
> I think. 

Really? I wonder. I bet it would break alot less old
code that other recent changes.

> (Not to mention brain

It makes my brain feel much better. :)

> and book breakage. :-)

Hey, all of the books will have to be rewritten for Python 3000.

Jim

--
Jim Fulton           mailto:jim at digicool.com
Technical Director   (888) 344-4332              Python Powered!
Digital Creations    http://www.digicool.com     http://www.python.org

Under US Code Title 47, Sec.227(b)(1)(C), Sec.227(a)(2)(B) This email
address may not be added to any commercial mail list with out my
permission.  Violation of my privacy with advertising or SPAM will
result in a suit for a MINIMUM of $500 damages/incident, $1500 for
repeats.



From gstein at lyra.org  Thu Jan 20 18:22:40 2000
From: gstein at lyra.org (Greg Stein)
Date: Thu, 20 Jan 2000 09:22:40 -0800 (PST)
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <200001201601.LAA21359@eric.cnri.reston.va.us>
Message-ID: <Pine.LNX.4.10.10001200907240.13911-100000@nebula.lyra.org>

On Thu, 20 Jan 2000, Guido van Rossum wrote:
>...
> Date:    Wed, 19 Jan 2000 20:17:55 -0500
> From:    "A.M. Kuchling" <amk1 at erols.com>
> To:      guido at python.org
> Subject: Python 1.6 timing
> 
> I thought a bit more about the release schedule for 1.6, and like the
> idea of delaying it less and less.  Another bad effect of delaying it
> is that not having Unicode in the core handicaps developing XML tools;
> we can continue working with wstrop, or integrate MAL's code into the
> XML-SIG's CVS tree, but it might mean abandoning the XML processing
> field to Perl & Tcl because the tools can't be made fully standard
> compliant in time.

I agree with Andrew's basic premise.

> Options I can think of:
> 
> 	1) Delegating some control to a pumpkin holder [...].

Seems fine.

> 	2) Releasing the Unicode+sre modules as separate add-ons to
>  	   1.5.  (But would that impose annoying
> 	   backward-compatibility constraints when they get integrated
> 	   into 1.6?)

Icky. :-)

> 	3) Add Unicode, sre, Distutils, plus other minor things and
>            call it 1.5.5, meaning it's not as big a revision as a 1.6
>            release, but it's bigger than just another patchlevel of
> 	   bugfixes.  I don't remember what other features were
> 	   planned for 1.6; was there anything major, if static typing
> 	   is left for 2.0?

Call it 1.6, per the rest of the thread.

>...
> For 1.5.5 (what happened to 1.5.3 and 1.5.4?), we can have a more
> conservative agenda, as suggested by Andrew: Unicode and distutils are
> probably the most important things to integrate.

Unicode: definitely. distutils seems pretty early, but I bet that some key
concepts could be added to 1.6, to make the transition and continued
development easier.

Note that if an announcement were made to the effect of "feature freeze on
February 15; only bug fixes afterwards," that you would get a lot of
people scrambling to submit their pet features. This would be a good way
to light some fires, to see what kinds of things get completed (i.e. we
may think some things aren't ready or are too far out, put that deadline
in and those positions could change...)

> (The import
> utilities are not ready for prime time in my opinion; there are too
> many issues.)

I'm waiting for that review :-)

If you raise issues, then I can knock them down. I don't see all that many
at the moment. But I'm biased :-)

> Anybody care to be the pumpkin?  That would cut the discussion short;
> otherwise the problem remains that I can't spend too much time on the
> next release unless I get funded for it; what little money I've
> received for CP4E I had better spend on getting some CP4E-related
> results ASAP, because the next installment of this funding is very
> much at stake...

I would volunteer for the pumpkin... around April-ish. My plate is rather
full with completing mod_dav and then integrating that into Apache 2.0.
Once the Apache integration begins, then I'd have some more free time.

But this begs the question of: what does the pumpkin-holder mean in the
*Python* world?

If it is collating fixes, producing snapshots, etc, then I'm comfy with
it. If it also contains responsibility for specific kinds of work, then
Fred would probably veto me :-), as I've got an outstanding doc that I owe
him (for about six months now... sigh; maybe I'll bribe MAL to write it; 
he knows the interface :-)).

But stll: what's it mean? How does the pumpkin reduce the Guido-load, yet
still enable the Guido-control?

[ I just had a talk about this with the guys at Inprise, re: InterBase,
  mentioning that the Dictator model works well for Python, but doesn't
  necessarily work well for new projects or commercially-started projects
  due to control/prejudice issues. Python people like it because of the
  resulting simplicity and cleanliness; I doubt we want a pumpkin approach
  that would allow that to go away! ]

Cheers,
-g

-- 
Greg Stein, http://www.lyra.org/




From guido at CNRI.Reston.VA.US  Thu Jan 20 18:20:33 2000
From: guido at CNRI.Reston.VA.US (Guido van Rossum)
Date: Thu, 20 Jan 2000 12:20:33 -0500
Subject: Python 2 namespace change? (was Re: [Python-Dev] Changing existing class instances)
In-Reply-To: Your message of "Thu, 20 Jan 2000 11:48:18 EST."
             <38873C52.29FEAC6D@digicool.com> 
References: <200001200419.XAA01969@mira.erols.com> <38871665.C3B6FFEE@digicool.com> <38871CE5.53FB9D68@digicool.com> <200001201545.KAA21304@eric.cnri.reston.va.us>  
            <38873C52.29FEAC6D@digicool.com> 
Message-ID: <200001201720.MAA21534@eric.cnri.reston.va.us>

[me]
> > I've never liked this very much, mostly because it breaks simplicity:
> > the idea that a namespace is a mapping from names to values
> > (e.g. {"limit": 100, "doit": <function...>, ...}) is beautifully
> > simple, while the idea of inserting an extra level of indirection, no
> > matter how powerful, is much murkier.

[Jim F]
> How so? It doesn't change the mapping semantics.

My assumption is that in your version, the dictionary would contain
special <object binding> objects which then would contain the
referenced objects.  E.g. {"limit": <binding: 100>, "doit": <binding:
<function ...>>}.  Thus, d["limit"] would be that <binding> object,
while previously it would return 100.

> Again, it would also make function global variable access
> faster and cleaner in some ways.

But I have other plans for that (if the optional static typing stuff
ever gets implemented).

> > however it would break a considerable amount of old code,
> > I think. 
> 
> Really? I wonder. I bet it would break alot less old
> code that other recent changes.

Oh?  Name some changes that broke a lot of code?

--Guido van Rossum (home page: http://www.python.org/~guido/)



From jeremy at cnri.reston.va.us  Thu Jan 20 18:36:32 2000
From: jeremy at cnri.reston.va.us (Jeremy Hylton)
Date: Thu, 20 Jan 2000 12:36:32 -0500 (EST)
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <14471.13834.480356.541389@anthem.cnri.reston.va.us>
References: <200001201601.LAA21359@eric.cnri.reston.va.us>
	<14471.13834.480356.541389@anthem.cnri.reston.va.us>
Message-ID: <14471.18336.257653.730100@bitdiddle.cnri.reston.va.us>

>>>>> "BAW" == Barry A Warsaw <bwarsaw at cnri.reston.va.us> writes:
>>>>> "Guido" == Guido van Rossum <guido at cnri.reston.va.us> writes:

  Guido> There are several other things I can think of now that were
  Guido> planned for 1.6: revamped import, rich comparisons, revised
  Guido> coercions, parallel for loop (for i in L; j in M: ...),
  Guido> extended slicing for all sequences.  I've also been thinking
  Guido> about making classes be types (not as huge a change as you
  Guido> think, if you don't allow subclassing built-in types), and
  Guido> adding a built-in array type suitable for use by NumPy.  I've
  Guido> also received a conservative GC patch that seems to be fairly
  Guido> easy to apply and has some of Tim Peters' blessing.

  BAW> All very cool things that could easily wait until 1.7.  After
  BAW> all, what's in a number?  If, as Andrew puts forth, getting a
  BAW> stable Python release with Unicode is very important for
  BAW> Python's future positioning, then I say let's go with his more
  BAW> modest list, mainly Unicode, sre, and Distutils.  We've already
  BAW> got string meths, tons of library improvements, and sundry
  BAW> other things.  That's a good enough laundry list for the next
  BAW> release.

We've had this conversation before, so it'll comes as no surprise that
I agree with you.  Question: If we go with the feature set you've
described, when will those features be ready?  What kind of schedule
could we set for releasing the first alpha?

Jeremy




From guido at CNRI.Reston.VA.US  Thu Jan 20 18:40:51 2000
From: guido at CNRI.Reston.VA.US (Guido van Rossum)
Date: Thu, 20 Jan 2000 12:40:51 -0500
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: Your message of "Thu, 20 Jan 2000 09:22:40 PST."
             <Pine.LNX.4.10.10001200907240.13911-100000@nebula.lyra.org> 
References: <Pine.LNX.4.10.10001200907240.13911-100000@nebula.lyra.org> 
Message-ID: <200001201740.MAA21608@eric.cnri.reston.va.us>

> Call it 1.6, per the rest of the thread.

OK.  I expect I'll get some complaints from some people who asked when
1.6 would be out (I've generally told them end of 2000); but it sounds
like a 1.7 would be necessary to fulfill the other promises, so it
shouldn't really matter -- it's all a case of relabeling for PR
purposes.

> Unicode: definitely. distutils seems pretty early, but I bet that some key
> concepts could be added to 1.6, to make the transition and continued
> development easier.

The point of adding distutils is that it will allow distribution of
packages without including distutils with each distribution.  Since
distutils was about 200K itself last time I looked, this is important.
I don't believe it would be good to have to say "My FooBar package is
really easy to install.  All you need to do is download and install
distutils, (which by the way is a 200K package that you have to
manually install), and then run "python setup.py" in the FooBar root
directory..."  This would be enough for the average person to run away
screaming.

I think I saw a distribution by AMK that had a setup.py that tried to
use distutils but had a crude fallback if distutils didn't exist;
however that defeats much of the purpose since the package author has
to figure out how to do the fallback.

Large distributions (e.g. NumPy) can afford to squeeze distutils in a
corner of their distribution, but for the average package it wouldn't
be of much use.

In other words, I'm for putting distutils in the next release,
essentially feature-freezing it.  Greg Ward, what do you think of
that?

> Note that if an announcement were made to the effect of "feature freeze on
> February 15; only bug fixes afterwards," that you would get a lot of
> people scrambling to submit their pet features. This would be a good way
> to light some fires, to see what kinds of things get completed (i.e. we
> may think some things aren't ready or are too far out, put that deadline
> in and those positions could change...)

I bet you we couldn't complete the import hooks by that date; I
consider imputil.py as a nice prototype, but the integration with the
C code is still missing.  Also the 50% slowdown is a problem I worry
about for inclusion a production version.  (Plus breakage of everybody
else's code who uses or hacks __import__; e.g. have you tested it with
rexec?)

> > (The import
> > utilities are not ready for prime time in my opinion; there are too
> > many issues.)
> 
> I'm waiting for that review :-)

It was kept up by the need to get the types documents out.

> If you raise issues, then I can knock them down. I don't see all that many
> at the moment. But I'm biased :-)
> 
> > Anybody care to be the pumpkin?  That would cut the discussion short;
> > otherwise the problem remains that I can't spend too much time on the
> > next release unless I get funded for it; what little money I've
> > received for CP4E I had better spend on getting some CP4E-related
> > results ASAP, because the next installment of this funding is very
> > much at stake...
> 
> I would volunteer for the pumpkin... around April-ish. My plate is rather
> full with completing mod_dav and then integrating that into Apache 2.0.
> Once the Apache integration begins, then I'd have some more free time.
> 
> But this begs the question of: what does the pumpkin-holder mean in the
> *Python* world?
> 
> If it is collating fixes, producing snapshots, etc, then I'm comfy with
> it. If it also contains responsibility for specific kinds of work, then
> Fred would probably veto me :-), as I've got an outstanding doc that I owe
> him (for about six months now... sigh; maybe I'll bribe MAL to write it; 
> he knows the interface :-)).
> 
> But stll: what's it mean? How does the pumpkin reduce the Guido-load, yet
> still enable the Guido-control?

Good questions.  I have to say that I feel reluctant to release any
kind of control -- yet at the same time I desperately need help
getting trivial stuff checked in.  One of the most important
time-consuming tasks is quality control: collecting fixes is all well
and good, but I routinely reject fixes that superficially look fine,
because they are subtly broken, or interfere with other plans, or just
because the code looks poorly written.  I also spend a lot of testing
before I check things in; running the standard test suite is a good
safeguard against general breakage, but you really have to play with
the code affected by the change before you can know that it works as
advertised.  My work attitude here means that what gets checked in is
generally rock solid, and that helps Python's reputation; but it is
very costly...

> [ I just had a talk about this with the guys at Inprise, re: InterBase,
>   mentioning that the Dictator model works well for Python, but doesn't
>   necessarily work well for new projects or commercially-started projects
>   due to control/prejudice issues. Python people like it because of the
>   resulting simplicity and cleanliness; I doubt we want a pumpkin approach
>   that would allow that to go away! ]

Agreed, of course.

--Guido van Rossum (home page: http://www.python.org/~guido/)



From da at ski.org  Thu Jan 20 18:57:51 2000
From: da at ski.org (David Ascher)
Date: Thu, 20 Jan 2000 09:57:51 -0800
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <14471.13834.480356.541389@anthem.cnri.reston.va.us>
Message-ID: <000701bf636f$de37c5e0$c355cfc0@ski.org>

[I just got GvR's post on the topic, but I'll send this anyway]

BAW:
> All very cool things that could easily wait until 1.7.  After all,
> what's in a number?

Guido has promised some of those features as being in 1.6 at conferences in
the past, but I agree that string methods for example are a more major
change than I'd expect to see in a 0.0.3-delta version change.

Maybe with a deadline (as Greg suggests) we can integrate some of the
pending patches (I agree with Greg that I at least would have found the time
for a revised patch for rich comparisons if I'd had a deadline -- call me
human =).
Coercion and extended slicing also seem like relatively minor changes,
compared with changing everything to be a class or adding GC!

Regardless, just like Greg, I'd like to know what a pumpkin-holder would
mean in the Python world.

I propose that it be called the Oracle instead.  As in, whoever is Oracle
would get some training with Tim Peters and learn how to channel G__do.  As
a Python user, I'd be most comfortable with such a change if the Oracle just
took over the technical stuff (reviewing patches, CVS checkins, running
tests, corralling help for doc & code, maintaining release notes, building
installers, etc.), but that the important decisions (e.g. whether to add a
feature to the core language) would be checked with G__do first.  We could
call the position "Administrative Assistant", but somehow that doesn't have
the prestige.

A progressive schedule where Guido watches over the Oracle periodically
would probably help build trust in the new mechanism.  The Oracle would be
expected to ask Guido for his opinion with everything at the beginning, and
as a trust builds between Guido and the Oracle and the community and the
mechanism, progressively less.

--david ascher




From gstein at lyra.org  Thu Jan 20 19:30:52 2000
From: gstein at lyra.org (Greg Stein)
Date: Thu, 20 Jan 2000 10:30:52 -0800 (PST)
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <200001201740.MAA21608@eric.cnri.reston.va.us>
Message-ID: <Pine.LNX.4.10.10001200950260.13911-100000@nebula.lyra.org>

On Thu, 20 Jan 2000, Guido van Rossum wrote:
>...
> In other words, I'm for putting distutils in the next release,
> essentially feature-freezing it.  Greg Ward, what do you think of
> that?

Oh, don't get me wrong. I'd like to see it in there for at least all the
reasons you cite. But it seems (to me) that it is still pretty alpha. But
hey: I'm shooting from the peanut gallery; we need GregW's comments.

> > Note that if an announcement were made to the effect of "feature freeze on
> > February 15; only bug fixes afterwards," that you would get a lot of
> > people scrambling to submit their pet features. This would be a good way
> > to light some fires, to see what kinds of things get completed (i.e. we
> > may think some things aren't ready or are too far out, put that deadline
> > in and those positions could change...)
> 
> I bet you we couldn't complete the import hooks by that date; I
> consider imputil.py as a nice prototype, but the integration with the
> C code is still missing.  Also the 50% slowdown is a problem I worry
> about for inclusion a production version.  (Plus breakage of everybody
> else's code who uses or hacks __import__; e.g. have you tested it with
> rexec?)

hehe... if the static typing is to be deferred, then I'll take that bet!

[discussion omitted; too tangental to this thread right now...]

>...
> Good questions.  I have to say that I feel reluctant to release any
> kind of control -- yet at the same time I desperately need help
> getting trivial stuff checked in.

Reading your comments below, we may be able to help.

First, presume that at least one (best would be several) people man the
"front lines" for any/all patches and bug reports. The front line can deal
with the bug reports, mostly by responding with "go away; enter it into
Jitterbug."

Patches fall under several catagories, detailed below:

> One of the most important
> time-consuming tasks is quality control: collecting fixes is all well
> and good, but I routinely reject fixes that superficially look fine,

Conversely, your "lieutenants" (LTs) would filter all ugly-looking
patches.

> because they are subtly broken,

If the LTs didn't catch these, then you could catch them from the checkin
diff email. However, the LTs would reduce the number of broken ones that
you would review.

> or interfere with other plans,

The LTs may know of this, but if not: you'd catch it at checkin time. The
patches would then be backed out, altered, or whatever.

> or just
> because the code looks poorly written.

The LTs would definitely catch this. If the style was *still* not up to
snuff, I'd have to believe it would only be in minor ways that you could
then touch up at your leisure.

> I also spend a lot of testing
> before I check things in;

Done by the LTs.

> running the standard test suite is a good
> safeguard against general breakage,

Ditto.

> but you really have to play with
> the code affected by the change before you can know that it works as
> advertised.

Ditto.

> My work attitude here means that what gets checked in is
> generally rock solid, and that helps Python's reputation; but it is
> very costly...

Based on my responses, I would venture to state that a group of LTs would
manage to keep the Python core rock solid, except for:

1) subtle breakages that require your broader knowledge of Python
2) changes that "go against the plan" (and the LTs were ignorant of it)
3) minor format issues

You would still review checkins, but the number of reviews would drop
since the (obvious) crap has been eliminated. #1 is based on your *broad*
knowledge of Python; I presume the LTs would be your match on various
subsets of Python. By keeping the LTs well-informed, #2 could be nearly
eliminated. #3 isn't that big of a deal, as I think your desired style is
relatively well-known and the LTs would simply endeavor to match existing
style.

You could avoid a lot of testing; you would probably be inclined to do
testing of items that you find dubious, but still this would be a
reduction.

=====

That may be an answer to the checkin problem. How about actual snapshots,
alphas, betas, releases, and accompanying notes/news/readme files? I
presume your LTs could run the alpha and beta aspects, but you would still
issue final releases.

Does your mail volume need to be reduced? (I think this has been asked
before) Specifically, would patches at python.org (and similar targets) need
to be established? (I would think so, as a matter of course, with the
expectation that some patches would still end up with you and need to be
bounced to patches@)

Cheers,
-g

-- 
Greg Stein, http://www.lyra.org/




From klm at digicool.com  Thu Jan 20 19:31:52 2000
From: klm at digicool.com (Ken Manheimer)
Date: Thu, 20 Jan 2000 13:31:52 -0500 (EST)
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <000701bf636f$de37c5e0$c355cfc0@ski.org>
Message-ID: <Pine.LNX.4.10.10001201321300.21609-100000@splat.digicool.com>

I must have missed the historic landmark where "pumpkin" was coined, but i
think i get the gist.  How about "Python Marshall" or "Python Activity
Marshall" (a la the PS_A_)?

Ken

David Ascher wrote:

> [...]
> Regardless, just like Greg, I'd like to know what a pumpkin-holder would
> mean in the Python world.
> 
> I propose that it be called the Oracle instead.  As in, whoever is Oracle
> would get some training with Tim Peters and learn how to channel G__do.  As
> a Python user, I'd be most comfortable with such a change if the Oracle just
> took over the technical stuff (reviewing patches, CVS checkins, running
> tests, corralling help for doc & code, maintaining release notes, building
> installers, etc.), but that the important decisions (e.g. whether to add a
> feature to the core language) would be checked with G__do first.  We could
> call the position "Administrative Assistant", but somehow that doesn't have
> the prestige.
> 
> A progressive schedule where Guido watches over the Oracle periodically
> would probably help build trust in the new mechanism.  The Oracle would be
> expected to ask Guido for his opinion with everything at the beginning, and
> as a trust builds between Guido and the Oracle and the community and the
> mechanism, progressively less.




From gstein at lyra.org  Thu Jan 20 19:42:43 2000
From: gstein at lyra.org (Greg Stein)
Date: Thu, 20 Jan 2000 10:42:43 -0800 (PST)
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <Pine.LNX.4.10.10001201321300.21609-100000@splat.digicool.com>
Message-ID: <Pine.LNX.4.10.10001201039320.13911-100000@nebula.lyra.org>

On Thu, 20 Jan 2000, Ken Manheimer wrote:
> I must have missed the historic landmark where "pumpkin" was coined, but i
> think i get the gist.  How about "Python Marshall" or "Python Activity
> Marshall" (a la the PS_A_)?

The "pumpkin" term comes from Perl-land...

I'm not super clear on the pumpkin-holders's entire job, but I think it is
basically the guy who sees that the version for which he "holds the
pumpkin" is completed and shipped. Not necessarily by himself :-), but as
the overseer (or "release manager" if you will).

The current Perl pumpkin-holder is a guy at ActiveState. I think it
changes for each version.

Cheers,
-g

-- 
Greg Stein, http://www.lyra.org/




From gvwilson at nevex.com  Thu Jan 20 19:51:17 2000
From: gvwilson at nevex.com (gvwilson at nevex.com)
Date: Thu, 20 Jan 2000 13:51:17 -0500 (EST)
Subject: [Python-Dev] Python 1.6 timing (fwd)
Message-ID: <Pine.LNX.4.10.10001201346510.7719-100000@akbar.nevex.com>

Guido> There are several other things I can think of now that were
Guido> planned for 1.6: revamped import, rich comparisons, revised
Guido> coercions, parallel for loop (for i in L; j in M: ...),
Guido> extended slicing for all sequences.  I've also been thinking
Guido> about making classes be types (not as huge a change as you
Guido> think, if you don't allow subclassing built-in types), and
Guido> adding a built-in array type suitable for use by NumPy.  I've
Guido> also received a conservative GC patch that seems to be fairly
Guido> easy to apply and has some of Tim Peters' blessing.

BAW> All very cool things that could easily wait until 1.7.  After
BAW> all, what's in a number?

GVW writes:

I agree on all counts except garbage collection --- I'm half-way through
the second day of the Python class I teach at Los Alamos (the people who
are funding the Python tool design competition), and it's come up a couple
of times.  People want to be able to prototype meshes, throw callbacks
around without worrying about circularity, and some other things that I
don't really understand yet.  There's also a couple of smart guys in the
class who are wondering about CPython vs. JPython ("So this'll be safe in
one version of the language, but not in the other?"), and about marketing
("Help me win a feature comparison against Java in my group...").

There's also been questions about tighter integration of NumPy (e.g.
overloading operators rather than calling 'greater()' to do comparison),
but I think that's a separate discussion...

My $0.02,
Greg




From tismer at tismer.com  Thu Jan 20 20:11:13 2000
From: tismer at tismer.com (Christian Tismer)
Date: Thu, 20 Jan 2000 20:11:13 +0100
Subject: [Python-Dev] Python 1.6 timing (fwd)
References: <Pine.LNX.4.10.10001201346510.7719-100000@akbar.nevex.com>
Message-ID: <38875DD1.B6596@tismer.com>

[garbage collection]

gvwilson at nevex.com wrote:

> I agree on all counts except garbage collection --- I'm half-way through
> the second day of the Python class I teach at Los Alamos (the people who
> are funding the Python tool design competition), and it's come up a couple
> of times.  People want to be able to prototype meshes, throw callbacks
> around without worrying about circularity, and some other things that I
> don't really understand yet.  There's also a couple of smart guys in the
> class who are wondering about CPython vs. JPython ("So this'll be safe in
> one version of the language, but not in the other?"), and about marketing
> ("Help me win a feature comparison against Java in my group...").

Guido once posted some proposal of a hybrid system *with* refcounts
and some additional garbage collection scheme to match circular
things. I believe this is a much better approach than what Java
and therefor also JPython does at the moment.

Although people might argue differently, I'm pretty sure that
reference counting is the stronger concept. By reference counting,
the idea of object ownership can be made explicit. This plays a
central role in the Corba specification for instance, and I made
the same observation when implementing continuations for Stackless
Python. Refcounts are no burden but a virtue.
Even better: Refcounting can lead to many new optimizations if
we pay the cost to make INCREF/DECREF into methods. It has its cost
(about 10 percent less pystones), but massive long-term benefits.

I'm currently in charge to develop a custom version of Python's
builtin types where this concept is used. Everything is refcounted,
but without storing the refcounts in the objects. This is possible
(proven) and will be shown in my next paper.

Conclusion: I vote for a kind of GC that does just what refcounts
cannot do, but please keep with the refcounts.

cheers - chris

-- 
Christian Tismer             :^)   <mailto:tismer at appliedbiometrics.com>
Virtual Photonics GmbH       :     Have a break! Take a ride on Python's
Carnotstr. 6                 :    *Starship* http://starship.python.net
10587 Berlin                 :     PGP key -> http://wwwkeys.pgp.net
PGP Fingerprint       E182 71C7 1A9D 66E9 9D15  D3CC D4D7 93E2 1FAE F6DF
     we're tired of banana software - shipped green, ripens at home



From tim_one at email.msn.com  Thu Jan 20 20:47:01 2000
From: tim_one at email.msn.com (Tim Peters)
Date: Thu, 20 Jan 2000 14:47:01 -0500
Subject: [Python-Dev] Changing existing class instances
In-Reply-To: <200001201520.KAA21137@eric.cnri.reston.va.us>
Message-ID: <000301bf637f$1f1c2d80$b72d153f@tim>

[Tim worries about stomping on unintended classes/defs]

[Guido]
> Agreed that that would be bad.  But I wouldn't search outer
> scopes -- I would only look for a class/def that I was about
> to stomp on.

Maybe I just don't grasp what that means, exactly.  Fair enough, since I'm
not expressing myself clearly either!

Suppose someone does

from Tkinter import *

in my.py, and later in my.py just *happens* to define, at module level,

class Misc:
    blah blah blah

Now Misc was already in my.py's global namespace because Tkinter.py just
happens to export a class of that name too (more by accident than design --
but accidents are what I'm most worried about here).

At the time my.py defines Misc, does Misc count as a class we're "about to
stomp on"?  If so-- & I've assumed so --it would wreak havoc.

But if not, I don't see how this case can be reliably distinguished "by
magic" from the cases where update is desired (if people are doing dynamic
updates to a long-running program, a new version of a class can come from
anywhere, so nothing like original file name or line number can distinguish
correctly either).

>> Modules differ because their namespace "search path"
>> consists solely of the more-global-than-global <wink>
>> sys.modules.

> "The search path doesn't enter into it."

I agree, but am at a loss to describe what's happening in the case above
using other terminology <wink>.  In a sense, you need a system-wide "unique
handle" to support bulletproof updating, and while sys.modules has supplied
that all along for module objects (in the form of the module name), I don't
believe there's anything analogous to key off of for function or class
objects.

>>    [suggesting]
>>    new.update(class_or_def_old, class_or_def_new)

> Only a slight semantics change (which my full proposal
> would require too): function objects would become mutable
> -- their func_code, func_defaults, func_doc and func_globals
> fields (and, why not, func_name too) should be changeable.

Of course I meant "no new semantics" in the sense of "won't cause current
exception-free code to alter behavior in any way".

> If you make all these assignable, it doesn't even have to
> be a privileged function.

I'm all for that!

> [sketching a Python approach to "updating import/reload"
>  building on the hypothetical new.update]

> That's certainly a reasonable compromise.  Note that the
> update on a class should imply an update on its methods,
> right?

Hadn't considered that!  Of course you're right.  So make it a pair of
nested loops <wink>.

so-long-as-it-can-be-written-in-python-it's-easy-ly
    y'rs  - tim





From guido at CNRI.Reston.VA.US  Thu Jan 20 21:02:20 2000
From: guido at CNRI.Reston.VA.US (Guido van Rossum)
Date: Thu, 20 Jan 2000 15:02:20 -0500
Subject: [Python-Dev] Changing existing class instances
In-Reply-To: Your message of "Thu, 20 Jan 2000 14:47:01 EST."
             <000301bf637f$1f1c2d80$b72d153f@tim> 
References: <000301bf637f$1f1c2d80$b72d153f@tim> 
Message-ID: <200001202002.PAA22435@eric.cnri.reston.va.us>

> [Tim worries about stomping on unintended classes/defs]
> 
> [Guido]
> > Agreed that that would be bad.  But I wouldn't search outer
> > scopes -- I would only look for a class/def that I was about
> > to stomp on.
> 
> Maybe I just don't grasp what that means, exactly.  Fair enough, since I'm
> not expressing myself clearly either!
> 
> Suppose someone does
> 
> from Tkinter import *
> 
> in my.py, and later in my.py just *happens* to define, at module level,
> 
> class Misc:
>     blah blah blah
> 
> Now Misc was already in my.py's global namespace because Tkinter.py just
> happens to export a class of that name too (more by accident than design --
> but accidents are what I'm most worried about here).

For a second I thought you got me there!

> At the time my.py defines Misc, does Misc count as a class we're "about to
> stomp on"?  If so-- & I've assumed so --it would wreak havoc.
> 
> But if not, I don't see how this case can be reliably distinguished "by
> magic" from the cases where update is desired (if people are doing dynamic
> updates to a long-running program, a new version of a class can come from
> anywhere, so nothing like original file name or line number can distinguish
> correctly either).

Fortunately, there's magic available: recently, all classes have a
__module__ attribute that is set to the full name of the module that
defined it (its key in __sys__.modules).

For functions, we would have to invent something similar.

> >> Modules differ because their namespace "search path"
> >> consists solely of the more-global-than-global <wink>
> >> sys.modules.
> 
> > "The search path doesn't enter into it."
> 
> I agree, but am at a loss to describe what's happening in the case above
> using other terminology <wink>.  In a sense, you need a system-wide "unique
> handle" to support bulletproof updating, and while sys.modules has supplied
> that all along for module objects (in the form of the module name), I don't
> believe there's anything analogous to key off of for function or class
> objects.
> 
> >>    [suggesting]
> >>    new.update(class_or_def_old, class_or_def_new)
> 
> > Only a slight semantics change (which my full proposal
> > would require too): function objects would become mutable
> > -- their func_code, func_defaults, func_doc and func_globals
> > fields (and, why not, func_name too) should be changeable.
> 
> Of course I meant "no new semantics" in the sense of "won't cause current
> exception-free code to alter behavior in any way".
> 
> > If you make all these assignable, it doesn't even have to
> > be a privileged function.
> 
> I'm all for that!
> 
> > [sketching a Python approach to "updating import/reload"
> >  building on the hypothetical new.update]
> 
> > That's certainly a reasonable compromise.  Note that the
> > update on a class should imply an update on its methods,
> > right?
> 
> Hadn't considered that!  Of course you're right.  So make it a pair of
> nested loops <wink>.
> 
> so-long-as-it-can-be-written-in-python-it's-easy-ly
>     y'rs  - tim

--Guido van Rossum (home page: http://www.python.org/~guido/)



From guido at CNRI.Reston.VA.US  Thu Jan 20 21:12:58 2000
From: guido at CNRI.Reston.VA.US (Guido van Rossum)
Date: Thu, 20 Jan 2000 15:12:58 -0500
Subject: [Python-Dev] Python 1.6 timing (fwd)
In-Reply-To: Your message of "Thu, 20 Jan 2000 20:11:13 +0100."
             <38875DD1.B6596@tismer.com> 
References: <Pine.LNX.4.10.10001201346510.7719-100000@akbar.nevex.com>  
            <38875DD1.B6596@tismer.com> 
Message-ID: <200001202012.PAA22501@eric.cnri.reston.va.us>

> Conclusion: I vote for a kind of GC that does just what refcounts
> cannot do, but please keep with the refcounts.

The patch that I received and that has Tim's <0.5 blessing> does just
that.  I haven't had the time to understand why it doesn't have his
<1.0 blessing>.

--Guido van Rossum (home page: http://www.python.org/~guido/)



From tim_one at email.msn.com  Thu Jan 20 21:35:44 2000
From: tim_one at email.msn.com (Tim Peters)
Date: Thu, 20 Jan 2000 15:35:44 -0500
Subject: [Python-Dev] Python 1.6 timing (fwd)
In-Reply-To: <200001202012.PAA22501@eric.cnri.reston.va.us>
Message-ID: <000901bf6385$eccfba20$b72d153f@tim>

[Christian]
> Conclusion: I vote for a kind of GC that does just
> what refcounts cannot do, but please keep with the
> refcounts.

[Guido]
> The patch that I received and that has Tim's <0.5
> blessing> does just that. I haven't had the time to
> understand why it doesn't have his <1.0 blessing>.

Primarily because it doesn't reclaim the most common cycles; e.g., cycles
among class instances aren't touched.  This seems easily repairable, but at
an unknown cost (it needs to do the "reachability" transitive closure
business from the set of all "suspicious" objects, and instances are never
considered suspicious now; adding them will certainly cause a lot more
pointer chasing).

Apart from that, the code appears unreasonably expensive as written today,
using e.g. splay trees instead of hash tables to keep track of objects.

The author hasn't said anything more in a bit over two weeks, so I suspect
he's off on other things now.  The technical approach is sound, but even its
inventor (Rafael Lins; Toby Kelsey may have reinvented it on his own,
though) stresses that getting it to run fast is difficult.

needs-work!-ly y'rs  - tim, who hasn't the time to do it





From tismer at tismer.com  Thu Jan 20 21:35:27 2000
From: tismer at tismer.com (Christian Tismer)
Date: Thu, 20 Jan 2000 21:35:27 +0100
Subject: [Python-Dev] Stackless Python 1.0 + Continuations 0.6
Message-ID: <3887718F.82E1B327@tismer.com>

ANNOUNCING:

               Stackless Python 1.0
           A Python Implementation That
             Does Not Use The C Stack

               * plus the real toy *

              Continuation Module 0.6
        Continuations as First Class Objects

What is it?
A plugin-replacement for core Python.
It should run any program which runs under Python 1.5.2 .
But it does not need space on the C stack.

Why did I write it?
Stackless Python was never written before (afaik), since it
was said to be impossible without major rewrites of core Python.
I have proven the controverse: It is easy to write, just hard to think.
About 3 times harder was finally the continuation module.
The whole project took about 6 man months where 80 percent of
the time was thinking and trying. The rest was coding and to
become a reference counting champion :-)

Recent changes:
Version 1.0 has been optimized like hell and is now
3-5 percent faster than Standard Python.

Continuation module is in version 0.6, very stable,
and it allows to save a program's "future" at any
time, in a portable way. Continuations are callable
Python objects with a very small footprint.

Who needs it?
Since the continuations are done, this is no more
only useful for C programmers who want to try certain new
ideas. Everybody who is interested to develop his
own generators, coroutines and tiny threads is
invited to check it out.

Status of the final 1.0:
Pystone works correctly and is 5% faster than standard
Python. Version 0.3 was 10 percent slower.
Continuations work with PythonWin and Idle.

The overall result is now better than expected,
and I'm happy to call this *FINAL*
(until the next version of course:)

Downloadable files can be found at
http://www.tismer.com/research/stackless/

Some older documentation:
http://www.tismer.com/research/stackless/stackless.htm

Some better documentation can be found in my IPC8 paper:
http://www.tismer.com/research/stackless/spc_final.zip
or be read directly as HTML
http://www.tismer.com/research/stackless/spcpaper.htm

Source code and a VC++6.0 build for Windows (340K):
http://www.tismer.com/research/stackless/spc_win32.zip

cheers - chris

== 
Christian Tismer             :^)   <mailto:tismer at appliedbiometrics.com>
Applied Biometrics GmbH      :     Have a break! Take a ride on Python's
Kaiserin-Augusta-Allee 101   :    *Starship* http://starship.python.net
10553 Berlin                 :     PGP key -> http://wwwkeys.pgp.net
PGP Fingerprint       E182 71C7 1A9D 66E9 9D15  D3CC D4D7 93E2 1FAE F6DF
     we're tired of banana software - shipped green, ripens at home

<P><A HREF="http://www.tismer.com/research/stackless/stackless.htm">
Stackless Python 1.0</A>
 - a version of Python 1.5.2 that does not need space on the C
stack.  (20-Jan-00)



From bwarsaw at cnri.reston.va.us  Thu Jan 20 22:12:37 2000
From: bwarsaw at cnri.reston.va.us (Barry A. Warsaw)
Date: Thu, 20 Jan 2000 16:12:37 -0500 (EST)
Subject: [Python-Dev] Python 1.6 timing
References: <Pine.LNX.4.10.10001201321300.21609-100000@splat.digicool.com>
	<Pine.LNX.4.10.10001201039320.13911-100000@nebula.lyra.org>
Message-ID: <14471.31301.504670.201702@anthem.cnri.reston.va.us>

We'd have to rework the CVS arrangement in order to give non-CNRI
employees write access to the tree.  I think I know how I'd go about
this, and it wouldn't be too hard, just a bit time-consuming.  If
that's the way we're going to go, I can start making plans.

-Barry



From guido at CNRI.Reston.VA.US  Thu Jan 20 22:16:39 2000
From: guido at CNRI.Reston.VA.US (Guido van Rossum)
Date: Thu, 20 Jan 2000 16:16:39 -0500
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: Your message of "Thu, 20 Jan 2000 16:12:37 EST."
             <14471.31301.504670.201702@anthem.cnri.reston.va.us> 
References: <Pine.LNX.4.10.10001201321300.21609-100000@splat.digicool.com> <Pine.LNX.4.10.10001201039320.13911-100000@nebula.lyra.org>  
            <14471.31301.504670.201702@anthem.cnri.reston.va.us> 
Message-ID: <200001202116.QAA22943@eric.cnri.reston.va.us>

[Barry]
> We'd have to rework the CVS arrangement in order to give non-CNRI
> employees write access to the tree.  I think I know how I'd go about
> this, and it wouldn't be too hard, just a bit time-consuming.  If
> that's the way we're going to go, I can start making plans.

I think before you make such changes you'd have to talk to Bob (good
luck).

I don't mind applying patches and doing the checkins -- it's the
decision-making that's time-consuming.

--Guido van Rossum (home page: http://www.python.org/~guido/)



From da at ski.org  Thu Jan 20 22:28:24 2000
From: da at ski.org (David Ascher)
Date: Thu, 20 Jan 2000 13:28:24 -0800
Subject: [Python-Dev] Python 1.6 timing (fwd)
In-Reply-To: <Pine.LNX.4.10.10001201346510.7719-100000@akbar.nevex.com>
Message-ID: <001401bf638d$486488f0$c355cfc0@ski.org>

Daddy Warbucks (uh, Greg Wilson =):

> There's also been questions about tighter integration of NumPy (e.g.
> overloading operators rather than calling 'greater()' to do comparison),
> but I think that's a separate discussion...

That's the rich comparison proposal which Guido mentioned.

--david



From bwarsaw at cnri.reston.va.us  Thu Jan 20 22:30:24 2000
From: bwarsaw at cnri.reston.va.us (Barry A. Warsaw)
Date: Thu, 20 Jan 2000 16:30:24 -0500 (EST)
Subject: [Python-Dev] Python 1.6 timing
References: <Pine.LNX.4.10.10001201321300.21609-100000@splat.digicool.com>
	<Pine.LNX.4.10.10001201039320.13911-100000@nebula.lyra.org>
	<14471.31301.504670.201702@anthem.cnri.reston.va.us>
	<200001202116.QAA22943@eric.cnri.reston.va.us>
Message-ID: <14471.32368.730988.252872@anthem.cnri.reston.va.us>

>>>>> "Guido" == Guido van Rossum <guido at cnri.reston.va.us> writes:

    Guido> I think before you make such changes you'd have to talk to
    Guido> Bob (good luck).

Heh.

    Guido> I don't mind applying patches and doing the checkins --
    Guido> it's the decision-making that's time-consuming.

Then maybe the current CVS arrangement is fine (cool with me).

-Barry



From klm at digicool.com  Thu Jan 20 23:08:28 2000
From: klm at digicool.com (Ken Manheimer)
Date: Thu, 20 Jan 2000 17:08:28 -0500 (EST)
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <14471.31301.504670.201702@anthem.cnri.reston.va.us>
Message-ID: <Pine.LNX.4.10.10001201646500.22921-100000@splat.digicool.com>

On Thu, 20 Jan 2000, Barry A. Warsaw wrote:

> We'd have to rework the CVS arrangement in order to give non-CNRI
> employees write access to the tree.  I think I know how I'd go about
> this, and it wouldn't be too hard, just a bit time-consuming.  If
> that's the way we're going to go, I can start making plans.

Though it may be moot if guido's going to continue mediating the checkins,
maybe this would be interesting (if only for barry, to compare
procedures). 

We basically use a captive cvs-":ext:"-over-ssh method, where the captive
.ssh/authorized_keys command is quite succinct:

command="set $SSH_ORIGINAL_COMMAND; shift; exec cvs $@" 1024 35 ...

The shellisms (set/shift/exec cvs $@) lock the user of the qualifying key
into executing a cvs command, and only a cvs command.

Also, for us the checkins are to a public mirror of our CVS repository, so
penetration of the security there doesn't jepordize the master repository
base.  We don't currently have any outsiders checking into our master
repository, and it doesn't seem to me that CVS provides sufficiently
managable discretion for doing that.

Oh, and a disappointment - the account under which cvs conducts the
checkins is the account on the CVS server host, not that of the host where
the checkins are being done.  This means that you can't use a single
account to serve multiple remote users (preventing masquerading quite
reliably by using a separate authorized_key public-key entry for each
remote user).  Therefore we have to have distinct (nailed-down) accounts
for each checkin-privileged person - more management burden.

Ken




From tim_one at email.msn.com  Fri Jan 21 00:53:18 2000
From: tim_one at email.msn.com (Tim Peters)
Date: Thu, 20 Jan 2000 18:53:18 -0500
Subject: [Python-Dev] Python 1.6 timing (fwd)
In-Reply-To: <001401bf638d$486488f0$c355cfc0@ski.org>
Message-ID: <000201bf63a1$8641b1c0$6ea0143f@tim>

[Greg Wilson]
> There's also been questions about tighter integration
> of NumPy (e.g. overloading operators rather than
> calling 'greater()' to do comparison), but I think
? that's a separate discussion...

[David Ascher]
> That's the rich comparison proposal which Guido mentioned.

But there's also been talk about moving (at least) the basic NumPy array
type into the core.  This would be a Good Thing.  Speaking for my employer,
however, only Unicode is an Important Thing <wink>.

As a developer, I have railed against schedule-driven release cycles.
Python tends toward the opposite end of that spectrum, driven by features no
matter how bloody long they take.  Add Unicode to what's already waiting to
go, and that's *good enough* reason for a major release; heck, it's been 9
months & we haven't even had a  1.5.2 bugfix patch.

BTW, do the Perl-Porters have real jobs?

pay-me-to-do-python-releases-and-you'll-get-a-major-new-
    release-every-three-days<wink>-ly y'rs  - tim





From da at ski.org  Fri Jan 21 01:01:45 2000
From: da at ski.org (David Ascher)
Date: Thu, 20 Jan 2000 16:01:45 -0800
Subject: [Python-Dev] Python 1.6 timing (fwd)
In-Reply-To: <000201bf63a1$8641b1c0$6ea0143f@tim>
Message-ID: <002601bf63a2$b4acf9b0$c355cfc0@ski.org>

Tim Peters

> But there's also been talk about moving (at least) the basic NumPy array
> type into the core.  This would be a Good Thing.

IMNSHO, moving the current NumPy array into the core would be a Bad Thing.
Moving a new similar object with cleaned up semantics and better
implementation in would be a Good Thing.  But it won't happen until 1.7 at
the earliest, as the semantics haven't even been agreed on, let alone the
code written.

--david




From da at ski.org  Fri Jan 21 01:07:16 2000
From: da at ski.org (David Ascher)
Date: Thu, 20 Jan 2000 16:07:16 -0800
Subject: [Python-Dev] Conference Schedules
Message-ID: <002701bf63a3$79a15ae0$c355cfc0@ski.org>

Given the rush of interesting discussions and progress which occurs in the
two weeks before Python conferences, I propose that we have a bi-weekly
conference.  We'll just have to remember to cancel them at the last minute
except a couple of times a year.

--david ascher
-------------- next part --------------
A non-text attachment was scrubbed...
Name: David Ascher.vcf
Type: text/x-vcard
Size: 527 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/python-dev/attachments/20000120/3b692d76/attachment.vcf>

From gstein at lyra.org  Fri Jan 21 01:53:59 2000
From: gstein at lyra.org (Greg Stein)
Date: Thu, 20 Jan 2000 16:53:59 -0800 (PST)
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <14471.31301.504670.201702@anthem.cnri.reston.va.us>
Message-ID: <Pine.LNX.4.10.10001201653130.13911-100000@nebula.lyra.org>

On Thu, 20 Jan 2000, Barry A. Warsaw wrote:
> We'd have to rework the CVS arrangement in order to give non-CNRI
> employees write access to the tree.  I think I know how I'd go about
> this, and it wouldn't be too hard, just a bit time-consuming.  If
> that's the way we're going to go, I can start making plans.

Or move the CVS tree off-site.

Cheers,
-g

-- 
Greg Stein, http://www.lyra.org/




From guido at CNRI.Reston.VA.US  Fri Jan 21 02:29:30 2000
From: guido at CNRI.Reston.VA.US (Guido van Rossum)
Date: Thu, 20 Jan 2000 20:29:30 -0500
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: Your message of "Thu, 20 Jan 2000 10:30:52 PST."
             <Pine.LNX.4.10.10001200950260.13911-100000@nebula.lyra.org> 
References: <Pine.LNX.4.10.10001200950260.13911-100000@nebula.lyra.org> 
Message-ID: <200001210129.UAA28292@eric.cnri.reston.va.us>

(I accidentally mailed this only to Greg; here's a repost of the
relevant parts to the list:)

[me]
> > Good questions.  I have to say that I feel reluctant to release any
> > kind of control -- yet at the same time I desperately need help
> > getting trivial stuff checked in.

[Greg Stein]
> Reading your comments below, we may be able to help.

[...Proposal of lieutenants condensed...]

> Based on my responses, I would venture to state that a group of LTs would
> manage to keep the Python core rock solid, except for:
> 
> 1) subtle breakages that require your broader knowledge of Python
> 2) changes that "go against the plan" (and the LTs were ignorant of it)
> 3) minor format issues
> 
> You would still review checkins, but the number of reviews would drop
> since the (obvious) crap has been eliminated. #1 is based on your *broad*
> knowledge of Python; I presume the LTs would be your match on various
> subsets of Python. By keeping the LTs well-informed, #2 could be nearly
> eliminated. #3 isn't that big of a deal, as I think your desired style is
> relatively well-known and the LTs would simply endeavor to match existing
> style.
> 
> You could avoid a lot of testing; you would probably be inclined to do
> testing of items that you find dubious, but still this would be a
> reduction.
> 
> =====
> 
> That may be an answer to the checkin problem. How about actual snapshots,
> alphas, betas, releases, and accompanying notes/news/readme files? I
> presume your LTs could run the alpha and beta aspects, but you would still
> issue final releases.

There's a lot of work in these (you may have noticed that the release
notes got sloppier as 1.5.2 neared its completion).

I would be happy to have the responsibility to decide to release
without the burden of having to do all the work.

> Does your mail volume need to be reduced? (I think this has been asked
> before) Specifically, would patches at python.org (and similar targets) need
> to be established? (I would think so, as a matter of course, with the
> expectation that some patches would still end up with you and need to be
> bounced to patches@)

It's not the mail volume that bothers me -- I can ignore 100s of
messages a day very quickly.  It's the time it takes to respond to all
of them.


As an experiment, I've collected about 40 messages with suggested
patches in them that I found in my inbox; the oldest are nearly two
years old.

You can access these from this address:

http://www.python.org/~guido/patch/

I would love any help I could get in responding with these, and taking
action in the form of patches.  I propose that if you decide that a
particular patch is worth checking in, you ask the author for the
bugrelease or wetsign disclaimer and let me know that I can check it
in; if changes to the patch are needed, I propose that you negotiate
these with the author first.  (I often ask them to test my version of
a patch when I have style suggestions but don't have access the target
platform or problem it solves.)

--Guido van Rossum (home page: http://www.python.org/~guido/)



From tim_one at email.msn.com  Fri Jan 21 10:38:21 2000
From: tim_one at email.msn.com (Tim Peters)
Date: Fri, 21 Jan 2000 04:38:21 -0500
Subject: [Python-Dev] Changing existing class instances
In-Reply-To: <Pine.LNX.4.10.10001192342450.13911-100000@nebula.lyra.org>
Message-ID: <001801bf63f3$414e0c60$ec2d153f@tim>

[Greg Stein]
> ...
> In other words, I definitely would support a new class
> object behavior that allows us to update a class' set of
> bases and dictionary on the fly.  This could then be used
> to support my solution for the recursive type scenario (which,
> in turn, means that we don't have to introduce Yet Another
> Namespace into Python to hold type names).

Parenthetically, I never grasped the appeal of the parenthetical comment.
Yet Another Namespace for Yet Another Entirely New Purpose seems highly
*desirable* to me!  Trying to overload the current namespace set makes it so
much harder to see that these are compile-time gimmicks, and users need to
be acutely aware of that if they're to use it effectively.  Note that I
understand (& wholly agree with) the need for runtime introspection.

different-things-different-rules-ly y'rs  - tim





From tim_one at email.msn.com  Fri Jan 21 10:38:24 2000
From: tim_one at email.msn.com (Tim Peters)
Date: Fri, 21 Jan 2000 04:38:24 -0500
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <20000120113352.A23763@trump.amber.org>
Message-ID: <001901bf63f3$432404e0$ec2d153f@tim>

[Christopher Petrilli]
> Heck, Python is infinately more conservative in its
> numbering than a lot of projects.  All that was mentioned
> would normally be enough to call it 2.0 easily. :-)  Modesty
> can be counter productive in PR  business...

Indeed, where I work a number of managers met the suggestion to use Python
1.5.x with "what?! we don't want to use software that's barely out of alpha
release -- besides, Perl is already on release 5".  I hear that Guido got
normal American glasses -- time to do normal American hyperinflated version
numbering too.

heck-ms-windows-will-soon-be-at-version-2000<wink>-ly y'rs  - tim





From tim_one at email.msn.com  Fri Jan 21 10:38:26 2000
From: tim_one at email.msn.com (Tim Peters)
Date: Fri, 21 Jan 2000 04:38:26 -0500
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <14471.14877.434886.471929@amarok.cnri.reston.va.us>
Message-ID: <001a01bf63f3$4473b660$ec2d153f@tim>

[Andrew M. Kuchling]
> ...
> Similarly, does the conservative GC patch splatter changes
> all over the place, or is it very localized?

Part of its problem is that it's *too* localized (which was, paradoxically,
I suspect part of its initial quick-eyeball appeal to Guido -- it "looks
like" an amazingly self-contained patch).  For example, all the code to
chase pointers in various types of objects is hiding in a single function,
which does a string of "if type is list then this else if type is tuple then
that ..." tests.  This stuff clearly needs to be distributed across the
object implementations and dispatched to via a new slot in type objects;
there's no code for that now.

I expect it would take a minimum of two weeks (full-time work) to make this
code ready for prime time (but mostly to slash the space and time use -- and
with no certainty of "good enough" in the end).

BTW, "conservative" is a misleading adjective for this approach -- it never
guesses ("guessing on the safe side" whether or not some bit pattern is a
pointer is what "conservative" customarily means in the GC world).

> Is adding the NumPy array type straightforward?

DavidA nixed that one in no uncertain terms!

maybe-hp-will-give-up-unicode-and-we-can-release-tomorrow-ly
    y'rs  - tim





From tim_one at email.msn.com  Fri Jan 21 10:52:13 2000
From: tim_one at email.msn.com (Tim Peters)
Date: Fri, 21 Jan 2000 04:52:13 -0500
Subject: [Python-Dev] Python 1.6 timing (fwd)
In-Reply-To: <Pine.LNX.4.10.10001201346510.7719-100000@akbar.nevex.com>
Message-ID: <001d01bf63f5$318e2600$ec2d153f@tim>

[Greg Wilson]
> ...
> There's also a couple of smart guys in the class who are
> wondering about CPython vs. JPython ("So this'll be safe in
> one version of the language, but not in the other?"),

Greg, people who have been exposed to Fortran (this is LANL, right <wink>?)
can't possibly have a problem with the concept of "not defined by the
standard".  Don't sell these as different *versions* of the language, but as
different implementations.  That's what they are.  The Python *language*
doesn't define anything about the lifetime of objects.  Even when CPython
grows "real GC", thanks to refcounting too you'll still be able to *rely* on
behaviors in CPython you'll see only accidentally in JPython.  You do so at
your own risk, same as e.g. you rely on floating point Fortran x+y+z getting
evaluated "left to right" at your own risk (BTW, x+y+z *is* "left to right"
in Python -- maybe they'll trade that for the lack of GC promises <wink>).





From tim_one at email.msn.com  Fri Jan 21 11:22:51 2000
From: tim_one at email.msn.com (Tim Peters)
Date: Fri, 21 Jan 2000 05:22:51 -0500
Subject: [Python-Dev] Changing existing class instances
In-Reply-To: <200001202002.PAA22435@eric.cnri.reston.va.us>
Message-ID: <001e01bf63f9$79660980$ec2d153f@tim>

[Tim, still worried about stomping on unintended classes/defs]

[example abusing Tkinter.Misc]

> For a second I thought you got me there!

That's twice as long as I thought you'd think that, so I win after all
<wink>.

> Fortunately, there's magic available: recently, all classes
> have a __module__ attribute that is set to the full name
> of the module that defined it (its key in __sys__.modules).
>
> For functions, we would have to invent something similar.

OK!  I didn't know about class.__module__ -- I hope you realize that relying
on your time machine is making you lazy <wink>.

I remain uncomfortable with automagic updating, but not as much so.  Both
kinds of errors still seem possible to me:

1. Automagically updating when it wasn't wanted.

Examples of this are getting harder to come by <wink>.  Off the top of my
head I'm reduced to stuff like this:

>>> adders = []
>>> for i in range(10):
	def adder(y, x=i):
		return y+x
	adders.append(adder)


>>> adders[2](40)
42
>>> adders[9](33)
42
>>>

"That kind of thing" has got to be rare, but can't be non-existent either
(well, isn't -- I've done it).

2. Failing to automagically update when it was wanted.

Implicit in the discussion so far is that long-running systems want to
update code at a granularity no finer than module level.  Is that realistic?
I'm unsure.  It's certainly easy to *imagine* the app running an updater
server thread, accepting new source for functions and classes, and offering
to compile and install the objects.

Under the explicit new.update scheme, such a service needn't bother clients
with communicating the full name of the original module; heck, in a *truly*
long-running app, over time the source tree will change, and classes and
functions will migrate across modules.  That will be a problem for the
explicit scheme too (how does it know *which* "class Misc" to update) -- but
at least it's an explicit problem then, and not a "mysterous failure" of
hidden magic.


I could live with both of those (#1 is more worrisome); but think it easier
all around to give the users some tools and tell them to solve the problems
however they see fit.

or-maybe-we-already-agreed-about-that-ly y'rs  - tim





From gstein at lyra.org  Fri Jan 21 12:08:19 2000
From: gstein at lyra.org (Greg Stein)
Date: Fri, 21 Jan 2000 03:08:19 -0800 (PST)
Subject: [Python-Dev] namespaces (was: Changing existing class instances)
In-Reply-To: <001801bf63f3$414e0c60$ec2d153f@tim>
Message-ID: <Pine.LNX.4.10.10001210254030.13911-100000@nebula.lyra.org>

On Fri, 21 Jan 2000, Tim Peters wrote:
> [Greg Stein]
> > ...
> > In other words, I definitely would support a new class
> > object behavior that allows us to update a class' set of
> > bases and dictionary on the fly.  This could then be used
> > to support my solution for the recursive type scenario (which,
> > in turn, means that we don't have to introduce Yet Another
> > Namespace into Python to hold type names).
> 
> Parenthetically, I never grasped the appeal of the parenthetical comment.
> Yet Another Namespace for Yet Another Entirely New Purpose seems highly
> *desirable* to me!  Trying to overload the current namespace set makes it so
> much harder to see that these are compile-time gimmicks, and users need to
> be acutely aware of that if they're to use it effectively.  Note that I
> understand (& wholly agree with) the need for runtime introspection.

And that is the crux of the issue: I think the names that are assigned to
these classes, interfaces, typedefs, or whatever, can follow the standard
Python semantics and be plopped into the appropriate namespace. There is
no overloading.

The compile-time behavior certainly understands what names have what
types; in this case, if a name is a "typedecl", then it can remember the
*value*, too. When the name is used later, it knows the corresponding
value to use. For instance:

  IntOrString = typedef int|str
  def foo(x: IntOrString):
    ...

In this example, the type-checker knows that IntOrString is a typedecl.
It also knows the *value* of "int|str" so the name IntOrString now has two
items associated with it at type-check time:

   # not "real" syntax, but you get the idea...

   namespace["IntOrString"] = (TypeDeclarator, int|str)

With the above information in hand, the type-checker knows what
IntOrString means in the declaration for foo().

The cool benefit is that the runtime semantics are exactly as you would
expect: a typedecl object is created and assigned to IntOrString. That
object is also associated with the "x" argument in the function object
referred to by the name "foo".

There is no "overloading" of namespaces. We are using Python namespaces
just like they should be, and the type-checker doesn't even have to be all
the smart to track this stuff.

To get back to the recursive class problem, consider the following code:

   decl incomplete class Foo
   decl incomplete class Bar

   class Foo:
     decl a: Bar

   class Bar:
     decl b: Foo

The "decl" statements would create an empty class object and store that
into the "current" namespace. There is no need to shove that off into
another namespace. When the "class Foo" comes along, the class object is
updated with the class definition for Foo.

It is conceivable to remove the need for "decl" if you allow "class" and
"def" to omit the ": suite" portion of their grammar:

  class Foo
  class Bar

  class Foo:
    decl a: Bar
  ...

  def some_function(x: some_type, y: another_type) -> third_type

  ... lots o' code ...

  def some_function(x, y):
    ...

Guido suggested that it may be possible to omit "decl" altogether.
Certainly, it can work for member declarations such as:

  class Foo:
    a: Bar


Anyhow... my point is that a new namespace is not needed. Assuming we want
objects for reflection at runtime, then the above proposal states *how*
those objects are realized at runtime. Further, the type-checker can
easily follow that information and perform the appropriate compile-time
checks.

No New Namespaces!  (lather, rinse, repeat)

Cheers,
-g

-- 
Greg Stein, http://www.lyra.org/




From gstein at lyra.org  Fri Jan 21 12:12:57 2000
From: gstein at lyra.org (Greg Stein)
Date: Fri, 21 Jan 2000 03:12:57 -0800 (PST)
Subject: [Python-Dev] Changing existing class instances
In-Reply-To: <200001202002.PAA22435@eric.cnri.reston.va.us>
Message-ID: <Pine.LNX.4.10.10001210311070.13911-100000@nebula.lyra.org>

On Thu, 20 Jan 2000, Guido van Rossum wrote:
> Tim Peters:
>...
> > At the time my.py defines Misc, does Misc count as a class we're "about to
> > stomp on"?  If so-- & I've assumed so --it would wreak havoc.
> > 
> > But if not, I don't see how this case can be reliably distinguished "by
> > magic" from the cases where update is desired (if people are doing dynamic
> > updates to a long-running program, a new version of a class can come from
> > anywhere, so nothing like original file name or line number can distinguish
> > correctly either).
> 
> Fortunately, there's magic available: recently, all classes have a
> __module__ attribute that is set to the full name of the module that
> defined it (its key in __sys__.modules).
> 
> For functions, we would have to invent something similar.

func.func_globals


__module__ and func_globals can prevent *other* modules from redefining
something accidentally, but it doesn't prevent Badness from within the
module.
[ Tim just posted an example of this: his "def adder()" example... ]

Cheers,
-g

-- 
Greg Stein, http://www.lyra.org/




From bwarsaw at cnri.reston.va.us  Fri Jan 21 15:38:52 2000
From: bwarsaw at cnri.reston.va.us (Barry A. Warsaw)
Date: Fri, 21 Jan 2000 09:38:52 -0500 (EST)
Subject: [Python-Dev] Changing existing class instances
References: <200001202002.PAA22435@eric.cnri.reston.va.us>
	<001e01bf63f9$79660980$ec2d153f@tim>
Message-ID: <14472.28540.765858.16133@anthem.cnri.reston.va.us>

>>>>> "TP" == Tim Peters <tim_one at email.msn.com> writes:

    TP> Under the explicit new.update scheme, such a service needn't
    TP> bother clients with communicating the full name of the
    TP> original module; heck, in a *truly* long-running app, over
    TP> time the source tree will change, and classes and functions
    TP> will migrate across modules.  That will be a problem for the
    TP> explicit scheme too (how does it know *which* "class Misc" to
    TP> update) -- but at least it's an explicit problem then, and not
    TP> a "mysterous failure" of hidden magic.

I completely agree.  I think in general, such long running apps are
rare, and in those cases you probably want to be explicit about when
and how the updates occur anyway.  The one place where automatic
updates would be convenient would be at the interactive prompt, so it
might be nice to add a module that could be imported by PYTHONSTARTUP,
and play hook games to enable automatic updates.

-Barry




From bwarsaw at cnri.reston.va.us  Fri Jan 21 15:39:32 2000
From: bwarsaw at cnri.reston.va.us (Barry A. Warsaw)
Date: Fri, 21 Jan 2000 09:39:32 -0500 (EST)
Subject: [Python-Dev] Python 1.6 timing
References: <14471.31301.504670.201702@anthem.cnri.reston.va.us>
	<Pine.LNX.4.10.10001201653130.13911-100000@nebula.lyra.org>
Message-ID: <14472.28580.945266.658533@anthem.cnri.reston.va.us>

>>>>> "GS" == Greg Stein <gstein at lyra.org> writes:

    GS> Or move the CVS tree off-site.

I don't see what this buys us.
-Barry



From gstein at lyra.org  Fri Jan 21 15:48:40 2000
From: gstein at lyra.org (Greg Stein)
Date: Fri, 21 Jan 2000 06:48:40 -0800 (PST)
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <14472.28580.945266.658533@anthem.cnri.reston.va.us>
Message-ID: <Pine.LNX.4.10.10001210646140.13911-100000@nebula.lyra.org>

On Fri, 21 Jan 2000, Barry A. Warsaw wrote:
> >>>>> "GS" == Greg Stein <gstein at lyra.org> writes:
> 
>     GS> Or move the CVS tree off-site.
> 
> I don't see what this buys us.

I was under the impression that CVS access restrictions are based on CNRI
security policy. If the CVS repository moves elsewhere, then many people
can access it without impact on CNRI's network and security policies.

However, if the external access issue is based on legal reasons (for
example, only CNRI people should alter Python code), then yes: moving the
repository will buy nothing.

Cheers,
-g

-- 
Greg Stein, http://www.lyra.org/




From bwarsaw at python.org  Fri Jan 21 17:08:11 2000
From: bwarsaw at python.org (bwarsaw at python.org)
Date: Fri, 21 Jan 2000 11:08:11 -0500 (EST)
Subject: [Python-Dev] Python 1.6 timing
References: <14472.28580.945266.658533@anthem.cnri.reston.va.us>
	<Pine.LNX.4.10.10001210646140.13911-100000@nebula.lyra.org>
Message-ID: <14472.33899.20409.602096@anthem.cnri.reston.va.us>

>>>>> "GS" == Greg Stein <gstein at lyra.org> writes:

    GS> I was under the impression that CVS access restrictions are
    GS> based on CNRI security policy. If the CVS repository moves
    GS> elsewhere, then many people can access it without impact on
    GS> CNRI's network and security policies.

Well, access to our /internal/ network is of course restricted.  CNRI
employees have write access to the tree by virtue of access to the
filesystem (i.e. by NFS).  My current arrangement for external ssh
mediated access to a writable cvs server on an internal machine is a
hack and not something that I want to perpetuate if more users were
added.

    GS> However, if the external access issue is based on legal
    GS> reasons (for example, only CNRI people should alter Python
    GS> code), then yes: moving the repository will buy nothing.

I'll let Guido comment on policy concerning write access to the Python
CVS tree.  From a technical standpoint, if this is something Guido
wanted to extend to non-CNRI employees, the way to do it would be to
host the primary repository on a CNRI machine outside our firewall,
e.g cvs.python.org.  At that point, we'd be accessing the tree the
same as anybody else.

-Barry



From gstein at lyra.org  Fri Jan 21 17:19:33 2000
From: gstein at lyra.org (Greg Stein)
Date: Fri, 21 Jan 2000 08:19:33 -0800 (PST)
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <14472.33899.20409.602096@anthem.cnri.reston.va.us>
Message-ID: <Pine.LNX.4.10.10001210816440.13911-100000@nebula.lyra.org>

On Fri, 21 Jan 2000 bwarsaw at python.org wrote:
> >>>>> "GS" == Greg Stein <gstein at lyra.org> writes:
>...
> From a technical standpoint, if this is something Guido
> wanted to extend to non-CNRI employees, the way to do it would be to
> host the primary repository on a CNRI machine outside our firewall,
> e.g cvs.python.org.  At that point, we'd be accessing the tree the
> same as anybody else.

Gotcha. Sounds great!

I'm not sure yet that Guido is looking for external people to do checkins
(as opposed to delivering refined patches to him)... So we probably don't
need an assessment from the legal department :-), but if Guido already
knows, then I'd be curious.

thx!
-g

-- 
Greg Stein, http://www.lyra.org/




From paul at prescod.net  Fri Jan 21 17:51:24 2000
From: paul at prescod.net (Paul Prescod)
Date: Fri, 21 Jan 2000 08:51:24 -0800
Subject: [Python-Dev] Re: [Types-sig] namespaces (was: Changing existing class instances)
References: <Pine.LNX.4.10.10001210254030.13911-100000@nebula.lyra.org>
Message-ID: <38888E8C.FE369A86@prescod.net>

Greg Stein wrote:
> Tim Peters:
> > Trying to overload the current namespace set makes it so
> > much harder to see that these are compile-time gimmicks, and users need to
> > be acutely aware of that if they're to use it effectively.  Note that I
> > understand (& wholly agree with) the need for runtime introspection.
> 
> And that is the crux of the issue: I think the names that are assigned to
> these classes, interfaces, typedefs, or whatever, can follow the standard
> Python semantics and be plopped into the appropriate namespace. There is
> no overloading.

This is indeed the crux of the issue. For those that missed it last
time, it became very clear to me that we are working with radically
different design aesthetics when we discussed the idea of having an
optional keyword that said: "this thing is usually handled at compile
time but I want to handle it at runtime. I know what I am doing." 

Greg complained that that would require the programmer to understand too
much what was being done at compile time and what at runtime and what.
>From my point of view this is *exactly* what a programmer *needs* to
know and if we make it too hard for them to know it then we have failed.

> There is no "overloading" of namespaces. We are using Python namespaces
> just like they should be, and the type-checker doesn't even have to be all
> the smart to track this stuff.

There is an overloading of namespaces because we will separately specify
the *compile time semantics* of these names. We need to separately
specify these semantics because we need all compile time type checkers
to behave identically.

Yes, it seems elegant to make type objects seem as if they are "just
like" Python objects. Unfortunately they aren't. Type objects are
evaluated -- and accepted or rejected -- at compile time. Every
programmer needs to understand that and it should be blatantly obvious
in the syntax, just as everything else in Python syntax is blatantly
obvious.

-- 
 Paul Prescod  - ISOGEN Consulting Engineer speaking for himself
Earth will soon support only survivor species -- dandelions, roaches, 
lizards, thistles, crows, rats. Not to mention 10 billion humans.
	- Planet of the Weeds, Harper's Magazine, October 1998




From skaller at maxtal.com.au  Fri Jan 21 22:01:03 2000
From: skaller at maxtal.com.au (skaller)
Date: Sat, 22 Jan 2000 08:01:03 +1100
Subject: [Python-Dev] Re: [Types-sig] namespaces (was: Changing existing class instances)
References: <Pine.LNX.4.10.10001210254030.13911-100000@nebula.lyra.org> <38888E8C.FE369A86@prescod.net>
Message-ID: <3888C90F.BECA3FF6@maxtal.com.au>

Paul Prescod wrote:
 
 
> Yes, it seems elegant to make type objects seem as if they are "just
> like" Python objects. Unfortunately they aren't.

	Yes they are. They even have a type, TypeType.

-- 
John (Max) Skaller, mailto:skaller at maxtal.com.au
10/1 Toxteth Rd Glebe NSW 2037 Australia voice: 61-2-9660-0850
homepage: http://www.maxtal.com.au/~skaller
download: ftp://ftp.cs.usyd.edu/au/jskaller



From tim_one at email.msn.com  Sun Jan 23 00:18:14 2000
From: tim_one at email.msn.com (Tim Peters)
Date: Sat, 22 Jan 2000 18:18:14 -0500
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <000701bf636f$de37c5e0$c355cfc0@ski.org>
Message-ID: <000401bf652e$f5266b60$132d153f@tim>

[David Ascher]
> ...
> Regardless, just like Greg, I'd like to know what a
> pumpkin-holder would mean in the Python world.
>
> I propose that it be called the Oracle instead.  As in,
> whoever is Oracle would get some training with Tim Peters
> and learn how to channel G__do.

I'm afraid that wouldn't work.  The whole secret to channeling Guido in the
*past* was to have been an ABC user:  all you had to do is notice the things
about ABC that you loved and the ones that would drive any sane
*experienced* programmer mad with frustration.  Voila!  Guido's mind is your
mind <wink>.

But the more Python sails into uncharted waters, the less reliable my
Guido-channeling pseudo-skills get.  He is, in Essence, Unfathomable.  Also
indispensable.

> As a Python user, I'd be most comfortable with such a change
> if the Oracle just took over the technical stuff (reviewing
> patches, CVS checkins, running tests, corralling help for
> doc & code, maintaining release notes, building installers,
> etc.), but that the important decisions (e.g. whether to add
> a feature to the core language) would be checked with G__do
> first.

Definitely.  But where do you find someone like that?  It's (or at least
*should* be) several full-time jobs.  Languages like Icon & Scheme do it via
university association (scads of grad student slave labor); REBOL did it by
floating a trendy Internet business plan that actually attracted enough
venture capital to hire about 30 people; Python, unfortunately <wink>, seems
to attract people who already have demanding jobs.

So I see it as an issue of finding warm bodies more than anything else.  In
the absence of funding "real jobs", I really don't see much hope.  Bits &
pieces can be farmed out (e.g., I doubt Guido has had to do any work on the
regular expression code since Andrew arrived), but that's it -- I expect the
past predicts the future quite accurately here.

Certainly much more *could* be "farmed out", but no single volunteer of the
kind Python has attracted so far is going to do a lot on their own month
after month after month.  Even with the best of intentions, their "real
life" will interfere severely more often than not (voice of experience,
there -- and I'd guess it's the same for *all* of us).

if-something-doesn't-change-nothing-will-change<wink>-ly y'rs
    - tim





From tim_one at email.msn.com  Sun Jan 23 00:18:11 2000
From: tim_one at email.msn.com (Tim Peters)
Date: Sat, 22 Jan 2000 18:18:11 -0500
Subject: Python 2 namespace change? (was Re: [Python-Dev] Changing existing class instances)
In-Reply-To: <38871CE5.53FB9D68@digicool.com>
Message-ID: <000301bf652e$f348d1c0$132d153f@tim>

[Jim Fulton]
> ...
> A change to the way that namespaces are handled
> could make this work and have a number of other benefits,
> like global name usage without namespace lookups.
>
> I've suggested this to Guido in the past.  His
> reasonable response is that this would be too big a
> change for Python 1. Maybe this is something to consider
> for Python 2?
>
> The basic idea (borrowed from Smalltalk) is to have a kind
> of dictionary that is a collection of "association"
> objects.  An association object is simply a pairing of a
> name with a value. Association objects can be shared among
> multiple namespaces.

Jim, I've been intrigued by this idea for all the years you've been
suggesting it <wink>, but I've never understood what it is you're proposing!
This is the Python-Dev list, so feel encouraged to present it in concrete
implementation terms instead of ambiguous English.  Or maybe an interface?

interface a_kind_of_dictionary_that_is_a_collection_of_\
              association_objects:
    # ??? beats me ...

Or maybe as a C struct?  For example, is "an association object" a (char*,
PyObject*) pair?

Does this kind of dictionary have keys?  If so, of what type?  What type are
the values?  Best I can make sense of the above, the values are "association
objects", each of which contains a name and a value, and a key is maybe a
duplicate of the name in the association object to which it maps.  "A name"
may or may not be a string -- I can't tell.  Or maybe by "dictionary" you
didn't intend Python's current meaning for that word at all.  I assume "a
value" is a PyObject*.  The whole thrust *appears* to be to get names to map
to a PyObject** instead of PyObject*, but if that's the ticket I don't know
what association objeects have to do with it.

> An import like:
>
>   from foo import spam
>
> would copy the association between the name 'foo' and a
> value from module 'spam' into the current module.

Where does the idea that 'spam' is a *module* here come from?  It doesn't
make sense to me, and I'm so lost I'll spare everyone my further confusions
<wink>.

suspecting-the-last-actually-doesn't-make-any-sense<wink>-ly
    y'rs  - tim





From tim_one at email.msn.com  Sun Jan 23 00:29:45 2000
From: tim_one at email.msn.com (Tim Peters)
Date: Sat, 22 Jan 2000 18:29:45 -0500
Subject: [Python-Dev] Python 1.6 timing (fwd)
In-Reply-To: <38875DD1.B6596@tismer.com>
Message-ID: <000701bf6530$90cc31c0$132d153f@tim>

[hristian Tismer]
> ...
> Even better: Refcounting can lead to many new optimizations
> if we pay the cost to make INCREF/DECREF into methods. It
> has its cost (about 10 percent less pystones), but massive
> long-term benefits.

The GC patch Guido forced <wink> me to look at is based on the observation
that it's impossible to create cyclic trash unless a decref leaves a nonzero
refcount.  So the patch adds a function call to the DECREF macro (if the new
refcount is > 0, the object must be added to the set of "suspicious"
objects; else the object must be removed from that set).

So it roughly adds the cost of a method call to each decref anyway.  You
would think it adds less <wink>, but "the set" now is represented as a splay
tree, so *gobs* of hairy code get executed in either case (splay trees do
mutating rotations even on a lookup).

> ...
> Conclusion: I vote for a kind of GC that does just what
> refcounts cannot do, but please keep with the refcounts.

I like 'em too!

BTW, Toby posted (at least an earlier version of) the patch to c.l.py, if
anyone else wants to dig into it (I may have mentioned before that I'm short
on time <wink>).





From tim_one at email.msn.com  Sun Jan 23 05:59:38 2000
From: tim_one at email.msn.com (Tim Peters)
Date: Sat, 22 Jan 2000 23:59:38 -0500
Subject: [Python-Dev] Changing existing class instances
In-Reply-To: <14472.28540.765858.16133@anthem.cnri.reston.va.us>
Message-ID: <000201bf655e$a6a49b80$732d153f@tim>

[Barry A. Warsaw]
> I completely agree.

That's no fun <wink>.

> I think in general, such long running apps are rare,

By definition, they're non-existent under Windows <0.7 wink>.  But it
depends on which field you're working in.  The closer you get to being part
of a business or consumer service, the more important it gets; e.g., I've
seen serious RFQs for software systems guaranteed to suffer no more than 5
minutes of downtime per *year* (& stiff penalties for failure to meet that).
I've never been on the winning end of such an RFQ, so am not sure what it
takes to meet it.

It's interesting to ponder.  Psion has published a little about the software
techniques they use in their PDAs (my Psion 3a's remarkably capable "Agenda"
app has been running non-stop for a bit over 3 years!).

> and in those cases you probably want to be explicit about when
> and how the updates occur anyway.

My guess is you'd want to be *paranoidly* explicit, leaving nothing to
chance.

> The one place where automatic updates would be convenient would
> be at the interactive prompt, so it might be nice to add a
> module that could be imported by PYTHONSTARTUP, and play hook
> games to enable automatic updates.

Returning the favor, I completely agree.  The single thing people at work
gripe most about is how to do development under IDLE in such a way that
their package-laden systems exhibit the hoped-for changes in response to
editing a module deep in the bowels of the system.  I don't have a *good*
answer to that now; reduced to stuff like writing custom scripts to
selectively clear out sys.modules.

non-stop-ly y'rs  - tim





From bwarsaw at cnri.reston.va.us  Sun Jan 23 16:07:26 2000
From: bwarsaw at cnri.reston.va.us (Barry A. Warsaw)
Date: Sun, 23 Jan 2000 10:07:26 -0500 (EST)
Subject: [Python-Dev] Python 1.6 timing
References: <000701bf636f$de37c5e0$c355cfc0@ski.org>
	<000401bf652e$f5266b60$132d153f@tim>
Message-ID: <14475.6446.336166.192186@anthem.cnri.reston.va.us>

>>>>> "TP" == Tim Peters <tim_one at email.msn.com> writes:

    TP> REBOL did it by floating a trendy Internet business plan that
    TP> actually attracted enough venture capital to hire about 30
    TP> people; Python, unfortunately <wink>, seems to attract people
    TP> who already have demanding jobs.

I think all we have to do is change the name for 1.6 to LinuxPython
2.0, then split off and go IPO.  The more money we lose, the higher
our stock will go and we can use our market cap to hire all those warm
bodies.

-Barry



From jeremy at cnri.reston.va.us  Sun Jan 23 19:54:40 2000
From: jeremy at cnri.reston.va.us (Jeremy Hylton)
Date: Sun, 23 Jan 2000 13:54:40 -0500 (EST)
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <000401bf652e$f5266b60$132d153f@tim>
References: <000701bf636f$de37c5e0$c355cfc0@ski.org>
	<000401bf652e$f5266b60$132d153f@tim>
Message-ID: <14475.20080.508651.261991@bitdiddle.cnri.reston.va.us>

>>>>> "TP" == Tim Peters <tim_one at email.msn.com> writes:

  TP> [David Ascher]
  >> I propose that it be called the Oracle instead.  As in, whoever
  >> is Oracle would get some training with Tim Peters and learn how
  >> to channel G__do.

  TP> I'm afraid that wouldn't work.  The whole secret to channeling
  TP> Guido in the *past* was to have been an ABC user: all you had to
  TP> do is notice the things about ABC that you loved and the ones
  TP> that would drive any sane *experienced* programmer mad with
  TP> frustration.  Voila!  Guido's mind is your mind <wink>.

I have discovered another approach.  CNRI put in a cleam room on the
second floor last year.  I recently discovered a little door behind
some metrology device in a corner of the clean room.  The door opens
onto a tunnel that leads directly into Guido's mind.  Unfortunately,
it won't be of much use for a pumpkin-holder or channeler, because
after about 15 minutes you are deposited on the shoulder of the Dulles
Toll Road.

who-wants-to-be-John-Malkovich-when-they-could-be-Guido-ly y'rs,
Jeremy





From skip at mojam.com  Wed Jan 26 04:42:06 2000
From: skip at mojam.com (Skip Montanaro)
Date: Tue, 25 Jan 2000 21:42:06 -0600
Subject: [Python-Dev] Multiple dicts for string interpolation?
Message-ID: <200001260342.VAA10627@beluga.mojam.com>

Every once in awhile I want to perform string interpolation using more than
one dictionary.  One way is to build a dictionary that's a union of multiple 
dictionaries:

    dict = {}
    dict.update(d1)
    dict.update(d2)
    ...
    s = format % dict

Another way is the MultiDict approach that Digital Creations (used to?) use
in their DocumentTemplate module (I can't remember the exact usage any
more):

    dict = MultiDict()
    dict.append(d1)
    dict.append(d2)
    ...
    s = format % dict

A MultiDict object maintains a list of the dicts it's been fed and searches
them in order when __getitem__ is called.

I'd like to propose a third alternative.  How about if the string
interpolation function accepted a tuple of dictionaries directly:

    s = format % (d1, d2)

It would only be used when named interpolation was expected.  I don't think
there would be any conflict with current % operator semantics.

Skip Montanaro | http://www.mojam.com/
skip at mojam.com | http://www.musi-cal.com/
847-971-7098




From guido at CNRI.Reston.VA.US  Wed Jan 26 05:13:28 2000
From: guido at CNRI.Reston.VA.US (Guido van Rossum)
Date: Tue, 25 Jan 2000 23:13:28 -0500
Subject: [Python-Dev] Multiple dicts for string interpolation?
In-Reply-To: Your message of "Tue, 25 Jan 2000 21:42:06 CST."
             <200001260342.VAA10627@beluga.mojam.com> 
References: <200001260342.VAA10627@beluga.mojam.com> 
Message-ID: <200001260413.XAA02813@eric.cnri.reston.va.us>

> I'd like to propose a third alternative.  How about if the string
> interpolation function accepted a tuple of dictionaries directly:
> 
>     s = format % (d1, d2)
> 
> It would only be used when named interpolation was expected.  I don't think
> there would be any conflict with current % operator semantics.

Gut feeling: it's dangerous to fill up every possible dark corner with
specific semantics that are occasionally useful, because if you go too
far you lose useful redundancy, and you end up with Perl.

Not sure whether this particular suggestion is "going too far."

I think it depends on to what extent this is a common, useful idiom.
Do you have evidence of that?  Examples?

--Guido van Rossum (home page: http://www.python.org/~guido/)



From skip at mojam.com  Wed Jan 26 05:38:53 2000
From: skip at mojam.com (Skip Montanaro)
Date: Tue, 25 Jan 2000 22:38:53 -0600 (CST)
Subject: [Python-Dev] Multiple dicts for string interpolation?
In-Reply-To: <200001260413.XAA02813@eric.cnri.reston.va.us>
References: <200001260342.VAA10627@beluga.mojam.com>
	<200001260413.XAA02813@eric.cnri.reston.va.us>
Message-ID: <14478.31325.891846.701373@beluga.mojam.com>

    >> I'd like to propose a third alternative.  How about if the string
    >> interpolation function accepted a tuple of dictionaries directly:
    >> 
    >> s = format % (d1, d2)

    Guido> Gut feeling: it's dangerous to fill up every possible dark corner
    Guido> with specific semantics that are occasionally useful, because if
    Guido> you go too far you lose useful redundancy, and you end up with
    Guido> Perl.

Yeah, I am kind of taking advantage of the fact that the format operator
doesn't happen to use tuples of dicts already, though this seems like a
natural extension of the current semantics.   Currently, you can have

    Style of                Simple form     Complex form
    Interpolation
    -------                 -----------     ------------
    sprintf                 string          tuple of strings
    named                   dict            tuple of dicts

It does complicate the decision making process in the string format routine
a bit.

    Guido> I think it depends on to what extent this is a common, useful
    Guido> idiom.  Do you have evidence of that?  Examples?

Well, the first place I ran into it was in DocumentTemplates a few years
ago.  They used an idiom heavily which may have now been replaced by
acquisition where you'd effectively push and pop value dicts onto a stack as
you entered and exited nested blocks of DTML code.  Their solution was a
special dict-like object.

The example that made the light click for me this evening was having an
object whose class dict stores constants and whose instant dict stores
varying values.  It seemed cleaner to me to do

    obj = Class()
    ...
    s = format % (Class.__dict__, obj.__dict__)

than go through the intermediate step of building a separate dict which
would just get discarded as soon as this bit of string building was
complete.  (I will perform this once for each of several thousand
instances.)

It's not a big deal.  If it seems too obscure the other obvious solutions
are not gruesome.

Skip



From skip at mojam.com  Wed Jan 26 05:40:20 2000
From: skip at mojam.com (Skip Montanaro)
Date: Tue, 25 Jan 2000 22:40:20 -0600 (CST)
Subject: [Python-Dev] Multiple dicts for string interpolation?
In-Reply-To: <14478.31325.891846.701373@beluga.mojam.com>
References: <200001260342.VAA10627@beluga.mojam.com>
	<200001260413.XAA02813@eric.cnri.reston.va.us>
	<14478.31325.891846.701373@beluga.mojam.com>
Message-ID: <14478.31412.36960.440988@beluga.mojam.com>

Oh crap...  Of course, the table should have been

    Style of                Simple form     Complex form
    Interpolation
    -------                 -----------     ------------
    sprintf                 string          tuple of strings
    named                   dict            

(empty fourth cell...)

Skip



From klm at digicool.com  Wed Jan 26 06:01:36 2000
From: klm at digicool.com (Ken Manheimer)
Date: Wed, 26 Jan 2000 00:01:36 -0500 (EST)
Subject: [Python-Dev] Multiple dicts for string interpolation?
In-Reply-To: <14478.31325.891846.701373@beluga.mojam.com>
Message-ID: <Pine.LNX.4.10.10001252337510.15410-100000@splat.digicool.com>

On Tue, 25 Jan 2000, Skip Montanaro wrote:

>     Guido> Skip:
>     >> I'd like to propose a third alternative.  How about if the string
>     >> interpolation function accepted a tuple of dictionaries directly:
>     >> 
>     >> s = format % (d1, d2)
> [...]
>     Guido> I think it depends on to what extent this is a common, useful
>     Guido> idiom.  Do you have evidence of that?  Examples?
> 
> Well, the first place I ran into it was in DocumentTemplates a few years
> ago.  They used an idiom heavily which may have now been replaced by
> acquisition where you'd effectively push and pop value dicts onto a stack as
> you entered and exited nested blocks of DTML code.  Their solution was a
> special dict-like object.

Implementation of acquisition basically uses a MultiDict underneath.
Consider acquisition as a cumulative context composed from the containers
of the target of a web request.  (Actually, a distinction is made between
the object containment hierarchy of the target and the successive
components of the path along which the target is reached by the request,
with the containment contexts taking precedence - but that's probably not
important here:-)  Add in incidental things like the server environment
(from which you can get HTTP_REFERER and cookies and so forth).  Each of
the components can be a dictionary or a MultiDict (or a sequence of pairs,
i think), and they're ultimately composed in a MultiDict.

I think another place in zope where multidicts play prominently is in the
security mechanism, where any object can have local roles, and the
ultimate role of a user within a context is composed from the union across
the containment hierarchy.  There probably are lots of other places where
multidicts are used.

Suffice to say that there's a lot of composing of contexts that goes on in
Zope in general, acquistion being a prime example but not the only one,
and multidicts play heavily in many.  I would be surprised if this need to
combine contexts is peculiar to web server, or general server
applications.

> [...]
> It's not a big deal.  If it seems too obscure the other obvious solutions
> are not gruesome.

I suppose we'd be pretty happy to have something like MultiDict as part of
python...

Ken
klm at digicool.com

(Who's the only one left in fredericksburg to speak up, at the moment:-)




From tim_one at email.msn.com  Wed Jan 26 06:39:19 2000
From: tim_one at email.msn.com (Tim Peters)
Date: Wed, 26 Jan 2000 00:39:19 -0500
Subject: [Python-Dev] Multiple dicts for string interpolation?
In-Reply-To: <200001260413.XAA02813@eric.cnri.reston.va.us>
Message-ID: <000101bf67bf$b103e460$592d153f@tim>

[Skip, wants to interpolate multiple dicts via "%",
 suggests passing a tuple of dicts:  format % (d1, d2, ...)]

[Guido]
> ...
> I think it depends on to what extent this is a common, useful
> idiom.  Do you have evidence of that?  Examples?

You yourself raised one last century <wink>:  simply wanting to interpolate
from both locals() and globals().  At the time, the idea of a new dict-like
mapping object (capturing Python's lookup rules) appealed to you.  I still
like that, and note that the apparent need becomes more acute if "deep
nesting" is ever added.

I wasn't aware of the MultiDict approach Skip mentioned, but thought it
looked spot on for the general case!  Skip, is the long-windedness of

    dict = MultiDict()
    dict.append(d1)
    dict.append(d2)
    ...
    s = format % dict

the part you didn't like about that?  If so, how about changing the
constructor to

    def __init__(self, *dicts):
         ...

instead so you could use it as a one-liner

    format % MultiDict(d1, d2, ...)

?  That's exactly the same as the tuple idea, except there's a nice
descriptive word in the middle of it <wink>.





From jack at oratrix.nl  Wed Jan 26 10:56:18 2000
From: jack at oratrix.nl (Jack Jansen)
Date: Wed, 26 Jan 2000 10:56:18 +0100
Subject: [Python-Dev] Multiple dicts for string interpolation? 
In-Reply-To: Message by "Tim Peters" <tim_one@email.msn.com> ,
	     Wed, 26 Jan 2000 00:39:19 -0500 , <000101bf67bf$b103e460$592d153f@tim> 
Message-ID: <20000126095619.DC67D36E440@snelboot.oratrix.nl>

> the part you didn't like about that?  If so, how about changing the
> constructor to
> 
>     def __init__(self, *dicts):
>          ...
> 
> instead so you could use it as a one-liner
> 
>     format % MultiDict(d1, d2, ...)
> 
> ?  That's exactly the same as the tuple idea, except there's a nice
> descriptive word in the middle of it <wink>.

I've always wonderer why dict+dict isn't supported (or possibly dict|dict, if 
the key-collision semantics of + on dict are seen as a problem). Is there a 
good reason for this, or is it just that there are other more important things 
to implement?

This wouldn't be a replacement for all uses of MultiDict, as it would probably 
have to create a new dict to keep semantics in line with those of list+list
--
Jack Jansen             | ++++ stop the execution of Mumia Abu-Jamal ++++
Jack.Jansen at oratrix.com | ++++ if you agree copy these lines to your sig ++++
www.oratrix.nl/~jack    | see http://www.xs4all.nl/~tank/spg-l/sigaction.htm 





From guido at CNRI.Reston.VA.US  Wed Jan 26 13:41:45 2000
From: guido at CNRI.Reston.VA.US (Guido van Rossum)
Date: Wed, 26 Jan 2000 07:41:45 -0500
Subject: [Python-Dev] Multiple dicts for string interpolation?
In-Reply-To: Your message of "Wed, 26 Jan 2000 10:56:18 +0100."
             <20000126095619.DC67D36E440@snelboot.oratrix.nl> 
References: <20000126095619.DC67D36E440@snelboot.oratrix.nl> 
Message-ID: <200001261241.HAA03001@eric.cnri.reston.va.us>

[Tim]
> >     format % MultiDict(d1, d2, ...)
> > 
> > ?  That's exactly the same as the tuple idea, except there's a nice
> > descriptive word in the middle of it <wink>.

Nice.

[Jack]
> I've always wonderer why dict+dict isn't supported (or possibly
> dict|dict, if the key-collision semantics of + on dict are seen as a
> problem). Is there a good reason for this, or is it just that there
> are other more important things to implement?

The reason is that + (or |) looks symmetrical, but for the key
collisions, one of them has to lose.  We now have dict1.update(dict2),
which is a bit more cumbersome, but makes it much clearer who is the
loser.

--Guido van Rossum (home page: http://www.python.org/~guido/)



From skip at mojam.com  Wed Jan 26 15:30:09 2000
From: skip at mojam.com (Skip Montanaro)
Date: Wed, 26 Jan 2000 08:30:09 -0600 (CST)
Subject: [Python-Dev] Multiple dicts for string interpolation?
In-Reply-To: <000101bf67bf$b103e460$592d153f@tim>
References: <200001260413.XAA02813@eric.cnri.reston.va.us>
	<000101bf67bf$b103e460$592d153f@tim>
Message-ID: <14479.1265.213769.810138@beluga.mojam.com>

    Tim> Skip, is the long-windedness of

    Tim>     dict = MultiDict()
    Tim>     dict.append(d1)
    Tim>     dict.append(d2)
    Tim>     ...
    Tim>     s = format % dict

    Tim> the part you didn't like about that?  If so, how about changing the
    Tim> constructor to

    Tim>     def __init__(self, *dicts):
    Tim>          ...

    Tim> instead so you could use it as a one-liner

    Tim>     format % MultiDict(d1, d2, ...)

    Tim> ?  That's exactly the same as the tuple idea, except there's a nice
    Tim> descriptive word in the middle of it <wink>.

The long-windedness was part of it.  The performance hit of composing
dictionaries thousands of times to perform a single format operation was
also a consideration.

Okay, side excursion into the Zope source tree...

What I was calling MultiDict is actually MultiMapping (written in C, BTW).
As a side effect of my Zope install here, I even already have it in sys.path
(go figure!).  And it turns out to work just as Tim surmised:

    >>> d1 = {"a": 1}
    >>> d2 = {"b": 2}
    >>> d = MultiMapping.MultiMapping(d1, d2)
    >>> d["b"]
    2
    >>> d["a"]
    1

Dang!  Turns out Jim Fulton has a time machine also.

I guess the next question is to extend Ken's comment about getting it into
the Python core.  Would that be something possible for 1.6?  I used a Python
version of MultiMapping in an ancient version of DocumentTemplate.  I'm sure
the C version has been around for at least two or three years and would
appear pretty darn stable, since it seems to be at the core of a lot of
Zope's coolness.

Skip



From ping at lfw.org  Thu Jan 27 08:06:01 2000
From: ping at lfw.org (Ka-Ping Yee)
Date: Wed, 26 Jan 2000 23:06:01 -0800 (PST)
Subject: [Python-Dev] Multiple dicts for string interpolation?
In-Reply-To: <14478.31325.891846.701373@beluga.mojam.com>
Message-ID: <Pine.LNX.4.10.10001262237010.2341-100000@skuld.lfw.org>

On Tue, 25 Jan 2000, Skip Montanaro wrote:
> 
>     Guido> I think it depends on to what extent this is a common, useful
>     Guido> idiom.  Do you have evidence of that?  Examples?
> 
> Well, the first place I ran into it was in DocumentTemplates a few years
> ago.  They used an idiom heavily which may have now been replaced by
> acquisition where you'd effectively push and pop value dicts onto a stack as
> you entered and exited nested blocks of DTML code.  Their solution was a
> special dict-like object.

That's really interesting.  I wrote a bunch of Python wrappers for
a UI toolkit a little while ago, and there were two main pieces of
machinery i built to make the toolkit pleasant to use:

    1. a reasonably nice C++ extension class kit (this is where i
       tried overloading operator new for the first time, so it
       would allocate memory that could be freed by PyMem_DEL --
       i don't know if CXX uses the same approach)

    2. a second layer of Python wrapper classes for the extension
       classes that implements extra methods in Python, and maintains
       a hierarchy of default keyword argument values along the
       inheritance hierarchy of widgets

The second of these things involved implementing exactly the kind
of dictionary stack that you mentioned.

The programming idiom for building widgets goes something like:

    defaultstack = {}  # maps class object to list of defaults dictionaries

    class Label(Component):
        defaults = _dict(text="Label", align=LEFT)

    class Button(Label):
        defaults = _dict(text="Button", align=CENTER, shadow=2)

    ...

    w = Window(...)

    Button.push(fg="white", bg="red",
                font="-*-courier-bold-r-normal--14-*-*-*-*-*-*-*")
    a = Button(w, text="one")
    b = Button(w, text="two")
    c = Button(w, text="three")
    Button.pop()

This way you can install some options for a while and make a bunch
of widgets with your defaults, then pop the options and go back to
the previous state.

The layers of dictionaries that get composed in every widget's
__init__ function are (in order of priority):

    1. any non-None keyword arguments to __init__
    2. any non-None values in class.defaults
    3. any non-None values in class.__bases__[0].defaults
    4. any non-None values in class.__bases__[0].__bases__[0].defaults
    etc.

When a new set of defaults is push()ed, the class's current
defaults are saved on the defaultstack for the class, and restored
when pop() gets called.

I don't *know* if this is really the best way to do things, but it
has seemed to work out pretty well in practice.  It makes it more
convenient to deal with all the options you have to throw around
especially when doing UI stuff.

Anyway, i noticed the same sort of thing today while wondering about
using keyword arguments for HTML tag attributes.  (Perhaps HTMLgen
does this sort of thing already -- sorry i haven't looked at it.)
Anyway, the following sort of helper might be useful in general:

    class Default:
        def __init__(self, cl, **defaults):
            self.cl = cl
            self.defaults = defaults

        def __call__(self, *args, **kw):
            for key, value in self.defaults:
                if not kw.has_key(key): kw[key] = value
            return apply(self.cl, args, kw)

Then you could do the same thing as above with:

    MyButton = Default(Button, fg="white", bg="red",
                       font="-*-courier-bold-r-normal--14-*-*-*-*-*-*-*")
    a = MyButton(w, text="one")
    b = MyButton(w, text="two")
    c = MyButton(w, text="three")

This is probably a cleaner way to do things.  I haven't tried it,
but it might be a nice thing to have in Tkinter.
 


-- ?!ng




From ping at lfw.org  Fri Jan 28 05:36:49 2000
From: ping at lfw.org (Ka-Ping Yee)
Date: Thu, 27 Jan 2000 20:36:49 -0800 (PST)
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <14475.20080.508651.261991@bitdiddle.cnri.reston.va.us>
Message-ID: <Pine.LNX.4.10.10001272033300.2341-100000@skuld.lfw.org>

On Sun, 23 Jan 2000, Jeremy Hylton wrote:
> 
> I have discovered another approach.  CNRI put in a cleam room on the
> second floor last year.  I recently discovered a little door behind
> some metrology device in a corner of the clean room.  The door opens
> onto a tunnel that leads directly into Guido's mind.  Unfortunately,
> it won't be of much use for a pumpkin-holder or channeler, because
> after about 15 minutes you are deposited on the shoulder of the Dulles
> Toll Road.

I almost fell out of my chair laughing when i read this.

What do you think would happen if Guido went into the tunnel?  Perhaps
    
    http://www.lfw.org/jminc/Guido/http://www.python.org/

(What you get is a generalization of some earlier silliness... the
description of the original is at http://www.lfw.org/jminc/.)


-- ?!ng




From jim at digicool.com  Fri Jan 28 16:02:12 2000
From: jim at digicool.com (Jim Fulton)
Date: Fri, 28 Jan 2000 10:02:12 -0500
Subject: [Python-Dev] Multiple dicts for string interpolation?
References: <200001260342.VAA10627@beluga.mojam.com>
Message-ID: <3891AF74.1E81D7F8@digicool.com>

Skip Montanaro wrote:
> 
> Every once in awhile I want to perform string interpolation using more than
> one dictionary.  One way is to build a dictionary that's a union of multiple
> dictionaries:
> 
>     dict = {}
>     dict.update(d1)
>     dict.update(d2)
>     ...
>     s = format % dict
> 
> Another way is the MultiDict approach that Digital Creations (used to?) use
> in their DocumentTemplate module (I can't remember the exact usage any
> more):
> 
>     dict = MultiDict()
>     dict.append(d1)
>     dict.append(d2)

Actually, push (and pop). The namspaces are managed as a stack.

>     ...
>     s = format % dict
> 
> A MultiDict object maintains a list of the dicts it's been fed and searches
> them in order when __getitem__ is called.
> 
> I'd like to propose a third alternative.  How about if the string
> interpolation function accepted a tuple of dictionaries directly:
> 
>     s = format % (d1, d2)
> 
> It would only be used when named interpolation was expected.  I don't think
> there would be any conflict with current % operator semantics.

Yes. In the current semantics, you output the two dictionaries.

Try: 

  '%s %s' % ({'hello':'skip'},{})

Jim

--
Jim Fulton           mailto:jim at digicool.com   Python Powered!        
Technical Director   (888) 344-4332            http://www.python.org  
Digital Creations    http://www.digicool.com   http://www.zope.org    

Under US Code Title 47, Sec.227(b)(1)(C), Sec.227(a)(2)(B) This email
address may not be added to any commercial mail list with out my
permission.  Violation of my privacy with advertising or SPAM will
result in a suit for a MINIMUM of $500 damages/incident, $1500 for
repeats.



From jim at digicool.com  Fri Jan 28 16:07:24 2000
From: jim at digicool.com (Jim Fulton)
Date: Fri, 28 Jan 2000 10:07:24 -0500
Subject: [Python-Dev] Multiple dicts for string interpolation?
References: <Pine.LNX.4.10.10001252337510.15410-100000@splat.digicool.com>
Message-ID: <3891B0AC.D39275DF@digicool.com>

Ken Manheimer wrote:
> 
> On Tue, 25 Jan 2000, Skip Montanaro wrote:
> 
> >     Guido> Skip:
> >     >> I'd like to propose a third alternative.  How about if the string
> >     >> interpolation function accepted a tuple of dictionaries directly:
> >     >>
> >     >> s = format % (d1, d2)
> > [...]
> >     Guido> I think it depends on to what extent this is a common, useful
> >     Guido> idiom.  Do you have evidence of that?  Examples?
> >
> > Well, the first place I ran into it was in DocumentTemplates a few years
> > ago.  They used an idiom heavily which may have now been replaced by
> > acquisition where you'd effectively push and pop value dicts onto a stack as
> > you entered and exited nested blocks of DTML code.  Their solution was a
> > special dict-like object.
> 
> Implementation of acquisition basically uses a MultiDict underneath.

No it doesn't.  Acquisition achieves combination of multiple 
namespaces in much the same way that inheritence does (through
delagation).

> Consider acquisition as a cumulative context composed from the containers
> of the target of a web request.  (Actually, a distinction is made between
> the object containment hierarchy of the target and the successive
> components of the path along which the target is reached by the request,
> with the containment contexts taking precedence - but that's probably not
> important here:-)  Add in incidental things like the server environment
> (from which you can get HTTP_REFERER and cookies and so forth).  Each of
> the components can be a dictionary or a MultiDict (or a sequence of pairs,
> i think), and they're ultimately composed in a MultiDict.
> 
> I think another place in zope where multidicts play prominently is in the
> security mechanism, where any object can have local roles, and the
> ultimate role of a user within a context is composed from the union across
> the containment hierarchy.  There probably are lots of other places where
> multidicts are used.

Acquisition plays a role in security, but MultiDicts-like things are 
not used.
 
> Suffice to say that there's a lot of composing of contexts that goes on in
> Zope in general, acquistion being a prime example but not the only one,
> and multidicts play heavily in many.  I would be surprised if this need to
> combine contexts is peculiar to web server, or general server
> applications.
> 
> > [...]
> > It's not a big deal.  If it seems too obscure the other obvious solutions
> > are not gruesome.
> 
> I suppose we'd be pretty happy to have something like MultiDict as part of
> python...

Note that Zope actually uses two separate flavors. The one used most
in Zope (in DocumentTemplate) has very specific hooks to work with
Zope's security machinery.

Jim

--
Jim Fulton           mailto:jim at digicool.com   Python Powered!        
Technical Director   (888) 344-4332            http://www.python.org  
Digital Creations    http://www.digicool.com   http://www.zope.org    

Under US Code Title 47, Sec.227(b)(1)(C), Sec.227(a)(2)(B) This email
address may not be added to any commercial mail list with out my
permission.  Violation of my privacy with advertising or SPAM will
result in a suit for a MINIMUM of $500 damages/incident, $1500 for
repeats.



From jim at digicool.com  Fri Jan 28 16:10:26 2000
From: jim at digicool.com (Jim Fulton)
Date: Fri, 28 Jan 2000 10:10:26 -0500
Subject: [Python-Dev] Multiple dicts for string interpolation?
References: <000101bf67bf$b103e460$592d153f@tim>
Message-ID: <3891B162.554622E2@digicool.com>

Tim Peters wrote:
> 
(snip)
> I wasn't aware of the MultiDict approach Skip mentioned,

See the MultiMapping module in ExtensionClass. You can get the
latest flavor of this in the latest Zope release.

> but thought it
> looked spot on for the general case!  Skip, is the long-windedness of
> 
>     dict = MultiDict()
>     dict.append(d1)
>     dict.append(d2)
>     ...
>     s = format % dict

Note the rather important *stack* sematics of
MultiMappings.  We often push and pop namespaces 
on and off of MultiMappings in use.
 
> the part you didn't like about that?  If so, how about changing the
> constructor to
> 
>     def __init__(self, *dicts):
>          ...
> 
> instead so you could use it as a one-liner
> 
>     format % MultiDict(d1, d2, ...)
> 
> ?  That's exactly the same as the tuple idea, except there's a nice
> descriptive word in the middle of it <wink>.

This is exactly what the current MultiMapping "class" does.

Jim

--
Jim Fulton           mailto:jim at digicool.com   Python Powered!        
Technical Director   (888) 344-4332            http://www.python.org  
Digital Creations    http://www.digicool.com   http://www.zope.org    

Under US Code Title 47, Sec.227(b)(1)(C), Sec.227(a)(2)(B) This email
address may not be added to any commercial mail list with out my
permission.  Violation of my privacy with advertising or SPAM will
result in a suit for a MINIMUM of $500 damages/incident, $1500 for
repeats.



From gward at cnri.reston.va.us  Fri Jan 28 17:39:54 2000
From: gward at cnri.reston.va.us (Greg Ward)
Date: Fri, 28 Jan 2000 11:39:54 -0500
Subject: [Python-Dev] To-do for Distutils 0.2 (and beyond)
Message-ID: <20000128113954.A12965@cnri.reston.va.us>

Hi all --

[oops: I *said* that I was cc'ing this to python-dev when I posted it to
 distutils-sig, but I just plain forgot to.  So here it is again, still
 presumed relevant to python-dev'ers because it directly affects the
 planned Python 1.6 feature set.  Please reply either to me directly or
 to distutils-sig, because that's where the implementation will be done.]

recent developments in the planned release schedule for Python 1.6
(Guido doesn't want to wait for everything planned, but get something
out the door in the next couple of months) are lighting a fire under me
to get a seriously usable version of Distutils ready *really* soon now.
This will be Distutils 0.2; I anticipate that 0.2.x will be included in
Python 1.6, where x is the number of attempts it takes me to get
something reasonably bug-free out the door.

Those if you who were at the Python Conference this past week will have
seen bits and pieces of my "laundry list" of desired features that
should be added to the Distutils at some point in the future.  Given the
shortened schedule, it looks like it's necessary to do some pruning and
concentrate on the essentials to get something in Python 1.6.

So, here is my current laundry list, sorted into a couple of categories:

essential for 0.2 (Python 1.6)
-----------------
* fix the "dist" command (two-phase manifest, better feedback)
  (steal ideas and hopefully code from Gordon Macmillan's installer)
* fix the "install" command (have the right interface and do the right
  thing for installating to non-standard or personal directories) 
* fix some bad nomenclature in the command classes
  (most likely 'options' -> 'user_options', 'set_default_options()' ->
  'initialize_options()', and 'set_final_options()' -> ??? (maybe
  'finalize_options()'?))
* build C libraries (for PIL, and other similar distributions)
* documentation (two small manuals that should become standard Python
  manuals: "Installing Python Modules" and "Developing and Distributing
  Python Modules")
* add a bdist command; should at least be able to generate dumb archives
  of built distributions (eg. a tarball that you unpack from /usr/local,
  or maybe /usr/local/lib/python1.5/site-packages)

desirable for 0.2
-----------------
* "what's installed" database
* dependency checking ("is version 1.3 of foo installed?")
* don't automatically clobber an existing installation -- confirm, or
  require a "force" option, or something
* command to install C headers (assuming more extensions than NumPy need
  to do this)

put off to 0.3 (Python 1.7?)
----------------------------
* JPython support (most importantly, know where to install .py modules
  when run from JPython and be able to build Java extensions for JPython)
* build static Python binary (for shared-library-challenged OSs)
* SWIG support (mainly, know how to run it before building the C
  extension it generates)
* PyFort support (ditto)
* Mac support
* allow overlapping multi-architecture installations (Michel Sanner's
  pet peeve and Guido's nightmare ;-) (this would *not* be the default;
  it would have to be explicitly chosen by brave/cheap/foolhardy
  installers)
* support for archive sites (Parnassus) to pull out meta-info

Anyone feel strongly about moving any of these items around, or
discarding any entirely, or adding anything?  Please let me know by
email; I'll summarize to the list.

Thanks --

       Greg



From jeremy at cnri.reston.va.us  Sat Jan 29 00:52:53 2000
From: jeremy at cnri.reston.va.us (Jeremy Hylton)
Date: Fri, 28 Jan 2000 18:52:53 -0500 (EST)
Subject: [Python-Dev] To-do for Distutils 0.2 (and beyond)
In-Reply-To: <20000128113954.A12965@cnri.reston.va.us>
References: <20000128113954.A12965@cnri.reston.va.us>
Message-ID: <14482.11221.451866.695357@bitdiddle.cnri.reston.va.us>

>>>>> "GW" == Greg Ward <gward at cnri.reston.va.us> writes:

 GW> desirable for 0.2
 GW> -----------------
 GW> * "what's installed" database
 GW> * dependency checking ("is version 1.3 of foo installed?")

These are *not* desirable for version 0.2.  Paul Dubois expressed some
concern about the complexity of these tasks.  I agree completely.  I
think the chances of getting this done correctly in the next month are
slim to none.  Don't waste your time adding the kitchen sink to
distutils :-); just bang on the simple stuff until it's rock solid.

Jeremy





From jim at digicool.com  Sat Jan 29 02:40:22 2000
From: jim at digicool.com (Jim Fulton)
Date: Fri, 28 Jan 2000 20:40:22 -0500
Subject: [Python-Dev] Multiple dicts for string interpolation?
References: <200001260413.XAA02813@eric.cnri.reston.va.us>
		<000101bf67bf$b103e460$592d153f@tim> <14479.1265.213769.810138@beluga.mojam.com>
Message-ID: <38924506.808D34F5@digicool.com>

Skip Montanaro wrote:
> 
(snip)
> I guess the next question is to extend Ken's comment about getting it into
> the Python core.  Would that be something possible for 1.6?  I used a Python
> version of MultiMapping in an ancient version of DocumentTemplate.  I'm sure
> the C version has been around for at least two or three years and would
> appear pretty darn stable,

Yes. I'm sure you'd have to de-ExtensionClass-ify it to get it 
into the core. :)

> since it seems to be at the core of a lot of
> Zope's coolness.

Actually, it isn't, as there is a separate similar thing
(TemplateDict) used in DocumentTemplate.

Jim

--
Jim Fulton           mailto:jim at digicool.com   Python Powered!        
Technical Director   (888) 344-4332            http://www.python.org  
Digital Creations    http://www.digicool.com   http://www.zope.org    

Under US Code Title 47, Sec.227(b)(1)(C), Sec.227(a)(2)(B) This email
address may not be added to any commercial mail list with out my
permission.  Violation of my privacy with advertising or SPAM will
result in a suit for a MINIMUM of $500 damages/incident, $1500 for
repeats.



From guido at CNRI.Reston.VA.US  Sun Jan 30 14:32:18 2000
From: guido at CNRI.Reston.VA.US (Guido van Rossum)
Date: Sun, 30 Jan 2000 08:32:18 -0500
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
Message-ID: <200001301332.IAA12252@eric.cnri.reston.va.us>

Dear developers,

Eric Raymond has sent me the following patch, which adds conditional
expressions to Python.  I'd like to hear opinions on whether this is a
good thing to add to Python, and whether this is the right syntax.

I am a bit skeptical about whether this is sufficiently Pythonic, but
on the other hand there have always been requests for such a feature,
and the existing solutions are ugly:

  a and b or c

only works when you know for sure that b will never be false, and

  (a and [b] or [c])[0] 

is dead ugly...

--Guido van Rossum (home page: http://www.python.org/~guido/)

Subject: Ternary select -- here it is.
From: "Eric S. Raymond" <esr at thyrsus.com>
To: Guido Van Rossum <guido at CNRI.Reston.Va.US>
Date: Sat, 29 Jan 2000 17:40:31 -0500
X-Eric-Conspiracy: There is no conspiracy

Dang, Guido, this was *fun*!

This patch extends the Python interpreter to support the C ternary
operator, and documents the extension in the Reference Manual.  The
implementation is dead simple and robust: it's adapted from the
existing code for if statements, and adds or changes less than 70 lines
of code all told.

Diffs between last version checked in and current workfile(s):

--- Grammar/Grammar	2000/01/28 17:10:18	1.1
+++ Grammar/Grammar	2000/01/29 22:14:05
@@ -61,7 +61,8 @@
 except_clause: 'except' [test [',' test]]
 suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT
 
-test: and_test ('or' and_test)* | lambdef
+test: bool_test ['?' bool_test ':' bool_test]
+bool_test: and_test ('or' and_test)* | lambdef
 and_test: not_test ('and' not_test)*
 not_test: 'not' not_test | comparison
 comparison: expr (comp_op expr)*
--- Include/token.h	2000/01/28 17:38:55	1.1
+++ Include/token.h	2000/01/29 01:27:00
@@ -74,10 +74,11 @@
 #define LEFTSHIFT	34
 #define RIGHTSHIFT	35
 #define DOUBLESTAR	36
+#define QUERY		37
 /* Don't forget to update the table _PyParser_TokenNames in tokenizer.c! */
-#define OP		37
-#define ERRORTOKEN	38
-#define N_TOKENS	39
+#define OP		38
+#define ERRORTOKEN	39
+#define N_TOKENS	34
 
 /* Special definitions for cooperation with parser */
 
--- Modules/parsermodule.c	2000/01/28 18:03:27	1.1
+++ Modules/parsermodule.c	2000/01/29 22:13:45
@@ -945,6 +945,7 @@
 #define	validate_star(ch)	validate_terminal(ch,	    STAR, "*")
 #define	validate_vbar(ch)	validate_terminal(ch,	    VBAR, "|")
 #define validate_doublestar(ch)	validate_terminal(ch, DOUBLESTAR, "**")
+#define validate_query(ch)	validate_terminal(ch,	   QUERY, "?")
 #define validate_dot(ch)	validate_terminal(ch,	     DOT, ".")
 #define	validate_name(ch, str)	validate_terminal(ch,	    NAME, str)
 
@@ -963,7 +964,8 @@
 VALIDATER(exec_stmt);		VALIDATER(compound_stmt);
 VALIDATER(while);		VALIDATER(for);
 VALIDATER(try);			VALIDATER(except_clause);
-VALIDATER(test);		VALIDATER(and_test);
+VALIDATER(test);
+VALIDATER(bool_test);		VALIDATER(and_test);
 VALIDATER(not_test);		VALIDATER(comparison);
 VALIDATER(comp_op);		VALIDATER(expr);
 VALIDATER(xor_expr);		VALIDATER(and_expr);
@@ -1829,12 +1831,34 @@
 }   /* validate_except_clause() */
 
 
+/*  bool_test ( | bool_test ? bool_test )
+ *
+ */
 static int
 validate_test(tree)
     node *tree;
 {
+    if (!validate_ntype(tree, test))
+	return 0;
+    else if (NCH(tree) == 1)
+	return(validate_bool_test(CHILD(tree, 0)));
+    else if (validate_numnodes(tree, 5, "expr"))
+    {
+	return validate_bool_test(CHILD(tree, 0))
+	    && validate_query(CHILD(tree, 1))
+	    && validate_bool_test(CHILD(tree, 2))
+	    && validate_colon(CHILD(tree, 3))
+	    && validate_bool_test(CHILD(tree, 4));
+    }
+}   /* validate_test() */
+
+
+static int
+validate_bool_test(tree)
+    node *tree;
+{
     int nch = NCH(tree);
-    int res = validate_ntype(tree, test) && is_odd(nch);
+    int res = validate_ntype(tree, bool_test) && is_odd(nch);
 
     if (res && (TYPE(CHILD(tree, 0)) == lambdef))
 	res = ((nch == 1)
@@ -1848,7 +1872,7 @@
     }
     return (res);
 
-}   /* validate_test() */
+}   /* validate_bool_test() */
 
 
 static int
--- Parser/tokenizer.c	2000/01/28 17:37:48	1.1
+++ Parser/tokenizer.c	2000/01/29 01:27:26
@@ -99,6 +99,7 @@
 	"LEFTSHIFT",
 	"RIGHTSHIFT",
 	"DOUBLESTAR",
+	"QUERY",
 	/* This table must match the #defines in token.h! */
 	"OP",
 	"<ERRORTOKEN>",
@@ -384,6 +385,7 @@
 	case '}':	return RBRACE;
 	case '^':	return CIRCUMFLEX;
 	case '~':	return TILDE;
+	case '?':	return QUERY;
 	default:	return OP;
 	}
 }
--- Python/compile.c	2000/01/28 23:17:19	1.1
+++ Python/compile.c	2000/01/29 22:19:29
@@ -1698,11 +1698,11 @@
 }
 
 static void
-com_test(c, n)
+com_bool_test(c, n)
 	struct compiling *c;
 	node *n;
 {
-	REQ(n, test); /* and_test ('or' and_test)* | lambdef */
+	REQ(n, bool_test); /* and_test ('or' and_test)* | lambdef */
 	if (NCH(n) == 1 && TYPE(CHILD(n, 0)) == lambdef) {
 		PyObject *v;
 		int i;
@@ -1738,6 +1738,32 @@
 }
 
 static void
+com_test(c, n)
+	struct compiling *c;
+	node *n;
+{
+	int op;
+	REQ(n, test);
+	com_bool_test(c, CHILD(n, 0));
+
+	/* is there a following ternary operator? */
+	/* XXX optimize the compilation when the guard is a constant */
+	if (NCH(n) == 5)
+	{
+	    int anchor1 = 0, anchor2 = 0;
+	    com_addfwref(c, JUMP_IF_FALSE, &anchor2);
+	    com_addbyte(c, POP_TOP);
+	    com_pop(c, 1);
+	    com_node(c, CHILD(n, 2));
+	    com_addfwref(c, JUMP_FORWARD, &anchor1);
+	    com_backpatch(c, anchor2);
+	    com_addbyte(c, POP_TOP);
+	    com_node(c, CHILD(n, 4));
+	    com_backpatch(c, anchor1);
+	}
+}
+
+static void
 com_list(c, n, toplevel)
 	struct compiling *c;
 	node *n;
@@ -2931,6 +2957,9 @@
 		break;
 	case test:
 		com_test(c, n);
+		break;
+	case bool_test:
+		com_bool_test(c, n);
 		break;
 	case and_test:
 		com_and_test(c, n);
--- Doc/ref/ref5.tex	2000/01/29 21:28:13	1.1
+++ Doc/ref/ref5.tex	2000/01/29 22:00:02
@@ -764,7 +764,7 @@
 \section{Boolean operations\label{Booleans}}
 \indexii{Boolean}{operation}
 
-Boolean operations have the lowest priority of all Python operations:
+Boolean operations have the lowest priority of all Python binary operations:
 
 \begin{verbatim}
 expression:     or_test | lambda_form
@@ -832,6 +832,24 @@
 def make_incrementor(increment):
     return lambda x, n=increment: x+n
 \end{verbatim}
+
+\section{Select\label{select}}
+\index{select}
+
+The select operator is a ternary operator with lower priority than
+boolean operations (and thus lower priority than all other binary and
+unary operators).
+
+\begin{verbatim}
+select_expr:    xor_expr | xor_expr "?" xor_expr ":" xor_expr
+\end{verbatim}
+
+If its first operand is nonempty, the value of a select operation is
+its second operand; otherwise the value is the third operand.
+
+(The semantics and precedence level of select are intended to be
+unsurprising to programmers familiar with \C's ternary select
+operator.)
 
 \section{Expression lists\label{exprlists}}
 \indexii{expression}{list}

End of diffs.
-- 
		<a href="http://www.tuxedo.org/~esr">Eric S. Raymond</a>

You know why there's a Second Amendment?  In case the government fails to
follow the first one.
         -- Rush Limbaugh, in a moment of unaccustomed profundity 17 Aug 1993



From jim at digicool.com  Sun Jan 30 14:52:32 2000
From: jim at digicool.com (Jim Fulton)
Date: Sun, 30 Jan 2000 08:52:32 -0500
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
References: <200001301332.IAA12252@eric.cnri.reston.va.us>
Message-ID: <38944220.3177B402@digicool.com>

Guido van Rossum wrote:
> 
> Dear developers,
> 
> Eric Raymond has sent me the following patch, which adds conditional
> expressions to Python.  I'd like to hear opinions on whether this is a
> good thing to add to Python, and whether this is the right syntax.

Yee ha! I think that this is a great idea. 

I'm surprised that using the colon doesn't cause problems.
I'm not a grammer lawyer, and don't care that much. I very 
much would like to see a conditional expression. I wouldn't
object if it was spelled differently than C's.

> I am a bit skeptical about whether this is sufficiently Pythonic, but
> on the other hand there have always been requests for such a feature,
> and the existing solutions are ugly:
> 
>   a and b or c
> 
> only works when you know for sure that b will never be false, and
> 
>   (a and [b] or [c])[0]
> 
> is dead ugly...

Yup.

   (a and (b,) or (c,))[0]

is even worse. ;)

Jim

--
Jim Fulton           mailto:jim at digicool.com
Technical Director   (888) 344-4332              Python Powered!
Digital Creations    http://www.digicool.com     http://www.python.org

Under US Code Title 47, Sec.227(b)(1)(C), Sec.227(a)(2)(B) This email
address may not be added to any commercial mail list with out my
permission.  Violation of my privacy with advertising or SPAM will
result in a suit for a MINIMUM of $500 damages/incident, $1500 for
repeats.



From esr at thyrsus.com  Sun Jan 30 16:59:42 2000
From: esr at thyrsus.com (Eric S. Raymond)
Date: Sun, 30 Jan 2000 10:59:42 -0500
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
In-Reply-To: <38944220.3177B402@digicool.com>; from Jim Fulton on Sun, Jan 30, 2000 at 08:52:32AM -0500
References: <200001301332.IAA12252@eric.cnri.reston.va.us> <38944220.3177B402@digicool.com>
Message-ID: <20000130105941.A10861@thyrsus.com>

Jim Fulton <jim at digicool.com>:
> I'm surprised that using the colon doesn't cause problems.

Pgen doesn't tag this ambiguous.  The LL(1) traversal actually helps
here; by the time you see a colon, you already know whether or not you're
parsing a ternary telect.
-- 
		<a href="http://www.tuxedo.org/~esr">Eric S. Raymond</a>

Don't think of it as `gun control', think of it as `victim
disarmament'. If we make enough laws, we can all be criminals.



From guido at CNRI.Reston.VA.US  Sun Jan 30 17:40:32 2000
From: guido at CNRI.Reston.VA.US (Guido van Rossum)
Date: Sun, 30 Jan 2000 11:40:32 -0500
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
In-Reply-To: Your message of "Sun, 30 Jan 2000 10:59:42 EST."
             <20000130105941.A10861@thyrsus.com> 
References: <200001301332.IAA12252@eric.cnri.reston.va.us> <38944220.3177B402@digicool.com>  
            <20000130105941.A10861@thyrsus.com> 
Message-ID: <200001301640.LAA12598@eric.cnri.reston.va.us>

> Jim Fulton <jim at digicool.com>:
> > I'm surprised that using the colon doesn't cause problems.

[ESR] 
> Pgen doesn't tag this ambiguous.  The LL(1) traversal actually helps
> here; by the time you see a colon, you already know whether or not you're
> parsing a ternary telect.

Interestingly, the very ad-hoc parsing that I described in the
compiling/parsing session on devday would be hit by this...  I was
looking for a colon at nesting level zero.  Serves me right for not
using a real parse :-)

--Guido van Rossum (home page: http://www.python.org/~guido/)



From da at ski.org  Sun Jan 30 19:07:51 2000
From: da at ski.org (David Ascher)
Date: Sun, 30 Jan 2000 10:07:51 -0800
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
References: <200001301332.IAA12252@eric.cnri.reston.va.us> <38944220.3177B402@digicool.com>             <20000130105941.A10861@thyrsus.com>  <200001301640.LAA12598@eric.cnri.reston.va.us>
Message-ID: <004101bf6b4c$ed2ab9b0$0100000a@ski.org>

FWIW, the lack of a ternary select is one of the frequently asked questions
in my Python courses.  It would make TomC happier as well.  I'm not sure the
latter is a feature. =)

On the topic of aesthetics, the C syntax doesn't strike me as the ultimate
in pythonicity but it's not too bad either.  I can't think of an alternative
that doesn't involve a new reserved word.

--david






From gvwilson at nevex.com  Sun Jan 30 21:22:21 2000
From: gvwilson at nevex.com (gvwilson at nevex.com)
Date: Sun, 30 Jan 2000 15:22:21 -0500 (EST)
Subject: [Python-Dev] Eight suggestions for Python books
Message-ID: <Pine.LNX.4.10.10001301519420.3368-100000@akbar.nevex.com>

I realize this is a bit off-topic, but based on discussions with various
publishers over the last couple of years, and on conversations at the
conference last week, I wrote up some notes on books that I think would
help Python succeed, and posted them to comp.lang.python under the heading
"Eight suggestions for Python books".  Some of the books are specificially
about Python, while others try to use Python to fill holes in the
curriculum, and thereby get Python into colleges through the side door (in
the same way that networking and computer graphics texts helped C become
more popular).  Hope it's useful...

Greg




From mal at lemburg.com  Sun Jan 30 22:34:51 2000
From: mal at lemburg.com (M.-A. Lemburg)
Date: Sun, 30 Jan 2000 22:34:51 +0100
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
References: <200001301332.IAA12252@eric.cnri.reston.va.us>
Message-ID: <3894AE7A.BE89D9B4@lemburg.com>

> --- Include/token.h     2000/01/28 17:38:55     1.1
> +++ Include/token.h     2000/01/29 01:27:00
> @@ -74,10 +74,11 @@
>  #define LEFTSHIFT      34
>  #define RIGHTSHIFT     35
>  #define DOUBLESTAR     36
> +#define QUERY          37
>  /* Don't forget to update the table _PyParser_TokenNames in tokenizer.c! */
> -#define OP             37
> -#define ERRORTOKEN     38
> -#define N_TOKENS       39
> +#define OP             38
> +#define ERRORTOKEN     39
> +#define N_TOKENS       34

Shouldn't this read #define N_TOKENS 40 ?!

Apart from that I wouldn't mind having this patch in the core :-)

-- 
Marc-Andre Lemburg
______________________________________________________________________
Business:                                      http://www.lemburg.com/
Python Pages:                           http://www.lemburg.com/python/




From tim_one at email.msn.com  Mon Jan 31 00:25:30 2000
From: tim_one at email.msn.com (Tim Peters)
Date: Sun, 30 Jan 2000 18:25:30 -0500
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
In-Reply-To: <200001301332.IAA12252@eric.cnri.reston.va.us>
Message-ID: <000301bf6b79$4f0c8a60$482d153f@tim>

[Guido van Rossum]
> Eric Raymond has sent me the following patch, which adds conditional
> expressions to Python.  I'd like to hear opinions on whether this
> is a good thing to add to Python,

Marginal; not evil, but of minor utility.

> and whether this is the right syntax.

If and only if you were a C programmer first.  BTW, insert <wink>s where
needed throughout <wink>.

> I am a bit skeptical about whether this is sufficiently Pythonic,
> but on the other hand there have always been requests for such a
> feature,

There have always been requests for the union of all features from all other
languages.

> and the existing solutions are ugly:
>
>   a and b or c
>
> only works when you know for sure that b will never be false,

Too error prone.

> and
>
>   (a and [b] or [c])[0]
>
> is dead ugly...

Well, I'm the guy who invented that one!  The thread that spawned it was
just playfully wondering whether it was *possible* -- and if I didn't solve
it, Majewski would have using even uglier __xxx__ trickery.  I've never used
it in a real program, and shoot people who do.

So there is no reasonable way to spell ?: as a one-liner today, period.  The
question is whether that's "a lack" worth doing something about.  I can live
without it.

Surprised that Jim (Fulton) seems so keen on it:  his cPickle.c uses ?:
exactly once in 4400 lines of C, and in a line that would have been clearer
if C had a max function (or is it min?  it can take a while to
reverse-engineer the intent of a ?:! ... not good when it happens; and I
recall one of the contributed patches that went into 1.5.2 longobject.c,
that had Guido & I both cracking a C manual just to figure out how C would
*parse* a particularly nutso blob of nested ?: thingies).

If this goes in (I'm not deadly opposed, just more opposed than in favor),
I'd like to see "else" used instead of the colon (cond "?" true "else"
false).  The question mark is reasonably mnemonic, but a colon makes no
sense here.

Now let's see whether people really want the functionality or are just
addicted to C syntax <ahem>.

BTW, a number of other changes would be needed to the Lang Ref manual (e.g.,
section 2.6 (Delimeters) explicitly says that "?" isn't used in Python
today, and that its appeareance outside a string literal or comment is "an
unconditional error"; etc).

crabby-old-man-ly y'rs  - tim





From esr at thyrsus.com  Mon Jan 31 00:43:17 2000
From: esr at thyrsus.com (Eric S. Raymond)
Date: Sun, 30 Jan 2000 18:43:17 -0500
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
In-Reply-To: <000301bf6b79$4f0c8a60$482d153f@tim>; from Tim Peters on Sun, Jan 30, 2000 at 06:25:30PM -0500
References: <200001301332.IAA12252@eric.cnri.reston.va.us> <000301bf6b79$4f0c8a60$482d153f@tim>
Message-ID: <20000130184317.A12833@thyrsus.com>

Tim Peters <tim_one at email.msn.com>:
> If this goes in (I'm not deadly opposed, just more opposed than in favor),
> I'd like to see "else" used instead of the colon (cond "?" true "else"
> false).  The question mark is reasonably mnemonic, but a colon makes no
> sense here.

I have to say that I think any ternary syntax that mixes a single-character
operator with a keyword would be intolerably ugly.
 
> Now let's see whether people really want the functionality or are just
> addicted to C syntax <ahem>.

It's not that simple.  People clearly want the functionality; we've
seen ample evidence of that.  Given that, I think the presumption has
to be in favor of using the familiar C syntax rather than an invention
that would necessarily be more obscure.

> BTW, a number of other changes would be needed to the Lang Ref manual (e.g.,
> section 2.6 (Delimeters) explicitly says that "?" isn't used in Python
> today, and that its appeareance outside a string literal or comment is "an
> unconditional error"; etc).

I'm certainly willing to fix that.
-- 
		<a href="http://www.tuxedo.org/~esr">Eric S. Raymond</a>

[The disarming of citizens] has a double effect, it palsies the hand
and brutalizes the mind: a habitual disuse of physical forces totally
destroys the moral [force]; and men lose at once the power of
protecting themselves, and of discerning the cause of their
oppression.
        -- Joel Barlow, "Advice to the Privileged Orders", 1792-93



From dascher at mindspring.com  Mon Jan 31 01:09:39 2000
From: dascher at mindspring.com (David Ascher)
Date: Sun, 30 Jan 2000 16:09:39 -0800
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
References: <200001301332.IAA12252@eric.cnri.reston.va.us> <000301bf6b79$4f0c8a60$482d153f@tim> <20000130184317.A12833@thyrsus.com>
Message-ID: <005c01bf6b7f$7a3a8f60$0100000a@ski.org>

> > Now let's see whether people really want the functionality or are just
> > addicted to C syntax <ahem>.
>
> It's not that simple.  People clearly want the functionality; we've
> seen ample evidence of that.

I personally haven't been stunned by the ample evidence you mention.  While
folks do ask about the ternary select periodically in classes and on the
net, none of my students at least are especially upset when I point out the
readability of:

if a:
      b = c
else:
      b = d

> Given that, I think the presumption has
> to be in favor of using the familiar C syntax rather than an invention
> that would necessarily be more obscure.

The presumption from the language design point of view is to do what's right
regardless of language background, not what's in C -- when Guido remembered
that, he chose 'and' and 'or' over '&&' and '||'.  When Guido forgot that,
he chose integer division =).  While all of the folks on this list are
comfortable with C, I can point out that a (possibly surprisingly) large
proportion of the Python programmers I have taught have never used C or
never felt comfortable with it. If CP4E succeeds, that proportion will grow,
not shrink.

I do think that taking a page from Randy Pausch would be a good idea in this
case.  My guess is that english words would emerge from trying to teach
non-programmers the concept, but I of course don't have data on the topic.
I wonder how high-school teachers teach the hook-colon in C intro classes,
specifically what _words_ they use.  Those words might lead to alternative
syntaxes.

Finally, something at the edge of my brain is trying to combine the logic of
the ternary select (which is clearly related to control flow) and a more
generalized switch statement.  But I'm not seeing anything syntactically
appealing at present.

That said, the hook-colon syntax is appealing from a release management
perspective because it fits within the current set of reserved words and
clearly isn't the hardest concept to teach.

--david




From petrilli at amber.org  Mon Jan 31 01:54:06 2000
From: petrilli at amber.org (Christopher Petrilli)
Date: Sun, 30 Jan 2000 19:54:06 -0500
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
In-Reply-To: <005c01bf6b7f$7a3a8f60$0100000a@ski.org>; from dascher@mindspring.com on Sun, Jan 30, 2000 at 04:09:39PM -0800
References: <200001301332.IAA12252@eric.cnri.reston.va.us> <000301bf6b79$4f0c8a60$482d153f@tim> <20000130184317.A12833@thyrsus.com> <005c01bf6b7f$7a3a8f60$0100000a@ski.org>
Message-ID: <20000130195406.A25682@trump.amber.org>

The question comes from what "problem" you're trying to solve.  The ?: syntax
does not introduce any new "functionality" to the language, nor does it
make it capable of solving problems or requirements that it can not do
at the current time.

The second qustion I'd ask is, who is this aimed at?  It's certainly not
aimed at first-time programmers, as I know from experience that the ?:
is one of the hardest things to teach people in C (after pointers), and
often I leave it out of training when I did it.  It's simply a "shorthand"
not a new functionality.  If its aimed at experienced programmers, I'd 
argue that it's at best "non-pythonic" and at worst a hack, taken from
a language in which it exposes the "macro assembler" approach.

Python is not a language that has been optimized for "minimal typing", it's
much more verbose than most languages, and so that argument shouldn' be
applied.  Perhaps it's for optimization?  That was I believe the original
argument made for it in K&R, in that optimizers in that day were rather
antiquated, wheras today, I believe that any C compiler would get it
right if it were expressed in its full form. (Timbot?)

So, it comes down to a few questions for me:

	Does it solve a new problem?	No
	Is it pythonic?			No
	Does it make it faster?		No

Given Pyton's CP4E goals, and its general place as an easy to use 
language, I'd argue this patch would be counter to all of those goals.

Sorry if I pushed someone's buton, but... I saw a lot of hints at making
Python MUCH more complex, which is counter to why I changed and dropped
many other languags.

Chris
-- 
| Christopher Petrilli
| petrilli at amber.org



From tim_one at email.msn.com  Mon Jan 31 01:44:34 2000
From: tim_one at email.msn.com (Tim Peters)
Date: Sun, 30 Jan 2000 19:44:34 -0500
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
In-Reply-To: <20000130184317.A12833@thyrsus.com>
Message-ID: <000801bf6b84$588c2d60$482d153f@tim>

[Tim, tosses off   cond "?" true "else" false
 in apparent hatred of colons]

[Eric S. Raymond]
> I have to say that I think any ternary syntax that mixes a
> single-character operator with a keyword would be intolerably ugly.

It's certainly not attractive <wink>.  Guido is the Master of Syntax; if he
decides the functionality is Pythonic, he'll dream up a good Pythonic
syntax.  I'll refrain from suggesting  "if" cond "lambda" true "else" false
<wink>.

>> Now let's see whether people really want the functionality or are just
>> addicted to C syntax <ahem>.

> It's not that simple.  People clearly want the functionality; we've
> seen ample evidence of that.

I have not.  Really!  This has been debated for nearly a decade, with no
consensus (the invention of the (a and [b] or [c])[0] atrocity predates
c.l.py!).  *Some* people certainly want ?: (or equivalent) a lot; but others
are equally opposed.  Note that lack of ?: didn't have enough of a
constituency in Andrew Kuchling's eyes either to make his original "Python
Warts" paper, or its revisions:

    http://starship.python.net/crew/amk/python/writing/warts.html

No change ever proposed has failed to attract vocal & persistent supporters,
so it's not as simple as *that* either <0.5 wink>.

> Given that, I think the presumption has to be in favor of using the
> familiar C syntax rather than an invention that would necessarily be
> more obscure.

By count, I'm sure many more languages (from virtually all functional
languages to Icon) use "if cond then true else false" for this purpose;
obscurity is relative to your background.  At least "if x then y else z" is
clear on the face of it (which may betray my background <wink>).  "then" has
no chance of getting into Python1, though.

My core objection is that ?: doesn't "look pretty":  it's not at all
suggestive of what it means, and the effects on precedence and associativity
are unattractive ("see C, copy C" is the only sense there is to it, and
rules for ?: are-- as I noted last time --obscure).  Good syntax counts for
a lot in Python -- which is why it doesn't look like C now.

Get a good syntax, and most of my objections vanish; I don't have a good
syntax to suggest, though.

passing-the-ball-back-to-guido-where-he-always-knew-it-
    would-land<wink>-ly y'rs  - tim





From esr at thyrsus.com  Mon Jan 31 02:07:11 2000
From: esr at thyrsus.com (Eric S. Raymond)
Date: Sun, 30 Jan 2000 20:07:11 -0500
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
In-Reply-To: <20000130195406.A25682@trump.amber.org>; from Christopher Petrilli on Sun, Jan 30, 2000 at 07:54:06PM -0500
References: <200001301332.IAA12252@eric.cnri.reston.va.us> <000301bf6b79$4f0c8a60$482d153f@tim> <20000130184317.A12833@thyrsus.com> <005c01bf6b7f$7a3a8f60$0100000a@ski.org> <20000130195406.A25682@trump.amber.org>
Message-ID: <20000130200711.A13063@thyrsus.com>

Christopher Petrilli <petrilli at amber.org>:
> The question comes from what "problem" you're trying to solve.  The ?: syntax
> does not introduce any new "functionality" to the language, nor does it
> make it capable of solving problems or requirements that it can not do
> at the current time.

Well, in a theoretical sense, you're right.  But then, even troff macros and
INTERCAL are Turing-complete <my-first-attempt-at-a-Tim-Peters-style-wink>.

One of the lessons of Python to this old LISPer is that *notation
matters*.  Theoretically, Python is a subset of Scheme-with-objects
using a vaguely C-like surface notation.  But even I would rather write
a for-loop than the equivalent recursion.  That's why I code in Python
now instead of trying to rescue LISP from its desuetitude.

So while it is *theoretically* true that ?: adds nothing, it is
*practically* true that it enables a large class of idioms that 
can't otherwise be comfortably expressed.  That matters.

Now, you can argue that the complexity ?: adds to language is not paid
for by the additional convenience; I disagree, but that's at least a
defensible argument.  But simply saying it "adds nothing to the
language" is a red herring -- neither do many of the other base
language features.

Why, for example, do we have more than one kind of loop construct?
Unecessary.  Wasteful.  Clearly either "for" or "while" must go.
As an exercise, try editing your complaint so that it refers to 
"for" everywhere it now refers to ?:.  Contemplate the edited
version until you achieve enlightenment ;-).
-- 
		<a href="http://www.tuxedo.org/~esr">Eric S. Raymond</a>

The same applies for other kinds of long-lasting low-level pain. [...]
The body's response to being jabbed, pierced, and cut is to produce
endorphins. [...]  So here's my programme for breaking that cycle of
dependency on Windows: get left arm tattooed with dragon motif, buy a
crate of Jamaican Hot! Pepper Sauce, get nipples pierced.  With any
luck that will produce enough endorphins to make Windows completely
redundant, and I can then upgrade to Linux and get on with things.
	-- Pieter Hintjens



From ping at lfw.org  Mon Jan 31 02:29:43 2000
From: ping at lfw.org (Ka-Ping Yee)
Date: Sun, 30 Jan 2000 19:29:43 -0600 (EST)
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
In-Reply-To: <000301bf6b79$4f0c8a60$482d153f@tim>
Message-ID: <Pine.LNX.4.10.10001301925190.24976-100000@server1.lfw.org>

On Sun, 30 Jan 2000, Tim Peters wrote:
> If this goes in (I'm not deadly opposed, just more opposed than in favor),
> I'd like to see "else" used instead of the colon (cond "?" true "else"
> false).  The question mark is reasonably mnemonic, but a colon makes no
> sense here.

I agree with that sentiment (along the lines of the philosophy that
chose "and" over "&&"), and it seems to me that it makes the most sense
to use words for both:

    a = x > 0 then x else -x

I don't have the time to do it right this second, but i suggest that
a scan through a decent chunk of Python would be useful to find out how
often this construct (in its "and"/"or" incarnation) actually gets used.
I promise to give it a try as soon as i get my notebook battery charged
up again.


-- ?!ng




From tim_one at email.msn.com  Mon Jan 31 03:41:59 2000
From: tim_one at email.msn.com (Tim Peters)
Date: Sun, 30 Jan 2000 21:41:59 -0500
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
In-Reply-To: <20000130195406.A25682@trump.amber.org>
Message-ID: <000201bf6b94$bfabc360$ee2d153f@tim>

[Christopher Petrilli]
> ...
> Python is not a language that has been optimized for "minimal
> typing", it's much more verbose than most languages, and so that
> argument shouldn't be applied.

Concise expression of common concepts is a Good Thing, though, and there's
nothing inherently evil about wanting one of two outcomes <wink>.  My
impression is that the people historically most in favor of ?: ("or
something like it") are also the ones most strongly in favor of embedded
assignment ("or something like it"), and I can't *dismiss* either gripe.
The Python

while 1:
    x = something_or_other()
    if not x:
        break
    consume(x)

idiom is truly grating at first -- more so than the multi-line ?:
alternatives, in my eyes.

> Perhaps it's for optimization?  That was I believe the original
> argument made for it in K&R, in that optimizers in that day were rather
> antiquated, wheras today, I believe that any C compiler would get it
> right if it were expressed in its full form. (Timbot?)

Indeed, a couple weeks ago we tracked down a "mysterious slowdown" of our
core speech recognizer to a particular compiler failing to optimize *unless*
we changed a ?: into a long winded if/else!  There's really nothing you can
say about "any C compiler" -- optimization is much more a black art than
anyone in that business will admit to in public <0.9 wink>.

C was definitely designed with "by hand" optimization in mind, and,
ironically, it's those features (particularly pointer aliasing) that make it
harder for compilers to optimize than is, say, Fortran.

But regardless of origin, ?: stands or falls on its other merits now.
Python's own implementation uses it often enough, and to good effect.  So it
can't be that Guido hates the idea <wink>.  It's just hard to love the
syntax.

> So, it comes down to a few questions for me:
>
> 	Does it solve a new problem?	No
> 	Is it pythonic?			No
> 	Does it make it faster?		No

Would a nice syntax allow clearer expression of some common computations?
Probably yes.  That's the same basis on which, e.g., list.pop and
list.extend and dict.get and 3-argument getattr and ... were adopted.
"Faster" applied to those too, but nobody pushed for 'em on that basis.
Clearer!  That's what really matters.  It's the same argument for list
comprehensions too.

> ...
> Sorry if I pushed someone's buton, but... I saw a lot of hints at making
> Python MUCH more complex, which is counter to why I changed and dropped
> many other languags.

A good antitode to feature panic is reviewing Misc/HISTORY:  Guido's
willingness to entertain suggestions far exceeds his willingness to adopt
them <wink>.

it-would-be-different-if-features-were-just-as-easy-to-
    take-out-ly y'rs  - tim





From tismer at tismer.com  Mon Jan 31 12:46:50 2000
From: tismer at tismer.com (Christian Tismer)
Date: Mon, 31 Jan 2000 12:46:50 +0100
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
References: <Pine.LNX.4.10.10001301925190.24976-100000@server1.lfw.org>
Message-ID: <3895762A.C1706E8@tismer.com>


Ka-Ping Yee wrote:
> 
> On Sun, 30 Jan 2000, Tim Peters wrote:
> > If this goes in (I'm not deadly opposed, just more opposed than in favor),
> > I'd like to see "else" used instead of the colon (cond "?" true "else"
> > false).  The question mark is reasonably mnemonic, but a colon makes no
> > sense here.
> 
> I agree with that sentiment (along the lines of the philosophy that
> chose "and" over "&&"), and it seems to me that it makes the most sense
> to use words for both:
> 
>     a = x > 0 then x else -x

I would favorise this as well instead of using ?: .
Maybe it would make sense to be even more verbose and use an "if"
as well?

       a = if x > 0 then x else -x

       sign = lambda x: if x > 0 then 1 elif x then -1 else 0

ciao - chris

-- 
Christian Tismer             :^)   <mailto:tismer at appliedbiometrics.com>
Applied Biometrics GmbH      :     Have a break! Take a ride on Python's
D?ppelstr. 31                :    *Starship* http://starship.python.net
12163 Berlin                 :     PGP key -> http://wwwkeys.pgp.net
PGP Fingerprint       E182 71C7 1A9D 66E9 9D15  D3CC D4D7 93E2 1FAE F6DF
     we're tired of banana software - shipped green, ripens at home



From gward at cnri.reston.va.us  Mon Jan 31 15:15:08 2000
From: gward at cnri.reston.va.us (Greg Ward)
Date: Mon, 31 Jan 2000 09:15:08 -0500
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
In-Reply-To: <Pine.LNX.4.10.10001301925190.24976-100000@server1.lfw.org>; from ping@lfw.org on Sun, Jan 30, 2000 at 07:29:43PM -0600
References: <000301bf6b79$4f0c8a60$482d153f@tim> <Pine.LNX.4.10.10001301925190.24976-100000@server1.lfw.org>
Message-ID: <20000131091507.A17073@cnri.reston.va.us>

On 30 January 2000, Ka-Ping Yee said:
> On Sun, 30 Jan 2000, Tim Peters wrote:
> > If this goes in (I'm not deadly opposed, just more opposed than in favor),
> > I'd like to see "else" used instead of the colon (cond "?" true "else"
> > false).  The question mark is reasonably mnemonic, but a colon makes no
> > sense here.
> 
> I agree with that sentiment (along the lines of the philosophy that
> chose "and" over "&&"), and it seems to me that it makes the most sense
> to use words for both:
> 
>     a = x > 0 then x else -x

Yeah, I agree with Tim: it's a handy feature and I frequently wish I
could do simple conditional assignment without resorting to a full-blown
if/else.  (I think I stumbled across "a and b or c" myself -- either
that or it was suggested by *Learning Python*, but lay dormant in my
subconscious for several months -- which means that I missed the "b must
always be true" subtlety until it bit me.  Ouch.  I avoid that idiom
now.)

BUT the C line-noise syntax is not appropriate.  It's fine in C, and
it's eminently appropriate in Perl -- both languages designed to
minimise wear-and-tear of programmers' keyboards.  But keyboards are
cheap nowadays, so perhaps we can be a bit more profligate with them.

I find Ping's proposed syntax intriguing.  Personally, I've always been
partial to the

    x = if a then b else c

syntax, even though I don't think I've ever used a language that
includes it.  (Oh wait, the toy ALGOL-knockoff that we used in Intro to
Compilers had it, so I *have* written a parser and simplistic code
generator for a language that includes it.  Perhaps that's why I like
it...)

But either of these -- ie. elevate "then" to keywordhood, with or
without "if", and no colons to be seen -- smell like they would play
havoc with Python's grammar.  And they turn a statement keyword "if"
into an expression keyword.  Not being at all familiar with Python's
parser, I should just shut up now, but it feels tricky.

And of course, any proposed syntax changes nowadays have to take JPython
into account.

        Greg



From guido at CNRI.Reston.VA.US  Mon Jan 31 15:36:52 2000
From: guido at CNRI.Reston.VA.US (Guido van Rossum)
Date: Mon, 31 Jan 2000 09:36:52 -0500
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
In-Reply-To: Your message of "Mon, 31 Jan 2000 09:15:08 EST."
             <20000131091507.A17073@cnri.reston.va.us> 
References: <000301bf6b79$4f0c8a60$482d153f@tim> <Pine.LNX.4.10.10001301925190.24976-100000@server1.lfw.org>  
            <20000131091507.A17073@cnri.reston.va.us> 
Message-ID: <200001311436.JAA15213@eric.cnri.reston.va.us>

> I find Ping's proposed syntax intriguing.  Personally, I've always been
> partial to the
> 
>     x = if a then b else c
> 
> syntax, even though I don't think I've ever used a language that
> includes it.  (Oh wait, the toy ALGOL-knockoff that we used in Intro to
> Compilers had it, so I *have* written a parser and simplistic code
> generator for a language that includes it.  Perhaps that's why I like
> it...)

Yes, this was in original Algol 60 and, by magic of a completely
different kind, again in Algol 68 (which was a completely different
language, and the Mount Everest of languages).

> But either of these -- ie. elevate "then" to keywordhood, with or
> without "if", and no colons to be seen -- smell like they would play
> havoc with Python's grammar.  And they turn a statement keyword "if"
> into an expression keyword.  Not being at all familiar with Python's
> parser, I should just shut up now, but it feels tricky.

The solution can be the same as what Algol used: 'if' outside
parentheses is a statement, and inside parentheses is an expression.
It's a bit of a grammar rearrangement, but totally unambiguous.

However, the added keyword means it won't be in 1.6.  The lively
discussion means that Eric's patch will have a hard time getting in
too...

--Guido van Rossum (home page: http://www.python.org/~guido/)



From jim at digicool.com  Mon Jan 31 16:04:45 2000
From: jim at digicool.com (Jim Fulton)
Date: Mon, 31 Jan 2000 10:04:45 -0500
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
References: <200001301332.IAA12252@eric.cnri.reston.va.us> <000301bf6b79$4f0c8a60$482d153f@tim> <20000130184317.A12833@thyrsus.com> <005c01bf6b7f$7a3a8f60$0100000a@ski.org> <20000130195406.A25682@trump.amber.org>
Message-ID: <3895A48D.F69B3DFA@digicool.com>

Christopher Petrilli wrote:
> 
> The question comes from what "problem" you're trying to solve. 

It would allow you to incorporate logic into expressions. 
There are contexts where only expressions are allowed, such as:

  - lambdas

  - DTML expr attributes

in which I'd very much like to incorporate tests.

> The ?: syntax
> does not introduce any new "functionality" to the language,

Yes it does.

> nor does it
> make it capable of solving problems or requirements that it can not do
> at the current time.

Ditto.
 
> The second qustion I'd ask is, who is this aimed at?  It's certainly not
> aimed at first-time programmers, as I know from experience that the ?:
> is one of the hardest things to teach people in C (after pointers),

Hm. I can't agree.

Smalltalk, came out of an essentially CP4E effort
two decades ago at Xerox PARC.  Smalltalk *only* had conditional
expressions. The message:

  [condition] ifTrue: [do something ...]
              ifFalse: [do something else ...]

is an expression in Smalltalk.

> and
> often I leave it out of training when I did it.  It's simply a "shorthand"
> not a new functionality. 

No, it allows testing in expressions.

> If its aimed at experienced programmers, I'd
> argue that it's at best "non-pythonic" and at worst a hack, taken from
> a language in which it exposes the "macro assembler" approach.

I don't agree.

> Python is not a language that has been optimized for "minimal typing",

That's not the issue.

> it's
> much more verbose than most languages, and so that argument shouldn' be
> applied.  Perhaps it's for optimization?  That was I believe the original
> argument made for it in K&R, in that optimizers in that day were rather
> antiquated, wheras today, I believe that any C compiler would get it
> right if it were expressed in its full form. (Timbot?)
> 
> So, it comes down to a few questions for me:
> 
>         Does it solve a new problem?    No

Yes.

>         Is it pythonic?                 No

Pythonicity is relative.

>         Does it make it faster?         No

Who cares?
 
Jim

--
Jim Fulton           mailto:jim at digicool.com   Python Powered!        
Technical Director   (888) 344-4332            http://www.python.org  
Digital Creations    http://www.digicool.com   http://www.zope.org    

Under US Code Title 47, Sec.227(b)(1)(C), Sec.227(a)(2)(B) This email
address may not be added to any commercial mail list with out my
permission.  Violation of my privacy with advertising or SPAM will
result in a suit for a MINIMUM of $500 damages/incident, $1500 for
repeats.



From tismer at tismer.com  Mon Jan 31 16:59:15 2000
From: tismer at tismer.com (Christian Tismer)
Date: Mon, 31 Jan 2000 16:59:15 +0100
Subject: [Python-Dev] Riskless deletion of nested structures
Message-ID: <3895B153.3D2E763D@tismer.com>

Howdy,

Please review!

While implementing Stackless Python, a new problem arose:
Nested structures like frame chains and tracebacks can now
easily grow somuch that they cause a stack overflow on deallocation.

To protect lists, tuples, frames, dicts and tracebacks against
this, I wrote a stackless deallocator.
At the moment, everything is done in trashcan.c .
This gives a slight performance loss of 5% for pystone, most probably
due to the double indirection and non-local code reference.
It is yet a hack, since I'm grabbing the tp->dealloc pointers of these
types and replace them by safe versions. This just in order to
try out things quickly. Later I will change this and incorporate
the stack checks into the affected modules, after I got some
feedback on this.

This patch applies to Stackless and standard Python as well:
Deallocation of deeply nested structures will never again cause
a stack overflow.

Installation for the intermediate version:
Insert a line

	_Py_trashcan_install();

at the end of Py_Initialize in pythonrun.c

Please try it and check my code wether there is a better solution.

cheers - chris

-- 
Christian Tismer             :^)   <mailto:tismer at appliedbiometrics.com>
Applied Biometrics GmbH      :     Have a break! Take a ride on Python's
D?ppelstr. 31                :    *Starship* http://starship.python.net
12163 Berlin                 :     PGP key -> http://wwwkeys.pgp.net
PGP Fingerprint       E182 71C7 1A9D 66E9 9D15  D3CC D4D7 93E2 1FAE F6DF
     we're tired of banana software - shipped green, ripens at home
-------------- next part --------------
A non-text attachment was scrubbed...
Name: trashcan.c
Type: application/x-unknown-content-type-cfile
Size: 2209 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/python-dev/attachments/20000131/4c063f63/attachment.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: trashcan.h
Type: application/x-unknown-content-type-hfile
Size: 246 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/python-dev/attachments/20000131/4c063f63/attachment-0001.bin>

From fdrake at acm.org  Mon Jan 31 18:08:11 2000
From: fdrake at acm.org (Fred L. Drake, Jr.)
Date: Mon, 31 Jan 2000 12:08:11 -0500 (EST)
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
In-Reply-To: <Pine.LNX.4.10.10001301925190.24976-100000@server1.lfw.org>
References: <000301bf6b79$4f0c8a60$482d153f@tim>
	<Pine.LNX.4.10.10001301925190.24976-100000@server1.lfw.org>
Message-ID: <14485.49531.600935.643400@weyr.cnri.reston.va.us>

Ka-Ping Yee writes:
 > a scan through a decent chunk of Python would be useful to find out how
 > often this construct (in its "and"/"or" incarnation) actually gets used.

  I'm not sure what the survey provides other than a lower bound.  I
think most Python programmers who want the ?: functionality avoid the
and/or approach because of the ugliness.  I know I do.
  But I'd really like to have the functionality if the syntax is
reasonable!  I could live with something like "if cond then true else
false"; the leading "if" is visually important; without it, you have
to scan over the test expression to find the "then", and that makes it
harder to read.


  -Fred

--
Fred L. Drake, Jr.	  <fdrake at acm.org>
Corporation for National Research Initiatives



From bwarsaw at cnri.reston.va.us  Mon Jan 31 18:33:25 2000
From: bwarsaw at cnri.reston.va.us (Barry A. Warsaw)
Date: Mon, 31 Jan 2000 12:33:25 -0500 (EST)
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
References: <000301bf6b79$4f0c8a60$482d153f@tim>
	<Pine.LNX.4.10.10001301925190.24976-100000@server1.lfw.org>
	<14485.49531.600935.643400@weyr.cnri.reston.va.us>
Message-ID: <14485.51045.97448.830202@anthem.cnri.reston.va.us>

Put me in the camp of "yeah, occasionally I wish I had it, but I can
always hack around it, and the C syntax just blows".  I'm sure if it's
wedgeable into CPython it would also be in JPython, but I dislike ?:
syntax enough to vote strongly against it for CPython 1.6.

A Forth-ish syntax might be more acceptable

    x = y > z if y else z

but come on!  You'll give ordinarily dandruff-free Python programmers
plenty of other reasons to scratch their heads with this one.

head-and-shoulders-above-the-rest-ly y'rs,
-Barry



From gvwilson at nevex.com  Mon Jan 31 18:44:53 2000
From: gvwilson at nevex.com (gvwilson at nevex.com)
Date: Mon, 31 Jan 2000 12:44:53 -0500 (EST)
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
In-Reply-To: <3895A48D.F69B3DFA@digicool.com>
Message-ID: <Pine.LNX.4.10.10001311239400.11154-100000@akbar.nevex.com>

> It (?:) would allow you to incorporate logic into expressions. 
> There are contexts where only expressions are allowed, such as:
>   - lambdas
>   - DTML expr attributes
> in which I'd very much like to incorporate tests.

Don't know much about DTML, but believe that being able to put
conditionals in lambdas would make the latter much more useful.

> > The ?: syntax
> > does not introduce any new "functionality" to the language,
> Yes it does.

Is anything possible with ?: that's impossible without? No --- Python is
Turing-equivalent before and after the change.

Is anything easier with ?: --- yes.

Does this make up for the added complexity?  Dunno (see below).

> > The second qustion I'd ask is, who is this aimed at?  It's certainly not
> > aimed at first-time programmers, as I know from experience that the ?:
> > is one of the hardest things to teach people in C (after pointers),
> Hm. I can't agree.

Strongly agree with the first author --- IME, ?: is very hard to teach.

Greg




From klm at digicool.com  Mon Jan 31 18:58:07 2000
From: klm at digicool.com (Ken Manheimer)
Date: Mon, 31 Jan 2000 12:58:07 -0500 (EST)
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
In-Reply-To: <14485.49531.600935.643400@weyr.cnri.reston.va.us>
Message-ID: <Pine.LNX.4.10.10001311236250.11106-100000@splat.digicool.com>

On Mon, 31 Jan 2000, Fred L. Drake, Jr. wrote:

> Ka-Ping Yee writes:
>  > a scan through a decent chunk of Python would be useful to find out how
>  > often this construct (in its "and"/"or" incarnation) actually gets used.
> 
>   I'm not sure what the survey provides other than a lower bound.  I
> think most Python programmers who want the ?: functionality avoid the
> and/or approach because of the ugliness.  I know I do.

Good point.  Just because the workaround is bad doesn't mean the thing
being worked-around is unimportant...

I should weigh in to say that i have really really wanted, in particular,
the ability to have a condition on the right hand side of an assignement.
IIR, on some occasions it seemed less clear to have to use separate
statements for what was essentially a single assignment that just, eg,
differed by a single term.  I wanted (want) some reasonable way to express
the condition in an expression.  I can see how this compactness could lead
to regex-style convolution of expressions, but that could be avoided by
providing a not-too-terse syntax.

(I should admit that may have succumbed to the (a and (b,) or (c,))[0]
grotesquerie at some point!  Not sure.  Wish i could recall what might
have justified succumbing - the mere fact that i may have, without
compelling justification, might-should disqualify my judgement on the
matter, ay?  Hey, maybe i didn't, i was just imagining it - now am i not a
sterling judge?-)

Ken
klm at digicool.com




From tismer at tismer.com  Mon Jan 31 20:55:36 2000
From: tismer at tismer.com (Christian Tismer)
Date: Mon, 31 Jan 2000 20:55:36 +0100
Subject: [Python-Dev] Ann: Stackless Python 1.02
Message-ID: <3895E8B8.995CA560@tismer.com>

Stackless Python is a Python without C stack usage.
It allows for all kinds of non-local control flow.
For info see http://www.tismer.com/research/stackless/

Update for Stackless Python V. 1.02:

- passes all standard tests
- should work with Zope now (try...finally was incorrect)
- has a smart object destructor for really deeply nested stuff

The "5 percent speedup" is no longer there currently, since
the smart object destructor needs to be optimized into
the objects. It is not done in this test phase but will come.

Please visit the Stackless Python homepage at

http://www.tismer.com/research/stackless/

Fact sheet, links to documentation, source and
binaries can be found there.

cheers - chris

<P><A HREF="http://www.tismer.com/research/stackless/">Stackless
Python 1.02 + Continuations 0.6</A> - a version of Python 1.5.2 that
does not need space on the C stack, and first-class callable
continuation objects for Python.  (31-Jan-2000)

Christian Tismer
Mission Impossible 5oftware Team



From tim_one at email.msn.com  Sun Jan  2 06:52:34 2000
From: tim_one at email.msn.com (Tim Peters)
Date: Sun, 2 Jan 2000 00:52:34 -0500
Subject: [Python-Dev] Re: [Distutils] Questions about distutils strategy
In-Reply-To: <199912091617.LAA05742@eric.cnri.reston.va.us>
Message-ID: <000401bf54e5$91587280$1f2d153f@tim>

Briefly backtracking to an old thread:

[Guido]
> ...
> The problem lies in which key is used.  All versions of
> Python 1.5.x (1.5, 1.5.1, 1.5.2) use the same key!  This
> is a main cause of trouble, because it means that different
> versions cannot peacefully live together even if the user
> installs them into different directories -- they will all
> use the registry keys of the last version installed.  This,
> in turn, means that someone who writes a Python application
> that has a dependency on a particular Python version (and
> which application worth distributing doesn't :-) cannot
> trust that if a Python installation is present, it is the
> right one.  But they also cannot simply bundle the standard
> installer for the correct Python version with their program,
> because its installation would overwrite an existing Python
> application, thus breaking some *other* Python apps that
> the user might already have installed.

Right, that's one class of intractable problem under Windows.

*Inside* my workplace, another kind of problem is caused when people try to
make a Python app available over the Windows network.  They stick the Python
they want and its libraries out on the network, with python.exe in the same
directory as the app.  Now some people have highly customized Python setups,
and the network Python picks up "the wrong" site.py etc.  That sucks, and
there appears no sane way to stop it.

Telling internal app distributors they need to invent a unique registry key
and fiddle their python.exe's resources is a non-starter.  Ditto telling
people with highly customized Pythons "don't do that".  Ditto telling anyone
they have to run any sort of installation script just to use a network app
(sometimes they don't even know they're running it! e.g., when it's a
subsystem invoked by another app).

So while everyone is thinking about the hardest possible scenarios, please
give a thought to the dirt simple one too <0.5 wink>:  an app distributor
who knows exactly what they're doing, and for whom *any* magical inference
is simply a barrier to overcome.  The latter can be satisfied by any number
of means, from an envar that says "please don't try to be helpful, *this* is
the directory you look in, and if you don't find stuff there give up" to a
cmdline switch that says the same.  Nothing Windows-specific there -- any OS
with an envar or a cmdline will play along <wink>.

> ...
> I thought a bit about how VB solves this.  I think that when
> you wrap up a VB app in, all the support code (mostly a big
> DLL) is wrapped with it.  When the user runs the installer,
> the DLL is installed (probably in the WINDOWS directory).  If
> a user installs several VB apps built with the same VB
> version, they all attempt to install the exact same DLL; of
> course the installers notice this and optimize it away, keeping
> a reference count.

This is the way most *MS* DLLs work; stuff like the C runtime libraries and
MS database drivers work exactly the same way.  It's rare for pkgs other
than MS's to attempt to use this mechanism, though (the reason is given
below).

> (Ignoring for now the fact that those reference counts don't
> always work!)

?  They work very well, in my experience.  Where they fail is when
installers & uninstallers break the rules.  MS publishes the list of MS DLLs
that are to be treated this way:  an installer "must" use refcounting on the
DLLs in the list.  Alas, some (especially older) installation pkgs don't.
Then the refcounts get screwed up.

That's what makes the mechanism brittle:  "the system" doesn't enforce it,
it relies on universal & intelligent cooperation.  It's very likely that
someone distributing a Python app will neglect (out of ignorance) to bump
the refcount on their Python components, so the refcount will be
artificially low, and a later uninstall of some unrelated pkg that *did*
follow the rules will merrily delete Python.

Gordon and I will repeat this until it sinks in <wink>:  almost everyone
with a successful Windows product ships the non-MS DLLs they rely on and
copies them into their own app directory.  It's simple and it works;
alternatives are complicated and don't work.  Many even ship & copy MS DLLs
(e.g., Scriptics copies its own msvcrt.dll (the MS C runtime) into Tcl's
directories).  Worrying about space consumed by redundant Python components
is a bad case of premature optimization <0.3 wink>.

> ...
> How can we do something similar for Python?

Seriously, short of getting MS to distribute Python and put the Python DLLs
on The List of refcounted resources, we should pursue this line reluctantly
if at all.  MS may have a better scheme in the future, but for now better
safe than sorry.


a-couple-mb-on-a-modern-pc-isn't-worth-the-time-it-took-
    to-read-this<wink>-ly y'rs  - tim





From gstein at lyra.org  Mon Jan  3 03:53:24 2000
From: gstein at lyra.org (Greg Stein)
Date: Sun, 2 Jan 2000 18:53:24 -0800 (PST)
Subject: [Python-Dev] new imputil.py
Message-ID: <Pine.LNX.4.10.10001021838400.412-200000@nebula.lyra.org>

Happy New Year!

I've attached a new imputil.py to this message. It isn't posted on my page
yet, as I'd like some feedback before declaring this new version viable.

In this imputil, there is an ImportManager class. It gets installed as the
import hook, with the presumption that it is the only import hook
(technically, it could chain, but I've disabled that for now). I think
Python 1.6 should drop the __import__ builtin and move to something like
sys.import_hook (to allow examination and change). Another alternative
would be sys.get_import_hook() and sys.set_import_hook().
[ I don't think we would want a "set" that returned the old version as the
  only way to get the current hook function; we want to be able to easily 
  find the ImportManager instance. ]

The ImportManager knows how to scan sys.path when it needs to find a
top-level module/package (e.g. given a.b.c, the "a" is the top-level; b.c
falls "below" that). sys.path can contain strings which specify a
filesystem directory, or it can contain Importer instances.

The manager also records an ordered list of suffix/importer pairs. The
add_suffix() method is used to append new suffixes, but clients can also
access the .suffixes attribute for fine-grained manipulation/ordering.

There is a new importer called _FilesystemImporter which understands how
to look into a directory for Python modules. It borrows/refers to the
ImportManager's .suffixes attribute, using that to find modules in a
directory. This is also the Importer that gets associated with each
filesystem-based module.

The importers used for suffix-based importing are derived from
SuffixImporter. While a function could be used here, future changes will
be easier if we presume class instances.

The new imputil works fine (use _test_revamp() to switch to the new import
mechanism). Importer subclasses using the old imputil should continue to
work, although I am deprecating the 2-tuple return value for get_code().
get_code() should return None or the 3-tuple form now.

I think I still have a bit more work to do, to enable something like
"import a.b.c" where a.zip is an archive on the path and "b.c" resides in
the archive. Note: it *is* possible to do
sys.path.append(ZipImporter(filename)) and have "a.b.c" in the Zip file.
It would simply be nicer to be able to drop arbitrary .zip files onto the
path and use their basename as the top-level name of a package. Anyhow: I
haven't looked at this scenario yet to find what the new system is missing
(if anything).

As always: feedback is more than appreciated! Especially from people using
imputil today. Did I break anything? Does the new scheme still feel right
to you? etc.

Cheers,
-g

p.s. I'd also like to remove PackageArchiveImporter and PackageArchive.
     They don't seem to add any real value. I might move DirectoryImporter
     and PathImporter to an "examples" file, too.

-- 
Greg Stein, http://www.lyra.org/

-------------- next part --------------
#
# imputil.py
#
# Written by Greg Stein. Public Domain.
# No Copyright, no Rights Reserved, and no Warranties.
#
# Utilities to help out with custom import mechanisms.
#
# Additional modifications were contribed by Marc-Andre Lemburg and
# Gordon McMillan.
#
# This module is maintained by Greg and is available at:
#    http://www.lyra.org/greg/python/imputil.py
#
# Since this isn't in the Python distribution yet, we'll use the CVS ID
# for tracking:
#   $Id: imputil.py,v 1.9 2000/01/03 02:38:29 gstein Exp $
#

# note: avoid importing non-builtin modules
import imp
import sys
import strop
import __builtin__

# for the DirectoryImporter
import struct
import marshal

_StringType = type('')
_ModuleType = type(sys)

class ImportManager:
  "Manage the import process."

  def install(self):
    ### warning: Python 1.6 will have a different hook mechanism; this
    ### code will need to change.
    self.__chain_import = __builtin__.__import__
    self.__chain_reload = __builtin__.reload
    __builtin__.__import__ = self._import_hook
    ### fix this
    #__builtin__.reload = None
    #__builtin__.reload = self._reload_hook

  def add_suffix(self, suffix, importer):
    assert isinstance(importer, SuffixImporter)
    self.suffixes.append((suffix, importer))

  ######################################################################
  #
  # PRIVATE METHODS
  #
  def __init__(self):
    # we're definitely going to be importing something in the future,
    # so let's just load the OS-related facilities.
    if not _os_stat:
      _os_bootstrap()

    # Initialize the set of suffixes that we recognize and import.
    # The default will import dynamic-load modules first, followed by
    # .py files (or a .py file's cached bytecode)
    self.suffixes = [ ]
    for desc in imp.get_suffixes():
      if desc[2] == imp.C_EXTENSION:
        self.suffixes.append((desc[0], DynLoadSuffixImporter(desc)))
    self.suffixes.append(('.py', PySuffixImporter()))

    # This is the importer that we use for grabbing stuff from the
    # filesystem. It defines one more method (import_from_dir) for our use.
    self.fs_imp = _FilesystemImporter(self.suffixes)

  def _import_hook(self, fqname, globals=None, locals=None, fromlist=None):
    """Python calls this hook to locate and import a module."""

    parts = strop.split(fqname, '.')

    # determine the context of this import
    parent = self._determine_import_context(globals)

    # if there is a parent, then its importer should manage this import
    if parent:
      module = parent.__importer__._do_import(parent, parts, fromlist)
      if module:
        return module

    # has the top module already been imported?
    try:
      top_module = sys.modules[parts[0]]
    except KeyError:

      # look for the topmost module
      top_module = self._import_top_module(parts[0])
      if not top_module:
        # the topmost module wasn't found at all.
        raise ImportError, 'No module named ' + fqname
        return self.__chain_import(name, globals, locals, fromlist)

    # fast-path simple imports
    if len(parts) == 1:
      if not fromlist:
        return top_module

      if not top_module.__dict__.get('__ispkg__'):
        # __ispkg__ isn't defined (the module was not imported by us), or
        # it is zero.
        #
        # In the former case, there is no way that we could import
        # sub-modules that occur in the fromlist (but we can't raise an
        # error because it may just be names) because we don't know how
        # to deal with packages that were imported by other systems.
        #
        # In the latter case (__ispkg__ == 0), there can't be any sub-
        # modules present, so we can just return.
        #
        # In both cases, since len(parts) == 1, the top_module is also
        # the "bottom" which is the defined return when a fromlist exists.
        return top_module

    importer = top_module.__dict__.get('__importer__')
    if importer:
      return importer._finish_import(top_module, parts[1:], fromlist)

    # If the importer does not exist, then we have to bail. A missing importer
    # means that something else imported the module, and we have no knowledge
    # of how to get sub-modules out of the thing.
    raise ImportError, 'No module named ' + fqname
    return self.__chain_import(name, globals, locals, fromlist)

  def _determine_import_context(self, globals):
    """Returns the context in which a module should be imported.

    The context could be a loaded (package) module and the imported module
    will be looked for within that package. The context could also be None,
    meaning there is no context -- the module should be looked for as a
    "top-level" module.
    """

    if not globals or not globals.get('__importer__'):
      # globals does not refer to one of our modules or packages. That
      # implies there is no relative import context (as far as we are
      # concerned), and it should just pick it off the standard path.
      return None

    # The globals refer to a module or package of ours. It will define
    # the context of the new import. Get the module/package fqname.
    parent_fqname = globals['__name__']

    # if a package is performing the import, then return itself (imports
    # refer to pkg contents)
    if globals['__ispkg__']:
      parent = sys.modules[parent_fqname]
      assert globals is parent.__dict__
      return parent

    i = strop.rfind(parent_fqname, '.')

    # a module outside of a package has no particular import context
    if i == -1:
      return None

    # if a module in a package is performing the import, then return the
    # package (imports refer to siblings)
    parent_fqname = parent_fqname[:i]
    parent = sys.modules[parent_fqname]
    assert parent.__name__ == parent_fqname
    return parent

  def _import_top_module(self, name):
    # scan sys.path looking for a location in the filesystem that contains
    # the module, or an Importer object that can import the module.
    for item in sys.path:
      if type(item) == _StringType:
        module = self.fs_imp.import_from_dir(item, name)
      else:
        module = item.import_top(name)
      if module:
        return module
    return None

  def _reload_hook(self, module):
    "Python calls this hook to reload a module."

    # reloading of a module may or may not be possible (depending on the
    # importer), but at least we can validate that it's ours to reload
    importer = module.__dict__.get('__importer__')
    if not importer:
      return self.__chain_reload(module)

    # okay. it is using the imputil system, and we must delegate it, but
    # we don't know what to do (yet)
    ### we should blast the module dict and do another get_code(). need to
    ### flesh this out and add proper docco...
    raise SystemError, "reload not yet implemented"


class Importer:
  "Base class for replacing standard import functions."

  def install(self):
    sys.path.insert(0, self)

  def import_top(self, name):
    "Import a top-level module."
    return self._import_one(None, name, name)

  ######################################################################
  #
  # PRIVATE METHODS
  #
  def _finish_import(self, top, parts, fromlist):
    # if "a.b.c" was provided, then load the ".b.c" portion down from
    # below the top-level module.
    bottom = self._load_tail(top, parts)

    # if the form is "import a.b.c", then return "a"
    if not fromlist:
      # no fromlist: return the top of the import tree
      return top

    # the top module was imported by self.
    #
    # this means that the bottom module was also imported by self (just
    # now, or in the past and we fetched it from sys.modules).
    #
    # since we imported/handled the bottom module, this means that we can
    # also handle its fromlist (and reliably use __ispkg__).

    # if the bottom node is a package, then (potentially) import some modules.
    #
    # note: if it is not a package, then "fromlist" refers to names in
    #       the bottom module rather than modules.
    # note: for a mix of names and modules in the fromlist, we will
    #       import all modules and insert those into the namespace of
    #       the package module. Python will pick up all fromlist names
    #       from the bottom (package) module; some will be modules that
    #       we imported and stored in the namespace, others are expected
    #       to be present already.
    if bottom.__ispkg__:
      self._import_fromlist(bottom, fromlist)

    # if the form is "from a.b import c, d" then return "b"
    return bottom

  def _import_one(self, parent, modname, fqname):
    "Import a single module."

    # has the module already been imported?
    try:
      return sys.modules[fqname]
    except KeyError:
      pass

    # load the module's code, or fetch the module itself
    result = self.get_code(parent, modname, fqname)
    if result is None:
      return None

    ### backwards-compat
    if len(result) == 2:
      result = result + ({},)

    module = self._process_result(result, fqname)

    # insert the module into its parent
    if parent:
      setattr(parent, modname, module)
    return module

  def _process_result(self, (ispkg, code, values), fqname):
    # did get_code() return an actual module? (rather than a code object)
    is_module = type(code) is _ModuleType

    # use the returned module, or create a new one to exec code into
    if is_module:
      module = code
    else:
      module = imp.new_module(fqname)

    ### record packages a bit differently??
    module.__importer__ = self
    module.__ispkg__ = ispkg

    # insert additional values into the module (before executing the code)
    module.__dict__.update(values)

    # the module is almost ready... make it visible
    sys.modules[fqname] = module

    # execute the code within the module's namespace
    if not is_module:
      exec code in module.__dict__

    return module

  def _load_tail(self, m, parts):
    """Import the rest of the modules, down from the top-level module.

    Returns the last module in the dotted list of modules.
    """
    for part in parts:
      fqname = "%s.%s" % (m.__name__, part)
      m = self._import_one(m, part, fqname)
      if not m:
        raise ImportError, "No module named " + fqname
    return m

  def _import_fromlist(self, package, fromlist):
    'Import any sub-modules in the "from" list.'

    # if '*' is present in the fromlist, then look for the '__all__' variable
    # to find additional items (modules) to import.
    if '*' in fromlist:
      fromlist = list(fromlist) + list(package.__dict__.get('__all__', []))

    for sub in fromlist:
      # if the name is already present, then don't try to import it (it
      # might not be a module!).
      if sub != '*' and not hasattr(package, sub):
        subname = "%s.%s" % (package.__name__, sub)
        submod = self._import_one(package, sub, subname)
        if not submod:
          raise ImportError, "cannot import name " + subname

  def _do_import(self, parent, parts, fromlist):
    """Attempt to import the module relative to parent.

    This method is used when the import context specifies that <self>
    imported the parent module.
    """
    top_name = parts[0]
    top_fqname = parent.__name__ + '.' + top_name
    top_module = self._import_one(parent, top_name, top_fqname)
    if not top_module:
      # this importer and parent could not find the module (relatively)
      return None

    return self._finish_import(top_module, parts[1:], fromlist)

  ######################################################################
  #
  # METHODS TO OVERRIDE
  #
  def get_code(self, parent, modname, fqname):
    """Find and retrieve the code for the given module.

    parent specifies a parent module to define a context for importing. It
    may be None, indicating no particular context for the search.

    modname specifies a single module (not dotted) within the parent.

    fqname specifies the fully-qualified module name. This is a (potentially)
    dotted name from the "root" of the module namespace down to the modname.
    If there is no parent, then modname==fqname.

    This method should return None, or a 3-tuple.

    * If the module was not found, then None should be returned.

    * The first item of the 2- or 3-tuple should be the integer 0 or 1,
      specifying whether the module that was found is a package or not.

    * The second item is the code object for the module (it will be
      executed within the new module's namespace). This item can also
      be a fully-loaded module object (e.g. loaded from a shared lib).

    * The third item is a dictionary of name/value pairs that will be
      inserted into new module before the code object is executed. This
      is provided in case the module's code expects certain values (such
      as where the module was found). When the second item is a module
      object, then these names/values will be inserted *after* the module
      has been loaded/initialized.
    """
    raise RuntimeError, "get_code not implemented"


######################################################################
#
# Some handy stuff for the Importers
#

# byte-compiled file suffic character
_suffix_char = __debug__ and 'c' or 'o'

# byte-compiled file suffix
_suffix = '.py' + _suffix_char

# the C_EXTENSION suffixes
_c_suffixes = filter(lambda x: x[2] == imp.C_EXTENSION, imp.get_suffixes())

def _compile(pathname, timestamp):
  """Compile (and cache) a Python source file.

  The file specified by <pathname> is compiled to a code object and
  returned.

  Presuming the appropriate privileges exist, the bytecodes will be
  saved back to the filesystem for future imports. The source file's
  modification timestamp must be provided as a Long value.
  """
  codestring = open(pathname, 'r').read()
  if codestring and codestring[-1] != '\n':
    codestring = codestring + '\n'
  code = __builtin__.compile(codestring, pathname, 'exec')

  # try to cache the compiled code
  try:
    f = open(pathname + _suffix_char, 'wb')
  except IOError:
    pass
  else:
    f.write('\0\0\0\0')
    f.write(struct.pack('<I', timestamp))
    marshal.dump(code, f)
    f.flush()
    f.seek(0, 0)
    f.write(imp.get_magic())
    f.close()

  return code

_os_stat = _os_path_join = None
def _os_bootstrap():
  "Set up 'os' module replacement functions for use during import bootstrap."

  names = sys.builtin_module_names

  join = None
  if 'posix' in names:
    sep = '/'
    from posix import stat
  elif 'nt' in names:
    sep = '\\'
    from nt import stat
  elif 'dos' in names:
    sep = '\\'
    from dos import stat
  elif 'os2' in names:
    sep = '\\'
    from os2 import stat
  elif 'mac' in names:
    from mac import stat
    def join(a, b):
      if a == '':
        return b
      path = s
      if ':' not in a:
        a = ':' + a
      if a[-1:] <> ':':
        a = a + ':'
      return a + b
  else:
    raise ImportError, 'no os specific module found'
  
  if join is None:
    def join(a, b, sep=sep):
      if a == '':
        return b
      lastchar = a[-1:]
      if lastchar == '/' or lastchar == sep:
        return a + b
      return a + sep + b

  global _os_stat
  _os_stat = stat

  global _os_path_join
  _os_path_join = join

def _os_path_isdir(pathname):
  "Local replacement for os.path.isdir()."
  try:
    s = _os_stat(pathname)
  except OSError:
    return None
  return (s[0] & 0170000) == 0040000

def _timestamp(pathname):
  "Return the file modification time as a Long."
  try:
    s = _os_stat(pathname)
  except OSError:
    return None
  return long(s[8])

def _fs_import(dir, modname, fqname):
  "Fetch a module from the filesystem."

  pathname = _os_path_join(dir, modname)
  if _os_path_isdir(pathname):
    values = { '__pkgdir__' : pathname, '__path__' : [ pathname ] }
    ispkg = 1
    pathname = _os_path_join(pathname, '__init__')
  else:
    values = { }
    ispkg = 0

    # look for dynload modules
    for desc in _c_suffixes:
      file = pathname + desc[0]
      try:
        fp = open(file, desc[1])
      except IOError:
        pass
      else:
        module = imp.load_module(fqname, fp, file, desc)
        values['__file__'] = file
        return 0, module, values

  t_py = _timestamp(pathname + '.py')
  t_pyc = _timestamp(pathname + _suffix)
  if t_py is None and t_pyc is None:
    return None
  code = None
  if t_py is None or (t_pyc is not None and t_pyc >= t_py):
    file = pathname + _suffix
    f = open(file, 'rb')
    if f.read(4) == imp.get_magic():
      t = struct.unpack('<I', f.read(4))[0]
      if t == t_py:
        code = marshal.load(f)
    f.close()
  if code is None:
    file = pathname + '.py'
    code = _compile(file, t_py)

  values['__file__'] = file
  return ispkg, code, values


######################################################################
#
# Simple function-based importer
#
class FuncImporter(Importer):
  "Importer subclass to use a supplied function rather than method overrides."
  def __init__(self, func):
    self.func = func
  def get_code(self, parent, modname, fqname):
    return self.func(parent, modname, fqname)

def install_with(func):
  FuncImporter(func).install()


######################################################################
#
# Base class for archive-based importing
#
class PackageArchiveImporter(Importer):
  """Importer subclass to import from (file) archives.

  This Importer handles imports of the style <archive>.<subfile>, where
  <archive> can be located using a subclass-specific mechanism and the
  <subfile> is found in the archive using a subclass-specific mechanism.

  This class defines two hooks for subclasses: one to locate an archive
  (and possibly return some context for future subfile lookups), and one
  to locate subfiles.
  """

  def get_code(self, parent, modname, fqname):
    if parent:
      # the Importer._finish_import logic ensures that we handle imports
      # under the top level module (package / archive).
      assert parent.__importer__ == self

      # if a parent "package" is provided, then we are importing a sub-file
      # from the archive.
      result = self.get_subfile(parent.__archive__, modname)
      if result is None:
        return None
      if type(result) == type(()):
        return (0,) + result
      return 0, result

    # no parent was provided, so the archive should exist somewhere on the
    # default "path".
    archive = self.get_archive(modname)
    if archive is None:
      return None
    return 1, "", {'__archive__':archive}

  def get_archive(self, modname):
    """Get an archive of modules.

    This method should locate an archive and return a value which can be
    used by get_subfile to load modules from it. The value may be a simple
    pathname, an open file, or a complex object that caches information
    for future imports.

    Return None if the archive was not found.
    """
    raise RuntimeError, "get_archive not implemented"

  def get_subfile(self, archive, modname):
    """Get code from a subfile in the specified archive.

    Given the specified archive (as returned by get_archive()), locate
    and return a code object for the specified module name.

    A 2-tuple may be returned, consisting of a code object and a dict
    of name/values to place into the target module.

    Return None if the subfile was not found.
    """
    raise RuntimeError, "get_subfile not implemented"


class PackageArchive(PackageArchiveImporter):
  "PackageArchiveImporter subclass that refers to a specific archive."

  def __init__(self, modname, archive_pathname):
    self.__modname = modname
    self.__path = archive_pathname

  def get_archive(self, modname):
    if modname == self.__modname:
      return self.__path
    return None

  # get_subfile is passed the full pathname of the archive


######################################################################
#
# Emulate the standard directory-based import mechanism
#
class DirectoryImporter(Importer):
  "Importer subclass to emulate the standard importer."

  def __init__(self, dir):
    self.dir = dir

  def get_code(self, parent, modname, fqname):
    if parent:
      dir = parent.__pkgdir__
    else:
      dir = self.dir

    # defer the loading of OS-related facilities
    if not _os_stat:
      _os_bootstrap()

    # Return the module (and other info) if found in the specified
    # directory. Otherwise, return None.
    return _fs_import(dir, modname, fqname)

  def __repr__(self):
    return '<%s.%s for "%s" at 0x%x>' % (self.__class__.__module__,
                                         self.__class__.__name__,
                                         self.dir,
                                         id(self))

######################################################################
#
# Emulate the standard path-style import mechanism
#
class PathImporter(Importer):
  def __init__(self, path=sys.path):
    self.path = path

    # we're definitely going to be importing something in the future,
    # so let's just load the OS-related facilities.
    if not _os_stat:
      _os_bootstrap()

  def get_code(self, parent, modname, fqname):
    if parent:
      # we are looking for a module inside of a specific package
      return _fs_import(parent.__pkgdir__, modname, fqname)

    # scan sys.path, looking for the requested module
    for dir in self.path:
      result = _fs_import(dir, modname, fqname)
      if result:
        return result

    # not found
    return None


######################################################################
#
# Emulate the import mechanism for builtin and frozen modules
#
class BuiltinImporter(Importer):
  def get_code(self, parent, modname, fqname):
    if parent:
      # these modules definitely do not occur within a package context
      return None

    # look for the module
    if imp.is_builtin(modname):
      type = imp.C_BUILTIN
    elif imp.is_frozen(modname):
      type = imp.PY_FROZEN
    else:
      # not found
      return None

    # got it. now load and return it.
    module = imp.load_module(modname, None, modname, ('', '', type))
    return 0, module, { }


######################################################################
#
# Internal importer used for importing from the filesystem
#
class _FilesystemImporter(Importer):
  def __init__(self, suffixes):
    # this list is shared with the ImportManager.
    self.suffixes = suffixes

  def import_from_dir(self, dir, fqname):
    result = self._import_pathname(_os_path_join(dir, fqname), fqname)
    if result:
      return self._process_result(result, fqname)
    return None

  def get_code(self, parent, modname, fqname):
    # This importer is never used with an empty parent. Its existence is
    # private to the ImportManager. The ImportManager uses the
    # import_from_dir() method to import top-level modules/packages.
    # This method is only used when we look for a module within a package.
    assert parent

    return self._import_pathname(_os_path_join(parent.__pkgdir__, modname),
                                 fqname)

  def _import_pathname(self, pathname, fqname):
    if _os_path_isdir(pathname):
      result = self._import_pathname(_os_path_join(pathname, '__init__'),
                                     fqname)
      if result:
        values = result[2]
        values['__pkgdir__'] = pathname
        values['__path__'] = [ pathname ]
        return 1, result[1], values
      return None

    for suffix, importer in self.suffixes:
      filename = pathname + suffix
      try:
        finfo = _os_stat(filename)
      except OSError:
        pass
      else:
        return importer.import_file(filename, finfo, fqname)
    return None

######################################################################
#
# SUFFIX-BASED IMPORTERS
#

class SuffixImporter:
  def import_file(self, filename, finfo, fqname):
    raise RuntimeError

class PySuffixImporter(SuffixImporter):
  def import_file(self, filename, finfo, fqname):
    file = filename[:-3] + _suffix
    t_py = long(finfo[8])
    t_pyc = _timestamp(file)

    code = None
    if t_pyc is not None and t_pyc >= t_py:
      f = open(file, 'rb')
      if f.read(4) == imp.get_magic():
        t = struct.unpack('<I', f.read(4))[0]
        if t == t_py:
          code = marshal.load(f)
      f.close()
    if code is None:
      file = filename
      code = _compile(file, t_py)

    return 0, code, { '__file__' : file }

class DynLoadSuffixImporter(SuffixImporter):
  def __init__(self, desc):
    self.desc = desc

  def import_file(self, filename, finfo, fqname):
    fp = open(filename, self.desc[1])
    module = imp.load_module(fqname, fp, filename, self.desc)
    module.__file__ = filename
    return 0, module, { }


######################################################################

def _test_dir():
  "Debug/test function to create DirectoryImporters from sys.path."
  path = sys.path[:]
  path.reverse()
  for d in path:
    DirectoryImporter(d).install()

def _test_revamp():
  "Debug/test function for the revamped import system."
  PathImporter().install()
  BuiltinImporter().install()

def _print_importers():
  items = sys.modules.items()
  items.sort()
  for name, module in items:
    if module:
      print name, module.__dict__.get('__importer__', '-- no importer')
    else:
      print name, '-- non-existent module'

def _test_revamp():
  ImportManager().install()
  sys.path.insert(0, BuiltinImporter())

######################################################################

From mal at lemburg.com  Mon Jan  3 13:28:34 2000
From: mal at lemburg.com (M.-A. Lemburg)
Date: Mon, 03 Jan 2000 13:28:34 +0100
Subject: [Python-Dev] new imputil.py
References: <Pine.LNX.4.10.10001021838400.412-200000@nebula.lyra.org>
Message-ID: <387095F2.2FA64D8E@lemburg.com>

Happy New Year :-)

[new imputil.py]

I tried the new module with the following code:

import imputil,sys

if sys.argv[1] != 'standard':
    print 'Installing imputil...',
    imputil.ImportManager().install()
    sys.path.insert(0, imputil.BuiltinImporter())
    print 'done.'
else:
    print 'Using builtin importer.'

print

print 'Importing standard stuff...',
import string,re,os,sys
print 'done.'

print 'Importing mx Extensions...',
from mx import DateTime,TextTools,ODBC,HTMLTools,UID,URL
print 'done.'

###

The new importer does load everything in the test set
(top level modules, packages, extensions within packages)
without problems on Linux.

Some comments:

? Why is the sys.path.insert(0,imputil.BuiltinImporter()) 
needed in order to get b/w compatibility ?

? Why is there no __path__ aware code in imputil.py (this is
definitely needed in order to make it a drop-in replacement) ?

? Performance is still 50% of the Python builtin importer --
a bummer if you ask me. More aggressive caching is definitely
needed, perhaps even some recoding of methods in C.

? The old chaining code should be moved into a subclass of
its own.

? The code should not import strop directly as this module
will probably go away RSN. Use string methods instead.

? The design of the ImportManager has some minor flaws: the
FS importer should be settable via class attributes, deinstallation
should be possible, a query mechanism to find the importer
used by a certain import would also be nice to be able to
verify correct setup.

? py/pyc/pyo file piping hooks would be nice to allow
imports of signed (and trusted) code and/or encrypted code
(a mixin class for these filters would do the trick).

? Wish list: a distutils importer hooked to a list of standard
package repositories, a module to file location mapper to
speed up file system based imports, 

-- 
Marc-Andre Lemburg
______________________________________________________________________
Y2000:                                             Happy New Century !
Business:                                      http://www.lemburg.com/
Python Pages:                           http://www.lemburg.com/python/




From gstein at lyra.org  Mon Jan  3 14:53:00 2000
From: gstein at lyra.org (Greg Stein)
Date: Mon, 3 Jan 2000 05:53:00 -0800 (PST)
Subject: [Python-Dev] new imputil.py
In-Reply-To: <387095F2.2FA64D8E@lemburg.com>
Message-ID: <Pine.LNX.4.10.10001030529560.412-100000@nebula.lyra.org>

Excellent... thanx for the feedback!

Comments:

On Mon, 3 Jan 2000, M.-A. Lemburg wrote:
>...
> The new importer does load everything in the test set
> (top level modules, packages, extensions within packages)
> without problems on Linux.

Great!

> Some comments:
> 
> ? Why is the sys.path.insert(0,imputil.BuiltinImporter()) 
> needed in order to get b/w compatibility ?

Because I didn't want to build too much knowledge into the ImportManager.
Heck, I think adding sys.path removed some of the design elegence; adding
real knowledge of builtins... well, we'll just not talk about that. :-)

We could certainly do it this way; let's see what Guido says. I'm not
truly adverse to it, but I'd recommend against adding a knowledge of
BuiltinImporter to the ImportManager.

> ? Why is there no __path__ aware code in imputil.py (this is
> definitely needed in order to make it a drop-in replacement) ?

Because I don't like __path__ :-)  I don't think it would be too hard to
add, though.

If Guido says we need __path__, then I'll add it. I do believe there was a
poll a while back where he asked whether anybody truly used it. I don't
remember the result and/or Guido's resolution of the matter.

> ? Performance is still 50% of the Python builtin importer --
> a bummer if you ask me. More aggressive caching is definitely
> needed, perhaps even some recoding of methods in C.

I'm scared of caching and the possibility for false positives/negatives.

But yes, it is still slower and could use some analysis and/or recoding
*if* the speed is a problem. Slower imports does not necessarily mean they
are "too slow."

> ? The old chaining code should be moved into a subclass of
> its own.

Good thought. But really: I'd just rather torch it. This kind of depends
on whether we can get away with saying the ImportManager is *the* gateway
between the interpreter and Python-level import hooks. In other words,
will ImportManager be the *only* Python code to ever be allowed to call
sys.set_import_hook() ? If the ImportManager doesn't have to "play with
other import hooks", then the chaining can be removed altogether.

> ? The code should not import strop directly as this module
> will probably go away RSN. Use string methods instead.

Yah. But I'm running this against 1.5.2 :-)

I might be able to do something where the string methods are used if
available, and use the strop module if not.
[ similar to the 'os' bootstrapping that is done ]

Finn Bock emailed me to say that JPython does not have strop, but does
have string methods.

> ? The design of the ImportManager has some minor flaws: the
> FS importer should be settable via class attributes,

The class or the object itself? Putting a class in there would be nice, or
possibly passing it to the constructor (with a suitable default).

This is a good idea, though. Please clarify what you'd like to see, and
I'll get it added.

> deinstallation
> should be possible,

Maybe. This is somewhat dependent upon whether it must "play nice."
Deinstallation would be quite easy if we move to a sys.get/set style of
interface, and it wouldn't be an issue to do de-install code.

> a query mechanism to find the importer
> used by a certain import would also be nice to be able to
> verify correct setup.

module.__importer__ provides the importer that was used. This is defined
behavior (the system relies on that being set to deal with packages
properly).

Is this sufficient, or were you looking for something else?

module.__ispkg__ is also set to 0/1 accordingly.

For backwards compat, __file__ and __path__ are also set. The __all__
attribute in an __init__.py file is used for "from package import *".

> ? py/pyc/pyo file piping hooks would be nice to allow
> imports of signed (and trusted) code and/or encrypted code
> (a mixin class for these filters would do the trick).

I'd happily accept a base SuffixImporter class for these "pipes". I don't
believe that the ImportManager, Importer, or SuffixImporter base classes
would need any changes, though.

Note that I probably will rearrange the _fs_import() and friends, per
Guido's suggestion to move them into a base class. That may be a step
towards having "pipes" available.

> ? Wish list: a distutils importer hooked to a list of standard
> package repositories, a module to file location mapper to
> speed up file system based imports, 

I'm not sure what the former would do. distutils is still a little
nebulous to me right now.

For a mapper, we can definitely have a custom Importer that knows where
certain modules are found. However, I suspect you're looking for some kind
of a cache, but there isn't a hook to say "I found <foo> at <this>
location" (which would be used to build the mapping).

Suggestions on both of these would be most welcome!

Cheers,
-g

-- 
Greg Stein, http://www.lyra.org/




From gvwilson at nevex.com  Mon Jan  3 15:02:32 2000
From: gvwilson at nevex.com (gvwilson at nevex.com)
Date: Mon, 3 Jan 2000 09:02:32 -0500 (EST)
Subject: [Python-Dev] Software Carpentry: GUI Toolkit?
Message-ID: <Pine.LNX.4.10.10001030852190.20692-100000@akbar.nevex.com>

Hi, folks.  I'm putting together guidelines for submissions to the
Software Carpentry design competition (www.software-carpentry.com), and
would like to know what I should recommend as a Python GUI toolkit.  As I
understand it, the alternatives are:

- Tkinter: the "standard" answer, but many people think it's showing its
  age, and it's an installation and update headaches because of its Tcl
  dependencies.

- some other GUI toolkit: but there's no consensus on which one, and
  documentation is lacking.

- CGI scripts (i.e. all interfaces are web pages): has the virtue of
  simplicity, but could also make some useful interfaces difficult to
  build (e.g. no drag and drop), and would require users to run a server,
  or at least get exec privileges, which can be an installation headache.

If I've missed a good answer, or if there's somewhere else I should look
for a solution, I'd be grateful for a pointer.

Thanks,
Greg





From jim at interet.com  Mon Jan  3 15:31:53 2000
From: jim at interet.com (James C. Ahlstrom)
Date: Mon, 03 Jan 2000 09:31:53 -0500
Subject: [Python-Dev] new imputil.py
References: <Pine.LNX.4.10.10001021838400.412-200000@nebula.lyra.org>
Message-ID: <3870B2D9.31D0D350@interet.com>

Greg Stein wrote:

> I've attached a new imputil.py to this message. It isn't posted on my page

I don't think you should be using "public domain" as a
copyright because you should be protecting the code.
Better to use "all rights transferred to CNRI pursuant
to the Python contribution agreement", or just copyright
it yourself for now.

You didn't incorporate the ZipImporter in
  ftp://ftp.interet.com/pub/importer.py
Is that because you want me to, or doesn't it work?

JimA



From gmcm at hypernet.com  Mon Jan  3 15:38:11 2000
From: gmcm at hypernet.com (Gordon McMillan)
Date: Mon, 3 Jan 2000 09:38:11 -0500
Subject: [Python-Dev] new imputil.py
In-Reply-To: <Pine.LNX.4.10.10001030529560.412-100000@nebula.lyra.org>
References: <387095F2.2FA64D8E@lemburg.com>
Message-ID: <1265213088-25101227@hypernet.com>

Greg Stein wrote:
> On Mon, 3 Jan 2000, M.-A. Lemburg wrote:
[big snip]
> > ? Wish list: a distutils importer hooked to a list of standard
> > package repositories, a module to file location mapper to speed
> > up file system based imports, 

> For a mapper, we can definitely have a custom Importer that knows
> where certain modules are found. However, I suspect you're
> looking for some kind of a cache, but there isn't a hook to say
> "I found <foo> at <this> location" (which would be used to build
> the mapping).
> 
> Suggestions on both of these would be most welcome!

Haven't played with the new one yet. But for awhile I've been 
considering a scheme where sys.path[0] has a cache of 
known binary extensions { logicalname: fullpath, ... } and 
sys.path[-1] is the brute force importer.

For standalones, sys.path[0] could be hardcoded. For normal 
installations, sys.path[-1] could inform sys.path[0] when a .so 
/ .dll / .pyd is found. So when a new one is installed, the first 
use will be expensive, but subsequent sessions would import 
it in 1 I/O.

I'd also like to point out that archives *can* be used in a 
development situation. Obviously I wouldn't bother putting a 
module under current development into an archive. But if the 
source is still installed and you haven't mucked with the 
__file__ attribute when you put it in the archive, then 
tracebacks will show you what you need. IDLE doesn't know 
the difference. So for most developers, the standard library 
can be served from an archive with no effect (other than speed).

- Gordon



From gstein at lyra.org  Mon Jan  3 15:57:35 2000
From: gstein at lyra.org (Greg Stein)
Date: Mon, 3 Jan 2000 06:57:35 -0800 (PST)
Subject: [Python-Dev] new imputil.py
In-Reply-To: <3870B2D9.31D0D350@interet.com>
Message-ID: <Pine.LNX.4.10.10001030651260.412-100000@nebula.lyra.org>

On Mon, 3 Jan 2000, James C. Ahlstrom wrote:
> Greg Stein wrote:
> > I've attached a new imputil.py to this message. It isn't posted on my page
> 
> I don't think you should be using "public domain" as a
> copyright because you should be protecting the code.
> Better to use "all rights transferred to CNRI pursuant
> to the Python contribution agreement", or just copyright
> it yourself for now.

Public Domain means there are no copyrights on the code. Anybody can claim
copyright to it. Anybody can start with my version, slap their name and
license on it, and do as they wish. There isn't a way for anybody to
"control" public domain software, so there is no need for protection.

I like to use Public Domain for code that I want to see as broadly used as
possible and/or for short things. There is also a lot that I just don't
care what happens with it. If I don't have a vested interest in something,
then PD is fine.

I wrote imputil as a tool for myself. It isn't something that I feel a
need to keep my name on it -- it works for me, it does what I want, it
doesn't matter what others do it. It does matter than other people *can*
do stuff with it, and PD gives them the most options.

Shades of grey... hard to fully explain in an email... but that's the
general sentiment. I've got a few things under other licenses, but PD
seemed best for imputil.

> You didn't incorporate the ZipImporter in
>   ftp://ftp.interet.com/pub/importer.py
> Is that because you want me to, or doesn't it work?

I had the redesign to do first. When that settles towards something that
Guido is happy with (or he has decided to punt the design altogether),
then I'll integrate the ZipImporter.

Cheers,
-g

-- 
Greg Stein, http://www.lyra.org/




From fdrake at acm.org  Mon Jan  3 21:05:22 2000
From: fdrake at acm.org (Fred L. Drake, Jr.)
Date: Mon, 3 Jan 2000 15:05:22 -0500 (EST)
Subject: [Python-Dev] new imputil.py
In-Reply-To: <1265213088-25101227@hypernet.com>
References: <387095F2.2FA64D8E@lemburg.com>
	<1265213088-25101227@hypernet.com>
Message-ID: <14449.258.374018.919406@weyr.cnri.reston.va.us>

Gordon McMillan writes:
 > I'd also like to point out that archives *can* be used in a 
 > development situation. Obviously I wouldn't bother putting a 
 > module under current development into an archive. But if the 
 > source is still installed and you haven't mucked with the 
 > __file__ attribute when you put it in the archive, then 
 > tracebacks will show you what you need. IDLE doesn't know 
 > the difference. So for most developers, the standard library 
 > can be served from an archive with no effect (other than speed).

  I don't see why we can't just add the source to the archive as well; 
this would allow proper tracebacks even outside the development of the 
library.  Not including sources would cleanly result in the same
situation as we currently see when there's only a .pyc file.
  Am I missing something fundamental?


  -Fred

--
Fred L. Drake, Jr.	  <fdrake at acm.org>
Corporation for National Research Initiatives



From mal at lemburg.com  Mon Jan  3 19:22:02 2000
From: mal at lemburg.com (M.-A. Lemburg)
Date: Mon, 03 Jan 2000 19:22:02 +0100
Subject: [Python-Dev] Better text processing support in py2k?
References: <000901bf53e1$eb4248c0$472d153f@tim>
Message-ID: <3870E8CA.7294B813@lemburg.com>

Tim Peters wrote:
> 
> >> This is why I do complex string processing in Icon <0.9 wink>.
> 
> [MAL]
> > You can have all that extra magic via callable tag objects
> > or callable matching functions. It's not exactly nice to
> > write, but I'm sure that a meta-language could do the
> > conversions for you.
> 
> That wasn't my point:  I do it in Icon because it *is* "exactly nice to
> write", and doesn't require any yet-another meta-language.  It's all
> straightforward, in a way that separate schemes pasted together can never be
> (simply because they *are* "separate schemes pasted together" <wink>).
>
> The point of my Python examples wasn't that they could do something
> mxTextTools can't do, but that they were *Python* examples:  every variation
> I mentioned (or that you're likely to think of) was easy to handle for any
> Python programmer because the "control flow" and "data type" etc aspects
> could be handled exactly the way they always are in *non* pattern-matching
> Python code too, rather than recoded in pattern-scheme-specific different
> ways (e.g., where I had a vanailla "if/break", you set up a special
> exception to tickle the matching engine).
> 
> I'm not attacking mxTextTools, so don't feel compelled to defend it --

Oh, I wasn't defending it -- I know that it is cryptic and sometimes
a pain to use. But given that you don't have to invoke a C compiler
to get a raw speed I find it a rather useful alternative to code
fast utility functions which would otherwise have to be written
in C.

The other reason it exists is simply because I don't like the
recursive style of regexps too much. mxTextTools is simple
and straightforward. Backtracking is still possible, but not
recommended.

> people using regexps in those examples are dead in the water.  mxTextTools
> is very good at what it does; if we have a real disagreement, it's probably
> that I'm less optimistic about the prospects for higher-level wrappers
> (e.g., MikeF's SimpleParse is much slower than "a real" BNF parsing system
> (ARBNFPS), in part because he isn't doing all the optimizations ARBNFPS
> does, but also in part because ARBNFPS uses an underlying engine more
> optimized to its specific task than mxTextTool's more-general engine *can*
> be).  So I don't see mxTextTools as being the answer to everything -- and if
> you hadn't written it, you would agree with that on first glance <wink>.

Oh, I'm sure it *is* the answer to all out problems ;-) ...

def main(*dummy):
    ...

from mx.TextTools import *
tag("",((main, Skip + CallTag, 0),))
 
> > Anyway, I'll keep focussing on the speed aspect of mxTextTools;
> > others can focus on abstractions, so that eventually everybody
> > will be happy :-)
> 
> You and I will be, anyway <wink>.

Happy New Year :-)
-- 
Marc-Andre Lemburg
______________________________________________________________________
Y2000:                                             Happy New Century !
Business:                                      http://www.lemburg.com/
Python Pages:                           http://www.lemburg.com/python/





From mal at lemburg.com  Tue Jan  4 19:36:00 2000
From: mal at lemburg.com (M.-A. Lemburg)
Date: Tue, 04 Jan 2000 19:36:00 +0100
Subject: [Python-Dev] new imputil.py
References: <Pine.LNX.4.10.10001030529560.412-100000@nebula.lyra.org>
Message-ID: <38723D90.D2AE1CA4@lemburg.com>

Greg Stein wrote:
> 
> Comments:
> 
> On Mon, 3 Jan 2000, M.-A. Lemburg wrote:
> >...
> > The new importer does load everything in the test set
> > (top level modules, packages, extensions within packages)
> > without problems on Linux.
> 
> Great!
> 
> > Some comments:
> >
> > ? Why is the sys.path.insert(0,imputil.BuiltinImporter())
> > needed in order to get b/w compatibility ?
> 
> Because I didn't want to build too much knowledge into the ImportManager.
> Heck, I think adding sys.path removed some of the design elegence; adding
> real knowledge of builtins... well, we'll just not talk about that. :-)
> 
> We could certainly do it this way; let's see what Guido says. I'm not
> truly adverse to it, but I'd recommend against adding a knowledge of
> BuiltinImporter to the ImportManager.

I was under the impression that the ImportManager should replace
the current implementation. In that light it should of course
provide all the needed techniques per default without the
need to tweak sys.path.

> > ? Why is there no __path__ aware code in imputil.py (this is
> > definitely needed in order to make it a drop-in replacement) ?
> 
> Because I don't like __path__ :-)  I don't think it would be too hard to
> add, though.
> 
> If Guido says we need __path__, then I'll add it. I do believe there was a
> poll a while back where he asked whether anybody truly used it. I don't
> remember the result and/or Guido's resolution of the matter.

AFAIK, JimF is using it in Zope. I will use it in the
b/w compatibility package for the soon to be released
mx Extensions packages (instead of using relative imports,
BTW -- can't wait for those to happen).
 
> > ? Performance is still 50% of the Python builtin importer --
> > a bummer if you ask me. More aggressive caching is definitely
> > needed, perhaps even some recoding of methods in C.
> 
> I'm scared of caching and the possibility for false positives/negatives.
> 
> But yes, it is still slower and could use some analysis and/or recoding
> *if* the speed is a problem. Slower imports does not necessarily mean they
> are "too slow."

There has been some moaning about the current Python startup
speed, so I guess people already find the existing strategy
too slow.
 
Anyway, put the cache risks into the user's hands and have
them decide whether or not to use them. The important thing
is providing a standard approach to caching which all
importers can use and hook into rather than having three
or four separate cache implementations.

> > ? The old chaining code should be moved into a subclass of
> > its own.
> 
> Good thought. But really: I'd just rather torch it. This kind of depends
> on whether we can get away with saying the ImportManager is *the* gateway
> between the interpreter and Python-level import hooks. In other words,
> will ImportManager be the *only* Python code to ever be allowed to call
> sys.set_import_hook() ? If the ImportManager doesn't have to "play with
> other import hooks", then the chaining can be removed altogether.

Hmm, nuking the chains might cause some problems with code
using the old ni.py or other code such as my old ClassModules.py
module which emulates modules using classes (provides all the
cool __getattr__ and __setattr__ features to modules as well).
 
> > ? The code should not import strop directly as this module
> > will probably go away RSN. Use string methods instead.
> 
> Yah. But I'm running this against 1.5.2 :-)
> 
> I might be able to do something where the string methods are used if
> available, and use the strop module if not.
> [ similar to the 'os' bootstrapping that is done ]
> 
> Finn Bock emailed me to say that JPython does not have strop, but does
> have string methods.

Since imputil.py targets 1.6 you can safely assume that string
methods are in place.
 
> > ? The design of the ImportManager has some minor flaws: the
> > FS importer should be settable via class attributes,
> 
> The class or the object itself? Putting a class in there would be nice, or
> possibly passing it to the constructor (with a suitable default).
> 
> This is a good idea, though. Please clarify what you'd like to see, and
> I'll get it added.

I usually put these things into the class so that subclasses
can easily override the setting.
 
> > deinstallation
> > should be possible,
> 
> Maybe. This is somewhat dependent upon whether it must "play nice."
> Deinstallation would be quite easy if we move to a sys.get/set style of
> interface, and it wouldn't be an issue to do de-install code.

I was thinking mainly of debugging situations where you play
around with new importer code -- its probably not important
for production code.

> > a query mechanism to find the importer
> > used by a certain import would also be nice to be able to
> > verify correct setup.
> 
> module.__importer__ provides the importer that was used. This is defined
> behavior (the system relies on that being set to deal with packages
> properly).
> 
> Is this sufficient, or were you looking for something else?

I was thinking of a situations like:

if <RelativeImporter is not installed>:
   <install RelativeImporter>

or

if <need SignedModuleImporter for modules xyz>:
   raise SystemError,'wrong setup'

Don't know if these queries are possible with the current
flags and attributes.
 
> module.__ispkg__ is also set to 0/1 accordingly.
> 
> For backwards compat, __file__ and __path__ are also set. The __all__
> attribute in an __init__.py file is used for "from package import *".
> 
> > ? py/pyc/pyo file piping hooks would be nice to allow
> > imports of signed (and trusted) code and/or encrypted code
> > (a mixin class for these filters would do the trick).
> 
> I'd happily accept a base SuffixImporter class for these "pipes". I don't
> believe that the ImportManager, Importer, or SuffixImporter base classes
> would need any changes, though.
> 
> Note that I probably will rearrange the _fs_import() and friends, per
> Guido's suggestion to move them into a base class. That may be a step
> towards having "pipes" available.

It would be nice to be able to use the concept of stackable streams
as source for byte and source code. For this to work one would have
to make the file reading process a little more abstract by using e.g. a
StreamReader instead (see the current unicode-proposal.txt version).

> > ? Wish list: a distutils importer hooked to a list of standard
> > package repositories, a module to file location mapper to
> > speed up file system based imports,
> 
> I'm not sure what the former would do. distutils is still a little
> nebulous to me right now.

Basically it should scan a set of URLs providing access to
package repositories which hold distutils installable package
archives. In case it finds a suitable package it should then
proceed to auto-install it and then continue the normal import
process.

> For a mapper, we can definitely have a custom Importer that knows where
> certain modules are found. However, I suspect you're looking for some kind
> of a cache, but there isn't a hook to say "I found <foo> at <this>
> location" (which would be used to build the mapping).

Right. I would like to see some standard mechanism used
throughout the ImportManager for this. One which all importers
can use and rely on. E.g. it would be nice to have an option
to load the cache from disk upon startup to reduce search times.
All this should be left for the user to configure with the
standard setting being no cache at all (to avoid confusion
and reduce support costs ;-).

-- 
Marc-Andre Lemburg
______________________________________________________________________
Y2000:                                             Happy New Century !
Business:                                      http://www.lemburg.com/
Python Pages:                           http://www.lemburg.com/python/




From bwarsaw at cnri.reston.va.us  Tue Jan  4 22:04:48 2000
From: bwarsaw at cnri.reston.va.us (Barry A. Warsaw)
Date: Tue, 4 Jan 2000 16:04:48 -0500 (EST)
Subject: [Python-Dev] new imputil.py
References: <Pine.LNX.4.10.10001021838400.412-200000@nebula.lyra.org>
Message-ID: <14450.24688.492098.917284@anthem.cnri.reston.va.us>

Happy New Year!

>>>>> "GS" == Greg Stein <gstein at lyra.org> writes:

    GS> I think Python 1.6 should drop the __import__ builtin and move
    GS> to something like sys.import_hook (to allow examination and
    GS> change).

Wait!  You can't remove builtin __import__ without breaking code.
E.g. Mailman uses __import__ quite a bit in its CGI (and other)
harnesses.  Why does __import__ need to be removed?  Why can't it just
just the same mechanism the import statement uses?

    GS> I might be able to do something where the string methods are
    GS> used if available, and use the strop module if not.  [ similar
    GS> to the 'os' bootstrapping that is done ]

    GS> Finn Bock emailed me to say that JPython does not have strop,
    GS> but does have string methods.

Sorry Greg, I haven't had time to look at this stuff at all, so maybe
I'm missing something essential, but if you just continue to use the
string module, you'll be fine for JPython and CPython 1.5.2.  In
CPython 1.5.2, you /will/ actually be using the strop module
under the covers.

In CPython 1.6 and JPython 1.1 you'll be using string methods under
the covers.  Your penalty is one layer of Python function calls.
Never use strop directly though.

>>>>> "MA" == M  <mal at lemburg.com> writes:

    MA> There has been some moaning about the current Python startup
    MA> speed, so I guess people already find the existing strategy
    MA> too slow.
 
Definitely.

-Barry



From gmcm at hypernet.com  Wed Jan  5 04:49:08 2000
From: gmcm at hypernet.com (Gordon McMillan)
Date: Tue, 4 Jan 2000 22:49:08 -0500
Subject: [Python-Dev] new imputil.py
In-Reply-To: <14449.258.374018.919406@weyr.cnri.reston.va.us>
References: <1265213088-25101227@hypernet.com>
Message-ID: <1265079245-1617919@hypernet.com>

Fred L. Drake, Jr.wrote:

> Gordon McMillan writes:
>  > I'd also like to point out that archives *can* be used in a >
>  development situation. Obviously I wouldn't bother putting a >
>  module under current development into an archive. But if the >
>  source is still installed and you haven't mucked with the >
>  __file__ attribute when you put it in the archive, then >
>  tracebacks will show you what you need. IDLE doesn't know > the
>  difference. So for most developers, the standard library > can
>  be served from an archive with no effect (other than speed).
> 
>   I don't see why we can't just add the source to the archive as
>   well; 
> this would allow proper tracebacks even outside the development
> of the library.  Not including sources would cleanly result in
> the same situation as we currently see when there's only a .pyc
> file.
>   Am I missing something fundamental?

Sure you could. Then you could patch IDLE, Pythonwin, etc. 
to open the proper archive and extract the source. Then you 
could patch them (and archive) to update on the fly.

And while you're at it, I'd really like a jacuzzi jet that gets my 
neck and shoulders without having to scrunch into all kinds of 
strange positions.

- Gordon


Return-Path: <owner-python-dev at python.org>
Delivered-To: python-dev at dinsdale.python.org
Received: from python.org (parrot.python.org [132.151.1.90])
	by dinsdale.python.org (Postfix) with ESMTP id A76701CD65
	for <python-dev at dinsdale.python.org>; Fri, 14 Jan 2000 12:39:29 -0500 (EST)
Received: from merlin.codesourcery.com (IDENT:qmailr@[206.168.99.1])
	by python.org (8.9.1a/8.9.1) with SMTP id MAA17463
	for <python-dev at python.org>; Fri, 14 Jan 2000 12:39:29 -0500 (EST)
Received: (qmail 2115 invoked by uid 513); 14 Jan 2000 17:44:23 -0000
Mailing-List: contact publicity-help at software-carpentry.com; run by ezmlm
Delivered-To: mailing list publicity at software-carpentry.com
Received: (qmail 2110 invoked from network); 14 Jan 2000 17:44:19 -0000
Date: Fri, 14 Jan 2000 12:40:13 -0500 (EST)
From: gvwilson at nevex.com
To: publicity at software-carpentry.com
Message-ID: <Pine.LNX.4.10.10001141228191.8785-100001 at akbar.nevex.com>
MIME-Version: 1.0
Content-Type: MULTIPART/MIXED; BOUNDARY="168427786-1646135556-947871613=:8785"
Subject: [Python-Dev] ANNOUNCEMENT: Open Source Design Competition
Sender: python-dev-admin at python.org
Errors-To: python-dev-admin at python.org
X-BeenThere: python-dev at python.org
X-Mailman-Version: 1.2 (experimental)
Precedence: bulk
List-Id: Python core developers <python-dev.python.org>

  This message is in MIME format.  The first part should be readable text,
  while the remaining parts are likely unreadable without MIME-aware tools.
  Send mail to mime at docserver.cac.washington.edu for more info.

--168427786-1646135556-947871613=:8785
Content-Type: TEXT/PLAIN; charset=US-ASCII

The Software Carpentry project is pleased to announce the launch of its
first Open Source design competition.  The project's logo is attached, and
details of the competition are included below.

This message is being sent to you because you have expressed an interest
in covering this story, or publicizing this project.  If you have any
questions, or do not wish to receive future notices about Software
Carpentry, please contact:

    Dr. Gregory V. Wilson
    Software Carpentry Project Coordinator
    (416) 593 2428
    gvwilson at software-carpentry.com

Thanks for your interest!

Greg Wilson

----------------------------------------------------------------------
----------------------------------------------------------------------

Los Alamos National Laboratory                     Code Sourcery, LLC

                          Software Carpentry

		    Open Source Design Competition

			 $100,000 in Prizes!

----------------------------------------------------------------------

The Software Carpentry project is pleased to announce its first Open
Source design competition, with prizes totaling $100,000.  Students
and professionals from any country, working individually or in teams,
are invited to submit design outlines for:

* a platform inspection tool to replace autoconf;

* a dependency management tool to replace make;

* an issue tracking system to replace gnats and Bugzilla; and

* a unit and regression testing harness with the functionality of
  XUnit, Expect, and DejaGnu.

Participants may submit separate entries in one or more categories by
March 31, 2000.  Entries must be in English, and no more than 5000
words long; examples are available at http://www.software-carpentry.com.

The competition will be judged by a panel that includes the following
noted software developers, authors, and computational scientists:

    Stephen Adler       Brookhaven National Laboratory
    Frank Alexander     Los Alamos National Laboratory
    Donnie Barnes       Red Hat
    Chris DiBona        VA Linux
    Paul Dubois         Lawrence Livermore National Laboratory
    Andrew Hunt         Pragmatic Programmers, LLC
    Stephen R. Lee      Los Alamos National Laboratory
    Josh MacDonald      University of California, Berkeley
    Brian Marick        Reliable Software Technologies
    Doug Mewhort        Queen's University
    Bruce Perens        co-founder of the Open Source Initiative
    Dave Thomas         Pragmatic Programmers, LLC
    Jon Udell           author of Practical Internet Groupware
    Guido van Rossum    inventor of Python
    Tom Van Vleck       TransIlluminant
    Phil Wadler         Bell Labs
    Scot Wingo          AuctionRover

The best four entries in each category will be awarded $2500, and
invited to submit full designs by June 1, 2000.  The best design in
each category will then receive an additional $7500, while runners-up
will each receive $2500.  Once winning designs have been announced,
$200,000 will be available through open bidding for implementation,
testing, and documentation.

All of the project's work will be Open Source; all tools will be
written in, or scriptable with, Python, and will be required to run on
both Linux and Microsoft Windows NT.

----------------------------------------------------------------------

The Software Carpentry project is sponsored by the Advanced Computing
Laboratory at the U.S. Department of Energy's Los Alamos National
Laboratory (http://www.acl.lanl.gov), and administered by Code 
Sourcery, LLC (http://www.codesourcery.com).  The project's aim
is to encourage adoption of better software development practices by
making software tools easier to use, and by documenting design,
testing, and related activities.  For more information on the project,
or to let us know that you intend to submit a proposal, see
http://www.software-carpentry.com, or mail info at software-carpentry.com.


--168427786-1646135556-947871613=:8785
Content-Type: IMAGE/GIF; name="software-carpentry-logo.gif"
Content-Transfer-Encoding: BASE64
Content-ID: <Pine.LNX.4.10.10001141240130.8785 at akbar.nevex.com>
Content-Description: 
Content-Disposition: attachment; filename="software-carpentry-logo.gif"

R0lGODlhLAGhANX/AIACFYU8R2RkZqWlp0pKS+np6tXV1snJyr+/wLW2u+Dh
5srM1Pf4/PT1+e7v877Ax4GDiZygq6Sos4yPl5aZobm7wNrc4aywuXF0efv8
/M7PzywtLJF8U0s4F6mTa76pgXBeQE0+LeDb2M7JxsfAvaCPi7yysJBxb7Ge
nf////7+/v39/fv7+/n5+fj4+Pb29vPz8/Ly8u/v7+3t7ebm5uLi4t3d3dnZ
2dLS0sXFxa6urh4eHg8PDwgICAMDAwAAACwAAAAALAGhAEAG/8CUcEgsGo/I
pHLJbDqf0Kh0Sq1ar9isdsvter/gsFipcjXLQ1aBhtDg3m/NLdN0rZotVpPV
aq7MTH9OLipFOSgxRXZ4dEx5e3pMLJFLGYBLgkxld0yLjpRKj0ktM4VEMgk6
FRcQGBILCrELEwITCRe4uRgEBAICvLwYF6sJEjV9RC4yRjKJRCwzoCkxy0QZ
BdIupUUzL0WkpkMyMEUrMnQ2HOoeHh/u7OocJi8uOiEgNUYzAhsbO/0EMPDb
UKFQDG/WYtjYEKJfCF4gfIEgQCOGtBfOhqiYcUmINmYIh7SQEU4ItSIZohWB
UW3IigLIRM7gJI7csxmNaip5QYNmEv8XNKRV2EBBxYAdDNSETLKChs0lNTRU
OFIBgqkZBZrA6MmEp7QiKOJxaDcihQsDJFCUKAHhBIgOHULEKGmEBoF//XYE
HDhhhYoCLZXIKKADAwQlJ1sgmNBKgEDHkIsy2ZozCQsaHZFcXpoEcJMCMwTb
ALWiRlYiMGx0/BtBQtaiLWxkFDKjhk8WNgKnmGGDZoFYFiwUFPLiBgRftf7S
UGTjqRAZo4mUPj1EYcwUKmhoEABiLAEIE2h15/BWQGsJEnANuFGkQA1QGWjY
zbvBVz8KQqavVE0kO42SL9jAmXu35bYSCnB15wEJNYR2SnRE0FBDSS40196E
RMSWAAUYTHD/zAET2BCOCqbtl5l8ShRwA2dHyHCDc0JQcEEBKsBmgIOh3EAd
Ei48oMABQjQgwQY//CCMQAqkUIOITKh4HRIz3HDJDOCBF94EFGQZwZbopYfL
A/iZpWMnNmQ1UH13IZCGDRgqUVpvS5AIYYqjIQBXBwpyI+USF0TgCwQX3HJB
el12GcFxyGG5I3Y2LIcdBCOscINhBVAAgwpsKlEDDoG1YMANoBSAw464UeBa
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
d8M73tIIAgA7
--168427786-1646135556-947871613=:8785--



From jeremy at cnri.reston.va.us  Mon Jan 17 21:35:37 2000
From: jeremy at cnri.reston.va.us (Jeremy Hylton)
Date: Mon, 17 Jan 2000 15:35:37 -0500 (EST)
Subject: [Python-Dev] developers day session on compilers
Message-ID: <14467.32025.761662.841271@goon.cnri.reston.va.us>

I am championing a Developers' Day session on a Python compiler.
There is a short Web page describing the goals of the session at
http://www.python.org/workshops/2000-01/compiler.html.

I'd appreciate feedback on the content and format of the session.  If
you have ideas for what we should talk about or do, please followup to
me or to the list.

Jeremy




From mal at lemburg.com  Tue Jan 18 23:55:04 2000
From: mal at lemburg.com (M.-A. Lemburg)
Date: Tue, 18 Jan 2000 23:55:04 +0100
Subject: [Python-Dev] Python Tools/
Message-ID: <3884EF48.A6107775@lemburg.com>

I was just looking through the Tools dir of the CVS version
(looking for a tool which autoexpands tabs in Python source
files -- which I didn't find) and found some other useful scripts
along the way.

To my surprise these executable files did not have a .py
extension even though were Python source files. Is this 
intended ? I find that scripts like "world" provide useful
information which would be nice to have in the standard
lib -- with .py extension...

Other tidbits:

I noted that at least in my CVS tree the Tools/ht2html
dir does not include any executable: have I missed something ?

The script Tools/scripts/parseentities.py is not executable
for some reason.

-- 
Marc-Andre Lemburg
______________________________________________________________________
Business:                                      http://www.lemburg.com/
Python Pages:                           http://www.lemburg.com/python/





From guido at CNRI.Reston.VA.US  Wed Jan 19 13:50:05 2000
From: guido at CNRI.Reston.VA.US (Guido van Rossum)
Date: Wed, 19 Jan 2000 07:50:05 -0500
Subject: [Python-Dev] Python Tools/
In-Reply-To: Your message of "Tue, 18 Jan 2000 23:55:04 +0100."
             <3884EF48.A6107775@lemburg.com> 
References: <3884EF48.A6107775@lemburg.com> 
Message-ID: <200001191250.HAA18786@eric.cnri.reston.va.us>

> I was just looking through the Tools dir of the CVS version
> (looking for a tool which autoexpands tabs in Python source
> files -- which I didn't find) and found some other useful scripts
> along the way.
> 
> To my surprise these executable files did not have a .py
> extension even though were Python source files. Is this 
> intended ? I find that scripts like "world" provide useful
> information which would be nice to have in the standard
> lib -- with .py extension...

I would agree, but that's Barry's creation, so I'll let him answer for
himself.  Any other scripts with the same problem?

> Other tidbits:
> 
> I noted that at least in my CVS tree the Tools/ht2html
> dir does not include any executable: have I missed something ?

Actually, that directory is a ghost and shouldn't have been exported
at all.  (Barry, can you erase it from sweetpea?)

> The script Tools/scripts/parseentities.py is not executable
> for some reason.

Fixed now.

--Guido van Rossum (home page: http://www.python.org/~guido/)



From bwarsaw at cnri.reston.va.us  Wed Jan 19 17:24:41 2000
From: bwarsaw at cnri.reston.va.us (Barry A. Warsaw)
Date: Wed, 19 Jan 2000 11:24:41 -0500 (EST)
Subject: [Python-Dev] Python Tools/
References: <3884EF48.A6107775@lemburg.com>
Message-ID: <14469.58697.116588.501355@anthem.cnri.reston.va.us>

>>>>> "M" == M  <mal at lemburg.com> writes:

    M> To my surprise these executable files did not have a .py
    M> extension even though were Python source files. Is this 
    M> intended ? I find that scripts like "world" provide useful
    M> information which would be nice to have in the standard
    M> lib -- with .py extension...

I hadn't thought about making world a module, but if others agree, I
can play a little CVS magic to move the file to world.py.

    M> I noted that at least in my CVS tree the Tools/ht2html dir does
    M> not include any executable: have I missed something ?

If you do a `cvs up -P' (-P for prune) you'll find that that directory
goes away.  At one point I started to add the ht2html scripts to the
Python tools, but then we decided not to.  Unfortunately, once a
directory's been added to CVS it can never be removed (hence -P).

If you're really interested in the ht2html scripts, which are used to
build the Python.Org and JPython.Org sites (as well as my personal
pages), please see

    http://www.python.org/~bwarsaw/software/pyware.html

-Barry



From bwarsaw at cnri.reston.va.us  Wed Jan 19 18:32:50 2000
From: bwarsaw at cnri.reston.va.us (Barry A. Warsaw)
Date: Wed, 19 Jan 2000 12:32:50 -0500 (EST)
Subject: [Python-Dev] Python Tools/
References: <3884EF48.A6107775@lemburg.com>
	<14469.58697.116588.501355@anthem.cnri.reston.va.us>
Message-ID: <14469.62786.178265.983781@anthem.cnri.reston.va.us>

>>>>> "BAW" == Barry A Warsaw <bwarsaw at cnri.reston.va.us> writes:

    BAW> If you do a `cvs up -P' (-P for prune) you'll find that that
    BAW> directory goes away.  At one point I started to add the
    BAW> ht2html scripts to the Python tools, but then we decided not
    BAW> to.  Unfortunately, once a directory's been added to CVS it
    BAW> can never be removed (hence -P).

I just check this and there is no ht2html directory in Tools anymore.
We probably did remove it after you (MAL) had checked it out.  You can
either ignore the directory, or delete it from your working dirs.  If
cvs complains after deleting it, you may have to manually edit the
CVS/Entries file.  Sorry about that -- we know better now.

-Barry



From gerrit.holl at pobox.com  Wed Jan 19 21:14:27 2000
From: gerrit.holl at pobox.com (Gerrit Holl)
Date: Wed, 19 Jan 2000 21:14:27 +0100
Subject: [Python-Dev] ''.join in 1.6
Message-ID: <20000119211427.A3755@stopcontact.palga.uucp>

Hello,

I have a question/suggestion about ''.join in Python 1.6.

Suppose I have this list:
l = ["This", "is", "a", "test"]

Currently, I would join it this way into a tab-delimeted string:
s = string.join(l, '\t')

In 1.6, I should do it this way:
'\t'.join(s)

I think it would be better to have that method on the *list*:
s.join('\t')

That's more clear, isn't it?

regards,
Gerrit.

-- 
Please correct any bad English you encounter in my email message!
-----BEGIN GEEK CODE BLOCK----- http://www.geekcode.com
Version: 3.12
GCS dpu s-:-- a14 C++++>$ UL++ P--- L+++ E--- W++ N o? K? w--- !O !M !V PS+ PE?
Y? PGP-- t- 5? X? R- tv- b+(++) DI D+ G++ !e !r !y
-----END GEEK CODE BLOCK-----



From fredrik at pythonware.com  Wed Jan 19 21:43:36 2000
From: fredrik at pythonware.com (Fredrik Lundh)
Date: Wed, 19 Jan 2000 21:43:36 +0100
Subject: [Python-Dev] ''.join in 1.6
References: <20000119211427.A3755@stopcontact.palga.uucp>
Message-ID: <005e01bf62bd$dc8073d0$f29b12c2@secret.pythonware.com>

> In 1.6, I should do it this way:
> '\t'.join(s)
> 
> I think it would be better to have that method on the *list*:
> s.join('\t')
> 
> That's more clear, isn't it?

what if "s" is a tuple?  an array?  a user-defined
sequence type?

</F>




From bwarsaw at cnri.reston.va.us  Wed Jan 19 21:36:24 2000
From: bwarsaw at cnri.reston.va.us (Barry A. Warsaw)
Date: Wed, 19 Jan 2000 15:36:24 -0500 (EST)
Subject: [Python-Dev] ''.join in 1.6
References: <20000119211427.A3755@stopcontact.palga.uucp>
Message-ID: <14470.8264.686274.888365@anthem.cnri.reston.va.us>

>>>>> "GH" == Gerrit Holl <gerrit.holl at pobox.com> writes:

    GH> I think it would be better to have that method on the *list*:
    GH> s.join('\t')

    GH> That's more clear, isn't it?

Perhaps, but you want join to work on any sequence don't you?  By
making it a method on string objects, you sort of get that for free
(as opposed to putting it on lists, sequences, and requiring all class
authors to add it as well).

-Barry



From da at ski.org  Wed Jan 19 21:54:03 2000
From: da at ski.org (David Ascher)
Date: Wed, 19 Jan 2000 12:54:03 -0800
Subject: [Python-Dev] ''.join in 1.6
In-Reply-To: <20000119211427.A3755@stopcontact.palga.uucp>
Message-ID: <003b01bf62bf$5191abc0$c355cfc0@ski.org>

Gerrit Holl

> Currently, I would join it this way into a tab-delimeted string:
> s = string.join(l, '\t')
>
> In 1.6, I should do it this way:
> '\t'.join(s)
>
> I think it would be better to have that method on the *list*:
> s.join('\t')
>
> That's more clear, isn't it?

As Tim pointed out when they were discussed, the clearest way to express it
with the new methods is to do:

tab = '\t'

tab.join(s)

Similarly

space = ' '
space.join(s)

etc.

--david ascher




From da at ski.org  Wed Jan 19 23:41:47 2000
From: da at ski.org (David Ascher)
Date: Wed, 19 Jan 2000 14:41:47 -0800
Subject: [Python-Dev] SOAP
Message-ID: <000101bf62ce$5e509e70$c355cfc0@ski.org>

Who if anyone is working on SOAP clients and servers for Python?

--david ascher
-------------- next part --------------
A non-text attachment was scrubbed...
Name: David Ascher.vcf
Type: text/x-vcard
Size: 527 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/python-dev/attachments/20000119/2e2d3203/attachment-0001.vcf>

From amk1 at erols.com  Thu Jan 20 05:19:33 2000
From: amk1 at erols.com (A.M. Kuchling)
Date: Wed, 19 Jan 2000 23:19:33 -0500
Subject: [Python-Dev] Changing existing class instances
Message-ID: <200001200419.XAA01969@mira.erols.com>

Currently, when you replace a class definition with an updated
version, it's really difficult to change existing class instances;
you'd have to essentially sweep every Python object and check if it's
an instance, starting at roots such as __main__ and sys.modules.  This
makes developing code in a long-running process difficult, Zope being
the best example of this.  When you modify a class definition used by
Zope code, you can't update existing instances floating around in
memory.

Over dinner, a friend and I were discussing this, and we thought it
probably isn't difficult to add an extra level of indirection to allow
fixing this.  The only other option we could think of is either the
complete scan of all objects, or inserting a forwarding pointer into
PyClassObjects that points to the replacing class if !NULL, and then
chase pointers when accessing PyInstanceObject->in_class.

A quick hack to implement the extra indirection took about
half an hour.  It does these things:

      * Defines a PyClassHandle type:
struct _PyClassHandle {
  PyClassHandle *next;		/* ptr to next PyClassHandle in linked list */
  PyClassObject *klass;		/* The class object */
} ;

      * The in_class attribute of PyInstanceObject becomes a
        PyClassHandle* instead of a PyClassObject*, and all code 
	such as inst->in_class becomes inst->in_class->klass.

      * As a quick hack to allow changing the class object referenced
        by a handle, I added a .forward( <newclassobject> ) method to
        class objects.  This basically does self.handle->klass =
        <newclassobject>.

The end result is that obj.__class__.forward(newclass) changes obj to
be an instance of newclass, and all other instances of obj.__class__
also mutate to become newclass instances.   

Making this purely automatic seems hard; you'd have to catch things
like 'import ftplib; ftplib.FTP = myclass', which would require
automatically calling ftplib.FTP.forward( myclass ) to make all
existing FTP instances mutate.  Would it be worthwhile to export some
hook for doing this in 1.6?  The cost is adding an extra pointer deref
to all access to PyInstanceObject->in_class.

(This could probably also be added to ExtensionClass, and probably
doesn't need to be added to core Python to help out Zope.  Just a
thought...)

-- 
A.M. Kuchling			http://starship.python.net/crew/amk/
Here the skull of a consumptive child becomes part of a great machine for
calculating the motions of the stars. Here, a yellow bird frets within the
ribcage of an unjust man.
    -- Welcome to Orqwith, in DOOM PATROL #22



From guido at CNRI.Reston.VA.US  Thu Jan 20 05:41:29 2000
From: guido at CNRI.Reston.VA.US (Guido van Rossum)
Date: Wed, 19 Jan 2000 23:41:29 -0500
Subject: [Python-Dev] Changing existing class instances
In-Reply-To: Your message of "Wed, 19 Jan 2000 23:19:33 EST."
             <200001200419.XAA01969@mira.erols.com> 
References: <200001200419.XAA01969@mira.erols.com> 
Message-ID: <200001200441.XAA20952@eric.cnri.reston.va.us>

> Currently, when you replace a class definition with an updated
> version, it's really difficult to change existing class instances;
> you'd have to essentially sweep every Python object and check if it's
> an instance, starting at roots such as __main__ and sys.modules.  This
> makes developing code in a long-running process difficult, Zope being
> the best example of this.  When you modify a class definition used by
> Zope code, you can't update existing instances floating around in
> memory.

There might be another solution.  When you reload a module, the module
object and its dictionary are reused.

Perhaps class and function objects could similarly be reused?  It
would mean that a class or def statement looks for an existing object
with the same name and type, and overwrites that.  Voila, all
references are automatically updated.

This is more work (e.g. for classes, a new bytecode may have to be
invented because the class creation process must be done differently)
but it's much less of a hack, and I think it would be more reliable.
(Even though it alters borderline semantics a bit.)

(Your extra indirection also slows things down, although I don't know
by how much -- not just the extra memory reference but also less
locality of reference so more cache hits.)

--Guido van Rossum (home page: http://www.python.org/~guido/)



From tim_one at email.msn.com  Thu Jan 20 06:59:51 2000
From: tim_one at email.msn.com (Tim Peters)
Date: Thu, 20 Jan 2000 00:59:51 -0500
Subject: [Python-Dev] Changing existing class instances
In-Reply-To: <200001200441.XAA20952@eric.cnri.reston.va.us>
Message-ID: <000b01bf630b$91a409a0$31a2143f@tim>

[Guido, on Andrew's idea for automagically updating
 classes]

> There might be another solution.  When you reload a module,
> the module object and its dictionary are reused.
>
> Perhaps class and function objects could similarly be
> reused?  It would mean that a class or def statement
> looks for an existing object with the same name and type,
> and overwrites that.  Voila, all references are
> automatically updated.

Too dangerous, I think.  While uncommon in general, I've certainly seen
(even written) functions that e.g. return a contained def or class.  The
intent in such cases is very much to create distinct defs or classes
(despite having the same names).  In this case I assume "the same name"
wouldn't *usually* be found, since the "contained def or class"'s name is
local to the containing function.  But if there ever happened to be a
module-level function or class of the same name, brrrr.

Modules differ because their namespace "search path" consists solely of the
more-global-than-global <wink> sys.modules.

> This is more work (e.g. for classes, a new bytecode may
> have to be invented because the class creation process
> must be done differently) but it's much less of a hack,
> and I think it would be more reliable. (Even though it
> alters borderline semantics a bit.)

How about an explicit function in the "new" module,

    new.update(class_or_def_old, class_or_def_new)

which overwrites old's guts with new's guts (in analogy with dict.update)?
Then no semantics change and you don't need new bytecodes.  In return, a
user who wants to e.g. replace an existing class C would need to do

    oldC = C
    do whatever they do to get the new C
    new.update(oldC, C)

Building on that, a short Python loop could do the magic for every class and
function in a module; and building on *that*, a short "updating import"
function could be written in Python.  View it as providing mechanism instead
of policy <0.9 wink>.

> (Your extra indirection also slows things down, although
> I don't know by how much -- not just the extra memory
> reference but also less locality of reference so more
> cache hits.)

Across the universe of all Python programs on all platforms, weighted by
importance, it was a slowdown of nearly 4.317%.

if-i-had-used-only-one-digit-everyone-would-have-
    known-i-was-making-it-up<wink>-ly y'rs  - tim





From gstein at lyra.org  Thu Jan 20 08:48:29 2000
From: gstein at lyra.org (Greg Stein)
Date: Wed, 19 Jan 2000 23:48:29 -0800 (PST)
Subject: [Python-Dev] Changing existing class instances
In-Reply-To: <000b01bf630b$91a409a0$31a2143f@tim>
Message-ID: <Pine.LNX.4.10.10001192342450.13911-100000@nebula.lyra.org>

Oh man, oh man... I think this is where I get to say something akin to "I
told you so."

:-)

I already described Tim's proposal in my type proposal paper, as a way to
deal with incomplete classes. Essentially, a class object is created
"empty" and is later "updated" with the correct bits. The empty class
allows two classes to refer to each other in the "recursive type"
scenario.

In other words, I definitely would support a new class object behavior
that allows us to update a class' set of bases and dictionary on the fly.
This could then be used to support my solution for the recursive type
scenario (which, in turn, means that we don't have to introduce Yet
Another Namespace into Python to hold type names).

Note: I would agree with Guido, however, on the "look for a class object
with the same name", but with the restriction that the name is only
replaced in the *target* namespace. i.e. a "class Foo" in a function will
only look for Foo in the function's local namespace; it would not
overwrite a class in the global space, nor would it overwrite class
objects returned by a prior invocation of the function.

Cheers,
-g

On Thu, 20 Jan 2000, Tim Peters wrote:
> [Guido, on Andrew's idea for automagically updating
>  classes]
> 
> > There might be another solution.  When you reload a module,
> > the module object and its dictionary are reused.
> >
> > Perhaps class and function objects could similarly be
> > reused?  It would mean that a class or def statement
> > looks for an existing object with the same name and type,
> > and overwrites that.  Voila, all references are
> > automatically updated.
> 
> Too dangerous, I think.  While uncommon in general, I've certainly seen
> (even written) functions that e.g. return a contained def or class.  The
> intent in such cases is very much to create distinct defs or classes
> (despite having the same names).  In this case I assume "the same name"
> wouldn't *usually* be found, since the "contained def or class"'s name is
> local to the containing function.  But if there ever happened to be a
> module-level function or class of the same name, brrrr.
> 
> Modules differ because their namespace "search path" consists solely of the
> more-global-than-global <wink> sys.modules.
> 
> > This is more work (e.g. for classes, a new bytecode may
> > have to be invented because the class creation process
> > must be done differently) but it's much less of a hack,
> > and I think it would be more reliable. (Even though it
> > alters borderline semantics a bit.)
> 
> How about an explicit function in the "new" module,
> 
>     new.update(class_or_def_old, class_or_def_new)
> 
> which overwrites old's guts with new's guts (in analogy with dict.update)?
> Then no semantics change and you don't need new bytecodes.  In return, a
> user who wants to e.g. replace an existing class C would need to do
> 
>     oldC = C
>     do whatever they do to get the new C
>     new.update(oldC, C)
> 
> Building on that, a short Python loop could do the magic for every class and
> function in a module; and building on *that*, a short "updating import"
> function could be written in Python.  View it as providing mechanism instead
> of policy <0.9 wink>.
> 
> > (Your extra indirection also slows things down, although
> > I don't know by how much -- not just the extra memory
> > reference but also less locality of reference so more
> > cache hits.)
> 
> Across the universe of all Python programs on all platforms, weighted by
> importance, it was a slowdown of nearly 4.317%.
> 
> if-i-had-used-only-one-digit-everyone-would-have-
>     known-i-was-making-it-up<wink>-ly y'rs  - tim
> 
> 
> 
> _______________________________________________
> Python-Dev maillist  -  Python-Dev at python.org
> http://www.python.org/mailman/listinfo/python-dev
> 

-- 
Greg Stein, http://www.lyra.org/




From fredrik at pythonware.com  Thu Jan 20 09:06:32 2000
From: fredrik at pythonware.com (Fredrik Lundh)
Date: Thu, 20 Jan 2000 09:06:32 +0100
Subject: [Python-Dev] SOAP
References: <000101bf62ce$5e509e70$c355cfc0@ski.org>
Message-ID: <006901bf631d$449eea50$f29b12c2@secret.pythonware.com>

David Ascher <da at ski.org> wrote:
> Who if anyone is working on SOAP clients and servers for Python?

we are (or rather, we will).  hope to have code
available during (late) Q1.

</F>




From gerrit.holl at pobox.com  Thu Jan 20 09:08:01 2000
From: gerrit.holl at pobox.com (Gerrit Holl)
Date: Thu, 20 Jan 2000 09:08:01 +0100
Subject: [Python-Dev] ''.join in 1.6
In-Reply-To: <005e01bf62bd$dc8073d0$f29b12c2@secret.pythonware.com>; from fredrik@pythonware.com on Wed, Jan 19, 2000 at 09:43:36PM +0100
References: <20000119211427.A3755@stopcontact.palga.uucp> <005e01bf62bd$dc8073d0$f29b12c2@secret.pythonware.com>
Message-ID: <20000120090801.A903@stopcontact.palga.uucp>

Fredrik Lundh wrote on 948314616:
> > In 1.6, I should do it this way:
> > '\t'.join(s)
> > 
> > I think it would be better to have that method on the *list*:
> > s.join('\t')
> > 
> > That's more clear, isn't it?
> 
> what if "s" is a tuple?  an array?  a user-defined
> sequence type?

I understand. Thanks for your answers.

regards,
Gerrit.

-- 
Please correct any bad English you encounter in my email message!
-----BEGIN GEEK CODE BLOCK----- http://www.geekcode.com
Version: 3.12
GCS dpu s-:-- a14 C++++>$ UL++ P--- L+++ E--- W++ N o? K? w--- !O !M !V PS+ PE?
Y? PGP-- t- 5? X? R- tv- b+(++) DI D+ G++ !e !r !y
-----END GEEK CODE BLOCK-----



From jim at digicool.com  Thu Jan 20 15:06:29 2000
From: jim at digicool.com (Jim Fulton)
Date: Thu, 20 Jan 2000 09:06:29 -0500
Subject: [Python-Dev] Changing existing class instances
References: <200001200419.XAA01969@mira.erols.com>
Message-ID: <38871665.C3B6FFEE@digicool.com>

"A.M. Kuchling" wrote:
> 
> Currently, when you replace a class definition with an updated
> version, it's really difficult to change existing class instances;
> you'd have to essentially sweep every Python object and check if it's
> an instance, starting at roots such as __main__ and sys.modules.  This
> makes developing code in a long-running process difficult, Zope being
> the best example of this.  When you modify a class definition used by
> Zope code, you can't update existing instances floating around in
> memory.

In the case of Zope, if the objects that you care about happen to be 
persistent objects, then it's relatively easy to arrange to get the
objects flushed from memory and reloaded with the new classes.
(There are some subtle issues to deal with, like worrying about 
multiple threads, but in a development environment, you can deal with
these, for example, by limiting the server to one thread.)

Note that this is really only a special case of a much larger problem.

Reloading a module redefines the global variables in a module.
It doesn't update any references to those global references
from other places, such as instances or *other* modules.

For example, imports like:

  from foo import spam

are not updated when foo is reloaded.

Maybe you are expecting too much from reload.

Jim      

--
Jim Fulton           mailto:jim at digicool.com
Technical Director   (888) 344-4332              Python Powered!
Digital Creations    http://www.digicool.com     http://www.python.org

Under US Code Title 47, Sec.227(b)(1)(C), Sec.227(a)(2)(B) This email
address may not be added to any commercial mail list with out my
permission.  Violation of my privacy with advertising or SPAM will
result in a suit for a MINIMUM of $500 damages/incident, $1500 for
repeats.



From jim at digicool.com  Thu Jan 20 15:34:13 2000
From: jim at digicool.com (Jim Fulton)
Date: Thu, 20 Jan 2000 09:34:13 -0500
Subject: Python 2 namespace change? (was Re: [Python-Dev] Changing existing class 
 instances)
References: <200001200419.XAA01969@mira.erols.com> <38871665.C3B6FFEE@digicool.com>
Message-ID: <38871CE5.53FB9D68@digicool.com>

Jim Fulton wrote:
> 
> Reloading a module redefines the global variables in a module.
> It doesn't update any references to those global references
> from other places, such as instances or *other* modules.
> 
> For example, imports like:
> 
>   from foo import spam
> 
> are not updated when foo is reloaded.

A change to the way that namespaces are handled 
could make this work and have a number of other benefits, 
like global name usage without namespace lookups.

I've suggested this to Guido in the past.  His 
reasonable response is that this would be too big a 
change for Python 1. Maybe this is something to consider
for Python 2?

The basic idea (borrowed from Smalltalk) is to have a kind 
of dictionary that is a collection of "association" 
objects.  An association object is simply a pairing of a 
name with a value. Association objects can be shared among 
multiple namespaces.  An import like:

  from foo import spam

would copy the association between the name 'foo' and a 
value from module 'spam' into the current module. If foo
is reloaded or if the name is reassigned in spam, the
association is modified and the change is seen in any
namespaces that imported foo.

Similarly if a function uses a global variable:

  spam=1

  def bar():
    global spam
    return spam*2

the compiled function contains the association between
spam and it's value. This means that:

  - When spam is used in the function, it doesn't have to
    be looked up,

  - The function object no longer needs to keep a reference
    to it's globals. This eliminates an annoying circular 
    reference.

(I would not replace existing dictionaries with this new kind.
 I'd have both kinds available.)

I think that this would be a really nice change for Python 2.

Jim

--
Jim Fulton           mailto:jim at digicool.com
Technical Director   (888) 344-4332              Python Powered!
Digital Creations    http://www.digicool.com     http://www.python.org

Under US Code Title 47, Sec.227(b)(1)(C), Sec.227(a)(2)(B) This email
address may not be added to any commercial mail list with out my
permission.  Violation of my privacy with advertising or SPAM will
result in a suit for a MINIMUM of $500 damages/incident, $1500 for
repeats.



From guido at CNRI.Reston.VA.US  Thu Jan 20 16:20:45 2000
From: guido at CNRI.Reston.VA.US (Guido van Rossum)
Date: Thu, 20 Jan 2000 10:20:45 -0500
Subject: [Python-Dev] Changing existing class instances
In-Reply-To: Your message of "Thu, 20 Jan 2000 00:59:51 EST."
             <000b01bf630b$91a409a0$31a2143f@tim> 
References: <000b01bf630b$91a409a0$31a2143f@tim> 
Message-ID: <200001201520.KAA21137@eric.cnri.reston.va.us>

> From: "Tim Peters" <tim_one at email.msn.com>
> 
> [Guido, on Andrew's idea for automagically updating
>  classes]
> 
> > There might be another solution.  When you reload a module,
> > the module object and its dictionary are reused.
> >
> > Perhaps class and function objects could similarly be
> > reused?  It would mean that a class or def statement
> > looks for an existing object with the same name and type,
> > and overwrites that.  Voila, all references are
> > automatically updated.
> 
> Too dangerous, I think.  While uncommon in general, I've certainly seen
> (even written) functions that e.g. return a contained def or class.  The
> intent in such cases is very much to create distinct defs or classes
> (despite having the same names).  In this case I assume "the same name"
> wouldn't *usually* be found, since the "contained def or class"'s name is
> local to the containing function.  But if there ever happened to be a
> module-level function or class of the same name, brrrr.

Agreed that that would be bad.  But I wouldn't search outer scopes --
I would only look for a class/def that I was about to stomp on.

> Modules differ because their namespace "search path" consists solely of the
> more-global-than-global <wink> sys.modules.

"The search path doesn't enter into it."

> > This is more work (e.g. for classes, a new bytecode may
> > have to be invented because the class creation process
> > must be done differently) but it's much less of a hack,
> > and I think it would be more reliable. (Even though it
> > alters borderline semantics a bit.)
> 
> How about an explicit function in the "new" module,
> 
>     new.update(class_or_def_old, class_or_def_new)
> 
> which overwrites old's guts with new's guts (in analogy with dict.update)?
> Then no semantics change and you don't need new bytecodes.

Only a slight semantics change (which my full proposal would require
too): function objects would become mutable -- their func_code,
func_defaults, func_doc and func_globals fields (and, why not,
func_name too) should be changeable.  If you make all these
assignable, it doesn't even have to be a privileged function.

> In return, a
> user who wants to e.g. replace an existing class C would need to do
> 
>     oldC = C
>     do whatever they do to get the new C
>     new.update(oldC, C)
> 
> Building on that, a short Python loop could do the magic for every class and
> function in a module; and building on *that*, a short "updating import"
> function could be written in Python.  View it as providing mechanism instead
> of policy <0.9 wink>.

That's certainly a reasonable compromise.  Note that the update on a
class should imply an update on its methods, right?

--Guido van Rossum (home page: http://www.python.org/~guido/)



From guido at CNRI.Reston.VA.US  Thu Jan 20 16:45:40 2000
From: guido at CNRI.Reston.VA.US (Guido van Rossum)
Date: Thu, 20 Jan 2000 10:45:40 -0500
Subject: Python 2 namespace change? (was Re: [Python-Dev] Changing existing class instances)
In-Reply-To: Your message of "Thu, 20 Jan 2000 09:34:13 EST."
             <38871CE5.53FB9D68@digicool.com> 
References: <200001200419.XAA01969@mira.erols.com> <38871665.C3B6FFEE@digicool.com>  
            <38871CE5.53FB9D68@digicool.com> 
Message-ID: <200001201545.KAA21304@eric.cnri.reston.va.us>

> I've suggested this to Guido in the past.  His 
> reasonable response is that this would be too big a 
> change for Python 1. Maybe this is something to consider
> for Python 2?

Note: from now on the new name for Python 2 is Python 3000. :-)

> The basic idea (borrowed from Smalltalk) is to have a kind 
> of dictionary that is a collection of "association" 
> objects.  An association object is simply a pairing of a 
> name with a value. Association objects can be shared among 
> multiple namespaces.

I've never liked this very much, mostly because it breaks simplicity:
the idea that a namespace is a mapping from names to values
(e.g. {"limit": 100, "doit": <function...>, ...}) is beautifully
simple, while the idea of inserting an extra level of indirection, no
matter how powerful, is much murkier.

There's also the huge change in semantics, as you point out;
currently,

	from foo import bar

has the same effect (on bar anyway) as

	import foo
	bar = foo.bar		# i.e. copying an object reference
	del foo

while under your proposal it would be more akin to changing all
references to bar to become references to foo.bar.

Of course that's what the moral equivalent of "from ... import ..."
does in most other languages anyway, so we might consider this for
Python 3000; however it would break a considerable amount of old code,
I think.  (Not to mention brain and book breakage. :-)

--Guido van Rossum (home page: http://www.python.org/~guido/)



From guido at CNRI.Reston.VA.US  Thu Jan 20 17:01:38 2000
From: guido at CNRI.Reston.VA.US (Guido van Rossum)
Date: Thu, 20 Jan 2000 11:01:38 -0500
Subject: [Python-Dev] Python 1.6 timing
Message-ID: <200001201601.LAA21359@eric.cnri.reston.va.us>

Andrew let me repost this mail of his to this list.  It's worth a
discussion here (if not in a larger forum).  My responses are at the
bottom.

------- Forwarded Message

Date:    Wed, 19 Jan 2000 20:17:55 -0500
From:    "A.M. Kuchling" <amk1 at erols.com>
To:      guido at python.org
Subject: Python 1.6 timing

I thought a bit more about the release schedule for 1.6, and like the
idea of delaying it less and less.  Another bad effect of delaying it
is that not having Unicode in the core handicaps developing XML tools;
we can continue working with wstrop, or integrate MAL's code into the
XML-SIG's CVS tree, but it might mean abandoning the XML processing
field to Perl & Tcl because the tools can't be made fully standard
compliant in time.

Options I can think of:

	1) Delegating some control to a pumpkin holder [...].

	2) Releasing the Unicode+sre modules as separate add-ons to
 	   1.5.  (But would that impose annoying
	   backward-compatibility constraints when they get integrated
	   into 1.6?)

	3) Add Unicode, sre, Distutils, plus other minor things and
           call it 1.5.5, meaning it's not as big a revision as a 1.6
           release, but it's bigger than just another patchlevel of
	   bugfixes.  I don't remember what other features were
	   planned for 1.6; was there anything major, if static typing
	   is left for 2.0?

- -- 
A.M. Kuchling			http://starship.python.net/crew/amk/
Life's too short for chess.
    -- H.J. Byron

------- End of Forwarded Message

There are several other things I can think of now that were planned
for 1.6: revamped import, rich comparisons, revised coercions,
parallel for loop (for i in L; j in M: ...), extended slicing for all
sequences.  I've also been thinking about making classes be types (not
as huge a change as you think, if you don't allow subclassing built-in
types), and adding a built-in array type suitable for use by NumPy.
I've also received a conservative GC patch that seems to be fairly
easy to apply and has some of Tim Peters' blessing.

For 1.5.5 (what happened to 1.5.3 and 1.5.4?), we can have a more
conservative agenda, as suggested by Andrew: Unicode and distutils are
probably the most important things to integrate.  (The import
utilities are not ready for prime time in my opinion; there are too
many issues.)

Anybody care to be the pumpkin?  That would cut the discussion short;
otherwise the problem remains that I can't spend too much time on the
next release unless I get funded for it; what little money I've
received for CP4E I had better spend on getting some CP4E-related
results ASAP, because the next installment of this funding is very
much at stake...

--Guido van Rossum (home page: http://www.python.org/~guido/)
Life's better without braces.
    -- Bruce Eckel



From bwarsaw at cnri.reston.va.us  Thu Jan 20 17:21:30 2000
From: bwarsaw at cnri.reston.va.us (Barry A. Warsaw)
Date: Thu, 20 Jan 2000 11:21:30 -0500 (EST)
Subject: [Python-Dev] Python 1.6 timing
References: <200001201601.LAA21359@eric.cnri.reston.va.us>
Message-ID: <14471.13834.480356.541389@anthem.cnri.reston.va.us>

>>>>> "Guido" == Guido van Rossum <guido at cnri.reston.va.us> writes:

    Guido> There are several other things I can think of now that were
    Guido> planned for 1.6: revamped import, rich comparisons, revised
    Guido> coercions, parallel for loop (for i in L; j in M: ...),
    Guido> extended slicing for all sequences.  I've also been
    Guido> thinking about making classes be types (not as huge a
    Guido> change as you think, if you don't allow subclassing
    Guido> built-in types), and adding a built-in array type suitable
    Guido> for use by NumPy.  I've also received a conservative GC
    Guido> patch that seems to be fairly easy to apply and has some of
    Guido> Tim Peters' blessing.

All very cool things that could easily wait until 1.7.  After all,
what's in a number?  If, as Andrew puts forth, getting a stable Python
release with Unicode is very important for Python's future
positioning, then I say let's go with his more modest list, mainly
Unicode, sre, and Distutils.  We've already got string meths, tons of
library improvements, and sundry other things.  That's a good enough
laundry list for the next release.


From jim at digicool.com  Thu Jan 20 17:21:33 2000
From: jim at digicool.com (Jim Fulton)
Date: Thu, 20 Jan 2000 11:21:33 -0500
Subject: Version numbering (was Re: [Python-Dev] Python 1.6 timing)
References: <200001201601.LAA21359@eric.cnri.reston.va.us>
Message-ID: <3887360D.C29A9836@digicool.com>

Guido van Rossum wrote:
> 
> Andrew let me repost this mail of his to this list.  It's worth a
> discussion here (if not in a larger forum).  My responses are at the
> bottom.
> 
(snip)
> 
> There are several other things I can think of now that were planned
> for 1.6: revamped import, rich comparisons, revised coercions,
> parallel for loop (for i in L; j in M: ...), extended slicing for all
> sequences.  I've also been thinking about making classes be types (not
> as huge a change as you think, if you don't allow subclassing built-in
> types), and adding a built-in array type suitable for use by NumPy.
> I've also received a conservative GC patch that seems to be fairly
> easy to apply and has some of Tim Peters' blessing.
> 
> For 1.5.5 (what happened to 1.5.3 and 1.5.4?), we can have a more
> conservative agenda, as suggested by Andrew: Unicode and distutils are
> probably the most important things to integrate.  (The import
> utilities are not ready for prime time in my opinion; there are too
> many issues.)

(snip)

What is the basis of the Python numbering scheme?

I thought that there was a notion that:

  - The first part changed with huge, possibly
    backward incompatible, changes,

  - The second part was for new functionality 
    
  - The third part was for bug fixes.

I thought I saw this scheme referenced somewhere and
possibly even attributed to Guido. (?) I think that 
this is a better scheme that what I've seen with 
the 1.5 releases.

Jim

--
Jim Fulton           mailto:jim at digicool.com
Technical Director   (888) 344-4332              Python Powered!
Digital Creations    http://www.digicool.com     http://www.python.org

Under US Code Title 47, Sec.227(b)(1)(C), Sec.227(a)(2)(B) This email
address may not be added to any commercial mail list with out my
permission.  Violation of my privacy with advertising or SPAM will
result in a suit for a MINIMUM of $500 damages/incident, $1500 for
repeats.



From petrilli at amber.org  Thu Jan 20 17:33:52 2000
From: petrilli at amber.org (Christopher Petrilli)
Date: Thu, 20 Jan 2000 11:33:52 -0500
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <14471.13834.480356.541389@anthem.cnri.reston.va.us>; from bwarsaw@cnri.reston.va.us on Thu, Jan 20, 2000 at 11:21:30AM -0500
References: <200001201601.LAA21359@eric.cnri.reston.va.us> <14471.13834.480356.541389@anthem.cnri.reston.va.us>
Message-ID: <20000120113352.A23763@trump.amber.org>

Barry A. Warsaw [bwarsaw at cnri.reston.va.us] wrote:
> All very cool things that could easily wait until 1.7.  After all,
> what's in a number?  If, as Andrew puts forth, getting a stable Python
> release with Unicode is very important for Python's future
> positioning, then I say let's go with his more modest list, mainly
> Unicode, sre, and Distutils.  We've already got string meths, tons of
> library improvements, and sundry other things.  That's a good enough
> laundry list for the next release.

Heck, Python is infinately more conservative in its numbering than 
a lot of projects.  All that was mentioned would normally be enough to
call it 2.0 easily. :-)  Modesty can be counter productive in PR 
business...also there is the issue of having two copies of 1.5.x installed
at the same time, which with Unicode could be a manjor consideraton
for some of us.

For me, numbering has always been (and I try and keep it this way with
Zope):

	X.Y.Z

	X = structural changes, backward incompaibility
	Y = new features
	Z = bug fixes only

Chris
-- 
| Christopher Petrilli
| petrilli at amber.org



From bwarsaw at cnri.reston.va.us  Thu Jan 20 17:30:32 2000
From: bwarsaw at cnri.reston.va.us (Barry A. Warsaw)
Date: Thu, 20 Jan 2000 11:30:32 -0500 (EST)
Subject: [Python-Dev] Python 1.6 timing
References: <200001201601.LAA21359@eric.cnri.reston.va.us>
	<14471.13834.480356.541389@anthem.cnri.reston.va.us>
	<20000120113352.A23763@trump.amber.org>
Message-ID: <14471.14376.9881.702264@anthem.cnri.reston.va.us>

>>>>> "CP" == Christopher Petrilli <petrilli at amber.org> writes:

    CP> For me, numbering has always been (and I try and keep it this
    CP> way with Zope):

    CP> 	X.Y.Z

    | 	X = structural changes, backward incompaibility
    | 	Y = new features
    | 	Z = bug fixes only

I agree.
-Barry



From petrilli at amber.org  Thu Jan 20 17:41:24 2000
From: petrilli at amber.org (Christopher Petrilli)
Date: Thu, 20 Jan 2000 11:41:24 -0500
Subject: [Python-Dev] SOAP
In-Reply-To: <006901bf631d$449eea50$f29b12c2@secret.pythonware.com>; from fredrik@pythonware.com on Thu, Jan 20, 2000 at 09:06:32AM +0100
References: <000101bf62ce$5e509e70$c355cfc0@ski.org> <006901bf631d$449eea50$f29b12c2@secret.pythonware.com>
Message-ID: <20000120114124.B23763@trump.amber.org>

Fredrik Lundh [fredrik at pythonware.com] wrote:
> David Ascher <da at ski.org> wrote:
> > Who if anyone is working on SOAP clients and servers for Python?
> 
> we are (or rather, we will).  hope to have code
> available during (late) Q1.
> 
> </F>

For what it's worth, this is also Zope's strategy.  We are commited to
having full SOAP integration in the system soon (when soon is, is another
queston for the marketing department). :-)   I am pretty sure that it will
be a bi-directional integration.

Chris
-- 
| Christopher Petrilli
| petrilli at amber.org



From akuchlin at mems-exchange.org  Thu Jan 20 17:38:53 2000
From: akuchlin at mems-exchange.org (Andrew M. Kuchling)
Date: Thu, 20 Jan 2000 11:38:53 -0500 (EST)
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <14471.13834.480356.541389@anthem.cnri.reston.va.us>
References: <200001201601.LAA21359@eric.cnri.reston.va.us>
	<14471.13834.480356.541389@anthem.cnri.reston.va.us>
Message-ID: <14471.14877.434886.471929@amarok.cnri.reston.va.us>

Barry A. Warsaw writes:
>    Guido> There are several other things I can think of now that were
>    Guido> planned for 1.6: revamped import, rich comparisons, revised
>    Guido> coercions, parallel for loop (for i in L; j in M: ...),
>    Guido> extended slicing for all sequences.  

I'm not clear on the status of these various things; how many of these
changes are deep ones that need lots of design, or affect massive
amounts of the code base?  For example, revamped import is a tricky
design problem (as we've seen on this list).  Is the spec for rich
comparisons clearly defined at this point?  Something like the
parallel for loop seems like a parser modification combined with a
code-generator modification, with no subtle implications for the rest
of the implementation, and so that seems a simple matter of
programming -- a week or so of effort.  (Maybe I've missed something?)

>    Guido> I've also been
>    Guido> thinking about making classes be types (not as huge a
>    Guido> change as you think, if you don't allow subclassing
>    Guido> built-in types), and adding a built-in array type suitable
>    Guido> for use by NumPy.  I've also received a conservative GC
>    Guido> patch that seems to be fairly easy to apply and has some of
>    Guido> Tim Peters' blessing.

Similarly, does the conservative GC patch splatter changes all over
the place, or is it very localized?  Is adding the NumPy array type
straightforward?  Remember, there would presumably be a couple of 1.6
alphas and betas to shake out bugs.

>From a political standpoint, I'd call the next release 1.6 and not
>bother with another installment in 1.5.x series.  And I agree with

Fair enough; forget about the 1.5.5 suggestion, and call it as 1.6.

>tree.  My free-time plate is pretty full with JPython and Mailman, but
>I'm willing to help where possible.

Ditto.

-- 
A.M. Kuchling			http://starship.python.net/crew/amk/
One trouble with being efficient is that it makes everybody hate you so.
    -- Bob Edwards, the Calgary Eyeopener, March 18, 1916




From jim at digicool.com  Thu Jan 20 17:48:18 2000
From: jim at digicool.com (Jim Fulton)
Date: Thu, 20 Jan 2000 11:48:18 -0500
Subject: Python 2 namespace change? (was Re: [Python-Dev] Changing existing 
 class instances)
References: <200001200419.XAA01969@mira.erols.com> <38871665.C3B6FFEE@digicool.com>  
	            <38871CE5.53FB9D68@digicool.com> <200001201545.KAA21304@eric.cnri.reston.va.us>
Message-ID: <38873C52.29FEAC6D@digicool.com>

Guido van Rossum wrote:
> 
> > I've suggested this to Guido in the past.  His
> > reasonable response is that this would be too big a
> > change for Python 1. Maybe this is something to consider
> > for Python 2?
> 
> Note: from now on the new name for Python 2 is Python 3000. :-)

I like it. 

> > The basic idea (borrowed from Smalltalk) is to have a kind
> > of dictionary that is a collection of "association"
> > objects.  An association object is simply a pairing of a
> > name with a value. Association objects can be shared among
> > multiple namespaces.
> 
> I've never liked this very much, mostly because it breaks simplicity:
> the idea that a namespace is a mapping from names to values
> (e.g. {"limit": 100, "doit": <function...>, ...}) is beautifully
> simple, while the idea of inserting an extra level of indirection, no
> matter how powerful, is much murkier.

How so? It doesn't change the mapping semantics.
 
> There's also the huge change in semantics, as you point out;
> currently,
> 
>         from foo import bar
> 
> has the same effect (on bar anyway) as
> 
>         import foo
>         bar = foo.bar           # i.e. copying an object reference
>         del foo
> 
> while under your proposal it would be more akin to changing all
> references to bar to become references to foo.bar.
> 
> Of course that's what the moral equivalent of "from ... import ..."
> does in most other languages anyway, so we might consider this for
> Python 3000;

Cool. Again, it would also make function global variable access
faster and cleaner in some ways.

> however it would break a considerable amount of old code,
> I think. 

Really? I wonder. I bet it would break alot less old
code that other recent changes.

> (Not to mention brain

It makes my brain feel much better. :)

> and book breakage. :-)

Hey, all of the books will have to be rewritten for Python 3000.

Jim

--
Jim Fulton           mailto:jim at digicool.com
Technical Director   (888) 344-4332              Python Powered!
Digital Creations    http://www.digicool.com     http://www.python.org

Under US Code Title 47, Sec.227(b)(1)(C), Sec.227(a)(2)(B) This email
address may not be added to any commercial mail list with out my
permission.  Violation of my privacy with advertising or SPAM will
result in a suit for a MINIMUM of $500 damages/incident, $1500 for
repeats.



From gstein at lyra.org  Thu Jan 20 18:22:40 2000
From: gstein at lyra.org (Greg Stein)
Date: Thu, 20 Jan 2000 09:22:40 -0800 (PST)
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <200001201601.LAA21359@eric.cnri.reston.va.us>
Message-ID: <Pine.LNX.4.10.10001200907240.13911-100000@nebula.lyra.org>

On Thu, 20 Jan 2000, Guido van Rossum wrote:
>...
> Date:    Wed, 19 Jan 2000 20:17:55 -0500
> From:    "A.M. Kuchling" <amk1 at erols.com>
> To:      guido at python.org
> Subject: Python 1.6 timing
> 
> I thought a bit more about the release schedule for 1.6, and like the
> idea of delaying it less and less.  Another bad effect of delaying it
> is that not having Unicode in the core handicaps developing XML tools;
> we can continue working with wstrop, or integrate MAL's code into the
> XML-SIG's CVS tree, but it might mean abandoning the XML processing
> field to Perl & Tcl because the tools can't be made fully standard
> compliant in time.

I agree with Andrew's basic premise.

> Options I can think of:
> 
> 	1) Delegating some control to a pumpkin holder [...].

Seems fine.

> 	2) Releasing the Unicode+sre modules as separate add-ons to
>  	   1.5.  (But would that impose annoying
> 	   backward-compatibility constraints when they get integrated
> 	   into 1.6?)

Icky. :-)

> 	3) Add Unicode, sre, Distutils, plus other minor things and
>            call it 1.5.5, meaning it's not as big a revision as a 1.6
>            release, but it's bigger than just another patchlevel of
> 	   bugfixes.  I don't remember what other features were
> 	   planned for 1.6; was there anything major, if static typing
> 	   is left for 2.0?

Call it 1.6, per the rest of the thread.

>...
> For 1.5.5 (what happened to 1.5.3 and 1.5.4?), we can have a more
> conservative agenda, as suggested by Andrew: Unicode and distutils are
> probably the most important things to integrate.

Unicode: definitely. distutils seems pretty early, but I bet that some key
concepts could be added to 1.6, to make the transition and continued
development easier.

Note that if an announcement were made to the effect of "feature freeze on
February 15; only bug fixes afterwards," that you would get a lot of
people scrambling to submit their pet features. This would be a good way
to light some fires, to see what kinds of things get completed (i.e. we
may think some things aren't ready or are too far out, put that deadline
in and those positions could change...)

> (The import
> utilities are not ready for prime time in my opinion; there are too
> many issues.)

I'm waiting for that review :-)

If you raise issues, then I can knock them down. I don't see all that many
at the moment. But I'm biased :-)

> Anybody care to be the pumpkin?  That would cut the discussion short;
> otherwise the problem remains that I can't spend too much time on the
> next release unless I get funded for it; what little money I've
> received for CP4E I had better spend on getting some CP4E-related
> results ASAP, because the next installment of this funding is very
> much at stake...

I would volunteer for the pumpkin... around April-ish. My plate is rather
full with completing mod_dav and then integrating that into Apache 2.0.
Once the Apache integration begins, then I'd have some more free time.

But this begs the question of: what does the pumpkin-holder mean in the
*Python* world?

If it is collating fixes, producing snapshots, etc, then I'm comfy with
it. If it also contains responsibility for specific kinds of work, then
Fred would probably veto me :-), as I've got an outstanding doc that I owe
him (for about six months now... sigh; maybe I'll bribe MAL to write it; 
he knows the interface :-)).

But stll: what's it mean? How does the pumpkin reduce the Guido-load, yet
still enable the Guido-control?

[ I just had a talk about this with the guys at Inprise, re: InterBase,
  mentioning that the Dictator model works well for Python, but doesn't
  necessarily work well for new projects or commercially-started projects
  due to control/prejudice issues. Python people like it because of the
  resulting simplicity and cleanliness; I doubt we want a pumpkin approach
  that would allow that to go away! ]

Cheers,
-g

-- 
Greg Stein, http://www.lyra.org/




From guido at CNRI.Reston.VA.US  Thu Jan 20 18:20:33 2000
From: guido at CNRI.Reston.VA.US (Guido van Rossum)
Date: Thu, 20 Jan 2000 12:20:33 -0500
Subject: Python 2 namespace change? (was Re: [Python-Dev] Changing existing class instances)
In-Reply-To: Your message of "Thu, 20 Jan 2000 11:48:18 EST."
             <38873C52.29FEAC6D@digicool.com> 
References: <200001200419.XAA01969@mira.erols.com> <38871665.C3B6FFEE@digicool.com> <38871CE5.53FB9D68@digicool.com> <200001201545.KAA21304@eric.cnri.reston.va.us>  
            <38873C52.29FEAC6D@digicool.com> 
Message-ID: <200001201720.MAA21534@eric.cnri.reston.va.us>

[me]
> > I've never liked this very much, mostly because it breaks simplicity:
> > the idea that a namespace is a mapping from names to values
> > (e.g. {"limit": 100, "doit": <function...>, ...}) is beautifully
> > simple, while the idea of inserting an extra level of indirection, no
> > matter how powerful, is much murkier.

[Jim F]
> How so? It doesn't change the mapping semantics.

My assumption is that in your version, the dictionary would contain
special <object binding> objects which then would contain the
referenced objects.  E.g. {"limit": <binding: 100>, "doit": <binding:
<function ...>>}.  Thus, d["limit"] would be that <binding> object,
while previously it would return 100.

> Again, it would also make function global variable access
> faster and cleaner in some ways.

But I have other plans for that (if the optional static typing stuff
ever gets implemented).

> > however it would break a considerable amount of old code,
> > I think. 
> 
> Really? I wonder. I bet it would break alot less old
> code that other recent changes.

Oh?  Name some changes that broke a lot of code?

--Guido van Rossum (home page: http://www.python.org/~guido/)



From jeremy at cnri.reston.va.us  Thu Jan 20 18:36:32 2000
From: jeremy at cnri.reston.va.us (Jeremy Hylton)
Date: Thu, 20 Jan 2000 12:36:32 -0500 (EST)
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <14471.13834.480356.541389@anthem.cnri.reston.va.us>
References: <200001201601.LAA21359@eric.cnri.reston.va.us>
	<14471.13834.480356.541389@anthem.cnri.reston.va.us>
Message-ID: <14471.18336.257653.730100@bitdiddle.cnri.reston.va.us>

>>>>> "BAW" == Barry A Warsaw <bwarsaw at cnri.reston.va.us> writes:
>>>>> "Guido" == Guido van Rossum <guido at cnri.reston.va.us> writes:

  Guido> There are several other things I can think of now that were
  Guido> planned for 1.6: revamped import, rich comparisons, revised
  Guido> coercions, parallel for loop (for i in L; j in M: ...),
  Guido> extended slicing for all sequences.  I've also been thinking
  Guido> about making classes be types (not as huge a change as you
  Guido> think, if you don't allow subclassing built-in types), and
  Guido> adding a built-in array type suitable for use by NumPy.  I've
  Guido> also received a conservative GC patch that seems to be fairly
  Guido> easy to apply and has some of Tim Peters' blessing.

  BAW> All very cool things that could easily wait until 1.7.  After
  BAW> all, what's in a number?  If, as Andrew puts forth, getting a
  BAW> stable Python release with Unicode is very important for
  BAW> Python's future positioning, then I say let's go with his more
  BAW> modest list, mainly Unicode, sre, and Distutils.  We've already
  BAW> got string meths, tons of library improvements, and sundry
  BAW> other things.  That's a good enough laundry list for the next
  BAW> release.

We've had this conversation before, so it'll comes as no surprise that
I agree with you.  Question: If we go with the feature set you've
described, when will those features be ready?  What kind of schedule
could we set for releasing the first alpha?

Jeremy




From guido at CNRI.Reston.VA.US  Thu Jan 20 18:40:51 2000
From: guido at CNRI.Reston.VA.US (Guido van Rossum)
Date: Thu, 20 Jan 2000 12:40:51 -0500
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: Your message of "Thu, 20 Jan 2000 09:22:40 PST."
             <Pine.LNX.4.10.10001200907240.13911-100000@nebula.lyra.org> 
References: <Pine.LNX.4.10.10001200907240.13911-100000@nebula.lyra.org> 
Message-ID: <200001201740.MAA21608@eric.cnri.reston.va.us>

> Call it 1.6, per the rest of the thread.

OK.  I expect I'll get some complaints from some people who asked when
1.6 would be out (I've generally told them end of 2000); but it sounds
like a 1.7 would be necessary to fulfill the other promises, so it
shouldn't really matter -- it's all a case of relabeling for PR
purposes.

> Unicode: definitely. distutils seems pretty early, but I bet that some key
> concepts could be added to 1.6, to make the transition and continued
> development easier.

The point of adding distutils is that it will allow distribution of
packages without including distutils with each distribution.  Since
distutils was about 200K itself last time I looked, this is important.
I don't believe it would be good to have to say "My FooBar package is
really easy to install.  All you need to do is download and install
distutils, (which by the way is a 200K package that you have to
manually install), and then run "python setup.py" in the FooBar root
directory..."  This would be enough for the average person to run away
screaming.

I think I saw a distribution by AMK that had a setup.py that tried to
use distutils but had a crude fallback if distutils didn't exist;
however that defeats much of the purpose since the package author has
to figure out how to do the fallback.

Large distributions (e.g. NumPy) can afford to squeeze distutils in a
corner of their distribution, but for the average package it wouldn't
be of much use.

In other words, I'm for putting distutils in the next release,
essentially feature-freezing it.  Greg Ward, what do you think of
that?

> Note that if an announcement were made to the effect of "feature freeze on
> February 15; only bug fixes afterwards," that you would get a lot of
> people scrambling to submit their pet features. This would be a good way
> to light some fires, to see what kinds of things get completed (i.e. we
> may think some things aren't ready or are too far out, put that deadline
> in and those positions could change...)

I bet you we couldn't complete the import hooks by that date; I
consider imputil.py as a nice prototype, but the integration with the
C code is still missing.  Also the 50% slowdown is a problem I worry
about for inclusion a production version.  (Plus breakage of everybody
else's code who uses or hacks __import__; e.g. have you tested it with
rexec?)

> > (The import
> > utilities are not ready for prime time in my opinion; there are too
> > many issues.)
> 
> I'm waiting for that review :-)

It was kept up by the need to get the types documents out.

> If you raise issues, then I can knock them down. I don't see all that many
> at the moment. But I'm biased :-)
> 
> > Anybody care to be the pumpkin?  That would cut the discussion short;
> > otherwise the problem remains that I can't spend too much time on the
> > next release unless I get funded for it; what little money I've
> > received for CP4E I had better spend on getting some CP4E-related
> > results ASAP, because the next installment of this funding is very
> > much at stake...
> 
> I would volunteer for the pumpkin... around April-ish. My plate is rather
> full with completing mod_dav and then integrating that into Apache 2.0.
> Once the Apache integration begins, then I'd have some more free time.
> 
> But this begs the question of: what does the pumpkin-holder mean in the
> *Python* world?
> 
> If it is collating fixes, producing snapshots, etc, then I'm comfy with
> it. If it also contains responsibility for specific kinds of work, then
> Fred would probably veto me :-), as I've got an outstanding doc that I owe
> him (for about six months now... sigh; maybe I'll bribe MAL to write it; 
> he knows the interface :-)).
> 
> But stll: what's it mean? How does the pumpkin reduce the Guido-load, yet
> still enable the Guido-control?

Good questions.  I have to say that I feel reluctant to release any
kind of control -- yet at the same time I desperately need help
getting trivial stuff checked in.  One of the most important
time-consuming tasks is quality control: collecting fixes is all well
and good, but I routinely reject fixes that superficially look fine,
because they are subtly broken, or interfere with other plans, or just
because the code looks poorly written.  I also spend a lot of testing
before I check things in; running the standard test suite is a good
safeguard against general breakage, but you really have to play with
the code affected by the change before you can know that it works as
advertised.  My work attitude here means that what gets checked in is
generally rock solid, and that helps Python's reputation; but it is
very costly...

> [ I just had a talk about this with the guys at Inprise, re: InterBase,
>   mentioning that the Dictator model works well for Python, but doesn't
>   necessarily work well for new projects or commercially-started projects
>   due to control/prejudice issues. Python people like it because of the
>   resulting simplicity and cleanliness; I doubt we want a pumpkin approach
>   that would allow that to go away! ]

Agreed, of course.

--Guido van Rossum (home page: http://www.python.org/~guido/)



From da at ski.org  Thu Jan 20 18:57:51 2000
From: da at ski.org (David Ascher)
Date: Thu, 20 Jan 2000 09:57:51 -0800
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <14471.13834.480356.541389@anthem.cnri.reston.va.us>
Message-ID: <000701bf636f$de37c5e0$c355cfc0@ski.org>

[I just got GvR's post on the topic, but I'll send this anyway]

BAW:
> All very cool things that could easily wait until 1.7.  After all,
> what's in a number?

Guido has promised some of those features as being in 1.6 at conferences in
the past, but I agree that string methods for example are a more major
change than I'd expect to see in a 0.0.3-delta version change.

Maybe with a deadline (as Greg suggests) we can integrate some of the
pending patches (I agree with Greg that I at least would have found the time
for a revised patch for rich comparisons if I'd had a deadline -- call me
human =).
Coercion and extended slicing also seem like relatively minor changes,
compared with changing everything to be a class or adding GC!

Regardless, just like Greg, I'd like to know what a pumpkin-holder would
mean in the Python world.

I propose that it be called the Oracle instead.  As in, whoever is Oracle
would get some training with Tim Peters and learn how to channel G__do.  As
a Python user, I'd be most comfortable with such a change if the Oracle just
took over the technical stuff (reviewing patches, CVS checkins, running
tests, corralling help for doc & code, maintaining release notes, building
installers, etc.), but that the important decisions (e.g. whether to add a
feature to the core language) would be checked with G__do first.  We could
call the position "Administrative Assistant", but somehow that doesn't have
the prestige.

A progressive schedule where Guido watches over the Oracle periodically
would probably help build trust in the new mechanism.  The Oracle would be
expected to ask Guido for his opinion with everything at the beginning, and
as a trust builds between Guido and the Oracle and the community and the
mechanism, progressively less.

--david ascher




From gstein at lyra.org  Thu Jan 20 19:30:52 2000
From: gstein at lyra.org (Greg Stein)
Date: Thu, 20 Jan 2000 10:30:52 -0800 (PST)
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <200001201740.MAA21608@eric.cnri.reston.va.us>
Message-ID: <Pine.LNX.4.10.10001200950260.13911-100000@nebula.lyra.org>

On Thu, 20 Jan 2000, Guido van Rossum wrote:
>...
> In other words, I'm for putting distutils in the next release,
> essentially feature-freezing it.  Greg Ward, what do you think of
> that?

Oh, don't get me wrong. I'd like to see it in there for at least all the
reasons you cite. But it seems (to me) that it is still pretty alpha. But
hey: I'm shooting from the peanut gallery; we need GregW's comments.

> > Note that if an announcement were made to the effect of "feature freeze on
> > February 15; only bug fixes afterwards," that you would get a lot of
> > people scrambling to submit their pet features. This would be a good way
> > to light some fires, to see what kinds of things get completed (i.e. we
> > may think some things aren't ready or are too far out, put that deadline
> > in and those positions could change...)
> 
> I bet you we couldn't complete the import hooks by that date; I
> consider imputil.py as a nice prototype, but the integration with the
> C code is still missing.  Also the 50% slowdown is a problem I worry
> about for inclusion a production version.  (Plus breakage of everybody
> else's code who uses or hacks __import__; e.g. have you tested it with
> rexec?)

hehe... if the static typing is to be deferred, then I'll take that bet!

[discussion omitted; too tangental to this thread right now...]

>...
> Good questions.  I have to say that I feel reluctant to release any
> kind of control -- yet at the same time I desperately need help
> getting trivial stuff checked in.

Reading your comments below, we may be able to help.

First, presume that at least one (best would be several) people man the
"front lines" for any/all patches and bug reports. The front line can deal
with the bug reports, mostly by responding with "go away; enter it into
Jitterbug."

Patches fall under several catagories, detailed below:

> One of the most important
> time-consuming tasks is quality control: collecting fixes is all well
> and good, but I routinely reject fixes that superficially look fine,

Conversely, your "lieutenants" (LTs) would filter all ugly-looking
patches.

> because they are subtly broken,

If the LTs didn't catch these, then you could catch them from the checkin
diff email. However, the LTs would reduce the number of broken ones that
you would review.

> or interfere with other plans,

The LTs may know of this, but if not: you'd catch it at checkin time. The
patches would then be backed out, altered, or whatever.

> or just
> because the code looks poorly written.

The LTs would definitely catch this. If the style was *still* not up to
snuff, I'd have to believe it would only be in minor ways that you could
then touch up at your leisure.

> I also spend a lot of testing
> before I check things in;

Done by the LTs.

> running the standard test suite is a good
> safeguard against general breakage,

Ditto.

> but you really have to play with
> the code affected by the change before you can know that it works as
> advertised.

Ditto.

> My work attitude here means that what gets checked in is
> generally rock solid, and that helps Python's reputation; but it is
> very costly...

Based on my responses, I would venture to state that a group of LTs would
manage to keep the Python core rock solid, except for:

1) subtle breakages that require your broader knowledge of Python
2) changes that "go against the plan" (and the LTs were ignorant of it)
3) minor format issues

You would still review checkins, but the number of reviews would drop
since the (obvious) crap has been eliminated. #1 is based on your *broad*
knowledge of Python; I presume the LTs would be your match on various
subsets of Python. By keeping the LTs well-informed, #2 could be nearly
eliminated. #3 isn't that big of a deal, as I think your desired style is
relatively well-known and the LTs would simply endeavor to match existing
style.

You could avoid a lot of testing; you would probably be inclined to do
testing of items that you find dubious, but still this would be a
reduction.

=====

That may be an answer to the checkin problem. How about actual snapshots,
alphas, betas, releases, and accompanying notes/news/readme files? I
presume your LTs could run the alpha and beta aspects, but you would still
issue final releases.

Does your mail volume need to be reduced? (I think this has been asked
before) Specifically, would patches at python.org (and similar targets) need
to be established? (I would think so, as a matter of course, with the
expectation that some patches would still end up with you and need to be
bounced to patches@)

Cheers,
-g

-- 
Greg Stein, http://www.lyra.org/




From klm at digicool.com  Thu Jan 20 19:31:52 2000
From: klm at digicool.com (Ken Manheimer)
Date: Thu, 20 Jan 2000 13:31:52 -0500 (EST)
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <000701bf636f$de37c5e0$c355cfc0@ski.org>
Message-ID: <Pine.LNX.4.10.10001201321300.21609-100000@splat.digicool.com>

I must have missed the historic landmark where "pumpkin" was coined, but i
think i get the gist.  How about "Python Marshall" or "Python Activity
Marshall" (a la the PS_A_)?

Ken

David Ascher wrote:

> [...]
> Regardless, just like Greg, I'd like to know what a pumpkin-holder would
> mean in the Python world.
> 
> I propose that it be called the Oracle instead.  As in, whoever is Oracle
> would get some training with Tim Peters and learn how to channel G__do.  As
> a Python user, I'd be most comfortable with such a change if the Oracle just
> took over the technical stuff (reviewing patches, CVS checkins, running
> tests, corralling help for doc & code, maintaining release notes, building
> installers, etc.), but that the important decisions (e.g. whether to add a
> feature to the core language) would be checked with G__do first.  We could
> call the position "Administrative Assistant", but somehow that doesn't have
> the prestige.
> 
> A progressive schedule where Guido watches over the Oracle periodically
> would probably help build trust in the new mechanism.  The Oracle would be
> expected to ask Guido for his opinion with everything at the beginning, and
> as a trust builds between Guido and the Oracle and the community and the
> mechanism, progressively less.




From gstein at lyra.org  Thu Jan 20 19:42:43 2000
From: gstein at lyra.org (Greg Stein)
Date: Thu, 20 Jan 2000 10:42:43 -0800 (PST)
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <Pine.LNX.4.10.10001201321300.21609-100000@splat.digicool.com>
Message-ID: <Pine.LNX.4.10.10001201039320.13911-100000@nebula.lyra.org>

On Thu, 20 Jan 2000, Ken Manheimer wrote:
> I must have missed the historic landmark where "pumpkin" was coined, but i
> think i get the gist.  How about "Python Marshall" or "Python Activity
> Marshall" (a la the PS_A_)?

The "pumpkin" term comes from Perl-land...

I'm not super clear on the pumpkin-holders's entire job, but I think it is
basically the guy who sees that the version for which he "holds the
pumpkin" is completed and shipped. Not necessarily by himself :-), but as
the overseer (or "release manager" if you will).

The current Perl pumpkin-holder is a guy at ActiveState. I think it
changes for each version.

Cheers,
-g

-- 
Greg Stein, http://www.lyra.org/




From gvwilson at nevex.com  Thu Jan 20 19:51:17 2000
From: gvwilson at nevex.com (gvwilson at nevex.com)
Date: Thu, 20 Jan 2000 13:51:17 -0500 (EST)
Subject: [Python-Dev] Python 1.6 timing (fwd)
Message-ID: <Pine.LNX.4.10.10001201346510.7719-100000@akbar.nevex.com>

Guido> There are several other things I can think of now that were
Guido> planned for 1.6: revamped import, rich comparisons, revised
Guido> coercions, parallel for loop (for i in L; j in M: ...),
Guido> extended slicing for all sequences.  I've also been thinking
Guido> about making classes be types (not as huge a change as you
Guido> think, if you don't allow subclassing built-in types), and
Guido> adding a built-in array type suitable for use by NumPy.  I've
Guido> also received a conservative GC patch that seems to be fairly
Guido> easy to apply and has some of Tim Peters' blessing.

BAW> All very cool things that could easily wait until 1.7.  After
BAW> all, what's in a number?

GVW writes:

I agree on all counts except garbage collection --- I'm half-way through
the second day of the Python class I teach at Los Alamos (the people who
are funding the Python tool design competition), and it's come up a couple
of times.  People want to be able to prototype meshes, throw callbacks
around without worrying about circularity, and some other things that I
don't really understand yet.  There's also a couple of smart guys in the
class who are wondering about CPython vs. JPython ("So this'll be safe in
one version of the language, but not in the other?"), and about marketing
("Help me win a feature comparison against Java in my group...").

There's also been questions about tighter integration of NumPy (e.g.
overloading operators rather than calling 'greater()' to do comparison),
but I think that's a separate discussion...

My $0.02,
Greg




From tismer at tismer.com  Thu Jan 20 20:11:13 2000
From: tismer at tismer.com (Christian Tismer)
Date: Thu, 20 Jan 2000 20:11:13 +0100
Subject: [Python-Dev] Python 1.6 timing (fwd)
References: <Pine.LNX.4.10.10001201346510.7719-100000@akbar.nevex.com>
Message-ID: <38875DD1.B6596@tismer.com>

[garbage collection]

gvwilson at nevex.com wrote:

> I agree on all counts except garbage collection --- I'm half-way through
> the second day of the Python class I teach at Los Alamos (the people who
> are funding the Python tool design competition), and it's come up a couple
> of times.  People want to be able to prototype meshes, throw callbacks
> around without worrying about circularity, and some other things that I
> don't really understand yet.  There's also a couple of smart guys in the
> class who are wondering about CPython vs. JPython ("So this'll be safe in
> one version of the language, but not in the other?"), and about marketing
> ("Help me win a feature comparison against Java in my group...").

Guido once posted some proposal of a hybrid system *with* refcounts
and some additional garbage collection scheme to match circular
things. I believe this is a much better approach than what Java
and therefor also JPython does at the moment.

Although people might argue differently, I'm pretty sure that
reference counting is the stronger concept. By reference counting,
the idea of object ownership can be made explicit. This plays a
central role in the Corba specification for instance, and I made
the same observation when implementing continuations for Stackless
Python. Refcounts are no burden but a virtue.
Even better: Refcounting can lead to many new optimizations if
we pay the cost to make INCREF/DECREF into methods. It has its cost
(about 10 percent less pystones), but massive long-term benefits.

I'm currently in charge to develop a custom version of Python's
builtin types where this concept is used. Everything is refcounted,
but without storing the refcounts in the objects. This is possible
(proven) and will be shown in my next paper.

Conclusion: I vote for a kind of GC that does just what refcounts
cannot do, but please keep with the refcounts.

cheers - chris

-- 
Christian Tismer             :^)   <mailto:tismer at appliedbiometrics.com>
Virtual Photonics GmbH       :     Have a break! Take a ride on Python's
Carnotstr. 6                 :    *Starship* http://starship.python.net
10587 Berlin                 :     PGP key -> http://wwwkeys.pgp.net
PGP Fingerprint       E182 71C7 1A9D 66E9 9D15  D3CC D4D7 93E2 1FAE F6DF
     we're tired of banana software - shipped green, ripens at home



From tim_one at email.msn.com  Thu Jan 20 20:47:01 2000
From: tim_one at email.msn.com (Tim Peters)
Date: Thu, 20 Jan 2000 14:47:01 -0500
Subject: [Python-Dev] Changing existing class instances
In-Reply-To: <200001201520.KAA21137@eric.cnri.reston.va.us>
Message-ID: <000301bf637f$1f1c2d80$b72d153f@tim>

[Tim worries about stomping on unintended classes/defs]

[Guido]
> Agreed that that would be bad.  But I wouldn't search outer
> scopes -- I would only look for a class/def that I was about
> to stomp on.

Maybe I just don't grasp what that means, exactly.  Fair enough, since I'm
not expressing myself clearly either!

Suppose someone does

from Tkinter import *

in my.py, and later in my.py just *happens* to define, at module level,

class Misc:
    blah blah blah

Now Misc was already in my.py's global namespace because Tkinter.py just
happens to export a class of that name too (more by accident than design --
but accidents are what I'm most worried about here).

At the time my.py defines Misc, does Misc count as a class we're "about to
stomp on"?  If so-- & I've assumed so --it would wreak havoc.

But if not, I don't see how this case can be reliably distinguished "by
magic" from the cases where update is desired (if people are doing dynamic
updates to a long-running program, a new version of a class can come from
anywhere, so nothing like original file name or line number can distinguish
correctly either).

>> Modules differ because their namespace "search path"
>> consists solely of the more-global-than-global <wink>
>> sys.modules.

> "The search path doesn't enter into it."

I agree, but am at a loss to describe what's happening in the case above
using other terminology <wink>.  In a sense, you need a system-wide "unique
handle" to support bulletproof updating, and while sys.modules has supplied
that all along for module objects (in the form of the module name), I don't
believe there's anything analogous to key off of for function or class
objects.

>>    [suggesting]
>>    new.update(class_or_def_old, class_or_def_new)

> Only a slight semantics change (which my full proposal
> would require too): function objects would become mutable
> -- their func_code, func_defaults, func_doc and func_globals
> fields (and, why not, func_name too) should be changeable.

Of course I meant "no new semantics" in the sense of "won't cause current
exception-free code to alter behavior in any way".

> If you make all these assignable, it doesn't even have to
> be a privileged function.

I'm all for that!

> [sketching a Python approach to "updating import/reload"
>  building on the hypothetical new.update]

> That's certainly a reasonable compromise.  Note that the
> update on a class should imply an update on its methods,
> right?

Hadn't considered that!  Of course you're right.  So make it a pair of
nested loops <wink>.

so-long-as-it-can-be-written-in-python-it's-easy-ly
    y'rs  - tim





From guido at CNRI.Reston.VA.US  Thu Jan 20 21:02:20 2000
From: guido at CNRI.Reston.VA.US (Guido van Rossum)
Date: Thu, 20 Jan 2000 15:02:20 -0500
Subject: [Python-Dev] Changing existing class instances
In-Reply-To: Your message of "Thu, 20 Jan 2000 14:47:01 EST."
             <000301bf637f$1f1c2d80$b72d153f@tim> 
References: <000301bf637f$1f1c2d80$b72d153f@tim> 
Message-ID: <200001202002.PAA22435@eric.cnri.reston.va.us>

> [Tim worries about stomping on unintended classes/defs]
> 
> [Guido]
> > Agreed that that would be bad.  But I wouldn't search outer
> > scopes -- I would only look for a class/def that I was about
> > to stomp on.
> 
> Maybe I just don't grasp what that means, exactly.  Fair enough, since I'm
> not expressing myself clearly either!
> 
> Suppose someone does
> 
> from Tkinter import *
> 
> in my.py, and later in my.py just *happens* to define, at module level,
> 
> class Misc:
>     blah blah blah
> 
> Now Misc was already in my.py's global namespace because Tkinter.py just
> happens to export a class of that name too (more by accident than design --
> but accidents are what I'm most worried about here).

For a second I thought you got me there!

> At the time my.py defines Misc, does Misc count as a class we're "about to
> stomp on"?  If so-- & I've assumed so --it would wreak havoc.
> 
> But if not, I don't see how this case can be reliably distinguished "by
> magic" from the cases where update is desired (if people are doing dynamic
> updates to a long-running program, a new version of a class can come from
> anywhere, so nothing like original file name or line number can distinguish
> correctly either).

Fortunately, there's magic available: recently, all classes have a
__module__ attribute that is set to the full name of the module that
defined it (its key in __sys__.modules).

For functions, we would have to invent something similar.

> >> Modules differ because their namespace "search path"
> >> consists solely of the more-global-than-global <wink>
> >> sys.modules.
> 
> > "The search path doesn't enter into it."
> 
> I agree, but am at a loss to describe what's happening in the case above
> using other terminology <wink>.  In a sense, you need a system-wide "unique
> handle" to support bulletproof updating, and while sys.modules has supplied
> that all along for module objects (in the form of the module name), I don't
> believe there's anything analogous to key off of for function or class
> objects.
> 
> >>    [suggesting]
> >>    new.update(class_or_def_old, class_or_def_new)
> 
> > Only a slight semantics change (which my full proposal
> > would require too): function objects would become mutable
> > -- their func_code, func_defaults, func_doc and func_globals
> > fields (and, why not, func_name too) should be changeable.
> 
> Of course I meant "no new semantics" in the sense of "won't cause current
> exception-free code to alter behavior in any way".
> 
> > If you make all these assignable, it doesn't even have to
> > be a privileged function.
> 
> I'm all for that!
> 
> > [sketching a Python approach to "updating import/reload"
> >  building on the hypothetical new.update]
> 
> > That's certainly a reasonable compromise.  Note that the
> > update on a class should imply an update on its methods,
> > right?
> 
> Hadn't considered that!  Of course you're right.  So make it a pair of
> nested loops <wink>.
> 
> so-long-as-it-can-be-written-in-python-it's-easy-ly
>     y'rs  - tim

--Guido van Rossum (home page: http://www.python.org/~guido/)



From guido at CNRI.Reston.VA.US  Thu Jan 20 21:12:58 2000
From: guido at CNRI.Reston.VA.US (Guido van Rossum)
Date: Thu, 20 Jan 2000 15:12:58 -0500
Subject: [Python-Dev] Python 1.6 timing (fwd)
In-Reply-To: Your message of "Thu, 20 Jan 2000 20:11:13 +0100."
             <38875DD1.B6596@tismer.com> 
References: <Pine.LNX.4.10.10001201346510.7719-100000@akbar.nevex.com>  
            <38875DD1.B6596@tismer.com> 
Message-ID: <200001202012.PAA22501@eric.cnri.reston.va.us>

> Conclusion: I vote for a kind of GC that does just what refcounts
> cannot do, but please keep with the refcounts.

The patch that I received and that has Tim's <0.5 blessing> does just
that.  I haven't had the time to understand why it doesn't have his
<1.0 blessing>.

--Guido van Rossum (home page: http://www.python.org/~guido/)



From tim_one at email.msn.com  Thu Jan 20 21:35:44 2000
From: tim_one at email.msn.com (Tim Peters)
Date: Thu, 20 Jan 2000 15:35:44 -0500
Subject: [Python-Dev] Python 1.6 timing (fwd)
In-Reply-To: <200001202012.PAA22501@eric.cnri.reston.va.us>
Message-ID: <000901bf6385$eccfba20$b72d153f@tim>

[Christian]
> Conclusion: I vote for a kind of GC that does just
> what refcounts cannot do, but please keep with the
> refcounts.

[Guido]
> The patch that I received and that has Tim's <0.5
> blessing> does just that. I haven't had the time to
> understand why it doesn't have his <1.0 blessing>.

Primarily because it doesn't reclaim the most common cycles; e.g., cycles
among class instances aren't touched.  This seems easily repairable, but at
an unknown cost (it needs to do the "reachability" transitive closure
business from the set of all "suspicious" objects, and instances are never
considered suspicious now; adding them will certainly cause a lot more
pointer chasing).

Apart from that, the code appears unreasonably expensive as written today,
using e.g. splay trees instead of hash tables to keep track of objects.

The author hasn't said anything more in a bit over two weeks, so I suspect
he's off on other things now.  The technical approach is sound, but even its
inventor (Rafael Lins; Toby Kelsey may have reinvented it on his own,
though) stresses that getting it to run fast is difficult.

needs-work!-ly y'rs  - tim, who hasn't the time to do it





From tismer at tismer.com  Thu Jan 20 21:35:27 2000
From: tismer at tismer.com (Christian Tismer)
Date: Thu, 20 Jan 2000 21:35:27 +0100
Subject: [Python-Dev] Stackless Python 1.0 + Continuations 0.6
Message-ID: <3887718F.82E1B327@tismer.com>

ANNOUNCING:

               Stackless Python 1.0
           A Python Implementation That
             Does Not Use The C Stack

               * plus the real toy *

              Continuation Module 0.6
        Continuations as First Class Objects

What is it?
A plugin-replacement for core Python.
It should run any program which runs under Python 1.5.2 .
But it does not need space on the C stack.

Why did I write it?
Stackless Python was never written before (afaik), since it
was said to be impossible without major rewrites of core Python.
I have proven the controverse: It is easy to write, just hard to think.
About 3 times harder was finally the continuation module.
The whole project took about 6 man months where 80 percent of
the time was thinking and trying. The rest was coding and to
become a reference counting champion :-)

Recent changes:
Version 1.0 has been optimized like hell and is now
3-5 percent faster than Standard Python.

Continuation module is in version 0.6, very stable,
and it allows to save a program's "future" at any
time, in a portable way. Continuations are callable
Python objects with a very small footprint.

Who needs it?
Since the continuations are done, this is no more
only useful for C programmers who want to try certain new
ideas. Everybody who is interested to develop his
own generators, coroutines and tiny threads is
invited to check it out.

Status of the final 1.0:
Pystone works correctly and is 5% faster than standard
Python. Version 0.3 was 10 percent slower.
Continuations work with PythonWin and Idle.

The overall result is now better than expected,
and I'm happy to call this *FINAL*
(until the next version of course:)

Downloadable files can be found at
http://www.tismer.com/research/stackless/

Some older documentation:
http://www.tismer.com/research/stackless/stackless.htm

Some better documentation can be found in my IPC8 paper:
http://www.tismer.com/research/stackless/spc_final.zip
or be read directly as HTML
http://www.tismer.com/research/stackless/spcpaper.htm

Source code and a VC++6.0 build for Windows (340K):
http://www.tismer.com/research/stackless/spc_win32.zip

cheers - chris

== 
Christian Tismer             :^)   <mailto:tismer at appliedbiometrics.com>
Applied Biometrics GmbH      :     Have a break! Take a ride on Python's
Kaiserin-Augusta-Allee 101   :    *Starship* http://starship.python.net
10553 Berlin                 :     PGP key -> http://wwwkeys.pgp.net
PGP Fingerprint       E182 71C7 1A9D 66E9 9D15  D3CC D4D7 93E2 1FAE F6DF
     we're tired of banana software - shipped green, ripens at home

<P><A HREF="http://www.tismer.com/research/stackless/stackless.htm">
Stackless Python 1.0</A>
 - a version of Python 1.5.2 that does not need space on the C
stack.  (20-Jan-00)



From bwarsaw at cnri.reston.va.us  Thu Jan 20 22:12:37 2000
From: bwarsaw at cnri.reston.va.us (Barry A. Warsaw)
Date: Thu, 20 Jan 2000 16:12:37 -0500 (EST)
Subject: [Python-Dev] Python 1.6 timing
References: <Pine.LNX.4.10.10001201321300.21609-100000@splat.digicool.com>
	<Pine.LNX.4.10.10001201039320.13911-100000@nebula.lyra.org>
Message-ID: <14471.31301.504670.201702@anthem.cnri.reston.va.us>

We'd have to rework the CVS arrangement in order to give non-CNRI
employees write access to the tree.  I think I know how I'd go about
this, and it wouldn't be too hard, just a bit time-consuming.  If
that's the way we're going to go, I can start making plans.

-Barry



From guido at CNRI.Reston.VA.US  Thu Jan 20 22:16:39 2000
From: guido at CNRI.Reston.VA.US (Guido van Rossum)
Date: Thu, 20 Jan 2000 16:16:39 -0500
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: Your message of "Thu, 20 Jan 2000 16:12:37 EST."
             <14471.31301.504670.201702@anthem.cnri.reston.va.us> 
References: <Pine.LNX.4.10.10001201321300.21609-100000@splat.digicool.com> <Pine.LNX.4.10.10001201039320.13911-100000@nebula.lyra.org>  
            <14471.31301.504670.201702@anthem.cnri.reston.va.us> 
Message-ID: <200001202116.QAA22943@eric.cnri.reston.va.us>

[Barry]
> We'd have to rework the CVS arrangement in order to give non-CNRI
> employees write access to the tree.  I think I know how I'd go about
> this, and it wouldn't be too hard, just a bit time-consuming.  If
> that's the way we're going to go, I can start making plans.

I think before you make such changes you'd have to talk to Bob (good
luck).

I don't mind applying patches and doing the checkins -- it's the
decision-making that's time-consuming.

--Guido van Rossum (home page: http://www.python.org/~guido/)



From da at ski.org  Thu Jan 20 22:28:24 2000
From: da at ski.org (David Ascher)
Date: Thu, 20 Jan 2000 13:28:24 -0800
Subject: [Python-Dev] Python 1.6 timing (fwd)
In-Reply-To: <Pine.LNX.4.10.10001201346510.7719-100000@akbar.nevex.com>
Message-ID: <001401bf638d$486488f0$c355cfc0@ski.org>

Daddy Warbucks (uh, Greg Wilson =):

> There's also been questions about tighter integration of NumPy (e.g.
> overloading operators rather than calling 'greater()' to do comparison),
> but I think that's a separate discussion...

That's the rich comparison proposal which Guido mentioned.

--david



From bwarsaw at cnri.reston.va.us  Thu Jan 20 22:30:24 2000
From: bwarsaw at cnri.reston.va.us (Barry A. Warsaw)
Date: Thu, 20 Jan 2000 16:30:24 -0500 (EST)
Subject: [Python-Dev] Python 1.6 timing
References: <Pine.LNX.4.10.10001201321300.21609-100000@splat.digicool.com>
	<Pine.LNX.4.10.10001201039320.13911-100000@nebula.lyra.org>
	<14471.31301.504670.201702@anthem.cnri.reston.va.us>
	<200001202116.QAA22943@eric.cnri.reston.va.us>
Message-ID: <14471.32368.730988.252872@anthem.cnri.reston.va.us>

>>>>> "Guido" == Guido van Rossum <guido at cnri.reston.va.us> writes:

    Guido> I think before you make such changes you'd have to talk to
    Guido> Bob (good luck).

Heh.

    Guido> I don't mind applying patches and doing the checkins --
    Guido> it's the decision-making that's time-consuming.

Then maybe the current CVS arrangement is fine (cool with me).

-Barry



From klm at digicool.com  Thu Jan 20 23:08:28 2000
From: klm at digicool.com (Ken Manheimer)
Date: Thu, 20 Jan 2000 17:08:28 -0500 (EST)
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <14471.31301.504670.201702@anthem.cnri.reston.va.us>
Message-ID: <Pine.LNX.4.10.10001201646500.22921-100000@splat.digicool.com>

On Thu, 20 Jan 2000, Barry A. Warsaw wrote:

> We'd have to rework the CVS arrangement in order to give non-CNRI
> employees write access to the tree.  I think I know how I'd go about
> this, and it wouldn't be too hard, just a bit time-consuming.  If
> that's the way we're going to go, I can start making plans.

Though it may be moot if guido's going to continue mediating the checkins,
maybe this would be interesting (if only for barry, to compare
procedures). 

We basically use a captive cvs-":ext:"-over-ssh method, where the captive
.ssh/authorized_keys command is quite succinct:

command="set $SSH_ORIGINAL_COMMAND; shift; exec cvs $@" 1024 35 ...

The shellisms (set/shift/exec cvs $@) lock the user of the qualifying key
into executing a cvs command, and only a cvs command.

Also, for us the checkins are to a public mirror of our CVS repository, so
penetration of the security there doesn't jepordize the master repository
base.  We don't currently have any outsiders checking into our master
repository, and it doesn't seem to me that CVS provides sufficiently
managable discretion for doing that.

Oh, and a disappointment - the account under which cvs conducts the
checkins is the account on the CVS server host, not that of the host where
the checkins are being done.  This means that you can't use a single
account to serve multiple remote users (preventing masquerading quite
reliably by using a separate authorized_key public-key entry for each
remote user).  Therefore we have to have distinct (nailed-down) accounts
for each checkin-privileged person - more management burden.

Ken




From tim_one at email.msn.com  Fri Jan 21 00:53:18 2000
From: tim_one at email.msn.com (Tim Peters)
Date: Thu, 20 Jan 2000 18:53:18 -0500
Subject: [Python-Dev] Python 1.6 timing (fwd)
In-Reply-To: <001401bf638d$486488f0$c355cfc0@ski.org>
Message-ID: <000201bf63a1$8641b1c0$6ea0143f@tim>

[Greg Wilson]
> There's also been questions about tighter integration
> of NumPy (e.g. overloading operators rather than
> calling 'greater()' to do comparison), but I think
? that's a separate discussion...

[David Ascher]
> That's the rich comparison proposal which Guido mentioned.

But there's also been talk about moving (at least) the basic NumPy array
type into the core.  This would be a Good Thing.  Speaking for my employer,
however, only Unicode is an Important Thing <wink>.

As a developer, I have railed against schedule-driven release cycles.
Python tends toward the opposite end of that spectrum, driven by features no
matter how bloody long they take.  Add Unicode to what's already waiting to
go, and that's *good enough* reason for a major release; heck, it's been 9
months & we haven't even had a  1.5.2 bugfix patch.

BTW, do the Perl-Porters have real jobs?

pay-me-to-do-python-releases-and-you'll-get-a-major-new-
    release-every-three-days<wink>-ly y'rs  - tim





From da at ski.org  Fri Jan 21 01:01:45 2000
From: da at ski.org (David Ascher)
Date: Thu, 20 Jan 2000 16:01:45 -0800
Subject: [Python-Dev] Python 1.6 timing (fwd)
In-Reply-To: <000201bf63a1$8641b1c0$6ea0143f@tim>
Message-ID: <002601bf63a2$b4acf9b0$c355cfc0@ski.org>

Tim Peters

> But there's also been talk about moving (at least) the basic NumPy array
> type into the core.  This would be a Good Thing.

IMNSHO, moving the current NumPy array into the core would be a Bad Thing.
Moving a new similar object with cleaned up semantics and better
implementation in would be a Good Thing.  But it won't happen until 1.7 at
the earliest, as the semantics haven't even been agreed on, let alone the
code written.

--david




From da at ski.org  Fri Jan 21 01:07:16 2000
From: da at ski.org (David Ascher)
Date: Thu, 20 Jan 2000 16:07:16 -0800
Subject: [Python-Dev] Conference Schedules
Message-ID: <002701bf63a3$79a15ae0$c355cfc0@ski.org>

Given the rush of interesting discussions and progress which occurs in the
two weeks before Python conferences, I propose that we have a bi-weekly
conference.  We'll just have to remember to cancel them at the last minute
except a couple of times a year.

--david ascher
-------------- next part --------------
A non-text attachment was scrubbed...
Name: David Ascher.vcf
Type: text/x-vcard
Size: 527 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/python-dev/attachments/20000120/3b692d76/attachment-0001.vcf>

From gstein at lyra.org  Fri Jan 21 01:53:59 2000
From: gstein at lyra.org (Greg Stein)
Date: Thu, 20 Jan 2000 16:53:59 -0800 (PST)
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <14471.31301.504670.201702@anthem.cnri.reston.va.us>
Message-ID: <Pine.LNX.4.10.10001201653130.13911-100000@nebula.lyra.org>

On Thu, 20 Jan 2000, Barry A. Warsaw wrote:
> We'd have to rework the CVS arrangement in order to give non-CNRI
> employees write access to the tree.  I think I know how I'd go about
> this, and it wouldn't be too hard, just a bit time-consuming.  If
> that's the way we're going to go, I can start making plans.

Or move the CVS tree off-site.

Cheers,
-g

-- 
Greg Stein, http://www.lyra.org/




From guido at CNRI.Reston.VA.US  Fri Jan 21 02:29:30 2000
From: guido at CNRI.Reston.VA.US (Guido van Rossum)
Date: Thu, 20 Jan 2000 20:29:30 -0500
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: Your message of "Thu, 20 Jan 2000 10:30:52 PST."
             <Pine.LNX.4.10.10001200950260.13911-100000@nebula.lyra.org> 
References: <Pine.LNX.4.10.10001200950260.13911-100000@nebula.lyra.org> 
Message-ID: <200001210129.UAA28292@eric.cnri.reston.va.us>

(I accidentally mailed this only to Greg; here's a repost of the
relevant parts to the list:)

[me]
> > Good questions.  I have to say that I feel reluctant to release any
> > kind of control -- yet at the same time I desperately need help
> > getting trivial stuff checked in.

[Greg Stein]
> Reading your comments below, we may be able to help.

[...Proposal of lieutenants condensed...]

> Based on my responses, I would venture to state that a group of LTs would
> manage to keep the Python core rock solid, except for:
> 
> 1) subtle breakages that require your broader knowledge of Python
> 2) changes that "go against the plan" (and the LTs were ignorant of it)
> 3) minor format issues
> 
> You would still review checkins, but the number of reviews would drop
> since the (obvious) crap has been eliminated. #1 is based on your *broad*
> knowledge of Python; I presume the LTs would be your match on various
> subsets of Python. By keeping the LTs well-informed, #2 could be nearly
> eliminated. #3 isn't that big of a deal, as I think your desired style is
> relatively well-known and the LTs would simply endeavor to match existing
> style.
> 
> You could avoid a lot of testing; you would probably be inclined to do
> testing of items that you find dubious, but still this would be a
> reduction.
> 
> =====
> 
> That may be an answer to the checkin problem. How about actual snapshots,
> alphas, betas, releases, and accompanying notes/news/readme files? I
> presume your LTs could run the alpha and beta aspects, but you would still
> issue final releases.

There's a lot of work in these (you may have noticed that the release
notes got sloppier as 1.5.2 neared its completion).

I would be happy to have the responsibility to decide to release
without the burden of having to do all the work.

> Does your mail volume need to be reduced? (I think this has been asked
> before) Specifically, would patches at python.org (and similar targets) need
> to be established? (I would think so, as a matter of course, with the
> expectation that some patches would still end up with you and need to be
> bounced to patches@)

It's not the mail volume that bothers me -- I can ignore 100s of
messages a day very quickly.  It's the time it takes to respond to all
of them.


As an experiment, I've collected about 40 messages with suggested
patches in them that I found in my inbox; the oldest are nearly two
years old.

You can access these from this address:

http://www.python.org/~guido/patch/

I would love any help I could get in responding with these, and taking
action in the form of patches.  I propose that if you decide that a
particular patch is worth checking in, you ask the author for the
bugrelease or wetsign disclaimer and let me know that I can check it
in; if changes to the patch are needed, I propose that you negotiate
these with the author first.  (I often ask them to test my version of
a patch when I have style suggestions but don't have access the target
platform or problem it solves.)

--Guido van Rossum (home page: http://www.python.org/~guido/)



From tim_one at email.msn.com  Fri Jan 21 10:38:21 2000
From: tim_one at email.msn.com (Tim Peters)
Date: Fri, 21 Jan 2000 04:38:21 -0500
Subject: [Python-Dev] Changing existing class instances
In-Reply-To: <Pine.LNX.4.10.10001192342450.13911-100000@nebula.lyra.org>
Message-ID: <001801bf63f3$414e0c60$ec2d153f@tim>

[Greg Stein]
> ...
> In other words, I definitely would support a new class
> object behavior that allows us to update a class' set of
> bases and dictionary on the fly.  This could then be used
> to support my solution for the recursive type scenario (which,
> in turn, means that we don't have to introduce Yet Another
> Namespace into Python to hold type names).

Parenthetically, I never grasped the appeal of the parenthetical comment.
Yet Another Namespace for Yet Another Entirely New Purpose seems highly
*desirable* to me!  Trying to overload the current namespace set makes it so
much harder to see that these are compile-time gimmicks, and users need to
be acutely aware of that if they're to use it effectively.  Note that I
understand (& wholly agree with) the need for runtime introspection.

different-things-different-rules-ly y'rs  - tim





From tim_one at email.msn.com  Fri Jan 21 10:38:24 2000
From: tim_one at email.msn.com (Tim Peters)
Date: Fri, 21 Jan 2000 04:38:24 -0500
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <20000120113352.A23763@trump.amber.org>
Message-ID: <001901bf63f3$432404e0$ec2d153f@tim>

[Christopher Petrilli]
> Heck, Python is infinately more conservative in its
> numbering than a lot of projects.  All that was mentioned
> would normally be enough to call it 2.0 easily. :-)  Modesty
> can be counter productive in PR  business...

Indeed, where I work a number of managers met the suggestion to use Python
1.5.x with "what?! we don't want to use software that's barely out of alpha
release -- besides, Perl is already on release 5".  I hear that Guido got
normal American glasses -- time to do normal American hyperinflated version
numbering too.

heck-ms-windows-will-soon-be-at-version-2000<wink>-ly y'rs  - tim





From tim_one at email.msn.com  Fri Jan 21 10:38:26 2000
From: tim_one at email.msn.com (Tim Peters)
Date: Fri, 21 Jan 2000 04:38:26 -0500
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <14471.14877.434886.471929@amarok.cnri.reston.va.us>
Message-ID: <001a01bf63f3$4473b660$ec2d153f@tim>

[Andrew M. Kuchling]
> ...
> Similarly, does the conservative GC patch splatter changes
> all over the place, or is it very localized?

Part of its problem is that it's *too* localized (which was, paradoxically,
I suspect part of its initial quick-eyeball appeal to Guido -- it "looks
like" an amazingly self-contained patch).  For example, all the code to
chase pointers in various types of objects is hiding in a single function,
which does a string of "if type is list then this else if type is tuple then
that ..." tests.  This stuff clearly needs to be distributed across the
object implementations and dispatched to via a new slot in type objects;
there's no code for that now.

I expect it would take a minimum of two weeks (full-time work) to make this
code ready for prime time (but mostly to slash the space and time use -- and
with no certainty of "good enough" in the end).

BTW, "conservative" is a misleading adjective for this approach -- it never
guesses ("guessing on the safe side" whether or not some bit pattern is a
pointer is what "conservative" customarily means in the GC world).

> Is adding the NumPy array type straightforward?

DavidA nixed that one in no uncertain terms!

maybe-hp-will-give-up-unicode-and-we-can-release-tomorrow-ly
    y'rs  - tim





From tim_one at email.msn.com  Fri Jan 21 10:52:13 2000
From: tim_one at email.msn.com (Tim Peters)
Date: Fri, 21 Jan 2000 04:52:13 -0500
Subject: [Python-Dev] Python 1.6 timing (fwd)
In-Reply-To: <Pine.LNX.4.10.10001201346510.7719-100000@akbar.nevex.com>
Message-ID: <001d01bf63f5$318e2600$ec2d153f@tim>

[Greg Wilson]
> ...
> There's also a couple of smart guys in the class who are
> wondering about CPython vs. JPython ("So this'll be safe in
> one version of the language, but not in the other?"),

Greg, people who have been exposed to Fortran (this is LANL, right <wink>?)
can't possibly have a problem with the concept of "not defined by the
standard".  Don't sell these as different *versions* of the language, but as
different implementations.  That's what they are.  The Python *language*
doesn't define anything about the lifetime of objects.  Even when CPython
grows "real GC", thanks to refcounting too you'll still be able to *rely* on
behaviors in CPython you'll see only accidentally in JPython.  You do so at
your own risk, same as e.g. you rely on floating point Fortran x+y+z getting
evaluated "left to right" at your own risk (BTW, x+y+z *is* "left to right"
in Python -- maybe they'll trade that for the lack of GC promises <wink>).





From tim_one at email.msn.com  Fri Jan 21 11:22:51 2000
From: tim_one at email.msn.com (Tim Peters)
Date: Fri, 21 Jan 2000 05:22:51 -0500
Subject: [Python-Dev] Changing existing class instances
In-Reply-To: <200001202002.PAA22435@eric.cnri.reston.va.us>
Message-ID: <001e01bf63f9$79660980$ec2d153f@tim>

[Tim, still worried about stomping on unintended classes/defs]

[example abusing Tkinter.Misc]

> For a second I thought you got me there!

That's twice as long as I thought you'd think that, so I win after all
<wink>.

> Fortunately, there's magic available: recently, all classes
> have a __module__ attribute that is set to the full name
> of the module that defined it (its key in __sys__.modules).
>
> For functions, we would have to invent something similar.

OK!  I didn't know about class.__module__ -- I hope you realize that relying
on your time machine is making you lazy <wink>.

I remain uncomfortable with automagic updating, but not as much so.  Both
kinds of errors still seem possible to me:

1. Automagically updating when it wasn't wanted.

Examples of this are getting harder to come by <wink>.  Off the top of my
head I'm reduced to stuff like this:

>>> adders = []
>>> for i in range(10):
	def adder(y, x=i):
		return y+x
	adders.append(adder)


>>> adders[2](40)
42
>>> adders[9](33)
42
>>>

"That kind of thing" has got to be rare, but can't be non-existent either
(well, isn't -- I've done it).

2. Failing to automagically update when it was wanted.

Implicit in the discussion so far is that long-running systems want to
update code at a granularity no finer than module level.  Is that realistic?
I'm unsure.  It's certainly easy to *imagine* the app running an updater
server thread, accepting new source for functions and classes, and offering
to compile and install the objects.

Under the explicit new.update scheme, such a service needn't bother clients
with communicating the full name of the original module; heck, in a *truly*
long-running app, over time the source tree will change, and classes and
functions will migrate across modules.  That will be a problem for the
explicit scheme too (how does it know *which* "class Misc" to update) -- but
at least it's an explicit problem then, and not a "mysterous failure" of
hidden magic.


I could live with both of those (#1 is more worrisome); but think it easier
all around to give the users some tools and tell them to solve the problems
however they see fit.

or-maybe-we-already-agreed-about-that-ly y'rs  - tim





From gstein at lyra.org  Fri Jan 21 12:08:19 2000
From: gstein at lyra.org (Greg Stein)
Date: Fri, 21 Jan 2000 03:08:19 -0800 (PST)
Subject: [Python-Dev] namespaces (was: Changing existing class instances)
In-Reply-To: <001801bf63f3$414e0c60$ec2d153f@tim>
Message-ID: <Pine.LNX.4.10.10001210254030.13911-100000@nebula.lyra.org>

On Fri, 21 Jan 2000, Tim Peters wrote:
> [Greg Stein]
> > ...
> > In other words, I definitely would support a new class
> > object behavior that allows us to update a class' set of
> > bases and dictionary on the fly.  This could then be used
> > to support my solution for the recursive type scenario (which,
> > in turn, means that we don't have to introduce Yet Another
> > Namespace into Python to hold type names).
> 
> Parenthetically, I never grasped the appeal of the parenthetical comment.
> Yet Another Namespace for Yet Another Entirely New Purpose seems highly
> *desirable* to me!  Trying to overload the current namespace set makes it so
> much harder to see that these are compile-time gimmicks, and users need to
> be acutely aware of that if they're to use it effectively.  Note that I
> understand (& wholly agree with) the need for runtime introspection.

And that is the crux of the issue: I think the names that are assigned to
these classes, interfaces, typedefs, or whatever, can follow the standard
Python semantics and be plopped into the appropriate namespace. There is
no overloading.

The compile-time behavior certainly understands what names have what
types; in this case, if a name is a "typedecl", then it can remember the
*value*, too. When the name is used later, it knows the corresponding
value to use. For instance:

  IntOrString = typedef int|str
  def foo(x: IntOrString):
    ...

In this example, the type-checker knows that IntOrString is a typedecl.
It also knows the *value* of "int|str" so the name IntOrString now has two
items associated with it at type-check time:

   # not "real" syntax, but you get the idea...

   namespace["IntOrString"] = (TypeDeclarator, int|str)

With the above information in hand, the type-checker knows what
IntOrString means in the declaration for foo().

The cool benefit is that the runtime semantics are exactly as you would
expect: a typedecl object is created and assigned to IntOrString. That
object is also associated with the "x" argument in the function object
referred to by the name "foo".

There is no "overloading" of namespaces. We are using Python namespaces
just like they should be, and the type-checker doesn't even have to be all
the smart to track this stuff.

To get back to the recursive class problem, consider the following code:

   decl incomplete class Foo
   decl incomplete class Bar

   class Foo:
     decl a: Bar

   class Bar:
     decl b: Foo

The "decl" statements would create an empty class object and store that
into the "current" namespace. There is no need to shove that off into
another namespace. When the "class Foo" comes along, the class object is
updated with the class definition for Foo.

It is conceivable to remove the need for "decl" if you allow "class" and
"def" to omit the ": suite" portion of their grammar:

  class Foo
  class Bar

  class Foo:
    decl a: Bar
  ...

  def some_function(x: some_type, y: another_type) -> third_type

  ... lots o' code ...

  def some_function(x, y):
    ...

Guido suggested that it may be possible to omit "decl" altogether.
Certainly, it can work for member declarations such as:

  class Foo:
    a: Bar


Anyhow... my point is that a new namespace is not needed. Assuming we want
objects for reflection at runtime, then the above proposal states *how*
those objects are realized at runtime. Further, the type-checker can
easily follow that information and perform the appropriate compile-time
checks.

No New Namespaces!  (lather, rinse, repeat)

Cheers,
-g

-- 
Greg Stein, http://www.lyra.org/




From gstein at lyra.org  Fri Jan 21 12:12:57 2000
From: gstein at lyra.org (Greg Stein)
Date: Fri, 21 Jan 2000 03:12:57 -0800 (PST)
Subject: [Python-Dev] Changing existing class instances
In-Reply-To: <200001202002.PAA22435@eric.cnri.reston.va.us>
Message-ID: <Pine.LNX.4.10.10001210311070.13911-100000@nebula.lyra.org>

On Thu, 20 Jan 2000, Guido van Rossum wrote:
> Tim Peters:
>...
> > At the time my.py defines Misc, does Misc count as a class we're "about to
> > stomp on"?  If so-- & I've assumed so --it would wreak havoc.
> > 
> > But if not, I don't see how this case can be reliably distinguished "by
> > magic" from the cases where update is desired (if people are doing dynamic
> > updates to a long-running program, a new version of a class can come from
> > anywhere, so nothing like original file name or line number can distinguish
> > correctly either).
> 
> Fortunately, there's magic available: recently, all classes have a
> __module__ attribute that is set to the full name of the module that
> defined it (its key in __sys__.modules).
> 
> For functions, we would have to invent something similar.

func.func_globals


__module__ and func_globals can prevent *other* modules from redefining
something accidentally, but it doesn't prevent Badness from within the
module.
[ Tim just posted an example of this: his "def adder()" example... ]

Cheers,
-g

-- 
Greg Stein, http://www.lyra.org/




From bwarsaw at cnri.reston.va.us  Fri Jan 21 15:38:52 2000
From: bwarsaw at cnri.reston.va.us (Barry A. Warsaw)
Date: Fri, 21 Jan 2000 09:38:52 -0500 (EST)
Subject: [Python-Dev] Changing existing class instances
References: <200001202002.PAA22435@eric.cnri.reston.va.us>
	<001e01bf63f9$79660980$ec2d153f@tim>
Message-ID: <14472.28540.765858.16133@anthem.cnri.reston.va.us>

>>>>> "TP" == Tim Peters <tim_one at email.msn.com> writes:

    TP> Under the explicit new.update scheme, such a service needn't
    TP> bother clients with communicating the full name of the
    TP> original module; heck, in a *truly* long-running app, over
    TP> time the source tree will change, and classes and functions
    TP> will migrate across modules.  That will be a problem for the
    TP> explicit scheme too (how does it know *which* "class Misc" to
    TP> update) -- but at least it's an explicit problem then, and not
    TP> a "mysterous failure" of hidden magic.

I completely agree.  I think in general, such long running apps are
rare, and in those cases you probably want to be explicit about when
and how the updates occur anyway.  The one place where automatic
updates would be convenient would be at the interactive prompt, so it
might be nice to add a module that could be imported by PYTHONSTARTUP,
and play hook games to enable automatic updates.

-Barry




From bwarsaw at cnri.reston.va.us  Fri Jan 21 15:39:32 2000
From: bwarsaw at cnri.reston.va.us (Barry A. Warsaw)
Date: Fri, 21 Jan 2000 09:39:32 -0500 (EST)
Subject: [Python-Dev] Python 1.6 timing
References: <14471.31301.504670.201702@anthem.cnri.reston.va.us>
	<Pine.LNX.4.10.10001201653130.13911-100000@nebula.lyra.org>
Message-ID: <14472.28580.945266.658533@anthem.cnri.reston.va.us>

>>>>> "GS" == Greg Stein <gstein at lyra.org> writes:

    GS> Or move the CVS tree off-site.

I don't see what this buys us.
-Barry



From gstein at lyra.org  Fri Jan 21 15:48:40 2000
From: gstein at lyra.org (Greg Stein)
Date: Fri, 21 Jan 2000 06:48:40 -0800 (PST)
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <14472.28580.945266.658533@anthem.cnri.reston.va.us>
Message-ID: <Pine.LNX.4.10.10001210646140.13911-100000@nebula.lyra.org>

On Fri, 21 Jan 2000, Barry A. Warsaw wrote:
> >>>>> "GS" == Greg Stein <gstein at lyra.org> writes:
> 
>     GS> Or move the CVS tree off-site.
> 
> I don't see what this buys us.

I was under the impression that CVS access restrictions are based on CNRI
security policy. If the CVS repository moves elsewhere, then many people
can access it without impact on CNRI's network and security policies.

However, if the external access issue is based on legal reasons (for
example, only CNRI people should alter Python code), then yes: moving the
repository will buy nothing.

Cheers,
-g

-- 
Greg Stein, http://www.lyra.org/




From bwarsaw at python.org  Fri Jan 21 17:08:11 2000
From: bwarsaw at python.org (bwarsaw at python.org)
Date: Fri, 21 Jan 2000 11:08:11 -0500 (EST)
Subject: [Python-Dev] Python 1.6 timing
References: <14472.28580.945266.658533@anthem.cnri.reston.va.us>
	<Pine.LNX.4.10.10001210646140.13911-100000@nebula.lyra.org>
Message-ID: <14472.33899.20409.602096@anthem.cnri.reston.va.us>

>>>>> "GS" == Greg Stein <gstein at lyra.org> writes:

    GS> I was under the impression that CVS access restrictions are
    GS> based on CNRI security policy. If the CVS repository moves
    GS> elsewhere, then many people can access it without impact on
    GS> CNRI's network and security policies.

Well, access to our /internal/ network is of course restricted.  CNRI
employees have write access to the tree by virtue of access to the
filesystem (i.e. by NFS).  My current arrangement for external ssh
mediated access to a writable cvs server on an internal machine is a
hack and not something that I want to perpetuate if more users were
added.

    GS> However, if the external access issue is based on legal
    GS> reasons (for example, only CNRI people should alter Python
    GS> code), then yes: moving the repository will buy nothing.

I'll let Guido comment on policy concerning write access to the Python
CVS tree.  From a technical standpoint, if this is something Guido
wanted to extend to non-CNRI employees, the way to do it would be to
host the primary repository on a CNRI machine outside our firewall,
e.g cvs.python.org.  At that point, we'd be accessing the tree the
same as anybody else.

-Barry



From gstein at lyra.org  Fri Jan 21 17:19:33 2000
From: gstein at lyra.org (Greg Stein)
Date: Fri, 21 Jan 2000 08:19:33 -0800 (PST)
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <14472.33899.20409.602096@anthem.cnri.reston.va.us>
Message-ID: <Pine.LNX.4.10.10001210816440.13911-100000@nebula.lyra.org>

On Fri, 21 Jan 2000 bwarsaw at python.org wrote:
> >>>>> "GS" == Greg Stein <gstein at lyra.org> writes:
>...
> From a technical standpoint, if this is something Guido
> wanted to extend to non-CNRI employees, the way to do it would be to
> host the primary repository on a CNRI machine outside our firewall,
> e.g cvs.python.org.  At that point, we'd be accessing the tree the
> same as anybody else.

Gotcha. Sounds great!

I'm not sure yet that Guido is looking for external people to do checkins
(as opposed to delivering refined patches to him)... So we probably don't
need an assessment from the legal department :-), but if Guido already
knows, then I'd be curious.

thx!
-g

-- 
Greg Stein, http://www.lyra.org/




From paul at prescod.net  Fri Jan 21 17:51:24 2000
From: paul at prescod.net (Paul Prescod)
Date: Fri, 21 Jan 2000 08:51:24 -0800
Subject: [Python-Dev] Re: [Types-sig] namespaces (was: Changing existing class instances)
References: <Pine.LNX.4.10.10001210254030.13911-100000@nebula.lyra.org>
Message-ID: <38888E8C.FE369A86@prescod.net>

Greg Stein wrote:
> Tim Peters:
> > Trying to overload the current namespace set makes it so
> > much harder to see that these are compile-time gimmicks, and users need to
> > be acutely aware of that if they're to use it effectively.  Note that I
> > understand (& wholly agree with) the need for runtime introspection.
> 
> And that is the crux of the issue: I think the names that are assigned to
> these classes, interfaces, typedefs, or whatever, can follow the standard
> Python semantics and be plopped into the appropriate namespace. There is
> no overloading.

This is indeed the crux of the issue. For those that missed it last
time, it became very clear to me that we are working with radically
different design aesthetics when we discussed the idea of having an
optional keyword that said: "this thing is usually handled at compile
time but I want to handle it at runtime. I know what I am doing." 

Greg complained that that would require the programmer to understand too
much what was being done at compile time and what at runtime and what.
>From my point of view this is *exactly* what a programmer *needs* to
know and if we make it too hard for them to know it then we have failed.

> There is no "overloading" of namespaces. We are using Python namespaces
> just like they should be, and the type-checker doesn't even have to be all
> the smart to track this stuff.

There is an overloading of namespaces because we will separately specify
the *compile time semantics* of these names. We need to separately
specify these semantics because we need all compile time type checkers
to behave identically.

Yes, it seems elegant to make type objects seem as if they are "just
like" Python objects. Unfortunately they aren't. Type objects are
evaluated -- and accepted or rejected -- at compile time. Every
programmer needs to understand that and it should be blatantly obvious
in the syntax, just as everything else in Python syntax is blatantly
obvious.

-- 
 Paul Prescod  - ISOGEN Consulting Engineer speaking for himself
Earth will soon support only survivor species -- dandelions, roaches, 
lizards, thistles, crows, rats. Not to mention 10 billion humans.
	- Planet of the Weeds, Harper's Magazine, October 1998




From skaller at maxtal.com.au  Fri Jan 21 22:01:03 2000
From: skaller at maxtal.com.au (skaller)
Date: Sat, 22 Jan 2000 08:01:03 +1100
Subject: [Python-Dev] Re: [Types-sig] namespaces (was: Changing existing class instances)
References: <Pine.LNX.4.10.10001210254030.13911-100000@nebula.lyra.org> <38888E8C.FE369A86@prescod.net>
Message-ID: <3888C90F.BECA3FF6@maxtal.com.au>

Paul Prescod wrote:
 
 
> Yes, it seems elegant to make type objects seem as if they are "just
> like" Python objects. Unfortunately they aren't.

	Yes they are. They even have a type, TypeType.

-- 
John (Max) Skaller, mailto:skaller at maxtal.com.au
10/1 Toxteth Rd Glebe NSW 2037 Australia voice: 61-2-9660-0850
homepage: http://www.maxtal.com.au/~skaller
download: ftp://ftp.cs.usyd.edu/au/jskaller



From tim_one at email.msn.com  Sun Jan 23 00:18:14 2000
From: tim_one at email.msn.com (Tim Peters)
Date: Sat, 22 Jan 2000 18:18:14 -0500
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <000701bf636f$de37c5e0$c355cfc0@ski.org>
Message-ID: <000401bf652e$f5266b60$132d153f@tim>

[David Ascher]
> ...
> Regardless, just like Greg, I'd like to know what a
> pumpkin-holder would mean in the Python world.
>
> I propose that it be called the Oracle instead.  As in,
> whoever is Oracle would get some training with Tim Peters
> and learn how to channel G__do.

I'm afraid that wouldn't work.  The whole secret to channeling Guido in the
*past* was to have been an ABC user:  all you had to do is notice the things
about ABC that you loved and the ones that would drive any sane
*experienced* programmer mad with frustration.  Voila!  Guido's mind is your
mind <wink>.

But the more Python sails into uncharted waters, the less reliable my
Guido-channeling pseudo-skills get.  He is, in Essence, Unfathomable.  Also
indispensable.

> As a Python user, I'd be most comfortable with such a change
> if the Oracle just took over the technical stuff (reviewing
> patches, CVS checkins, running tests, corralling help for
> doc & code, maintaining release notes, building installers,
> etc.), but that the important decisions (e.g. whether to add
> a feature to the core language) would be checked with G__do
> first.

Definitely.  But where do you find someone like that?  It's (or at least
*should* be) several full-time jobs.  Languages like Icon & Scheme do it via
university association (scads of grad student slave labor); REBOL did it by
floating a trendy Internet business plan that actually attracted enough
venture capital to hire about 30 people; Python, unfortunately <wink>, seems
to attract people who already have demanding jobs.

So I see it as an issue of finding warm bodies more than anything else.  In
the absence of funding "real jobs", I really don't see much hope.  Bits &
pieces can be farmed out (e.g., I doubt Guido has had to do any work on the
regular expression code since Andrew arrived), but that's it -- I expect the
past predicts the future quite accurately here.

Certainly much more *could* be "farmed out", but no single volunteer of the
kind Python has attracted so far is going to do a lot on their own month
after month after month.  Even with the best of intentions, their "real
life" will interfere severely more often than not (voice of experience,
there -- and I'd guess it's the same for *all* of us).

if-something-doesn't-change-nothing-will-change<wink>-ly y'rs
    - tim





From tim_one at email.msn.com  Sun Jan 23 00:18:11 2000
From: tim_one at email.msn.com (Tim Peters)
Date: Sat, 22 Jan 2000 18:18:11 -0500
Subject: Python 2 namespace change? (was Re: [Python-Dev] Changing existing class instances)
In-Reply-To: <38871CE5.53FB9D68@digicool.com>
Message-ID: <000301bf652e$f348d1c0$132d153f@tim>

[Jim Fulton]
> ...
> A change to the way that namespaces are handled
> could make this work and have a number of other benefits,
> like global name usage without namespace lookups.
>
> I've suggested this to Guido in the past.  His
> reasonable response is that this would be too big a
> change for Python 1. Maybe this is something to consider
> for Python 2?
>
> The basic idea (borrowed from Smalltalk) is to have a kind
> of dictionary that is a collection of "association"
> objects.  An association object is simply a pairing of a
> name with a value. Association objects can be shared among
> multiple namespaces.

Jim, I've been intrigued by this idea for all the years you've been
suggesting it <wink>, but I've never understood what it is you're proposing!
This is the Python-Dev list, so feel encouraged to present it in concrete
implementation terms instead of ambiguous English.  Or maybe an interface?

interface a_kind_of_dictionary_that_is_a_collection_of_\
              association_objects:
    # ??? beats me ...

Or maybe as a C struct?  For example, is "an association object" a (char*,
PyObject*) pair?

Does this kind of dictionary have keys?  If so, of what type?  What type are
the values?  Best I can make sense of the above, the values are "association
objects", each of which contains a name and a value, and a key is maybe a
duplicate of the name in the association object to which it maps.  "A name"
may or may not be a string -- I can't tell.  Or maybe by "dictionary" you
didn't intend Python's current meaning for that word at all.  I assume "a
value" is a PyObject*.  The whole thrust *appears* to be to get names to map
to a PyObject** instead of PyObject*, but if that's the ticket I don't know
what association objeects have to do with it.

> An import like:
>
>   from foo import spam
>
> would copy the association between the name 'foo' and a
> value from module 'spam' into the current module.

Where does the idea that 'spam' is a *module* here come from?  It doesn't
make sense to me, and I'm so lost I'll spare everyone my further confusions
<wink>.

suspecting-the-last-actually-doesn't-make-any-sense<wink>-ly
    y'rs  - tim





From tim_one at email.msn.com  Sun Jan 23 00:29:45 2000
From: tim_one at email.msn.com (Tim Peters)
Date: Sat, 22 Jan 2000 18:29:45 -0500
Subject: [Python-Dev] Python 1.6 timing (fwd)
In-Reply-To: <38875DD1.B6596@tismer.com>
Message-ID: <000701bf6530$90cc31c0$132d153f@tim>

[hristian Tismer]
> ...
> Even better: Refcounting can lead to many new optimizations
> if we pay the cost to make INCREF/DECREF into methods. It
> has its cost (about 10 percent less pystones), but massive
> long-term benefits.

The GC patch Guido forced <wink> me to look at is based on the observation
that it's impossible to create cyclic trash unless a decref leaves a nonzero
refcount.  So the patch adds a function call to the DECREF macro (if the new
refcount is > 0, the object must be added to the set of "suspicious"
objects; else the object must be removed from that set).

So it roughly adds the cost of a method call to each decref anyway.  You
would think it adds less <wink>, but "the set" now is represented as a splay
tree, so *gobs* of hairy code get executed in either case (splay trees do
mutating rotations even on a lookup).

> ...
> Conclusion: I vote for a kind of GC that does just what
> refcounts cannot do, but please keep with the refcounts.

I like 'em too!

BTW, Toby posted (at least an earlier version of) the patch to c.l.py, if
anyone else wants to dig into it (I may have mentioned before that I'm short
on time <wink>).





From tim_one at email.msn.com  Sun Jan 23 05:59:38 2000
From: tim_one at email.msn.com (Tim Peters)
Date: Sat, 22 Jan 2000 23:59:38 -0500
Subject: [Python-Dev] Changing existing class instances
In-Reply-To: <14472.28540.765858.16133@anthem.cnri.reston.va.us>
Message-ID: <000201bf655e$a6a49b80$732d153f@tim>

[Barry A. Warsaw]
> I completely agree.

That's no fun <wink>.

> I think in general, such long running apps are rare,

By definition, they're non-existent under Windows <0.7 wink>.  But it
depends on which field you're working in.  The closer you get to being part
of a business or consumer service, the more important it gets; e.g., I've
seen serious RFQs for software systems guaranteed to suffer no more than 5
minutes of downtime per *year* (& stiff penalties for failure to meet that).
I've never been on the winning end of such an RFQ, so am not sure what it
takes to meet it.

It's interesting to ponder.  Psion has published a little about the software
techniques they use in their PDAs (my Psion 3a's remarkably capable "Agenda"
app has been running non-stop for a bit over 3 years!).

> and in those cases you probably want to be explicit about when
> and how the updates occur anyway.

My guess is you'd want to be *paranoidly* explicit, leaving nothing to
chance.

> The one place where automatic updates would be convenient would
> be at the interactive prompt, so it might be nice to add a
> module that could be imported by PYTHONSTARTUP, and play hook
> games to enable automatic updates.

Returning the favor, I completely agree.  The single thing people at work
gripe most about is how to do development under IDLE in such a way that
their package-laden systems exhibit the hoped-for changes in response to
editing a module deep in the bowels of the system.  I don't have a *good*
answer to that now; reduced to stuff like writing custom scripts to
selectively clear out sys.modules.

non-stop-ly y'rs  - tim





From bwarsaw at cnri.reston.va.us  Sun Jan 23 16:07:26 2000
From: bwarsaw at cnri.reston.va.us (Barry A. Warsaw)
Date: Sun, 23 Jan 2000 10:07:26 -0500 (EST)
Subject: [Python-Dev] Python 1.6 timing
References: <000701bf636f$de37c5e0$c355cfc0@ski.org>
	<000401bf652e$f5266b60$132d153f@tim>
Message-ID: <14475.6446.336166.192186@anthem.cnri.reston.va.us>

>>>>> "TP" == Tim Peters <tim_one at email.msn.com> writes:

    TP> REBOL did it by floating a trendy Internet business plan that
    TP> actually attracted enough venture capital to hire about 30
    TP> people; Python, unfortunately <wink>, seems to attract people
    TP> who already have demanding jobs.

I think all we have to do is change the name for 1.6 to LinuxPython
2.0, then split off and go IPO.  The more money we lose, the higher
our stock will go and we can use our market cap to hire all those warm
bodies.

-Barry



From jeremy at cnri.reston.va.us  Sun Jan 23 19:54:40 2000
From: jeremy at cnri.reston.va.us (Jeremy Hylton)
Date: Sun, 23 Jan 2000 13:54:40 -0500 (EST)
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <000401bf652e$f5266b60$132d153f@tim>
References: <000701bf636f$de37c5e0$c355cfc0@ski.org>
	<000401bf652e$f5266b60$132d153f@tim>
Message-ID: <14475.20080.508651.261991@bitdiddle.cnri.reston.va.us>

>>>>> "TP" == Tim Peters <tim_one at email.msn.com> writes:

  TP> [David Ascher]
  >> I propose that it be called the Oracle instead.  As in, whoever
  >> is Oracle would get some training with Tim Peters and learn how
  >> to channel G__do.

  TP> I'm afraid that wouldn't work.  The whole secret to channeling
  TP> Guido in the *past* was to have been an ABC user: all you had to
  TP> do is notice the things about ABC that you loved and the ones
  TP> that would drive any sane *experienced* programmer mad with
  TP> frustration.  Voila!  Guido's mind is your mind <wink>.

I have discovered another approach.  CNRI put in a cleam room on the
second floor last year.  I recently discovered a little door behind
some metrology device in a corner of the clean room.  The door opens
onto a tunnel that leads directly into Guido's mind.  Unfortunately,
it won't be of much use for a pumpkin-holder or channeler, because
after about 15 minutes you are deposited on the shoulder of the Dulles
Toll Road.

who-wants-to-be-John-Malkovich-when-they-could-be-Guido-ly y'rs,
Jeremy





From skip at mojam.com  Wed Jan 26 04:42:06 2000
From: skip at mojam.com (Skip Montanaro)
Date: Tue, 25 Jan 2000 21:42:06 -0600
Subject: [Python-Dev] Multiple dicts for string interpolation?
Message-ID: <200001260342.VAA10627@beluga.mojam.com>

Every once in awhile I want to perform string interpolation using more than
one dictionary.  One way is to build a dictionary that's a union of multiple 
dictionaries:

    dict = {}
    dict.update(d1)
    dict.update(d2)
    ...
    s = format % dict

Another way is the MultiDict approach that Digital Creations (used to?) use
in their DocumentTemplate module (I can't remember the exact usage any
more):

    dict = MultiDict()
    dict.append(d1)
    dict.append(d2)
    ...
    s = format % dict

A MultiDict object maintains a list of the dicts it's been fed and searches
them in order when __getitem__ is called.

I'd like to propose a third alternative.  How about if the string
interpolation function accepted a tuple of dictionaries directly:

    s = format % (d1, d2)

It would only be used when named interpolation was expected.  I don't think
there would be any conflict with current % operator semantics.

Skip Montanaro | http://www.mojam.com/
skip at mojam.com | http://www.musi-cal.com/
847-971-7098




From guido at CNRI.Reston.VA.US  Wed Jan 26 05:13:28 2000
From: guido at CNRI.Reston.VA.US (Guido van Rossum)
Date: Tue, 25 Jan 2000 23:13:28 -0500
Subject: [Python-Dev] Multiple dicts for string interpolation?
In-Reply-To: Your message of "Tue, 25 Jan 2000 21:42:06 CST."
             <200001260342.VAA10627@beluga.mojam.com> 
References: <200001260342.VAA10627@beluga.mojam.com> 
Message-ID: <200001260413.XAA02813@eric.cnri.reston.va.us>

> I'd like to propose a third alternative.  How about if the string
> interpolation function accepted a tuple of dictionaries directly:
> 
>     s = format % (d1, d2)
> 
> It would only be used when named interpolation was expected.  I don't think
> there would be any conflict with current % operator semantics.

Gut feeling: it's dangerous to fill up every possible dark corner with
specific semantics that are occasionally useful, because if you go too
far you lose useful redundancy, and you end up with Perl.

Not sure whether this particular suggestion is "going too far."

I think it depends on to what extent this is a common, useful idiom.
Do you have evidence of that?  Examples?

--Guido van Rossum (home page: http://www.python.org/~guido/)



From skip at mojam.com  Wed Jan 26 05:38:53 2000
From: skip at mojam.com (Skip Montanaro)
Date: Tue, 25 Jan 2000 22:38:53 -0600 (CST)
Subject: [Python-Dev] Multiple dicts for string interpolation?
In-Reply-To: <200001260413.XAA02813@eric.cnri.reston.va.us>
References: <200001260342.VAA10627@beluga.mojam.com>
	<200001260413.XAA02813@eric.cnri.reston.va.us>
Message-ID: <14478.31325.891846.701373@beluga.mojam.com>

    >> I'd like to propose a third alternative.  How about if the string
    >> interpolation function accepted a tuple of dictionaries directly:
    >> 
    >> s = format % (d1, d2)

    Guido> Gut feeling: it's dangerous to fill up every possible dark corner
    Guido> with specific semantics that are occasionally useful, because if
    Guido> you go too far you lose useful redundancy, and you end up with
    Guido> Perl.

Yeah, I am kind of taking advantage of the fact that the format operator
doesn't happen to use tuples of dicts already, though this seems like a
natural extension of the current semantics.   Currently, you can have

    Style of                Simple form     Complex form
    Interpolation
    -------                 -----------     ------------
    sprintf                 string          tuple of strings
    named                   dict            tuple of dicts

It does complicate the decision making process in the string format routine
a bit.

    Guido> I think it depends on to what extent this is a common, useful
    Guido> idiom.  Do you have evidence of that?  Examples?

Well, the first place I ran into it was in DocumentTemplates a few years
ago.  They used an idiom heavily which may have now been replaced by
acquisition where you'd effectively push and pop value dicts onto a stack as
you entered and exited nested blocks of DTML code.  Their solution was a
special dict-like object.

The example that made the light click for me this evening was having an
object whose class dict stores constants and whose instant dict stores
varying values.  It seemed cleaner to me to do

    obj = Class()
    ...
    s = format % (Class.__dict__, obj.__dict__)

than go through the intermediate step of building a separate dict which
would just get discarded as soon as this bit of string building was
complete.  (I will perform this once for each of several thousand
instances.)

It's not a big deal.  If it seems too obscure the other obvious solutions
are not gruesome.

Skip



From skip at mojam.com  Wed Jan 26 05:40:20 2000
From: skip at mojam.com (Skip Montanaro)
Date: Tue, 25 Jan 2000 22:40:20 -0600 (CST)
Subject: [Python-Dev] Multiple dicts for string interpolation?
In-Reply-To: <14478.31325.891846.701373@beluga.mojam.com>
References: <200001260342.VAA10627@beluga.mojam.com>
	<200001260413.XAA02813@eric.cnri.reston.va.us>
	<14478.31325.891846.701373@beluga.mojam.com>
Message-ID: <14478.31412.36960.440988@beluga.mojam.com>

Oh crap...  Of course, the table should have been

    Style of                Simple form     Complex form
    Interpolation
    -------                 -----------     ------------
    sprintf                 string          tuple of strings
    named                   dict            

(empty fourth cell...)

Skip



From klm at digicool.com  Wed Jan 26 06:01:36 2000
From: klm at digicool.com (Ken Manheimer)
Date: Wed, 26 Jan 2000 00:01:36 -0500 (EST)
Subject: [Python-Dev] Multiple dicts for string interpolation?
In-Reply-To: <14478.31325.891846.701373@beluga.mojam.com>
Message-ID: <Pine.LNX.4.10.10001252337510.15410-100000@splat.digicool.com>

On Tue, 25 Jan 2000, Skip Montanaro wrote:

>     Guido> Skip:
>     >> I'd like to propose a third alternative.  How about if the string
>     >> interpolation function accepted a tuple of dictionaries directly:
>     >> 
>     >> s = format % (d1, d2)
> [...]
>     Guido> I think it depends on to what extent this is a common, useful
>     Guido> idiom.  Do you have evidence of that?  Examples?
> 
> Well, the first place I ran into it was in DocumentTemplates a few years
> ago.  They used an idiom heavily which may have now been replaced by
> acquisition where you'd effectively push and pop value dicts onto a stack as
> you entered and exited nested blocks of DTML code.  Their solution was a
> special dict-like object.

Implementation of acquisition basically uses a MultiDict underneath.
Consider acquisition as a cumulative context composed from the containers
of the target of a web request.  (Actually, a distinction is made between
the object containment hierarchy of the target and the successive
components of the path along which the target is reached by the request,
with the containment contexts taking precedence - but that's probably not
important here:-)  Add in incidental things like the server environment
(from which you can get HTTP_REFERER and cookies and so forth).  Each of
the components can be a dictionary or a MultiDict (or a sequence of pairs,
i think), and they're ultimately composed in a MultiDict.

I think another place in zope where multidicts play prominently is in the
security mechanism, where any object can have local roles, and the
ultimate role of a user within a context is composed from the union across
the containment hierarchy.  There probably are lots of other places where
multidicts are used.

Suffice to say that there's a lot of composing of contexts that goes on in
Zope in general, acquistion being a prime example but not the only one,
and multidicts play heavily in many.  I would be surprised if this need to
combine contexts is peculiar to web server, or general server
applications.

> [...]
> It's not a big deal.  If it seems too obscure the other obvious solutions
> are not gruesome.

I suppose we'd be pretty happy to have something like MultiDict as part of
python...

Ken
klm at digicool.com

(Who's the only one left in fredericksburg to speak up, at the moment:-)




From tim_one at email.msn.com  Wed Jan 26 06:39:19 2000
From: tim_one at email.msn.com (Tim Peters)
Date: Wed, 26 Jan 2000 00:39:19 -0500
Subject: [Python-Dev] Multiple dicts for string interpolation?
In-Reply-To: <200001260413.XAA02813@eric.cnri.reston.va.us>
Message-ID: <000101bf67bf$b103e460$592d153f@tim>

[Skip, wants to interpolate multiple dicts via "%",
 suggests passing a tuple of dicts:  format % (d1, d2, ...)]

[Guido]
> ...
> I think it depends on to what extent this is a common, useful
> idiom.  Do you have evidence of that?  Examples?

You yourself raised one last century <wink>:  simply wanting to interpolate
from both locals() and globals().  At the time, the idea of a new dict-like
mapping object (capturing Python's lookup rules) appealed to you.  I still
like that, and note that the apparent need becomes more acute if "deep
nesting" is ever added.

I wasn't aware of the MultiDict approach Skip mentioned, but thought it
looked spot on for the general case!  Skip, is the long-windedness of

    dict = MultiDict()
    dict.append(d1)
    dict.append(d2)
    ...
    s = format % dict

the part you didn't like about that?  If so, how about changing the
constructor to

    def __init__(self, *dicts):
         ...

instead so you could use it as a one-liner

    format % MultiDict(d1, d2, ...)

?  That's exactly the same as the tuple idea, except there's a nice
descriptive word in the middle of it <wink>.





From jack at oratrix.nl  Wed Jan 26 10:56:18 2000
From: jack at oratrix.nl (Jack Jansen)
Date: Wed, 26 Jan 2000 10:56:18 +0100
Subject: [Python-Dev] Multiple dicts for string interpolation? 
In-Reply-To: Message by "Tim Peters" <tim_one@email.msn.com> ,
	     Wed, 26 Jan 2000 00:39:19 -0500 , <000101bf67bf$b103e460$592d153f@tim> 
Message-ID: <20000126095619.DC67D36E440@snelboot.oratrix.nl>

> the part you didn't like about that?  If so, how about changing the
> constructor to
> 
>     def __init__(self, *dicts):
>          ...
> 
> instead so you could use it as a one-liner
> 
>     format % MultiDict(d1, d2, ...)
> 
> ?  That's exactly the same as the tuple idea, except there's a nice
> descriptive word in the middle of it <wink>.

I've always wonderer why dict+dict isn't supported (or possibly dict|dict, if 
the key-collision semantics of + on dict are seen as a problem). Is there a 
good reason for this, or is it just that there are other more important things 
to implement?

This wouldn't be a replacement for all uses of MultiDict, as it would probably 
have to create a new dict to keep semantics in line with those of list+list
--
Jack Jansen             | ++++ stop the execution of Mumia Abu-Jamal ++++
Jack.Jansen at oratrix.com | ++++ if you agree copy these lines to your sig ++++
www.oratrix.nl/~jack    | see http://www.xs4all.nl/~tank/spg-l/sigaction.htm 





From guido at CNRI.Reston.VA.US  Wed Jan 26 13:41:45 2000
From: guido at CNRI.Reston.VA.US (Guido van Rossum)
Date: Wed, 26 Jan 2000 07:41:45 -0500
Subject: [Python-Dev] Multiple dicts for string interpolation?
In-Reply-To: Your message of "Wed, 26 Jan 2000 10:56:18 +0100."
             <20000126095619.DC67D36E440@snelboot.oratrix.nl> 
References: <20000126095619.DC67D36E440@snelboot.oratrix.nl> 
Message-ID: <200001261241.HAA03001@eric.cnri.reston.va.us>

[Tim]
> >     format % MultiDict(d1, d2, ...)
> > 
> > ?  That's exactly the same as the tuple idea, except there's a nice
> > descriptive word in the middle of it <wink>.

Nice.

[Jack]
> I've always wonderer why dict+dict isn't supported (or possibly
> dict|dict, if the key-collision semantics of + on dict are seen as a
> problem). Is there a good reason for this, or is it just that there
> are other more important things to implement?

The reason is that + (or |) looks symmetrical, but for the key
collisions, one of them has to lose.  We now have dict1.update(dict2),
which is a bit more cumbersome, but makes it much clearer who is the
loser.

--Guido van Rossum (home page: http://www.python.org/~guido/)



From skip at mojam.com  Wed Jan 26 15:30:09 2000
From: skip at mojam.com (Skip Montanaro)
Date: Wed, 26 Jan 2000 08:30:09 -0600 (CST)
Subject: [Python-Dev] Multiple dicts for string interpolation?
In-Reply-To: <000101bf67bf$b103e460$592d153f@tim>
References: <200001260413.XAA02813@eric.cnri.reston.va.us>
	<000101bf67bf$b103e460$592d153f@tim>
Message-ID: <14479.1265.213769.810138@beluga.mojam.com>

    Tim> Skip, is the long-windedness of

    Tim>     dict = MultiDict()
    Tim>     dict.append(d1)
    Tim>     dict.append(d2)
    Tim>     ...
    Tim>     s = format % dict

    Tim> the part you didn't like about that?  If so, how about changing the
    Tim> constructor to

    Tim>     def __init__(self, *dicts):
    Tim>          ...

    Tim> instead so you could use it as a one-liner

    Tim>     format % MultiDict(d1, d2, ...)

    Tim> ?  That's exactly the same as the tuple idea, except there's a nice
    Tim> descriptive word in the middle of it <wink>.

The long-windedness was part of it.  The performance hit of composing
dictionaries thousands of times to perform a single format operation was
also a consideration.

Okay, side excursion into the Zope source tree...

What I was calling MultiDict is actually MultiMapping (written in C, BTW).
As a side effect of my Zope install here, I even already have it in sys.path
(go figure!).  And it turns out to work just as Tim surmised:

    >>> d1 = {"a": 1}
    >>> d2 = {"b": 2}
    >>> d = MultiMapping.MultiMapping(d1, d2)
    >>> d["b"]
    2
    >>> d["a"]
    1

Dang!  Turns out Jim Fulton has a time machine also.

I guess the next question is to extend Ken's comment about getting it into
the Python core.  Would that be something possible for 1.6?  I used a Python
version of MultiMapping in an ancient version of DocumentTemplate.  I'm sure
the C version has been around for at least two or three years and would
appear pretty darn stable, since it seems to be at the core of a lot of
Zope's coolness.

Skip



From ping at lfw.org  Thu Jan 27 08:06:01 2000
From: ping at lfw.org (Ka-Ping Yee)
Date: Wed, 26 Jan 2000 23:06:01 -0800 (PST)
Subject: [Python-Dev] Multiple dicts for string interpolation?
In-Reply-To: <14478.31325.891846.701373@beluga.mojam.com>
Message-ID: <Pine.LNX.4.10.10001262237010.2341-100000@skuld.lfw.org>

On Tue, 25 Jan 2000, Skip Montanaro wrote:
> 
>     Guido> I think it depends on to what extent this is a common, useful
>     Guido> idiom.  Do you have evidence of that?  Examples?
> 
> Well, the first place I ran into it was in DocumentTemplates a few years
> ago.  They used an idiom heavily which may have now been replaced by
> acquisition where you'd effectively push and pop value dicts onto a stack as
> you entered and exited nested blocks of DTML code.  Their solution was a
> special dict-like object.

That's really interesting.  I wrote a bunch of Python wrappers for
a UI toolkit a little while ago, and there were two main pieces of
machinery i built to make the toolkit pleasant to use:

    1. a reasonably nice C++ extension class kit (this is where i
       tried overloading operator new for the first time, so it
       would allocate memory that could be freed by PyMem_DEL --
       i don't know if CXX uses the same approach)

    2. a second layer of Python wrapper classes for the extension
       classes that implements extra methods in Python, and maintains
       a hierarchy of default keyword argument values along the
       inheritance hierarchy of widgets

The second of these things involved implementing exactly the kind
of dictionary stack that you mentioned.

The programming idiom for building widgets goes something like:

    defaultstack = {}  # maps class object to list of defaults dictionaries

    class Label(Component):
        defaults = _dict(text="Label", align=LEFT)

    class Button(Label):
        defaults = _dict(text="Button", align=CENTER, shadow=2)

    ...

    w = Window(...)

    Button.push(fg="white", bg="red",
                font="-*-courier-bold-r-normal--14-*-*-*-*-*-*-*")
    a = Button(w, text="one")
    b = Button(w, text="two")
    c = Button(w, text="three")
    Button.pop()

This way you can install some options for a while and make a bunch
of widgets with your defaults, then pop the options and go back to
the previous state.

The layers of dictionaries that get composed in every widget's
__init__ function are (in order of priority):

    1. any non-None keyword arguments to __init__
    2. any non-None values in class.defaults
    3. any non-None values in class.__bases__[0].defaults
    4. any non-None values in class.__bases__[0].__bases__[0].defaults
    etc.

When a new set of defaults is push()ed, the class's current
defaults are saved on the defaultstack for the class, and restored
when pop() gets called.

I don't *know* if this is really the best way to do things, but it
has seemed to work out pretty well in practice.  It makes it more
convenient to deal with all the options you have to throw around
especially when doing UI stuff.

Anyway, i noticed the same sort of thing today while wondering about
using keyword arguments for HTML tag attributes.  (Perhaps HTMLgen
does this sort of thing already -- sorry i haven't looked at it.)
Anyway, the following sort of helper might be useful in general:

    class Default:
        def __init__(self, cl, **defaults):
            self.cl = cl
            self.defaults = defaults

        def __call__(self, *args, **kw):
            for key, value in self.defaults:
                if not kw.has_key(key): kw[key] = value
            return apply(self.cl, args, kw)

Then you could do the same thing as above with:

    MyButton = Default(Button, fg="white", bg="red",
                       font="-*-courier-bold-r-normal--14-*-*-*-*-*-*-*")
    a = MyButton(w, text="one")
    b = MyButton(w, text="two")
    c = MyButton(w, text="three")

This is probably a cleaner way to do things.  I haven't tried it,
but it might be a nice thing to have in Tkinter.
 


-- ?!ng




From ping at lfw.org  Fri Jan 28 05:36:49 2000
From: ping at lfw.org (Ka-Ping Yee)
Date: Thu, 27 Jan 2000 20:36:49 -0800 (PST)
Subject: [Python-Dev] Python 1.6 timing
In-Reply-To: <14475.20080.508651.261991@bitdiddle.cnri.reston.va.us>
Message-ID: <Pine.LNX.4.10.10001272033300.2341-100000@skuld.lfw.org>

On Sun, 23 Jan 2000, Jeremy Hylton wrote:
> 
> I have discovered another approach.  CNRI put in a cleam room on the
> second floor last year.  I recently discovered a little door behind
> some metrology device in a corner of the clean room.  The door opens
> onto a tunnel that leads directly into Guido's mind.  Unfortunately,
> it won't be of much use for a pumpkin-holder or channeler, because
> after about 15 minutes you are deposited on the shoulder of the Dulles
> Toll Road.

I almost fell out of my chair laughing when i read this.

What do you think would happen if Guido went into the tunnel?  Perhaps
    
    http://www.lfw.org/jminc/Guido/http://www.python.org/

(What you get is a generalization of some earlier silliness... the
description of the original is at http://www.lfw.org/jminc/.)


-- ?!ng




From jim at digicool.com  Fri Jan 28 16:02:12 2000
From: jim at digicool.com (Jim Fulton)
Date: Fri, 28 Jan 2000 10:02:12 -0500
Subject: [Python-Dev] Multiple dicts for string interpolation?
References: <200001260342.VAA10627@beluga.mojam.com>
Message-ID: <3891AF74.1E81D7F8@digicool.com>

Skip Montanaro wrote:
> 
> Every once in awhile I want to perform string interpolation using more than
> one dictionary.  One way is to build a dictionary that's a union of multiple
> dictionaries:
> 
>     dict = {}
>     dict.update(d1)
>     dict.update(d2)
>     ...
>     s = format % dict
> 
> Another way is the MultiDict approach that Digital Creations (used to?) use
> in their DocumentTemplate module (I can't remember the exact usage any
> more):
> 
>     dict = MultiDict()
>     dict.append(d1)
>     dict.append(d2)

Actually, push (and pop). The namspaces are managed as a stack.

>     ...
>     s = format % dict
> 
> A MultiDict object maintains a list of the dicts it's been fed and searches
> them in order when __getitem__ is called.
> 
> I'd like to propose a third alternative.  How about if the string
> interpolation function accepted a tuple of dictionaries directly:
> 
>     s = format % (d1, d2)
> 
> It would only be used when named interpolation was expected.  I don't think
> there would be any conflict with current % operator semantics.

Yes. In the current semantics, you output the two dictionaries.

Try: 

  '%s %s' % ({'hello':'skip'},{})

Jim

--
Jim Fulton           mailto:jim at digicool.com   Python Powered!        
Technical Director   (888) 344-4332            http://www.python.org  
Digital Creations    http://www.digicool.com   http://www.zope.org    

Under US Code Title 47, Sec.227(b)(1)(C), Sec.227(a)(2)(B) This email
address may not be added to any commercial mail list with out my
permission.  Violation of my privacy with advertising or SPAM will
result in a suit for a MINIMUM of $500 damages/incident, $1500 for
repeats.



From jim at digicool.com  Fri Jan 28 16:07:24 2000
From: jim at digicool.com (Jim Fulton)
Date: Fri, 28 Jan 2000 10:07:24 -0500
Subject: [Python-Dev] Multiple dicts for string interpolation?
References: <Pine.LNX.4.10.10001252337510.15410-100000@splat.digicool.com>
Message-ID: <3891B0AC.D39275DF@digicool.com>

Ken Manheimer wrote:
> 
> On Tue, 25 Jan 2000, Skip Montanaro wrote:
> 
> >     Guido> Skip:
> >     >> I'd like to propose a third alternative.  How about if the string
> >     >> interpolation function accepted a tuple of dictionaries directly:
> >     >>
> >     >> s = format % (d1, d2)
> > [...]
> >     Guido> I think it depends on to what extent this is a common, useful
> >     Guido> idiom.  Do you have evidence of that?  Examples?
> >
> > Well, the first place I ran into it was in DocumentTemplates a few years
> > ago.  They used an idiom heavily which may have now been replaced by
> > acquisition where you'd effectively push and pop value dicts onto a stack as
> > you entered and exited nested blocks of DTML code.  Their solution was a
> > special dict-like object.
> 
> Implementation of acquisition basically uses a MultiDict underneath.

No it doesn't.  Acquisition achieves combination of multiple 
namespaces in much the same way that inheritence does (through
delagation).

> Consider acquisition as a cumulative context composed from the containers
> of the target of a web request.  (Actually, a distinction is made between
> the object containment hierarchy of the target and the successive
> components of the path along which the target is reached by the request,
> with the containment contexts taking precedence - but that's probably not
> important here:-)  Add in incidental things like the server environment
> (from which you can get HTTP_REFERER and cookies and so forth).  Each of
> the components can be a dictionary or a MultiDict (or a sequence of pairs,
> i think), and they're ultimately composed in a MultiDict.
> 
> I think another place in zope where multidicts play prominently is in the
> security mechanism, where any object can have local roles, and the
> ultimate role of a user within a context is composed from the union across
> the containment hierarchy.  There probably are lots of other places where
> multidicts are used.

Acquisition plays a role in security, but MultiDicts-like things are 
not used.
 
> Suffice to say that there's a lot of composing of contexts that goes on in
> Zope in general, acquistion being a prime example but not the only one,
> and multidicts play heavily in many.  I would be surprised if this need to
> combine contexts is peculiar to web server, or general server
> applications.
> 
> > [...]
> > It's not a big deal.  If it seems too obscure the other obvious solutions
> > are not gruesome.
> 
> I suppose we'd be pretty happy to have something like MultiDict as part of
> python...

Note that Zope actually uses two separate flavors. The one used most
in Zope (in DocumentTemplate) has very specific hooks to work with
Zope's security machinery.

Jim

--
Jim Fulton           mailto:jim at digicool.com   Python Powered!        
Technical Director   (888) 344-4332            http://www.python.org  
Digital Creations    http://www.digicool.com   http://www.zope.org    

Under US Code Title 47, Sec.227(b)(1)(C), Sec.227(a)(2)(B) This email
address may not be added to any commercial mail list with out my
permission.  Violation of my privacy with advertising or SPAM will
result in a suit for a MINIMUM of $500 damages/incident, $1500 for
repeats.



From jim at digicool.com  Fri Jan 28 16:10:26 2000
From: jim at digicool.com (Jim Fulton)
Date: Fri, 28 Jan 2000 10:10:26 -0500
Subject: [Python-Dev] Multiple dicts for string interpolation?
References: <000101bf67bf$b103e460$592d153f@tim>
Message-ID: <3891B162.554622E2@digicool.com>

Tim Peters wrote:
> 
(snip)
> I wasn't aware of the MultiDict approach Skip mentioned,

See the MultiMapping module in ExtensionClass. You can get the
latest flavor of this in the latest Zope release.

> but thought it
> looked spot on for the general case!  Skip, is the long-windedness of
> 
>     dict = MultiDict()
>     dict.append(d1)
>     dict.append(d2)
>     ...
>     s = format % dict

Note the rather important *stack* sematics of
MultiMappings.  We often push and pop namespaces 
on and off of MultiMappings in use.
 
> the part you didn't like about that?  If so, how about changing the
> constructor to
> 
>     def __init__(self, *dicts):
>          ...
> 
> instead so you could use it as a one-liner
> 
>     format % MultiDict(d1, d2, ...)
> 
> ?  That's exactly the same as the tuple idea, except there's a nice
> descriptive word in the middle of it <wink>.

This is exactly what the current MultiMapping "class" does.

Jim

--
Jim Fulton           mailto:jim at digicool.com   Python Powered!        
Technical Director   (888) 344-4332            http://www.python.org  
Digital Creations    http://www.digicool.com   http://www.zope.org    

Under US Code Title 47, Sec.227(b)(1)(C), Sec.227(a)(2)(B) This email
address may not be added to any commercial mail list with out my
permission.  Violation of my privacy with advertising or SPAM will
result in a suit for a MINIMUM of $500 damages/incident, $1500 for
repeats.



From gward at cnri.reston.va.us  Fri Jan 28 17:39:54 2000
From: gward at cnri.reston.va.us (Greg Ward)
Date: Fri, 28 Jan 2000 11:39:54 -0500
Subject: [Python-Dev] To-do for Distutils 0.2 (and beyond)
Message-ID: <20000128113954.A12965@cnri.reston.va.us>

Hi all --

[oops: I *said* that I was cc'ing this to python-dev when I posted it to
 distutils-sig, but I just plain forgot to.  So here it is again, still
 presumed relevant to python-dev'ers because it directly affects the
 planned Python 1.6 feature set.  Please reply either to me directly or
 to distutils-sig, because that's where the implementation will be done.]

recent developments in the planned release schedule for Python 1.6
(Guido doesn't want to wait for everything planned, but get something
out the door in the next couple of months) are lighting a fire under me
to get a seriously usable version of Distutils ready *really* soon now.
This will be Distutils 0.2; I anticipate that 0.2.x will be included in
Python 1.6, where x is the number of attempts it takes me to get
something reasonably bug-free out the door.

Those if you who were at the Python Conference this past week will have
seen bits and pieces of my "laundry list" of desired features that
should be added to the Distutils at some point in the future.  Given the
shortened schedule, it looks like it's necessary to do some pruning and
concentrate on the essentials to get something in Python 1.6.

So, here is my current laundry list, sorted into a couple of categories:

essential for 0.2 (Python 1.6)
-----------------
* fix the "dist" command (two-phase manifest, better feedback)
  (steal ideas and hopefully code from Gordon Macmillan's installer)
* fix the "install" command (have the right interface and do the right
  thing for installating to non-standard or personal directories) 
* fix some bad nomenclature in the command classes
  (most likely 'options' -> 'user_options', 'set_default_options()' ->
  'initialize_options()', and 'set_final_options()' -> ??? (maybe
  'finalize_options()'?))
* build C libraries (for PIL, and other similar distributions)
* documentation (two small manuals that should become standard Python
  manuals: "Installing Python Modules" and "Developing and Distributing
  Python Modules")
* add a bdist command; should at least be able to generate dumb archives
  of built distributions (eg. a tarball that you unpack from /usr/local,
  or maybe /usr/local/lib/python1.5/site-packages)

desirable for 0.2
-----------------
* "what's installed" database
* dependency checking ("is version 1.3 of foo installed?")
* don't automatically clobber an existing installation -- confirm, or
  require a "force" option, or something
* command to install C headers (assuming more extensions than NumPy need
  to do this)

put off to 0.3 (Python 1.7?)
----------------------------
* JPython support (most importantly, know where to install .py modules
  when run from JPython and be able to build Java extensions for JPython)
* build static Python binary (for shared-library-challenged OSs)
* SWIG support (mainly, know how to run it before building the C
  extension it generates)
* PyFort support (ditto)
* Mac support
* allow overlapping multi-architecture installations (Michel Sanner's
  pet peeve and Guido's nightmare ;-) (this would *not* be the default;
  it would have to be explicitly chosen by brave/cheap/foolhardy
  installers)
* support for archive sites (Parnassus) to pull out meta-info

Anyone feel strongly about moving any of these items around, or
discarding any entirely, or adding anything?  Please let me know by
email; I'll summarize to the list.

Thanks --

       Greg



From jeremy at cnri.reston.va.us  Sat Jan 29 00:52:53 2000
From: jeremy at cnri.reston.va.us (Jeremy Hylton)
Date: Fri, 28 Jan 2000 18:52:53 -0500 (EST)
Subject: [Python-Dev] To-do for Distutils 0.2 (and beyond)
In-Reply-To: <20000128113954.A12965@cnri.reston.va.us>
References: <20000128113954.A12965@cnri.reston.va.us>
Message-ID: <14482.11221.451866.695357@bitdiddle.cnri.reston.va.us>

>>>>> "GW" == Greg Ward <gward at cnri.reston.va.us> writes:

 GW> desirable for 0.2
 GW> -----------------
 GW> * "what's installed" database
 GW> * dependency checking ("is version 1.3 of foo installed?")

These are *not* desirable for version 0.2.  Paul Dubois expressed some
concern about the complexity of these tasks.  I agree completely.  I
think the chances of getting this done correctly in the next month are
slim to none.  Don't waste your time adding the kitchen sink to
distutils :-); just bang on the simple stuff until it's rock solid.

Jeremy





From jim at digicool.com  Sat Jan 29 02:40:22 2000
From: jim at digicool.com (Jim Fulton)
Date: Fri, 28 Jan 2000 20:40:22 -0500
Subject: [Python-Dev] Multiple dicts for string interpolation?
References: <200001260413.XAA02813@eric.cnri.reston.va.us>
		<000101bf67bf$b103e460$592d153f@tim> <14479.1265.213769.810138@beluga.mojam.com>
Message-ID: <38924506.808D34F5@digicool.com>

Skip Montanaro wrote:
> 
(snip)
> I guess the next question is to extend Ken's comment about getting it into
> the Python core.  Would that be something possible for 1.6?  I used a Python
> version of MultiMapping in an ancient version of DocumentTemplate.  I'm sure
> the C version has been around for at least two or three years and would
> appear pretty darn stable,

Yes. I'm sure you'd have to de-ExtensionClass-ify it to get it 
into the core. :)

> since it seems to be at the core of a lot of
> Zope's coolness.

Actually, it isn't, as there is a separate similar thing
(TemplateDict) used in DocumentTemplate.

Jim

--
Jim Fulton           mailto:jim at digicool.com   Python Powered!        
Technical Director   (888) 344-4332            http://www.python.org  
Digital Creations    http://www.digicool.com   http://www.zope.org    

Under US Code Title 47, Sec.227(b)(1)(C), Sec.227(a)(2)(B) This email
address may not be added to any commercial mail list with out my
permission.  Violation of my privacy with advertising or SPAM will
result in a suit for a MINIMUM of $500 damages/incident, $1500 for
repeats.



From guido at CNRI.Reston.VA.US  Sun Jan 30 14:32:18 2000
From: guido at CNRI.Reston.VA.US (Guido van Rossum)
Date: Sun, 30 Jan 2000 08:32:18 -0500
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
Message-ID: <200001301332.IAA12252@eric.cnri.reston.va.us>

Dear developers,

Eric Raymond has sent me the following patch, which adds conditional
expressions to Python.  I'd like to hear opinions on whether this is a
good thing to add to Python, and whether this is the right syntax.

I am a bit skeptical about whether this is sufficiently Pythonic, but
on the other hand there have always been requests for such a feature,
and the existing solutions are ugly:

  a and b or c

only works when you know for sure that b will never be false, and

  (a and [b] or [c])[0] 

is dead ugly...

--Guido van Rossum (home page: http://www.python.org/~guido/)

Subject: Ternary select -- here it is.
From: "Eric S. Raymond" <esr at thyrsus.com>
To: Guido Van Rossum <guido at CNRI.Reston.Va.US>
Date: Sat, 29 Jan 2000 17:40:31 -0500
X-Eric-Conspiracy: There is no conspiracy

Dang, Guido, this was *fun*!

This patch extends the Python interpreter to support the C ternary
operator, and documents the extension in the Reference Manual.  The
implementation is dead simple and robust: it's adapted from the
existing code for if statements, and adds or changes less than 70 lines
of code all told.

Diffs between last version checked in and current workfile(s):

--- Grammar/Grammar	2000/01/28 17:10:18	1.1
+++ Grammar/Grammar	2000/01/29 22:14:05
@@ -61,7 +61,8 @@
 except_clause: 'except' [test [',' test]]
 suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT
 
-test: and_test ('or' and_test)* | lambdef
+test: bool_test ['?' bool_test ':' bool_test]
+bool_test: and_test ('or' and_test)* | lambdef
 and_test: not_test ('and' not_test)*
 not_test: 'not' not_test | comparison
 comparison: expr (comp_op expr)*
--- Include/token.h	2000/01/28 17:38:55	1.1
+++ Include/token.h	2000/01/29 01:27:00
@@ -74,10 +74,11 @@
 #define LEFTSHIFT	34
 #define RIGHTSHIFT	35
 #define DOUBLESTAR	36
+#define QUERY		37
 /* Don't forget to update the table _PyParser_TokenNames in tokenizer.c! */
-#define OP		37
-#define ERRORTOKEN	38
-#define N_TOKENS	39
+#define OP		38
+#define ERRORTOKEN	39
+#define N_TOKENS	34
 
 /* Special definitions for cooperation with parser */
 
--- Modules/parsermodule.c	2000/01/28 18:03:27	1.1
+++ Modules/parsermodule.c	2000/01/29 22:13:45
@@ -945,6 +945,7 @@
 #define	validate_star(ch)	validate_terminal(ch,	    STAR, "*")
 #define	validate_vbar(ch)	validate_terminal(ch,	    VBAR, "|")
 #define validate_doublestar(ch)	validate_terminal(ch, DOUBLESTAR, "**")
+#define validate_query(ch)	validate_terminal(ch,	   QUERY, "?")
 #define validate_dot(ch)	validate_terminal(ch,	     DOT, ".")
 #define	validate_name(ch, str)	validate_terminal(ch,	    NAME, str)
 
@@ -963,7 +964,8 @@
 VALIDATER(exec_stmt);		VALIDATER(compound_stmt);
 VALIDATER(while);		VALIDATER(for);
 VALIDATER(try);			VALIDATER(except_clause);
-VALIDATER(test);		VALIDATER(and_test);
+VALIDATER(test);
+VALIDATER(bool_test);		VALIDATER(and_test);
 VALIDATER(not_test);		VALIDATER(comparison);
 VALIDATER(comp_op);		VALIDATER(expr);
 VALIDATER(xor_expr);		VALIDATER(and_expr);
@@ -1829,12 +1831,34 @@
 }   /* validate_except_clause() */
 
 
+/*  bool_test ( | bool_test ? bool_test )
+ *
+ */
 static int
 validate_test(tree)
     node *tree;
 {
+    if (!validate_ntype(tree, test))
+	return 0;
+    else if (NCH(tree) == 1)
+	return(validate_bool_test(CHILD(tree, 0)));
+    else if (validate_numnodes(tree, 5, "expr"))
+    {
+	return validate_bool_test(CHILD(tree, 0))
+	    && validate_query(CHILD(tree, 1))
+	    && validate_bool_test(CHILD(tree, 2))
+	    && validate_colon(CHILD(tree, 3))
+	    && validate_bool_test(CHILD(tree, 4));
+    }
+}   /* validate_test() */
+
+
+static int
+validate_bool_test(tree)
+    node *tree;
+{
     int nch = NCH(tree);
-    int res = validate_ntype(tree, test) && is_odd(nch);
+    int res = validate_ntype(tree, bool_test) && is_odd(nch);
 
     if (res && (TYPE(CHILD(tree, 0)) == lambdef))
 	res = ((nch == 1)
@@ -1848,7 +1872,7 @@
     }
     return (res);
 
-}   /* validate_test() */
+}   /* validate_bool_test() */
 
 
 static int
--- Parser/tokenizer.c	2000/01/28 17:37:48	1.1
+++ Parser/tokenizer.c	2000/01/29 01:27:26
@@ -99,6 +99,7 @@
 	"LEFTSHIFT",
 	"RIGHTSHIFT",
 	"DOUBLESTAR",
+	"QUERY",
 	/* This table must match the #defines in token.h! */
 	"OP",
 	"<ERRORTOKEN>",
@@ -384,6 +385,7 @@
 	case '}':	return RBRACE;
 	case '^':	return CIRCUMFLEX;
 	case '~':	return TILDE;
+	case '?':	return QUERY;
 	default:	return OP;
 	}
 }
--- Python/compile.c	2000/01/28 23:17:19	1.1
+++ Python/compile.c	2000/01/29 22:19:29
@@ -1698,11 +1698,11 @@
 }
 
 static void
-com_test(c, n)
+com_bool_test(c, n)
 	struct compiling *c;
 	node *n;
 {
-	REQ(n, test); /* and_test ('or' and_test)* | lambdef */
+	REQ(n, bool_test); /* and_test ('or' and_test)* | lambdef */
 	if (NCH(n) == 1 && TYPE(CHILD(n, 0)) == lambdef) {
 		PyObject *v;
 		int i;
@@ -1738,6 +1738,32 @@
 }
 
 static void
+com_test(c, n)
+	struct compiling *c;
+	node *n;
+{
+	int op;
+	REQ(n, test);
+	com_bool_test(c, CHILD(n, 0));
+
+	/* is there a following ternary operator? */
+	/* XXX optimize the compilation when the guard is a constant */
+	if (NCH(n) == 5)
+	{
+	    int anchor1 = 0, anchor2 = 0;
+	    com_addfwref(c, JUMP_IF_FALSE, &anchor2);
+	    com_addbyte(c, POP_TOP);
+	    com_pop(c, 1);
+	    com_node(c, CHILD(n, 2));
+	    com_addfwref(c, JUMP_FORWARD, &anchor1);
+	    com_backpatch(c, anchor2);
+	    com_addbyte(c, POP_TOP);
+	    com_node(c, CHILD(n, 4));
+	    com_backpatch(c, anchor1);
+	}
+}
+
+static void
 com_list(c, n, toplevel)
 	struct compiling *c;
 	node *n;
@@ -2931,6 +2957,9 @@
 		break;
 	case test:
 		com_test(c, n);
+		break;
+	case bool_test:
+		com_bool_test(c, n);
 		break;
 	case and_test:
 		com_and_test(c, n);
--- Doc/ref/ref5.tex	2000/01/29 21:28:13	1.1
+++ Doc/ref/ref5.tex	2000/01/29 22:00:02
@@ -764,7 +764,7 @@
 \section{Boolean operations\label{Booleans}}
 \indexii{Boolean}{operation}
 
-Boolean operations have the lowest priority of all Python operations:
+Boolean operations have the lowest priority of all Python binary operations:
 
 \begin{verbatim}
 expression:     or_test | lambda_form
@@ -832,6 +832,24 @@
 def make_incrementor(increment):
     return lambda x, n=increment: x+n
 \end{verbatim}
+
+\section{Select\label{select}}
+\index{select}
+
+The select operator is a ternary operator with lower priority than
+boolean operations (and thus lower priority than all other binary and
+unary operators).
+
+\begin{verbatim}
+select_expr:    xor_expr | xor_expr "?" xor_expr ":" xor_expr
+\end{verbatim}
+
+If its first operand is nonempty, the value of a select operation is
+its second operand; otherwise the value is the third operand.
+
+(The semantics and precedence level of select are intended to be
+unsurprising to programmers familiar with \C's ternary select
+operator.)
 
 \section{Expression lists\label{exprlists}}
 \indexii{expression}{list}

End of diffs.
-- 
		<a href="http://www.tuxedo.org/~esr">Eric S. Raymond</a>

You know why there's a Second Amendment?  In case the government fails to
follow the first one.
         -- Rush Limbaugh, in a moment of unaccustomed profundity 17 Aug 1993



From jim at digicool.com  Sun Jan 30 14:52:32 2000
From: jim at digicool.com (Jim Fulton)
Date: Sun, 30 Jan 2000 08:52:32 -0500
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
References: <200001301332.IAA12252@eric.cnri.reston.va.us>
Message-ID: <38944220.3177B402@digicool.com>

Guido van Rossum wrote:
> 
> Dear developers,
> 
> Eric Raymond has sent me the following patch, which adds conditional
> expressions to Python.  I'd like to hear opinions on whether this is a
> good thing to add to Python, and whether this is the right syntax.

Yee ha! I think that this is a great idea. 

I'm surprised that using the colon doesn't cause problems.
I'm not a grammer lawyer, and don't care that much. I very 
much would like to see a conditional expression. I wouldn't
object if it was spelled differently than C's.

> I am a bit skeptical about whether this is sufficiently Pythonic, but
> on the other hand there have always been requests for such a feature,
> and the existing solutions are ugly:
> 
>   a and b or c
> 
> only works when you know for sure that b will never be false, and
> 
>   (a and [b] or [c])[0]
> 
> is dead ugly...

Yup.

   (a and (b,) or (c,))[0]

is even worse. ;)

Jim

--
Jim Fulton           mailto:jim at digicool.com
Technical Director   (888) 344-4332              Python Powered!
Digital Creations    http://www.digicool.com     http://www.python.org

Under US Code Title 47, Sec.227(b)(1)(C), Sec.227(a)(2)(B) This email
address may not be added to any commercial mail list with out my
permission.  Violation of my privacy with advertising or SPAM will
result in a suit for a MINIMUM of $500 damages/incident, $1500 for
repeats.



From esr at thyrsus.com  Sun Jan 30 16:59:42 2000
From: esr at thyrsus.com (Eric S. Raymond)
Date: Sun, 30 Jan 2000 10:59:42 -0500
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
In-Reply-To: <38944220.3177B402@digicool.com>; from Jim Fulton on Sun, Jan 30, 2000 at 08:52:32AM -0500
References: <200001301332.IAA12252@eric.cnri.reston.va.us> <38944220.3177B402@digicool.com>
Message-ID: <20000130105941.A10861@thyrsus.com>

Jim Fulton <jim at digicool.com>:
> I'm surprised that using the colon doesn't cause problems.

Pgen doesn't tag this ambiguous.  The LL(1) traversal actually helps
here; by the time you see a colon, you already know whether or not you're
parsing a ternary telect.
-- 
		<a href="http://www.tuxedo.org/~esr">Eric S. Raymond</a>

Don't think of it as `gun control', think of it as `victim
disarmament'. If we make enough laws, we can all be criminals.



From guido at CNRI.Reston.VA.US  Sun Jan 30 17:40:32 2000
From: guido at CNRI.Reston.VA.US (Guido van Rossum)
Date: Sun, 30 Jan 2000 11:40:32 -0500
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
In-Reply-To: Your message of "Sun, 30 Jan 2000 10:59:42 EST."
             <20000130105941.A10861@thyrsus.com> 
References: <200001301332.IAA12252@eric.cnri.reston.va.us> <38944220.3177B402@digicool.com>  
            <20000130105941.A10861@thyrsus.com> 
Message-ID: <200001301640.LAA12598@eric.cnri.reston.va.us>

> Jim Fulton <jim at digicool.com>:
> > I'm surprised that using the colon doesn't cause problems.

[ESR] 
> Pgen doesn't tag this ambiguous.  The LL(1) traversal actually helps
> here; by the time you see a colon, you already know whether or not you're
> parsing a ternary telect.

Interestingly, the very ad-hoc parsing that I described in the
compiling/parsing session on devday would be hit by this...  I was
looking for a colon at nesting level zero.  Serves me right for not
using a real parse :-)

--Guido van Rossum (home page: http://www.python.org/~guido/)



From da at ski.org  Sun Jan 30 19:07:51 2000
From: da at ski.org (David Ascher)
Date: Sun, 30 Jan 2000 10:07:51 -0800
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
References: <200001301332.IAA12252@eric.cnri.reston.va.us> <38944220.3177B402@digicool.com>             <20000130105941.A10861@thyrsus.com>  <200001301640.LAA12598@eric.cnri.reston.va.us>
Message-ID: <004101bf6b4c$ed2ab9b0$0100000a@ski.org>

FWIW, the lack of a ternary select is one of the frequently asked questions
in my Python courses.  It would make TomC happier as well.  I'm not sure the
latter is a feature. =)

On the topic of aesthetics, the C syntax doesn't strike me as the ultimate
in pythonicity but it's not too bad either.  I can't think of an alternative
that doesn't involve a new reserved word.

--david






From gvwilson at nevex.com  Sun Jan 30 21:22:21 2000
From: gvwilson at nevex.com (gvwilson at nevex.com)
Date: Sun, 30 Jan 2000 15:22:21 -0500 (EST)
Subject: [Python-Dev] Eight suggestions for Python books
Message-ID: <Pine.LNX.4.10.10001301519420.3368-100000@akbar.nevex.com>

I realize this is a bit off-topic, but based on discussions with various
publishers over the last couple of years, and on conversations at the
conference last week, I wrote up some notes on books that I think would
help Python succeed, and posted them to comp.lang.python under the heading
"Eight suggestions for Python books".  Some of the books are specificially
about Python, while others try to use Python to fill holes in the
curriculum, and thereby get Python into colleges through the side door (in
the same way that networking and computer graphics texts helped C become
more popular).  Hope it's useful...

Greg




From mal at lemburg.com  Sun Jan 30 22:34:51 2000
From: mal at lemburg.com (M.-A. Lemburg)
Date: Sun, 30 Jan 2000 22:34:51 +0100
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
References: <200001301332.IAA12252@eric.cnri.reston.va.us>
Message-ID: <3894AE7A.BE89D9B4@lemburg.com>

> --- Include/token.h     2000/01/28 17:38:55     1.1
> +++ Include/token.h     2000/01/29 01:27:00
> @@ -74,10 +74,11 @@
>  #define LEFTSHIFT      34
>  #define RIGHTSHIFT     35
>  #define DOUBLESTAR     36
> +#define QUERY          37
>  /* Don't forget to update the table _PyParser_TokenNames in tokenizer.c! */
> -#define OP             37
> -#define ERRORTOKEN     38
> -#define N_TOKENS       39
> +#define OP             38
> +#define ERRORTOKEN     39
> +#define N_TOKENS       34

Shouldn't this read #define N_TOKENS 40 ?!

Apart from that I wouldn't mind having this patch in the core :-)

-- 
Marc-Andre Lemburg
______________________________________________________________________
Business:                                      http://www.lemburg.com/
Python Pages:                           http://www.lemburg.com/python/




From tim_one at email.msn.com  Mon Jan 31 00:25:30 2000
From: tim_one at email.msn.com (Tim Peters)
Date: Sun, 30 Jan 2000 18:25:30 -0500
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
In-Reply-To: <200001301332.IAA12252@eric.cnri.reston.va.us>
Message-ID: <000301bf6b79$4f0c8a60$482d153f@tim>

[Guido van Rossum]
> Eric Raymond has sent me the following patch, which adds conditional
> expressions to Python.  I'd like to hear opinions on whether this
> is a good thing to add to Python,

Marginal; not evil, but of minor utility.

> and whether this is the right syntax.

If and only if you were a C programmer first.  BTW, insert <wink>s where
needed throughout <wink>.

> I am a bit skeptical about whether this is sufficiently Pythonic,
> but on the other hand there have always been requests for such a
> feature,

There have always been requests for the union of all features from all other
languages.

> and the existing solutions are ugly:
>
>   a and b or c
>
> only works when you know for sure that b will never be false,

Too error prone.

> and
>
>   (a and [b] or [c])[0]
>
> is dead ugly...

Well, I'm the guy who invented that one!  The thread that spawned it was
just playfully wondering whether it was *possible* -- and if I didn't solve
it, Majewski would have using even uglier __xxx__ trickery.  I've never used
it in a real program, and shoot people who do.

So there is no reasonable way to spell ?: as a one-liner today, period.  The
question is whether that's "a lack" worth doing something about.  I can live
without it.

Surprised that Jim (Fulton) seems so keen on it:  his cPickle.c uses ?:
exactly once in 4400 lines of C, and in a line that would have been clearer
if C had a max function (or is it min?  it can take a while to
reverse-engineer the intent of a ?:! ... not good when it happens; and I
recall one of the contributed patches that went into 1.5.2 longobject.c,
that had Guido & I both cracking a C manual just to figure out how C would
*parse* a particularly nutso blob of nested ?: thingies).

If this goes in (I'm not deadly opposed, just more opposed than in favor),
I'd like to see "else" used instead of the colon (cond "?" true "else"
false).  The question mark is reasonably mnemonic, but a colon makes no
sense here.

Now let's see whether people really want the functionality or are just
addicted to C syntax <ahem>.

BTW, a number of other changes would be needed to the Lang Ref manual (e.g.,
section 2.6 (Delimeters) explicitly says that "?" isn't used in Python
today, and that its appeareance outside a string literal or comment is "an
unconditional error"; etc).

crabby-old-man-ly y'rs  - tim





From esr at thyrsus.com  Mon Jan 31 00:43:17 2000
From: esr at thyrsus.com (Eric S. Raymond)
Date: Sun, 30 Jan 2000 18:43:17 -0500
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
In-Reply-To: <000301bf6b79$4f0c8a60$482d153f@tim>; from Tim Peters on Sun, Jan 30, 2000 at 06:25:30PM -0500
References: <200001301332.IAA12252@eric.cnri.reston.va.us> <000301bf6b79$4f0c8a60$482d153f@tim>
Message-ID: <20000130184317.A12833@thyrsus.com>

Tim Peters <tim_one at email.msn.com>:
> If this goes in (I'm not deadly opposed, just more opposed than in favor),
> I'd like to see "else" used instead of the colon (cond "?" true "else"
> false).  The question mark is reasonably mnemonic, but a colon makes no
> sense here.

I have to say that I think any ternary syntax that mixes a single-character
operator with a keyword would be intolerably ugly.
 
> Now let's see whether people really want the functionality or are just
> addicted to C syntax <ahem>.

It's not that simple.  People clearly want the functionality; we've
seen ample evidence of that.  Given that, I think the presumption has
to be in favor of using the familiar C syntax rather than an invention
that would necessarily be more obscure.

> BTW, a number of other changes would be needed to the Lang Ref manual (e.g.,
> section 2.6 (Delimeters) explicitly says that "?" isn't used in Python
> today, and that its appeareance outside a string literal or comment is "an
> unconditional error"; etc).

I'm certainly willing to fix that.
-- 
		<a href="http://www.tuxedo.org/~esr">Eric S. Raymond</a>

[The disarming of citizens] has a double effect, it palsies the hand
and brutalizes the mind: a habitual disuse of physical forces totally
destroys the moral [force]; and men lose at once the power of
protecting themselves, and of discerning the cause of their
oppression.
        -- Joel Barlow, "Advice to the Privileged Orders", 1792-93



From dascher at mindspring.com  Mon Jan 31 01:09:39 2000
From: dascher at mindspring.com (David Ascher)
Date: Sun, 30 Jan 2000 16:09:39 -0800
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
References: <200001301332.IAA12252@eric.cnri.reston.va.us> <000301bf6b79$4f0c8a60$482d153f@tim> <20000130184317.A12833@thyrsus.com>
Message-ID: <005c01bf6b7f$7a3a8f60$0100000a@ski.org>

> > Now let's see whether people really want the functionality or are just
> > addicted to C syntax <ahem>.
>
> It's not that simple.  People clearly want the functionality; we've
> seen ample evidence of that.

I personally haven't been stunned by the ample evidence you mention.  While
folks do ask about the ternary select periodically in classes and on the
net, none of my students at least are especially upset when I point out the
readability of:

if a:
      b = c
else:
      b = d

> Given that, I think the presumption has
> to be in favor of using the familiar C syntax rather than an invention
> that would necessarily be more obscure.

The presumption from the language design point of view is to do what's right
regardless of language background, not what's in C -- when Guido remembered
that, he chose 'and' and 'or' over '&&' and '||'.  When Guido forgot that,
he chose integer division =).  While all of the folks on this list are
comfortable with C, I can point out that a (possibly surprisingly) large
proportion of the Python programmers I have taught have never used C or
never felt comfortable with it. If CP4E succeeds, that proportion will grow,
not shrink.

I do think that taking a page from Randy Pausch would be a good idea in this
case.  My guess is that english words would emerge from trying to teach
non-programmers the concept, but I of course don't have data on the topic.
I wonder how high-school teachers teach the hook-colon in C intro classes,
specifically what _words_ they use.  Those words might lead to alternative
syntaxes.

Finally, something at the edge of my brain is trying to combine the logic of
the ternary select (which is clearly related to control flow) and a more
generalized switch statement.  But I'm not seeing anything syntactically
appealing at present.

That said, the hook-colon syntax is appealing from a release management
perspective because it fits within the current set of reserved words and
clearly isn't the hardest concept to teach.

--david




From petrilli at amber.org  Mon Jan 31 01:54:06 2000
From: petrilli at amber.org (Christopher Petrilli)
Date: Sun, 30 Jan 2000 19:54:06 -0500
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
In-Reply-To: <005c01bf6b7f$7a3a8f60$0100000a@ski.org>; from dascher@mindspring.com on Sun, Jan 30, 2000 at 04:09:39PM -0800
References: <200001301332.IAA12252@eric.cnri.reston.va.us> <000301bf6b79$4f0c8a60$482d153f@tim> <20000130184317.A12833@thyrsus.com> <005c01bf6b7f$7a3a8f60$0100000a@ski.org>
Message-ID: <20000130195406.A25682@trump.amber.org>

The question comes from what "problem" you're trying to solve.  The ?: syntax
does not introduce any new "functionality" to the language, nor does it
make it capable of solving problems or requirements that it can not do
at the current time.

The second qustion I'd ask is, who is this aimed at?  It's certainly not
aimed at first-time programmers, as I know from experience that the ?:
is one of the hardest things to teach people in C (after pointers), and
often I leave it out of training when I did it.  It's simply a "shorthand"
not a new functionality.  If its aimed at experienced programmers, I'd 
argue that it's at best "non-pythonic" and at worst a hack, taken from
a language in which it exposes the "macro assembler" approach.

Python is not a language that has been optimized for "minimal typing", it's
much more verbose than most languages, and so that argument shouldn' be
applied.  Perhaps it's for optimization?  That was I believe the original
argument made for it in K&R, in that optimizers in that day were rather
antiquated, wheras today, I believe that any C compiler would get it
right if it were expressed in its full form. (Timbot?)

So, it comes down to a few questions for me:

	Does it solve a new problem?	No
	Is it pythonic?			No
	Does it make it faster?		No

Given Pyton's CP4E goals, and its general place as an easy to use 
language, I'd argue this patch would be counter to all of those goals.

Sorry if I pushed someone's buton, but... I saw a lot of hints at making
Python MUCH more complex, which is counter to why I changed and dropped
many other languags.

Chris
-- 
| Christopher Petrilli
| petrilli at amber.org



From tim_one at email.msn.com  Mon Jan 31 01:44:34 2000
From: tim_one at email.msn.com (Tim Peters)
Date: Sun, 30 Jan 2000 19:44:34 -0500
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
In-Reply-To: <20000130184317.A12833@thyrsus.com>
Message-ID: <000801bf6b84$588c2d60$482d153f@tim>

[Tim, tosses off   cond "?" true "else" false
 in apparent hatred of colons]

[Eric S. Raymond]
> I have to say that I think any ternary syntax that mixes a
> single-character operator with a keyword would be intolerably ugly.

It's certainly not attractive <wink>.  Guido is the Master of Syntax; if he
decides the functionality is Pythonic, he'll dream up a good Pythonic
syntax.  I'll refrain from suggesting  "if" cond "lambda" true "else" false
<wink>.

>> Now let's see whether people really want the functionality or are just
>> addicted to C syntax <ahem>.

> It's not that simple.  People clearly want the functionality; we've
> seen ample evidence of that.

I have not.  Really!  This has been debated for nearly a decade, with no
consensus (the invention of the (a and [b] or [c])[0] atrocity predates
c.l.py!).  *Some* people certainly want ?: (or equivalent) a lot; but others
are equally opposed.  Note that lack of ?: didn't have enough of a
constituency in Andrew Kuchling's eyes either to make his original "Python
Warts" paper, or its revisions:

    http://starship.python.net/crew/amk/python/writing/warts.html

No change ever proposed has failed to attract vocal & persistent supporters,
so it's not as simple as *that* either <0.5 wink>.

> Given that, I think the presumption has to be in favor of using the
> familiar C syntax rather than an invention that would necessarily be
> more obscure.

By count, I'm sure many more languages (from virtually all functional
languages to Icon) use "if cond then true else false" for this purpose;
obscurity is relative to your background.  At least "if x then y else z" is
clear on the face of it (which may betray my background <wink>).  "then" has
no chance of getting into Python1, though.

My core objection is that ?: doesn't "look pretty":  it's not at all
suggestive of what it means, and the effects on precedence and associativity
are unattractive ("see C, copy C" is the only sense there is to it, and
rules for ?: are-- as I noted last time --obscure).  Good syntax counts for
a lot in Python -- which is why it doesn't look like C now.

Get a good syntax, and most of my objections vanish; I don't have a good
syntax to suggest, though.

passing-the-ball-back-to-guido-where-he-always-knew-it-
    would-land<wink>-ly y'rs  - tim





From esr at thyrsus.com  Mon Jan 31 02:07:11 2000
From: esr at thyrsus.com (Eric S. Raymond)
Date: Sun, 30 Jan 2000 20:07:11 -0500
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
In-Reply-To: <20000130195406.A25682@trump.amber.org>; from Christopher Petrilli on Sun, Jan 30, 2000 at 07:54:06PM -0500
References: <200001301332.IAA12252@eric.cnri.reston.va.us> <000301bf6b79$4f0c8a60$482d153f@tim> <20000130184317.A12833@thyrsus.com> <005c01bf6b7f$7a3a8f60$0100000a@ski.org> <20000130195406.A25682@trump.amber.org>
Message-ID: <20000130200711.A13063@thyrsus.com>

Christopher Petrilli <petrilli at amber.org>:
> The question comes from what "problem" you're trying to solve.  The ?: syntax
> does not introduce any new "functionality" to the language, nor does it
> make it capable of solving problems or requirements that it can not do
> at the current time.

Well, in a theoretical sense, you're right.  But then, even troff macros and
INTERCAL are Turing-complete <my-first-attempt-at-a-Tim-Peters-style-wink>.

One of the lessons of Python to this old LISPer is that *notation
matters*.  Theoretically, Python is a subset of Scheme-with-objects
using a vaguely C-like surface notation.  But even I would rather write
a for-loop than the equivalent recursion.  That's why I code in Python
now instead of trying to rescue LISP from its desuetitude.

So while it is *theoretically* true that ?: adds nothing, it is
*practically* true that it enables a large class of idioms that 
can't otherwise be comfortably expressed.  That matters.

Now, you can argue that the complexity ?: adds to language is not paid
for by the additional convenience; I disagree, but that's at least a
defensible argument.  But simply saying it "adds nothing to the
language" is a red herring -- neither do many of the other base
language features.

Why, for example, do we have more than one kind of loop construct?
Unecessary.  Wasteful.  Clearly either "for" or "while" must go.
As an exercise, try editing your complaint so that it refers to 
"for" everywhere it now refers to ?:.  Contemplate the edited
version until you achieve enlightenment ;-).
-- 
		<a href="http://www.tuxedo.org/~esr">Eric S. Raymond</a>

The same applies for other kinds of long-lasting low-level pain. [...]
The body's response to being jabbed, pierced, and cut is to produce
endorphins. [...]  So here's my programme for breaking that cycle of
dependency on Windows: get left arm tattooed with dragon motif, buy a
crate of Jamaican Hot! Pepper Sauce, get nipples pierced.  With any
luck that will produce enough endorphins to make Windows completely
redundant, and I can then upgrade to Linux and get on with things.
	-- Pieter Hintjens



From ping at lfw.org  Mon Jan 31 02:29:43 2000
From: ping at lfw.org (Ka-Ping Yee)
Date: Sun, 30 Jan 2000 19:29:43 -0600 (EST)
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
In-Reply-To: <000301bf6b79$4f0c8a60$482d153f@tim>
Message-ID: <Pine.LNX.4.10.10001301925190.24976-100000@server1.lfw.org>

On Sun, 30 Jan 2000, Tim Peters wrote:
> If this goes in (I'm not deadly opposed, just more opposed than in favor),
> I'd like to see "else" used instead of the colon (cond "?" true "else"
> false).  The question mark is reasonably mnemonic, but a colon makes no
> sense here.

I agree with that sentiment (along the lines of the philosophy that
chose "and" over "&&"), and it seems to me that it makes the most sense
to use words for both:

    a = x > 0 then x else -x

I don't have the time to do it right this second, but i suggest that
a scan through a decent chunk of Python would be useful to find out how
often this construct (in its "and"/"or" incarnation) actually gets used.
I promise to give it a try as soon as i get my notebook battery charged
up again.


-- ?!ng




From tim_one at email.msn.com  Mon Jan 31 03:41:59 2000
From: tim_one at email.msn.com (Tim Peters)
Date: Sun, 30 Jan 2000 21:41:59 -0500
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
In-Reply-To: <20000130195406.A25682@trump.amber.org>
Message-ID: <000201bf6b94$bfabc360$ee2d153f@tim>

[Christopher Petrilli]
> ...
> Python is not a language that has been optimized for "minimal
> typing", it's much more verbose than most languages, and so that
> argument shouldn't be applied.

Concise expression of common concepts is a Good Thing, though, and there's
nothing inherently evil about wanting one of two outcomes <wink>.  My
impression is that the people historically most in favor of ?: ("or
something like it") are also the ones most strongly in favor of embedded
assignment ("or something like it"), and I can't *dismiss* either gripe.
The Python

while 1:
    x = something_or_other()
    if not x:
        break
    consume(x)

idiom is truly grating at first -- more so than the multi-line ?:
alternatives, in my eyes.

> Perhaps it's for optimization?  That was I believe the original
> argument made for it in K&R, in that optimizers in that day were rather
> antiquated, wheras today, I believe that any C compiler would get it
> right if it were expressed in its full form. (Timbot?)

Indeed, a couple weeks ago we tracked down a "mysterious slowdown" of our
core speech recognizer to a particular compiler failing to optimize *unless*
we changed a ?: into a long winded if/else!  There's really nothing you can
say about "any C compiler" -- optimization is much more a black art than
anyone in that business will admit to in public <0.9 wink>.

C was definitely designed with "by hand" optimization in mind, and,
ironically, it's those features (particularly pointer aliasing) that make it
harder for compilers to optimize than is, say, Fortran.

But regardless of origin, ?: stands or falls on its other merits now.
Python's own implementation uses it often enough, and to good effect.  So it
can't be that Guido hates the idea <wink>.  It's just hard to love the
syntax.

> So, it comes down to a few questions for me:
>
> 	Does it solve a new problem?	No
> 	Is it pythonic?			No
> 	Does it make it faster?		No

Would a nice syntax allow clearer expression of some common computations?
Probably yes.  That's the same basis on which, e.g., list.pop and
list.extend and dict.get and 3-argument getattr and ... were adopted.
"Faster" applied to those too, but nobody pushed for 'em on that basis.
Clearer!  That's what really matters.  It's the same argument for list
comprehensions too.

> ...
> Sorry if I pushed someone's buton, but... I saw a lot of hints at making
> Python MUCH more complex, which is counter to why I changed and dropped
> many other languags.

A good antitode to feature panic is reviewing Misc/HISTORY:  Guido's
willingness to entertain suggestions far exceeds his willingness to adopt
them <wink>.

it-would-be-different-if-features-were-just-as-easy-to-
    take-out-ly y'rs  - tim





From tismer at tismer.com  Mon Jan 31 12:46:50 2000
From: tismer at tismer.com (Christian Tismer)
Date: Mon, 31 Jan 2000 12:46:50 +0100
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
References: <Pine.LNX.4.10.10001301925190.24976-100000@server1.lfw.org>
Message-ID: <3895762A.C1706E8@tismer.com>


Ka-Ping Yee wrote:
> 
> On Sun, 30 Jan 2000, Tim Peters wrote:
> > If this goes in (I'm not deadly opposed, just more opposed than in favor),
> > I'd like to see "else" used instead of the colon (cond "?" true "else"
> > false).  The question mark is reasonably mnemonic, but a colon makes no
> > sense here.
> 
> I agree with that sentiment (along the lines of the philosophy that
> chose "and" over "&&"), and it seems to me that it makes the most sense
> to use words for both:
> 
>     a = x > 0 then x else -x

I would favorise this as well instead of using ?: .
Maybe it would make sense to be even more verbose and use an "if"
as well?

       a = if x > 0 then x else -x

       sign = lambda x: if x > 0 then 1 elif x then -1 else 0

ciao - chris

-- 
Christian Tismer             :^)   <mailto:tismer at appliedbiometrics.com>
Applied Biometrics GmbH      :     Have a break! Take a ride on Python's
D?ppelstr. 31                :    *Starship* http://starship.python.net
12163 Berlin                 :     PGP key -> http://wwwkeys.pgp.net
PGP Fingerprint       E182 71C7 1A9D 66E9 9D15  D3CC D4D7 93E2 1FAE F6DF
     we're tired of banana software - shipped green, ripens at home



From gward at cnri.reston.va.us  Mon Jan 31 15:15:08 2000
From: gward at cnri.reston.va.us (Greg Ward)
Date: Mon, 31 Jan 2000 09:15:08 -0500
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
In-Reply-To: <Pine.LNX.4.10.10001301925190.24976-100000@server1.lfw.org>; from ping@lfw.org on Sun, Jan 30, 2000 at 07:29:43PM -0600
References: <000301bf6b79$4f0c8a60$482d153f@tim> <Pine.LNX.4.10.10001301925190.24976-100000@server1.lfw.org>
Message-ID: <20000131091507.A17073@cnri.reston.va.us>

On 30 January 2000, Ka-Ping Yee said:
> On Sun, 30 Jan 2000, Tim Peters wrote:
> > If this goes in (I'm not deadly opposed, just more opposed than in favor),
> > I'd like to see "else" used instead of the colon (cond "?" true "else"
> > false).  The question mark is reasonably mnemonic, but a colon makes no
> > sense here.
> 
> I agree with that sentiment (along the lines of the philosophy that
> chose "and" over "&&"), and it seems to me that it makes the most sense
> to use words for both:
> 
>     a = x > 0 then x else -x

Yeah, I agree with Tim: it's a handy feature and I frequently wish I
could do simple conditional assignment without resorting to a full-blown
if/else.  (I think I stumbled across "a and b or c" myself -- either
that or it was suggested by *Learning Python*, but lay dormant in my
subconscious for several months -- which means that I missed the "b must
always be true" subtlety until it bit me.  Ouch.  I avoid that idiom
now.)

BUT the C line-noise syntax is not appropriate.  It's fine in C, and
it's eminently appropriate in Perl -- both languages designed to
minimise wear-and-tear of programmers' keyboards.  But keyboards are
cheap nowadays, so perhaps we can be a bit more profligate with them.

I find Ping's proposed syntax intriguing.  Personally, I've always been
partial to the

    x = if a then b else c

syntax, even though I don't think I've ever used a language that
includes it.  (Oh wait, the toy ALGOL-knockoff that we used in Intro to
Compilers had it, so I *have* written a parser and simplistic code
generator for a language that includes it.  Perhaps that's why I like
it...)

But either of these -- ie. elevate "then" to keywordhood, with or
without "if", and no colons to be seen -- smell like they would play
havoc with Python's grammar.  And they turn a statement keyword "if"
into an expression keyword.  Not being at all familiar with Python's
parser, I should just shut up now, but it feels tricky.

And of course, any proposed syntax changes nowadays have to take JPython
into account.

        Greg



From guido at CNRI.Reston.VA.US  Mon Jan 31 15:36:52 2000
From: guido at CNRI.Reston.VA.US (Guido van Rossum)
Date: Mon, 31 Jan 2000 09:36:52 -0500
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
In-Reply-To: Your message of "Mon, 31 Jan 2000 09:15:08 EST."
             <20000131091507.A17073@cnri.reston.va.us> 
References: <000301bf6b79$4f0c8a60$482d153f@tim> <Pine.LNX.4.10.10001301925190.24976-100000@server1.lfw.org>  
            <20000131091507.A17073@cnri.reston.va.us> 
Message-ID: <200001311436.JAA15213@eric.cnri.reston.va.us>

> I find Ping's proposed syntax intriguing.  Personally, I've always been
> partial to the
> 
>     x = if a then b else c
> 
> syntax, even though I don't think I've ever used a language that
> includes it.  (Oh wait, the toy ALGOL-knockoff that we used in Intro to
> Compilers had it, so I *have* written a parser and simplistic code
> generator for a language that includes it.  Perhaps that's why I like
> it...)

Yes, this was in original Algol 60 and, by magic of a completely
different kind, again in Algol 68 (which was a completely different
language, and the Mount Everest of languages).

> But either of these -- ie. elevate "then" to keywordhood, with or
> without "if", and no colons to be seen -- smell like they would play
> havoc with Python's grammar.  And they turn a statement keyword "if"
> into an expression keyword.  Not being at all familiar with Python's
> parser, I should just shut up now, but it feels tricky.

The solution can be the same as what Algol used: 'if' outside
parentheses is a statement, and inside parentheses is an expression.
It's a bit of a grammar rearrangement, but totally unambiguous.

However, the added keyword means it won't be in 1.6.  The lively
discussion means that Eric's patch will have a hard time getting in
too...

--Guido van Rossum (home page: http://www.python.org/~guido/)



From jim at digicool.com  Mon Jan 31 16:04:45 2000
From: jim at digicool.com (Jim Fulton)
Date: Mon, 31 Jan 2000 10:04:45 -0500
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
References: <200001301332.IAA12252@eric.cnri.reston.va.us> <000301bf6b79$4f0c8a60$482d153f@tim> <20000130184317.A12833@thyrsus.com> <005c01bf6b7f$7a3a8f60$0100000a@ski.org> <20000130195406.A25682@trump.amber.org>
Message-ID: <3895A48D.F69B3DFA@digicool.com>

Christopher Petrilli wrote:
> 
> The question comes from what "problem" you're trying to solve. 

It would allow you to incorporate logic into expressions. 
There are contexts where only expressions are allowed, such as:

  - lambdas

  - DTML expr attributes

in which I'd very much like to incorporate tests.

> The ?: syntax
> does not introduce any new "functionality" to the language,

Yes it does.

> nor does it
> make it capable of solving problems or requirements that it can not do
> at the current time.

Ditto.
 
> The second qustion I'd ask is, who is this aimed at?  It's certainly not
> aimed at first-time programmers, as I know from experience that the ?:
> is one of the hardest things to teach people in C (after pointers),

Hm. I can't agree.

Smalltalk, came out of an essentially CP4E effort
two decades ago at Xerox PARC.  Smalltalk *only* had conditional
expressions. The message:

  [condition] ifTrue: [do something ...]
              ifFalse: [do something else ...]

is an expression in Smalltalk.

> and
> often I leave it out of training when I did it.  It's simply a "shorthand"
> not a new functionality. 

No, it allows testing in expressions.

> If its aimed at experienced programmers, I'd
> argue that it's at best "non-pythonic" and at worst a hack, taken from
> a language in which it exposes the "macro assembler" approach.

I don't agree.

> Python is not a language that has been optimized for "minimal typing",

That's not the issue.

> it's
> much more verbose than most languages, and so that argument shouldn' be
> applied.  Perhaps it's for optimization?  That was I believe the original
> argument made for it in K&R, in that optimizers in that day were rather
> antiquated, wheras today, I believe that any C compiler would get it
> right if it were expressed in its full form. (Timbot?)
> 
> So, it comes down to a few questions for me:
> 
>         Does it solve a new problem?    No

Yes.

>         Is it pythonic?                 No

Pythonicity is relative.

>         Does it make it faster?         No

Who cares?
 
Jim

--
Jim Fulton           mailto:jim at digicool.com   Python Powered!        
Technical Director   (888) 344-4332            http://www.python.org  
Digital Creations    http://www.digicool.com   http://www.zope.org    

Under US Code Title 47, Sec.227(b)(1)(C), Sec.227(a)(2)(B) This email
address may not be added to any commercial mail list with out my
permission.  Violation of my privacy with advertising or SPAM will
result in a suit for a MINIMUM of $500 damages/incident, $1500 for
repeats.



From tismer at tismer.com  Mon Jan 31 16:59:15 2000
From: tismer at tismer.com (Christian Tismer)
Date: Mon, 31 Jan 2000 16:59:15 +0100
Subject: [Python-Dev] Riskless deletion of nested structures
Message-ID: <3895B153.3D2E763D@tismer.com>

Howdy,

Please review!

While implementing Stackless Python, a new problem arose:
Nested structures like frame chains and tracebacks can now
easily grow somuch that they cause a stack overflow on deallocation.

To protect lists, tuples, frames, dicts and tracebacks against
this, I wrote a stackless deallocator.
At the moment, everything is done in trashcan.c .
This gives a slight performance loss of 5% for pystone, most probably
due to the double indirection and non-local code reference.
It is yet a hack, since I'm grabbing the tp->dealloc pointers of these
types and replace them by safe versions. This just in order to
try out things quickly. Later I will change this and incorporate
the stack checks into the affected modules, after I got some
feedback on this.

This patch applies to Stackless and standard Python as well:
Deallocation of deeply nested structures will never again cause
a stack overflow.

Installation for the intermediate version:
Insert a line

	_Py_trashcan_install();

at the end of Py_Initialize in pythonrun.c

Please try it and check my code wether there is a better solution.

cheers - chris

-- 
Christian Tismer             :^)   <mailto:tismer at appliedbiometrics.com>
Applied Biometrics GmbH      :     Have a break! Take a ride on Python's
D?ppelstr. 31                :    *Starship* http://starship.python.net
12163 Berlin                 :     PGP key -> http://wwwkeys.pgp.net
PGP Fingerprint       E182 71C7 1A9D 66E9 9D15  D3CC D4D7 93E2 1FAE F6DF
     we're tired of banana software - shipped green, ripens at home
-------------- next part --------------
A non-text attachment was scrubbed...
Name: trashcan.c
Type: application/x-unknown-content-type-cfile
Size: 2209 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/python-dev/attachments/20000131/4c063f63/attachment-0002.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: trashcan.h
Type: application/x-unknown-content-type-hfile
Size: 246 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/python-dev/attachments/20000131/4c063f63/attachment-0003.bin>

From fdrake at acm.org  Mon Jan 31 18:08:11 2000
From: fdrake at acm.org (Fred L. Drake, Jr.)
Date: Mon, 31 Jan 2000 12:08:11 -0500 (EST)
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
In-Reply-To: <Pine.LNX.4.10.10001301925190.24976-100000@server1.lfw.org>
References: <000301bf6b79$4f0c8a60$482d153f@tim>
	<Pine.LNX.4.10.10001301925190.24976-100000@server1.lfw.org>
Message-ID: <14485.49531.600935.643400@weyr.cnri.reston.va.us>

Ka-Ping Yee writes:
 > a scan through a decent chunk of Python would be useful to find out how
 > often this construct (in its "and"/"or" incarnation) actually gets used.

  I'm not sure what the survey provides other than a lower bound.  I
think most Python programmers who want the ?: functionality avoid the
and/or approach because of the ugliness.  I know I do.
  But I'd really like to have the functionality if the syntax is
reasonable!  I could live with something like "if cond then true else
false"; the leading "if" is visually important; without it, you have
to scan over the test expression to find the "then", and that makes it
harder to read.


  -Fred

--
Fred L. Drake, Jr.	  <fdrake at acm.org>
Corporation for National Research Initiatives



From bwarsaw at cnri.reston.va.us  Mon Jan 31 18:33:25 2000
From: bwarsaw at cnri.reston.va.us (Barry A. Warsaw)
Date: Mon, 31 Jan 2000 12:33:25 -0500 (EST)
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
References: <000301bf6b79$4f0c8a60$482d153f@tim>
	<Pine.LNX.4.10.10001301925190.24976-100000@server1.lfw.org>
	<14485.49531.600935.643400@weyr.cnri.reston.va.us>
Message-ID: <14485.51045.97448.830202@anthem.cnri.reston.va.us>

Put me in the camp of "yeah, occasionally I wish I had it, but I can
always hack around it, and the C syntax just blows".  I'm sure if it's
wedgeable into CPython it would also be in JPython, but I dislike ?:
syntax enough to vote strongly against it for CPython 1.6.

A Forth-ish syntax might be more acceptable

    x = y > z if y else z

but come on!  You'll give ordinarily dandruff-free Python programmers
plenty of other reasons to scratch their heads with this one.

head-and-shoulders-above-the-rest-ly y'rs,
-Barry



From gvwilson at nevex.com  Mon Jan 31 18:44:53 2000
From: gvwilson at nevex.com (gvwilson at nevex.com)
Date: Mon, 31 Jan 2000 12:44:53 -0500 (EST)
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
In-Reply-To: <3895A48D.F69B3DFA@digicool.com>
Message-ID: <Pine.LNX.4.10.10001311239400.11154-100000@akbar.nevex.com>

> It (?:) would allow you to incorporate logic into expressions. 
> There are contexts where only expressions are allowed, such as:
>   - lambdas
>   - DTML expr attributes
> in which I'd very much like to incorporate tests.

Don't know much about DTML, but believe that being able to put
conditionals in lambdas would make the latter much more useful.

> > The ?: syntax
> > does not introduce any new "functionality" to the language,
> Yes it does.

Is anything possible with ?: that's impossible without? No --- Python is
Turing-equivalent before and after the change.

Is anything easier with ?: --- yes.

Does this make up for the added complexity?  Dunno (see below).

> > The second qustion I'd ask is, who is this aimed at?  It's certainly not
> > aimed at first-time programmers, as I know from experience that the ?:
> > is one of the hardest things to teach people in C (after pointers),
> Hm. I can't agree.

Strongly agree with the first author --- IME, ?: is very hard to teach.

Greg




From klm at digicool.com  Mon Jan 31 18:58:07 2000
From: klm at digicool.com (Ken Manheimer)
Date: Mon, 31 Jan 2000 12:58:07 -0500 (EST)
Subject: [Python-Dev] Adding C ternary select (a?b:c) to Python?
In-Reply-To: <14485.49531.600935.643400@weyr.cnri.reston.va.us>
Message-ID: <Pine.LNX.4.10.10001311236250.11106-100000@splat.digicool.com>

On Mon, 31 Jan 2000, Fred L. Drake, Jr. wrote:

> Ka-Ping Yee writes:
>  > a scan through a decent chunk of Python would be useful to find out how
>  > often this construct (in its "and"/"or" incarnation) actually gets used.
> 
>   I'm not sure what the survey provides other than a lower bound.  I
> think most Python programmers who want the ?: functionality avoid the
> and/or approach because of the ugliness.  I know I do.

Good point.  Just because the workaround is bad doesn't mean the thing
being worked-around is unimportant...

I should weigh in to say that i have really really wanted, in particular,
the ability to have a condition on the right hand side of an assignement.
IIR, on some occasions it seemed less clear to have to use separate
statements for what was essentially a single assignment that just, eg,
differed by a single term.  I wanted (want) some reasonable way to express
the condition in an expression.  I can see how this compactness could lead
to regex-style convolution of expressions, but that could be avoided by
providing a not-too-terse syntax.

(I should admit that may have succumbed to the (a and (b,) or (c,))[0]
grotesquerie at some point!  Not sure.  Wish i could recall what might
have justified succumbing - the mere fact that i may have, without
compelling justification, might-should disqualify my judgement on the
matter, ay?  Hey, maybe i didn't, i was just imagining it - now am i not a
sterling judge?-)

Ken
klm at digicool.com




From tismer at tismer.com  Mon Jan 31 20:55:36 2000
From: tismer at tismer.com (Christian Tismer)
Date: Mon, 31 Jan 2000 20:55:36 +0100
Subject: [Python-Dev] Ann: Stackless Python 1.02
Message-ID: <3895E8B8.995CA560@tismer.com>

Stackless Python is a Python without C stack usage.
It allows for all kinds of non-local control flow.
For info see http://www.tismer.com/research/stackless/

Update for Stackless Python V. 1.02:

- passes all standard tests
- should work with Zope now (try...finally was incorrect)
- has a smart object destructor for really deeply nested stuff

The "5 percent speedup" is no longer there currently, since
the smart object destructor needs to be optimized into
the objects. It is not done in this test phase but will come.

Please visit the Stackless Python homepage at

http://www.tismer.com/research/stackless/

Fact sheet, links to documentation, source and
binaries can be found there.

cheers - chris

<P><A HREF="http://www.tismer.com/research/stackless/">Stackless
Python 1.02 + Continuations 0.6</A> - a version of Python 1.5.2 that
does not need space on the C stack, and first-class callable
continuation objects for Python.  (31-Jan-2000)

Christian Tismer
Mission Impossible 5oftware Team