[Python-Dev] Packaging and binary distributions for Python 3.3
Vinay Sajip
vinay_sajip at yahoo.co.uk
Mon Oct 17 11:15:55 CEST 2011
Paul Moore <p.f.moore <at> gmail.com> writes:
> Interesting. That's not a use case that I have encountered, but I can
> see it could be an issue. I have been working on the basis that a
> bdist_simple format that matches the functionality of bdist_wininst is
> at least good enough for those projects that currently use
> bdist_wininst. The only potential issue right now is with postinstall
> scripts, which bdist_simple doesn't support. It would be easy enough
> to add, and indeed it may be possible to use existing packaging
> functionality already (I haven't looked into this area).
The packaging machinery contains a reasonably good set of hooks which a
setup.cfg can plug into, which is IMO more flexible than just a post-
installation script (e.g. sometimes you need your code to run before
installation, to determine where to install things).
> I don't disagree, but I'm struggling to see how that would be done.
See example below.
> Can you give an example of a setup.cfg, that would work like this?
> Suppose I have two files, foo.py and bar.pyd, which are a pure-python
> module and a compiled C extension. How would I write a setup.cfg and
> lay out the directory structure to allow pysetup install to do the
> right thing? I tried to do this myself, but couldn't get it to work
> the way I expected. It may be I was just hitting bugs, but it felt to
> me like I was going at the problem the wrong way.
It may not work for you, because in the default branch, packaging is currently
missing some functionality or has bugs (I've raised about a dozen issues since
trying to get packaging working with virtual environments).
In the pythonv branch (which is pretty up to date with default), I've added the
missing functionality/fixed some of the issues. Here's an example: I've created
an empty virtual environment. Here are the contents of it at the moment:
C:\TEMP\VENV
│ env.cfg
│
├───Include
├───Lib
│ └───site-packages
└───Scripts
activate.bat
deactivate.bat
pysetup3-script.py
pysetup3.exe
[various stock Python binaries omitted]
Here's an example setup.cfg:
[global]
setup_hooks = hooks.setup
[install_data]
pre-hook.win32 = hooks.pre_install_data
[metadata]
name = dory
version = 0.1
requires_python = >= 3.3
[other metadata omitted]
[files]
modules = dory
packages = apackage
apackage.asubpackage
scripts = dory
extra_files =
hooks.py
resources =
data/data.bin = {data}
compiled/ spam.pyd = {compiled}
#[extension: spam]
#language = c
#sources = spammodule.c
The extension section is commented out because we're not building the extension
at installation time. This setup.cfg works hand-in-hand with some hooks, in
file hooks.py below:
def setup(config):
# Can do various checks here. For example, platform
# compatibility checks, or set up different binaries
# to install for x86 vs. x64, etc.
# Do this by setting up config['files']['resources']
# appropriately based on installation time environment.
pass
def pre_install_data(cmd):
# assumes os.name == 'nt' for simplicity of this example
cmd.categories['compiled'] = '%s/Lib/site-packages' % cmd.install_dir
Notice how in setup.cfg, file 'spam.pyd' in 'compiled' is expected to be copied
to category 'compiled', whose path is set in hooks.pre_install_data.
Here's the project directory:
C:\USERS\VINAY\PROJECTS\DORY
│ dory
│ dory.py
│ hooks.py
│ setup.cfg
│
├───apackage
│ │ __init__.py
│ │
│ └───asubpackage
│ __init__.py
│
├───compiled
│ spam.pyd
│
└───data
data.bin
At the moment, the "spam" module is of course not installed:
(venv) c:\Users\Vinay\Projects\dory>python -c "import spam"
Traceback (most recent call last):
File "<string>", line 1, in <module>
ImportError: No module named 'spam'
Now, we install the project:
(venv) c:\Users\Vinay\Projects\dory>pysetup3 install .
Installing from source directory: c:\Users\Vinay\Projects\dory
running install_dist
running build
running build_py
running build_scripts
copying and adjusting dory -> build\scripts-3.3
running install_lib
creating C:\temp\venv\Lib\site-packages\apackage
byte-compiling C:\temp\venv\Lib\site-packages\apackage\__init__.py to __init__.c
python-33.pyc
byte-compiling C:\temp\venv\Lib\site-packages\dory.py to dory.cpython-33.pyc
running install_scripts
running pre_hook hooks.pre_install_data for command install_data
running install_data
running install_distinfo
creating C:\temp\venv\Lib\site-packages\dory-0.1.dist-info
creating C:\temp\venv\Lib\site-packages\dory-0.1.dist-info\METADATA
creating C:\temp\venv\Lib\site-packages\dory-0.1.dist-info\INSTALLER
creating C:\temp\venv\Lib\site-packages\dory-0.1.dist-info\REQUESTED
creating C:\temp\venv\Lib\site-packages\dory-0.1.dist-info\RESOURCES
creating C:\temp\venv\Lib\site-packages\dory-0.1.dist-info\RECORD
Now, the virtualenv looks like this:
C:\TEMP\VENV
│ env.cfg
│
├───data
│ data.bin
│
├───Include
├───Lib
│ └───site-packages
│ │ dory.py
│ │ spam.pyd
│ │
│ ├───apackage
│ │ │ __init__.py
│ │ │
│ │ ├───asubpackage
│ │ │ │ __init__.py
│ │ │ │
│ │ │ └───__pycache__
│ │ │ __init__.cpython-33.pyc
│ │ │
│ │ └───__pycache__
│ │ __init__.cpython-33.pyc
│ │
│ ├───dory-0.1.dist-info
│ │ INSTALLER
│ │ METADATA
│ │ RECORD
│ │ REQUESTED
│ │ RESOURCES
│ │
│ └───__pycache__
│ dory.cpython-33.pyc
│
└───Scripts
activate.bat
deactivate.bat
dory-script.py
dory.exe
pysetup3-script.py
pysetup3.exe
[various stock Python binaries omitted]
Now we can import "spam" and run something from it:
(venv) c:\Users\Vinay\Projects\dory>python -c "import spam; spam.system('cd')"
c:\Users\Vinay\Projects\dory
> I'd like to see a bdist_xxx command to do the build step
> as you describe, if only to make it trivially simple for developers to
> produce binary distributions. Having to package stuff up manually is
> bound to put at least some developers off. If you can give me the
> example I mentioned above, I could work on modifying the bdist_simple
> code I posted to the tracker today to produce that format rather than
> my custom format based on bdist_wininst.
Example as above, though you may need to use the pythonv branch to actually get
it working. I can zip up the directory and send it to you, but at the moment
there's missing functionality in pythonv in terms of the link step when
building the extension. (I overcame this by linking manually .) If you want, I
can zip all the project files up and send them to you.
In the more general case, one might want an arrangement with a directory
structure like compiled/x86/..., compiled/x64/... in the built zip, with the
hooks.py code setting up the resources appropriately based on the target
environment as determined at installation time.
> For the installation step, you shouldn't even need to unzip, as
> pysetup3 can do the unpacking for you.
Indeed, with pythonv I could just zip the whole "dory" project directory and
install with e.g. "pysetup3 install dory-1.0-win32-py3.3.zip".
> Agreed. Personally, as I've said, I'm happy not to use Add/Remove even
> for system installations - pysetup list and pysetup remove do what I
> need without slowing down the Add/Remove list. But I accept that's not
> likely to be the view of many Windows users. Anyone using virtual
> envs, though, is probably by definition comfortable enough with
> command line tools to be willing to use pysetup3.
A fair subset of those who must have ARP integration will probably also want to
install using MSI, so that would be taken care of by having a good bdist_simple
-> bdist_msi conversion.
Regards,
Vinay Sajip
More information about the Python-Dev
mailing list