Mailing List Archive

new imputil.py
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/
Re: new imputil.py [ In reply to ]
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/
Re: new imputil.py [ In reply to ]
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/
Re: new imputil.py [ In reply to ]
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
Re: new imputil.py [ In reply to ]
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
Re: new imputil.py [ In reply to ]
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/
Re: new imputil.py [ In reply to ]
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
Re: new imputil.py [ In reply to ]
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/
Re: new imputil.py [ In reply to ]
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
Re: new imputil.py [ In reply to ]
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--