[Distutils] FW: new import mechanism and a "small" distribution

Greg Stein gstein@lyra.org
Sun, 31 Jan 1999 08:02:56 -0800


This is a multi-part message in MIME format.

------=_NextPart_000_0001_01BE4CF0.1C1CBCE0
Content-Type: text/plain;
	charset="iso-8859-1"
Content-Transfer-Encoding: 7bit

crap... missed the "s" in distutils. what fun now -- divergent threads (here
and python-list). sigh.

-----Original Message-----
From: Greg Stein [mailto:gstein@lyra.org]
Sent: Sunday, January 31, 1999 8:00 AM
To: distutil-sig@python.org
Cc: python-list@python.org
Subject: new import mechanism and a "small" distribution


A while back, Mark Hammond brought up a "new import architecture" proposal
after some discussion with Jack Jansen and Guido. I responded in my usual
diplomatic style and said "feh. the two-step import style is bunk." Then, I
expounded on a few of the ideas that I had come up with after working with a
lot of custom import stuff (for COM support, for sticking .pyc files into
resources or structured-storage files, or for creating distribs with very
few files). In essence, I maintained that importers should really be a
single step find-and-load, and that Python would be best served by having a
list of object instances, each performing this find-and-load step. Imagine,
if you will, replacing sys.path with a list of "directory importers" where
each importer checks a directory for the requested file. Next step in our
hypothetical case is to add a new importer into sys.path that checks the
Windows Registry for paths and looks there, or an importer that looks inside
the resource fork of a Mac file. Heck, or use the typical example: have an
importer that grabs a code object from over the web.

Okay... enough background and rambling. If you're interested, go look at the
four messages in the thread titled "Freeze and new import architecture" in
the distutils-sig archive at:
http://www.python.org/pipermail/distutils-sig/1998-December/thread.html

What I'm posting here is two things:

1) imputil.py : this is a module that defines an import utility class
(imputil.Importer). There are a few subclasses in here for different types
of importers. More detail below.

2) a "small distribution" : the demo is for Win32, but it the basic
mechanism is quite portable. In this small distro, you can place onto
somebody's computer a mere 5 files and NO registry keys. Python starts up
just fine and you can import all modules from the standard library.

Basically, imputil.Importer's logic was derived from knee.py, which is an
emulation of Python's algorithm. Importer defines one method that subclasses
should override: get_code(). The doc strings and examples in the module
cover that method relatively well. The Importer class will install an import
hook and "chain" to the previous hook. This allows the use of multiple
Importers, each one attempting to perform the import, and finally falling
back to the builtin import mechanism. (note that there is no way to
deinstall an importer at the moment, as it can't go "up" the chain to detach
itself; the "right" way to do this is to define an Importer that contains a
manageable list of Importers, and removing the chaining in favor of the
manager iterating over the list)

The small distribution replaces site.py and uses an archive of the standard
library to fetch code objects from. This library is named "py15.pyl" in the
demo, and is generated by the batch file in support/regen.bat (with the help
of support/easygen.py). The resulting library is portable, as it is merely a
giant glom of .pyc files and a marshalled table of contents (mapping module
names to file positions). Look in site.py for the SimpleArchive class to get
a feel for how to write a simple subclass of Importer.

As another demo, imputil.py contains a class named DirectoryImporter. This
subclass attempts to emulate Python's behavior for importing from a
directory. It is instantiated with a directory to look in, for modules and
packages. If a module is found, it will perform the usual .pyc caching if
necessary (or use the cached .pyc). There is a demo function named
imputil._test_dir() that will read sys.path and construct a chain of
DirectoryImporter instances. You can then import away and Python will
actually use the Importers rather than sys.path iteration.

Lastly, imputil.py contains two (untested) subclasses for importing from a
package contained in archive-type files (such as .gz, .zip, .tar, or a Mac
file of resources). For example, you could distribute "package.gz" along
with a gzip Importer. When somebody said "import package.module", it would
look inside package.gz for the "module" module.

I think that's it. This is the first release of this stuff, so there are
bound to be improvements or bugfixes or just simple comments :-).  Please
feel free to speak up.

thx,
-g

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

------=_NextPart_000_0001_01BE4CF0.1C1CBCE0
Content-Type: application/x-zip-compressed;
	name="Small.zip"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
	filename="Small.zip"

UEsDBBQAAAAIANUGnyPalk5YhwQAAAAQAAAKAAAAcHl0aG9uLmV4Ze1XT2zbVBj/HLc07Zo2QwtH
5qJW2gFFGR5iiibkwTJxaITbLmUCgRsSt07VOpHjrqvUQ9QAa2QqKsSBwg6pygEiDkXqYYIdMq0i
CHVakXrYoUI5DCmCHRCnHSoe3/NznaTLNg7TJFB/yc/v/b73fZ/fv9gv0beXgQeANiQhANeAQYLH
I4fsOf59D2x03uq7xg3e6rugpbJCxkhPGPFpIRHX9bQpvK8KxowupHTh3JsjwnQ6qQZ9vq5+J4cc
ARjk2qHv129O7eetQi93hGv3gAdFF7OF/HihFKiSWN3D+k2xX8JYXfD21c983dItGCSAM7SUAa7y
8MQwLz16DoOmetnEcpcDdyz1QTAIOJqgkYybcYBux2D7PdPsJ+E3yNzYWEKOn/cBv3IwxRyLHDM0
znGTn5E1EuDMCc6N3bfuB/wkOMR/Gta5fq812N8mD9WOosxvem8uN4IMbEgSbLmIWfcmiQaCBNr2
UQmSqzSJnCwMgB1dHRl9q6DWKpE9qic5EvgKw/ObbZX2UEjCJwwhlfZTTo0Eitho+V5EXfCSwFWq
Aieo8q/OU+Et+E6jrD2Hu3XVj7UPyzM92jremARyLHHtZ7yR1o1tmpe6fsdGYQX6aZ7YnaXIHdny
CSiGlmLV4aXIjrwUvTtEAp/Z8ce0NhoKNPQSCyWBZXrvWLXgtyJV2YruDFmxu8O1X/4mJL/ZXYjs
yiTwMbr88YIVuWd5rc5CdBvn76Qzf5Zas2LbwyTwgTP0yB4drBX9M1nw0WlR3nvH+u3dm878LqIX
GfjcmWWNPrbwwkHtlVbrIZabdbOi+b62832L138D2rNXcT5HkIc4BPd4l0P8j2BK9fqPWN9Anmmw
fXSWnWVa4SVsex65g+27yN+RfyE9aHsW+RpyGDmGNJCfnmVx16UnEz/KyXNKNJ7SQZ4ztbR+8uVg
cmoKYBsU9XLKhDdAuZjImOdTU6ZqwHmPbYQEKEpGUZSUnjJV/RJcRD2hmtOYJ25MZKGbs5swZBoW
sC2rmjNZFHFTUw0D4EtQ4snJmaypjCdT+MpIsXyJ9DQ92wLoTI8zlWMZlHgmo5hzGbRUaO8SasZU
tLienFINESA6Mvr68AXW+w3AXLpppKfGM/BUUD97e+wzs4Dd7sHyNDviN7Rz9vNBfohda2HvbHOM
LezLWCtispoHXCyOAByrSzgB7Ngr2VHsgJxr8G9Gjt0sl2MF/VATXsrlMlqI/aV/dOyCfoj9DnxY
wjo6ZhuAC3N/sQFXUH9CXNynumHxem29QqtdJVEMMd35RakIIK6JItOwskYNJVd3LvNo4Nf2NawA
X6IZmO4Kh0OwVuTDji4h0MFtL4XD4RI67MeLohgOF7tKvKNDIo+GkqtF0fZwNW8bxKLbH2bgRdjv
D+4WVODqI+s/rIcadfl6+ZH6gD/N2KRFO72tD2KrCQCzt/fIbbK1h6IyPwtwpd7403yL+AOgy1bF
VS5jF3K41Vx2ALfA5bgFGEOGkH6uqf0AF5D5HNzIlzuQvc2sHr/RKobYG5D+hgTBb+9y+ot4Om/i
fwBQSwMEFAAAAAgAgKwwJXNJW4VvBQAAQxIAAA0AAABleGNlcHRpb25zLnB5rVhtb9s2EP6uX3Fw
UdjObCPtvgXIgHVLsGBrEzTpsC0IMlo621wkUiCpOAL643ekKJmS7MgFaiSxRN7rc8e7Y0aj0S8p
0xqWTGMCy4KnZs4F4EuMueFSwIajYirelIsouttwDfTDQOAWVshMoRC2G1S4LIGlKZgNgjZMJEzt
k6ZnkVEs4faZyEuiVVysQS7/w9joGTCSpzBPWUzWbLnZQGzNQ70AcNrX/Bl1dFOajRRjHdpJSlMr
K8OYnrnOyMxMkrxK+FwqjsKQ2BViSs58lNoQP9fGcsUyIcs3skgTeha0ViAYCVupngJDKpyinUNk
163MiFTx+KmEgkwFuYKr6wulpIKMlbBUyJ5mhIZx8GSkN4pllpHRjtxrtZosxhISrtkyJZnWYY/y
zMKqKgmV92Q7xoVxlM5AuzX/C6QzjCT9RmGpoqUKkcitsIZZosqTXWAB/pYFxEyARW7tFS/LCG2k
CJzKEJ5i5QWnHy3GhiJl/UCRYOLig3W0KoMY/HsyjmxIbbp4G3cuVSyli3mCKy4oNkyDKfKUJNgg
MC4q9RglqCjySZBKNu+ET6B5lb7BphVK6CaEw0W9OjmZRvA1gh/mc7j1SerC5Dbc56v/diSlNphd
vHATLP6O5VIS3xWlklJFHu5dZblUxkkMV6+7KxfXl92lzwWlXIbd5U+sv/azIZcpDL2N25IQe+mu
3pV5XwTFSFlEuht/SPlU5F1M3J/wxblFUW8pa3YIotZ6qFhREmRoeHyUjutnVKtUbveq+QeV/JU/
c93xoyG4TCWz6XsjuTCHLPqTpcUeJF3kO6sfkcqJd200GkVRdY6a9DpztJTJ8PhIiWseHyca09UM
Tpha6+mZFwVgVxd2Dc7BfkUBI+Wz5wsY+AqENDu+3Y79KKTTJGA8blYxJY4UxaThmML5Obzby0ca
d3T3pw/TQIzGYZZpaP6aYkvQNa7zwIuaudHFH2oM26exQdQz50TSUO6SfNLi8rS2Sgk6NQQtdQMU
kh7kaqXR0IPBF/v1SQp0xJle0yuFcufAtwWu3ujD/VMPbrdZaQzhfkUGhex9WwYXK9nif/fQ2jeq
bDPYj6OucZlVrxU2/qXCx794jKymlqSqtvalu+DYh1fyt5s2hMK0OT7imSspqIuYw1Gl4/aBKrzv
XCtqrEGpNxtmQMZxoUAWRvMEwy6p3VleODE3imdM8dT1addsmGvogdzr26pxkw115V6MvkOGuA3q
GC4hmwRsdggadHr3bQY53dr0GdMky4/t6LyhUYC2p+AkV6OTbcA0mRFLYRGnHsrjjR0SLGK1HmrM
H77czTrCtAQ/tXAxdxMaFCJn8ZNt0YlENxH4WQcX60XHmI60Kn41xDOYOGzslFMBMX2dfYs08MVP
DmNrmcsBmkukoOD60YGc2kqw5aiZHlmqZUdShszOEnZGoZSQNoloUqoTeeoRymnKMNrmVwuprlV2
IiErtpRZusjzlNsBJKTZpcGsHfhZL9St9Gl4g9y6Pz173ysfhyrHmzp4MeX7GR0Owv3xFs2lkrbR
CTmZHmfoN/SstkcEv21iNoP39697Zwe81Q/0e0a/Y3gLk8OI9UrR4Q9dKXzpqc2Zhm2utrU6n/bo
tzQdYe7rph7RUltVb9HCtK6U/qxMuhVzT5f0VewQKRW0L+66V7pszqXmL3QvSYoUm2IXigun0731
ud2hm+FpkLaehAcJg9F6kLaZeAcpd8PfIGlv7h/kaA/Zw+Sd0XiIvjUbTzrce+j70/ARTL0Z+wie
8A4xGNbmEjEJ2PbDfwxZ+240qL65Xg1SBrP/sQeA7o29SfY7zJhNgT9t1xHH5/6L0ZkSmsvAoXtA
yNkdSvv1qksd/Q9QSwMEFAAAAAgAZTs/JpD/XKucAQAATgMAAAcAAABzaXRlLnB5hVJNa9wwEL0v
7H+YxgfbYEQL7SWQQ469hECOcRFae7wWq69IcoL/fUaSWbwtoRcbad6bN2/0quOhgiAjwiQVfayH
OCPcBS2UuoPnNc7WwChD9PK0RGkNEY6H40FqZ30E+tGtup4JtwzxetTCh1moRBiUCAFeqKDw0Q+z
fMdmY7PfGY2+vT8eAEacgHNpZOS8CaimDkQhcCfibITGAgRIVabkyQu/wgNYh6b5G9tB7U91+y+B
BcRL83OrNHaaAsaupT7FBVuME8OlqR9k3d0yPYqRmF82Lb325WgHarztgylL/D2tTSsq1s8Y+WBH
3Kw74dHEDrQdi5vpbb8BOYGx8arBZhH4BdfmFgXgMS7ewJM1WK6cDR3I4C7nZHijvxban698EWkz
lSb8j6GdbNbpMikZzS8sTYgUsqbMWFVVck5R8zhES885eashrIEJf35//Z5nouYkWp/v+16vMNph
0bSc0PcuB7Xvc27T8ccv5lZVl7VWsInlcBv8ALklLlVvM0kSLbvOlqOe4pjWwjl8I3XOtZCG8zoP
znfYT1BLAwQUAAAACABoPj8mMGpxqG0PAACYMQAACgAAAGltcHV0aWwucHm1WluP28YVfq4B/4eJ
FoGoRMvYbh8KtxvDhZ100TYObCMvm4VAkaMVY4pUOEOvhSD/vec6nKG0aydIXCBdkTPnfvnODM8e
Pjgzg6+b2tfWGd+ZrW32phu8ua391pSD893O1Lt913uzs+W2aGu3c7Dt4QPc23bePjXF+66uZFXd
3sDT9nw91A38MLuuGhoLO4QI/F/42x3G58733fhmtZL9q9Vfzs7OzO32YPy2dqZunbdFZbqN+QmE
M4NDhmG5W63Ms2cs26brYY81L+relr7rD5dE2/Yxz6H04eeu6N22aHB32RTOGd3w9OEDY2b/Kpw1
/AJJ93bfFCVyd75oq6JXC5jN0Ja+7lqXz5CWMZXdkOBF02TONpsFETQG/85XK7AqKCqbL2Ld4SU/
Xq1O7Oht04Ep0h38kFefpgQbmIw82Hbdu+P1gTiv5Z+yFlef/SH/iBL9x3z/+vKH529fmv+9fPvv
Vy/ehDdovFhUsuDStMXOLs1N062Lxl1817Xwq+nK8cem73ZN7Tz9VIvP/gtLPIQ6eEzcBX9LkKq7
UJrKgt93dWsphMqu9faDx6jjKKSdvHZf9Lb1wVBho8osezMRdTHyEI8jAxaAkg5yJmK5NBBqqAo9
BFsUQ+P1JRPy3X5pfFE3U8fCixUTzlhIttqCt9Ub3GlAGzSQ2MdAWPuhb0+FZpaYXK09GjrWbGNm
Rb7Oy5m5LZzZ9937urLVEpVoDQUWqjPjJVQ2utZU3W1L1JTMGoLullaCpOeNfW8bdRUvWXce65Pq
TSGKlsiCTVKhkBTk7g61non5WU4RTbSfFbNgJChxQcVgJax841PdJpJymNjg397aiXU9lrqJXKJL
21UWxSsgsMp3xY0VybRkdTuNFidGOFNCXIyBXO2RAgo+pTJTmWcgysb2VPPRr1hZlQ7/i2SS6OwL
eIY1tWinIghvrIuQTfUHNAGRXepKje2pRLcY9U2T8lbXNE3YTgnbOksJ00ElrlsQHYUkPkDUAtNj
FYSbxo35/gDbW+Jp9nX5zgx74qOGYXIpnZB/Yo9MiC6E6j/YLURzHdyDhvIpoVsNCluRQtBde4t6
pYpA0qOlQeneGvthD+3LVhPVOuS0763D4lM0PTTFQx6CVuqAW4mk2XvobRmLv1iEME7KhVpAlt2V
2EkOkWUgg9Rj5dJUszSV1pJK8puJj30x7ixS2tl+KmVf1ODtNwfo+7uXfd/1SzOT5oQRfrCEKRq7
A0PYKuq4d5diZqMFWfjMXyQlf4blDcvSTKIaeMLv9+rBfJ5UCCGG1fpHta4+zG+sz+bagG2/Ws2X
VHQXmqYoUFRblFjVWX5PuYo+h02YWt3QhygDjuJkzUYk8RZij+xCuA6CyTKvqRpjn6EE8yMFt+2G
pmKURYlSY/9j/wfEs4eSELiKh1GzMWLewnLVJ6ihHTcSXtRyubn0nEngw7q1SueoDUO+2Ft1hvnW
xo30KyW6+RmTSiTkJrjiZ9A0RKwrcA0+Abdcj3Kz00OtEt1qj64ymUKHoNH+3Q2L13o3NtijNJzE
XIweDi4Xl14lgl7rUgCeWP3UmOBOXgdtuqrLABGDH/italQjD8TYeQ9mrbKEx9LM83mU5qN/Bu+g
c6PFgzHMtqBIAgq+Loem6CexFNQHnhfm/PEUW6QBIj2D+aUNImqryvvY8q5eN4DC1epTJye/r57W
1/GyT7C7WD2YmiMFFUtWJzUutnwMXyNAxiUogWUpRL0HTJgsJDHabu26ZvB2kStmCZ4mR8f+vcMv
W0tIf9TDKJ6cCU3bOHtq+WjQsIUe118+fnod+LGaYX/wzexzl3/uZuZzk03suyQmixPMw2ZcwA8l
diboF4IswF5cu5Stoxl4X1R3xwJCsFWtTBgcAl7Lj/0ATRHadpauH+k4LLwHiOwBamqnAey3i2mp
5M2MVO+y1hmiBt/XwHAUqEVc3B+gaAf/a4RkAa0QSyVzt5F4XGITRVY/ZaI7BNdUTu3Rzj2bIMkN
5jaWgDg/UJo0MYAax6/4TnPkUgCiwfG/CeguGuCwSEXyCEIC0BSwtK2e8WIw5NH4E1WFpBzYD6Xd
e/MfeyAsEtVx55Q5gDIc0sTU0PwBeFRjME51Co6XfXdMZHHVDM4ETXJog1pVEoondIAd/CTY6ewM
6JcdtXIGEWDUNbT6qt5AgQWBm8OzZzHXPAYyouT0vYN2SC9ZpatHUWPFCGfYuuQat63x6ATQHY89
zlKDf180Ax9JCeoPeF81EKs1ts2YzcJ8bZ4EsxHiFSiZD/sKaqqsu3pyHfU6+8GWg9c5v0qGcN4+
dyM01yiwper2+Bq7Vswt0lUHlhCHpAWgiNAjRItJ0oMRCu/745gJLKLIiF1K6TTOwQKoZRaeZA+K
BUoEPIW9ZTlO4dqB0sF7HIyR5FiWCcmRm6T5OMCeflPbpnIZLuUeFJWSU21gF3UAJLcYl+9O1a4d
L5vkkgiIyHkXMdRZgtXXWeK7Tn2DFCozM1+aEz09HlmmA1OwcpiYdKbQOtUejBvW55KOOvDR+DQz
uAPHiShD5l/MCeDJfCfrlXw4R+nehVNOALEwxgKGxVCsi7VmyBmmEAIBU1RVjQNN0VC2OSPx6haU
ZQykg3dJgvb45CPMyRckdxZUBrPRA86EhQ49LNTSXF0vQmKgzGCOk/TDjEnBgRVBKndcNPCsCNsL
tsAgOw4oWTzB7OqbracogFFZIeZnYxNGgA5SfHZByuL8g2uhcVDqgTvhbRyw8PP+iMX1yXJgeUfU
wsulEjyOWt760dAtixZXi/okG0avkI0DdpxA4hGb5oYwZ8fFhN7cP7fSIIRG+zEWM96Pg5W0Ap2s
Pnog/En/iBL9R0+LzdtX5tUPL1+/vnzxMrxF1UP3/TRcMZt9Q6nSIthC0PU+agyaajcAwdRQuca0
DBRub8t6U1s+wKNHUl0gTnmihTeKJJEiWxdgDE6+TGtXIFARqATy1HgSQfcq8dAVE6Gh3BZ9uQ0C
iYqJRAlaMhkGT9V5QEKLuOsJFg/Z+vOEDpWioWkO5z8PRYPPqriE5jDz146bebbvcCSuoQocJMyZ
IUdraDOzvuv8TBtRRIwP9qgnje2fuDC1S9oRTjfUv1QjZOXFRTgF4D0k3s76LWSnnHIk4LQwT879
sG8Y+Bfmr/wr7P9CuEZYl0+JEewKb6SkxNdW6NsqVwpv0YZ17zwjH1H8yTlyFH7RdnwHyMHewMj7
CJc8XmrSsVsOGB63W+v5gDaIhkeQJB/PIvG5Mg81PpHIARRsRzAWIr9b/2TLMdI0fmqvZ54qjYCp
Kg4nPKY5BlKLPDLmvYAQSwm2Laj1cqr8FYFDUKTu41NWE05gGXfRySqebwcB4B3oYI8UAz4qeegO
FCV6c4GtqsT7v1F9UIZI8Pks/ACOBSFBAq6ZG8qt0gIH3FKUTqKGvKKWmOmwzaX+9QB5s7Na67WQ
Gan4yYHnwwcfL5qf8o/udc/MG6If7jHP16C5Xpfh9emZXpB+Aysu5XGmf3AxnelPbEe8GlwxOCx/
btjjwWQVOKRXC5yZ3Xvb92B7x5CT+tiqbmu/Wkkxx93JVSo+gH6L//f76n98+YVU7pnZHj6IbnVX
GO7ZKE9iF3qc6/3v4k/w1+RmGtsAtKjEbVAfIr99zyXgOS/8TR4UsEGVO9vUMIsov+S6+7fZ/dSp
R70ZW+hMatbM1Ee3ibeWrkmCmhRf63MUbSQWGo3IGh3ETGd12Ix7xxMp2YIAT8SPT0juGNonY3tY
7g97G8bViwv+nUVXMmFj9miJmJrXjuLSu0fL8JzfnI3Nb3Lj6rpYb+0pdIRFt1Zcl/iQSmnpNfMM
T5BmYiulEJlKHmWpWdBxsvbeo4zowWMocLOl+WUeWXv+VP78NY0qZRqA7ATA4U0AHouJCJ0eYrn7
+n/DZ67RPoGAKF3BNR1KeF1uoQ20oeENmGDrg4niBnOELqd01qPQq31ODZYJCb4r+KBQaKGtOTeA
QbeHyEZyAkHKDhd+0H5Fbb0syi3NkngbR1dVTAhLwGYAyTUpRs1fj/bXMUv1TUDMJ3ck3X2qKY0u
05Ril8meu3zHUJvuFY3aVJCEQtAqSmPe+y1B8pNrTEZHuYy/1FkaRIvFUnwvQR57/RT0GcnHiFfF
eK7IUV2sfJeI1h3kHBYoukyJiSNXxjlMJoE5VHXxU6PoytsXPWgxHUFOeFcN+Pu8q7tPQ45TrSQ7
3VmkoZx+GbUXDOvxu4RCrV0Gf8fXuykYCJ1FC4jm0+RjKx2LLnRH8hY3waspjd9QgfjQnFlcTJge
nTKPTJNyOB71niWlha78HNYcLyNYqBo6QYhsfwLIeLmDqVPOScP9b6Xf1iVgY/xSUD4UZPcefYj3
SYDDnuKrWPSegADREtfDb/As/Dd6BuMzfuKEL1aryq4HPLXGbJyXcyy8826eroaF83x/mOMpS0zg
jwM+LGYAH/t3N/BE73aTmzBeqbqNSGCPcYHW6pwWKSqn+NEAodAWJ+rCFzliJz5Iq7Cu4LTlYxwQ
Dn+XUMvKAsE7fVqEOwqTfuEJZRbshl/zFIBB+LDD9koJO+Lky1BnsOA0OBuRfxG1dA5vc8NsGF/M
gDKibCc3bXIV89z7vl7D6JZeyEgkduFaTvYClS7c1ITswYc5fczwU1e3GdhzCvbAU7qkdvA+m9YX
o5PfhfkFT2PVc3PzdOTzaxAPz8Vg6WN9cJcoIyyYa4DrTW4SDRHzIyaPVF+/2h/CgSRWe4iG3T7w
gKim6F6Mq8v7l2sSRN8UIgvBfZRKTOWjSJD64UX0YEoL0jELtLAjTTh8fUF/jO7YoCkBR52SF6zZ
r+cxjt/keMyc/Y1QOQQPAdxdcVOXWQzOaVSgz4bzocWpJJv/83K+HLcv6LJLl6MSBPNBsuQ4V9SV
T45zzI9sE+TZ5GXTOZuNZi3ls8DEiEKE/YMQkeeW1JlLNgvv0c9YMDCWtH8pkRPV0dHTWsPSSI/T
MsrKHPb4MS2SJH31Js3OuwaBpmtvMnf1d72gI3lUs1Qa0EvlVMFQH3AOFpqJ69Hf8wX7KDWqrMc4
Gn9enT++pnuBH9t5Yu1APfrxJS1Lojj+kFqlH3fEOszx3Cn+9EauNAjcyzkV7Wfxjh1wX5RTawIe
t1Gob/LbvvY2m//4iP93/EriO4ru0dJhsUZuNUCccCDF8btpBrfNogfO2ncw0ppHR+wmyXZXEtwR
SenFOwURG4oPaFYeBF9hveYgEYCHd+P45xV/pULltodO1ys/xPt06oevhNkxfqkm5zofB1Of8u/h
g/8DUEsDBAoAAAAAAA47PyYAAAAAAAAAAAAAAAAIAAAAc3VwcG9ydC9QSwMEFAAAAAgACTA/Jgv0
yMA4BgAARBAAABIAAABzdXBwb3J0L2Vhc3lnZW4ucHmlV1tv2zYUfm6A/IfTBIXkzBGSdg+F0QTI
uq4IsHZFk2IbXENgJNohLEuaSNf1iv73fYcXXWK3GLYEiSTyXL9zI48PD45pIUvZCCNJ0FGh7o5o
rgqJjcODwwO1qqvGkN7q9n0lGn0viva76ra0adaZ6X+qctF+LqSp6m633qZZtaqtLr9k1Eqy1vTN
1evrl3RB0bs/f/0penQMYnNflQTzGtFsQfHqj1vsp2ku79aLNCVR5hRlEVUNRVXEQnI5J6XTWmRL
sZBxPpocHhCpOQxOamHuE/lZaaPjnH6g6OPHNFWlMmma1NvIkRI10qybks7/LWP2nzmrvZz+/Sy4
w/hoI1Z1zNJKsZKOy9MVVbmIoQokpqOYPp+NggB9X62LPOD+QArsDAvT02eTGV0gAAzH0LJAw4sm
hdOIwx7DEDRGhAPC/gXqvcTTyek5G2ltsFSXTvR+zZa85/fbqpSthxkyQTVxPqZ6uRiTyH3ga+Si
oaMb7JfIysnRmHJmIprDRE55UiUHqkCIrIQQEVYLs33QIjxcgfBeL7ZKMxe/Bka7XVamn4bDfaKs
Ko0q17LHAbt7BKXcYAH6+b9TzYYkUSCRhZb76HcpAzZsw9gTOoQCRWeNW1lVOQM+JvnZQGRwVdeF
MliKWceoRQIr08mzGT0e5s2u2GNecc2C5uui2J7+tRaFmiuZs8o1DGe1iU2He6UBIJ6SPIhBCFeP
At/fwig0B501qjZjpix7CnqMFPLWmuuds2keSrGzud1l4G3GIaO5o9VWommEKpBHfXzBknKoLfzn
bnUQnYFMxMZ/7+U/68DSSyi1UMgAz73QJIpGinxLdxL+av6HBBaUq/lcNhLJjlgHEchCOWmxPCrk
QhRH4MzEWnPj14jnqa5lhiBkQclKsPAgwv1Un2TTqJw9F25ytPRJiyxSKkG3j9v0QTmORtMzmxp5
C4cvyd+v3r+9fvt6QvkaeZXxJFKu2LlIH2DkeYh+uX5/c8sEUDb1RDOo2CEk+vnDO1/ubms3HblD
WUzrRmYyl2Umrae+hfk3R12hgbpy2HUzisbk/uDu01m/MkI3reyM+tgWbNzbw/ziORY0PA4co2+z
DDl4MeraSx8a7mBjcqUP0nEv20Lv3IhiGSNp9JiqtanXIMLARmlpJ/IYDXcFMDhQ2uptZIHa4xVw
MQkaggFYF/SFvtpvGJ5zOJlg0uLR9Uxxp7tOS6C98MeGpKg2krtw2AKbk54gUOlSbvt830smqJaZ
qZotaKpPKpf5IBse9E+nY5ozYG6w7BA9VNVHYb8mh15dCOSVrlYytC48gdDK9S8IrWyN3/72khlM
xaP1i9ManfyMhI9oEkAAADoejcPu7fWbV7zLwzUROuNnbD+KKhNF92nfRqPA+TUYx8MBLaVonVBS
2/CJ2gJ5V4TmYwON1NoT5YFtHq/eRObScOPG6fTnEM5un1lsgNcCKIQh0Ug7QrfSBPI8qOy3l/2Z
PbItEWWK9rbqmdRkdjpe7DsQdfPMk/Wnua8HW/aR54JTZ7uZGL20u3zUAIEX1SNqT79JUO5pWmIM
CD7mjjqmB/XMbg9p3aAO7z0cvpHs3tQbDJh6aCmCFZdS5ghDhSHQYj+KOu5cFgOThnkuRXZPRjSA
KhyvfH675vK/o+hGuKd5UJzRVW5nlB/87NhgkOypZ8+yQzrng08tS39sipq7yMM5TzB1l/Fzjv8j
P6ZXYoGByL2xPeY6YlTzIHYOhMTIokAZ78bK728aOB3PEx71KFsHsT/3QmRo3Rn2jUxxP4rx5/A8
ca385GTQxJ3c4FNLHG28WwO9/iLGB98z9xt5E1xz+s7EcGR1pVlV31de9nfIJF/jFgBRgd1zeXqL
7o+7VrmDXcKxjaMLhYBBzahPlxWVlnF77VkJVfq0gXkwFlnJdrkbaeIeMS65CTY+Tc8nMwBymkXh
SlIAKWYZ0Qs6D7cClzQfbq5ev5rQE03T02xGL5wBl/QCqJxf0tS+PL2kJEloFtETarWEo4oXRHSa
TdqOiMlui0bbKwTOJFrj3utrj0XgJmnic4/XctP14uVm2jYmm2jsyBinAnu9gfdMxD19G3dJg0Mz
xqV0To4hwwqG6jTl9MD92h2SGchwSHagHh78A1BLAwQUAAAACABiOz8m3x7QkGUAAACMAAAAEQAA
AHN1cHBvcnQvcmVnZW4uYmF0c3B19vBX8Hdz4+Xi5dLTiymoLMnIz1NITSyuTE/N0yuoVNBNVgCL
G5oCeTkKSulWMcVFyVCFhnqmMTmZSTEFOYkluuWZeUrY5SHCuZUKKfnJpbmpeSXFUHklBTsFkD0l
FSW8XABQSwECFAAUAAAACADVBp8j2pZOWIcEAAAAEAAACgAAAAAAAAAAACAA/4EAAAAAcHl0aG9u
LmV4ZVBLAQIUABQAAAAIAICsMCVzSVuFbwUAAEMSAAANAAAAAAAAAAEAIQAkga8EAABleGNlcHRp
b25zLnB5UEsBAhQAFAAAAAgAZTs/JpD/XKucAQAATgMAAAcAAAAAAAAAAQAgALaBSQoAAHNpdGUu
cHlQSwECFAAUAAAACABoPj8mMGpxqG0PAACYMQAACgAAAAAAAAABACAAtoEKDAAAaW1wdXRpbC5w
eVBLAQIUAAoAAAAAAA47PyYAAAAAAAAAAAAAAAAIAAAAAAAAAAAAEAD/QZ8bAABzdXBwb3J0L1BL
AQIUABQAAAAIAAkwPyYL9MjAOAYAAEQQAAASAAAAAAAAAAEAIAC2gcUbAABzdXBwb3J0L2Vhc3ln
ZW4ucHlQSwECFAAUAAAACABiOz8m3x7QkGUAAACMAAAAEQAAAAAAAAABACAA/4EtIgAAc3VwcG9y
dC9yZWdlbi5iYXRQSwUGAAAAAAcABwCVAQAAwSIAAAAA

------=_NextPart_000_0001_01BE4CF0.1C1CBCE0--