stdeb-0.8.5/0000755000076500000240000000000012471220353013107 5ustar strawstaff00000000000000stdeb-0.8.5/.gitignore0000644000076500000240000000027212471220204015073 0ustar strawstaff00000000000000build deb_dist *.pyc stdeb.egg-info/PKG-INFO stdeb.egg-info/SOURCES.txt stdeb.egg-info/dependency_links.txt stdeb.egg-info/entry_points.txt stdeb.egg-info/top_level.txt dist *~ MANIFEST stdeb-0.8.5/.travis.yml0000644000076500000240000000173012471220204015214 0ustar strawstaff00000000000000# http://travis-ci.org/#!/astraw/stdeb language: python python: - "2.7_with_system_site_packages" - "3.2_with_system_site_packages" before_install: - sudo apt-get update - sudo apt-get install python-all-dev python3-all-dev debhelper python-setuptools python3-setuptools apt-file python-requests - wget http://debs.strawlab.org/precise/python3-requests_2.3.0-0ads1_all.deb -O python3-requests_2.3.0-0ads1_all.deb - sudo dpkg -i python3-requests_2.3.0-0ads1_all.deb install: - which python - which pip - pip --version - python -c "import sys; print(sys.version)" # Build a .deb file and then install it. - python setup.py --command-packages=stdeb.command bdist_deb - for f in deb_dist/*.deb; do echo; echo $f; dpkg --contents $f; done - sudo dpkg -i deb_dist/*.deb script: - sudo env "PATH=$PATH" bash -x ./test.sh - sudo env "PATH=$PATH" bash -x ./test-pypi-install.sh - sudo env "PATH=$PATH" bash -x ./test2and3.sh stdeb-0.8.5/CHANGELOG.txt0000644000076500000240000002303412471220204015134 0ustar strawstaff00000000000000Since (and including) release 0.8.0, updates to this file are no longer made. Please see README.rst. = Release 0.7.1 (2014-05-04) = 2014-05-05 Add a install_deb distutils command. This builds and installs a python package as a system package. 2014-05-05 bugfixes = Release 0.7.0 (2014-05-04) = 2014-05-04 Run test scripts on http://travis-ci.org/ 2014-05-04 Add py2dsc-deb command. This command builds a .deb file from source package. 2014-04-10 Update PyPI URL to current location. (Thanks to Asheesh Laroia.) 2013-11-17 Use HTTPS URLS instead of HTTP. (Note: urllib2 does not validate certificates.) 2013-11-17 Add pypi-download command. This command provides a quick way to download a source package from PyPI. 2010-11-27 Use dh_python2 instead of dh_pysupport. (Thanks to Piotr Ożarowski.) 2010-06-19 Do not workaround Debian Bug #548392 by default. 2010-06-19 By default, do not attempt to migrate old stdeb based packages that used pycentral. = Release 0.6.0 (2010-06-18) = 2010-06-18 Do not die if sources.list does not contain deb-src lines. (Debian Bug#580376) 2010-06-18 Document need to call "apt-file update". Emit nicer error when user needs to call "apt-file update". (Closes #568122) 2010-06-18 Allow stopping if a requirement can't be satisfied. (Closes GH-7) Patch originally from Zooko. 2010-06-18 Create debian/source/format. (Closes GH-27) 2010-06-16 Added {$misc:Depends} to depends. (Closes #568692) 2010-06-03 Update to Standards-Version 3.8.4 2010-06-02 Bugfix: separate binary-arch and binary-indep targets. 2010-05-02 Add 'debianize' distutils command to create debian directory. This was suggested by Barry Warsaw in Python issue 1054967. 2010-05-02 Don't change dots to dashes in debian package names. (This was suggested by Barry Warsaw in Python issue 1054967.) Allow underscores in python package names, replace dashes with underscores (Derek Smith). 2010-02-05 Bugfix: add python-pkg-resouces to Depends for stdeb itself. = Release 0.5.1 (2010-01-09) = 2010-01-08 Fix bug where default description was wrong. Patch by Roland Sommer. (Closes GH-19). 2009-12-30 The option 'Distribution' option is changed to 'Suite' 2009-12-30 Limit long description to 20 lines. = Release 0.5.0 (2009-12-30) = 2009-12-30 All stdeb.cfg options can now be set using distutils command option passing. This required a couple of renamings (--default-maintiner should now be --maintainer, --default-distribution should now be --suite), although the old way will still work, as it is only deprecated for now. 2009-12-30 Add pypi-install script to automatically download a package distribution, build a .deb file from it, and install it. (Closes GH-16) 2009-12-30 Don't allow specifying sdist_dsc options to bdist_deb 2009-12-29 The --process-dependencies option to py2dsc was dropped, because this functionality went beyond the scope of the py2dsc script. The functionality could be added to a new script if desired. 2009-12-29 Add Section option to stdeb.cfg. (Closes GH-13) 2009-12-29 Move stdeb.cfg file from egg-info directory to alongside setup.py 2009-12-28 --guess-conflicts-provides-replaces option. Provides automatic finding of original Debian source package's binaries, and create Conflicts/Provides/Replaces entries in debian/control for them. (Closes GH-17) 2009-12-28 Remove dependency on setuptools. (Closes GH-18) = Release 0.4.3 (2009-12-28) = 2009-12-01 add '--force-buildsystem' command option to allow forcing of python-distutils build system, even in presence of Makefile (defaults to True) 2009-11-30 Fixed a typo on the sdist_dsc.py which was throwing exception from paver. Fix #14 = Release 0.4.2 (2009-11-02) = 2009-11-02 Bump debian/compat to '7'. 2009-11-02 Don't include python-central in build package's Depends list. 2009-11-02 bugfix: actually parse list of supported Python versions correctly = Release 0.4.1 (2009-10-04) = 2009-10-03 Emit warnings if debhelper and python-support too old 2009-10-03 Update and improve documentation 2009-10-03 Allow command-line specified breaking of backward compatibility. (Closes GH-12) 2009-10-01 Fix incorrect handling of symlinks. (Ximin Luo) 2009-10-01 relax dependency on python-support down to 0.8.4 for Debian Lenny 2009-10-01 only include python-all-dev in Build-Deps if extension modules present (Alexander D. Sedov) 2009-09-29 bdist_deb accepts all sdist_dsc arguments (Gerry Reno) = Release 0.4 (2009-09-27) = 2009-06-01 Use debhelper 7 by default 2009-06-01 Switch from python-central to python-support 2009-06-02 workaround Debian #479852: remove left over python-central symlinks 2009-03-23 Unset environment variables set by dpkg-buildpackage = Release 0.3.2 (2009-10-04) = 2009-09-29 bdist_deb accepts all sdist_dsc arguments (Gerry Reno) 2009-09-29 add --disable-single-version-externally-managed option (initial patch from Gerry Reno) = Release 0.3.1 (2009-09-27) = 2009-09-22 Implement bdist_deb command (initial patch from Gerry Reno) = Release 0.3 (2009-03-21) = 2009-03-14 On Python2.6, pass "--install-layout=deb" to the distutils install command. This is required for Ubuntu Jaunty, and the current implementation in stdeb is also compatible with the python2.6 package in Debian experimental. 2009-02-24 bugfix to autofind-depends feature: include good package if found, even when version information not specified = Release 0.2.3 (2009-02-17) = 2009-02-16 new patch from zooko to improve regexp search for dependencies 2009-02-14 fix a crash with an undefined variable 'ver' (from Brett) 2009-02-14 Add --ignore-install-requires option. (From Brett) adds the ignore-install-requires command line option to keep stdeb from guessing python packages names from requires.txt and lets you specify your own Depends: without adding those from the egg requires.txt.... = Release 0.2.2 (2009-01-29) = 2009-01-29 Rename README.txt to README.rst so it renders on github better. 2009-06-29 Integrate zooko's autofind-depends patch. 2008-04-28 Allow comments after config entry = Release 0.2.1 (2008-04-26) = 2008-04-26 Find .egg-info directory in debian/rules using a glob rather than attempting to guess it, which was fragile. 2008-04-26 Use Python2.5's subprocess.check_call() instead of our home-brewed version. 2008-04-26 Use "date -R" instead of "822-date". 2008-04-26 Erase temporary directories created on prior run of stdeb. 2008-04-26 Don't break if no author is specified in setup.py. 2008-04-26 Add tests for more styles of packages. = Release 0.2 (2008-04-26) = 2008-03-27 Add ability to pass environment variables to setup.py script. 2008-03-18 Do not allow '.' in source package names. 2008-01-20 Allows a user to build every dependency a package has stated on it's setup.py, recursively. 2007-10-29 Allow upstream tarball to have different name from debian .orig.tar.gz but keep md5sum. 2007-05-28 Fix bug where python distribution name contained '-' but setuptools renamed this to '_'. 2007-05-11 Fix py2dsc script to properly set __file__ and __name__. 2007-04-18 Fix bug where .egg-info renaming failed when upstream version contained '-'. = Release 0.2.a1 (2007-04-02) = 2007-04-02 Make default distribution 'unstable' 2007-03-28 Removed versioned Python interpreter from packages in /usr/bin and /usr/lib. Bump version to 0.2.a1. Include version in autogenerated debian/rules and debian/changelog. 2007-03-15 pycentral support enabled by default 2007-02-04 fix for cases in which setup.py wants __file__ variable 2006-09-07 added --patch-posix to support posix-mode patches 2006-09-07 always extract source using "dpkg-source -x" 2006-09-07 moved working directory for patches one level shallower (may require patch level 1 instead of patch level 0) 2006-08-25 added Forced-Upstream-Version field in .cfg file 2006-08-22 patching source works when --premade-distfile option is given but distfile must be regenerated 2006-08-22 patch level supported via --patch-level option 2006-08-22 Add support for bzip2 tarballs 2006-08-13 Generate source by copying tree, not "python setup.py sdist" 2006-08-13 Patches can be applied prior to first call to setup.py 2006-07-21 Allow patches to upstream source via Stdeb-Patch-File in .cfg file. 2006-07-21 Don't bother trying to rename .egg-info directories. 2006-07-09 Ability to specify MIME-Desktop-Files, MIME-File, and Shared-MIME-File in configuration file. 2006-07-09 Use of dh_python for generation of postinst and prerm scripts. 2006-07-05 Auto-generation of debian/postinst and debian/prerm scripts that create and remove .pyc and .pyo files. 2006-06-21 Upstream .tar.gz files can be used exactly, allowing md5sums to match. 2006-06-21 Expanded source directory is only deleted when commandline option is set. =========================================================== 2006-06-14 Release 0.1, svn version 11 2006-06-18 Refactored to support calling from scripts. =========================================================== 2006-06-14 Release 0.0.1, svn version 3 2006-06-14 Initial import of repository and initial release. stdeb-0.8.5/LICENSE.txt0000644000076500000240000000204712471220204014730 0ustar strawstaff00000000000000Copyright (c) 2006-2014 stdeb authors. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. stdeb-0.8.5/MANIFEST.in0000644000076500000240000000025112471220204014636 0ustar strawstaff00000000000000include *.txt include *.rst include *.sh include stdeb.cfg include MANIFEST.in include .gitignore include .travis.yml include Vagrantfile* recursive-include test_data * stdeb-0.8.5/PKG-INFO0000644000076500000240000012115512471220353014211 0ustar strawstaff00000000000000Metadata-Version: 1.1 Name: stdeb Version: 0.8.5 Summary: Python to Debian source package conversion utility Home-page: http://github.com/astraw/stdeb Author: Andrew Straw Author-email: strawman@astraw.com License: MIT Description: .. image:: https://travis-ci.org/astraw/stdeb.png?branch=master :target: https://travis-ci.org/astraw/stdeb stdeb - Python to Debian source package conversion utility ========================================================== `stdeb `_ produces Debian source packages from Python packages via a new distutils command, ``sdist_dsc``. Automatic defaults are provided for the Debian package, but many aspects of the resulting package can be customized (see the customizing section, below). An additional command, ``bdist_deb``, creates a Debian binary package, a .deb file. The ``install_deb`` command installs this .deb file. The ``debianize`` command builds a ``debian/`` directory directly alongside your setup.py. Several convenience utilities are also provided: * ``pypi-download`` will query the `Python Package Index (PyPI) `_ for a package and download it. * ``pypi-install`` will query the `Python Package Index (PyPI) `_ for a package, download it, create a .deb from it, and then install the .deb. * ``py2dsc`` will convert a distutils-built source tarball into a Debian source package. * ``py2dsc-deb`` will convert a distutils-built source tarball into a Debian source package and then use the Debian machinery to build a .deb file from this. .. contents:: Python 3 support ---------------- As explained in more detail below, the heart of stdeb is the sdist_dsc distutils command. This command runs once to generate a Debian source package. This Debian source package can specify building packages for Python 2, Python 3, or both. Furthermore, this generation can be done with the Python 2 or Python 3 interpreter. By default, only packages are built for the version of Python being used. To override this, use ``--with-python2=True`` or ``--with-python3=True`` as an argument to the sdist_dsc distutils command (or use both to be sure). For example, to build only a Python 3 package using the Python 3 interpreter:: python3 setup.py --command-packages=stdeb.command bdist_deb To build both Python 2 and Python 3 packages using the Python 3 interpreter (and only the Python3 package installs scripts):: python3 setup.py --command-packages=stdeb.command sdist_dsc --with-python2=True --with-python3=True --no-python2-scripts=True bdist_deb News ---- * 2015-02-18: **Version 0.8.5**. See the `download page `__. Bugfixes: reverted change that installed into virtualenv when built in virtualenv. Improvements: Added `--allow-virtualenv-install-location` to allow installing into virtualenv location. Supports Debian Squeeze (6), Debian Wheezy (7), Ubuntu Precise (12.04), Ubuntu Trusty (14.04) and later releases. * 2015-02-16: **Version 0.8.4**. See the `download page `__. Bugfixes: works on Python 3.4 (e.g. Ubuntu Trusty) again. Improvements: Improved customization for Python 3 (Dirk Thomas added `force-x-python3-version` and `X-Python3-Version` and Louis for `Recommends3`, `Suggests3`, `Provides3` and `Replaces3` support. Supports Debian Squeeze (6), Debian Wheezy (7), Ubuntu Precise (12.04), Ubuntu Trusty (14.04) and later releases. * 2015-02-14: **Version 0.8.3**. See the `download page `__. This is a bugfix release which fixes several aspects of Unicode support. Tests pass on Debian Squeeze (6), Debian Wheezy (7), and Ubuntu Precise (12.04). Support for Python 3.4 (e.g. Ubuntu Trusty 14.04) was mistakenly broken and was fixed in the 0.8.3 release. * 2014-8-14: **Version 0.8.2**. See the `download page `__. This is a bugfix release fixing a serious issue that would cause a Python 2 package to be built if only a Python 3 package was requested in some circumstances. * 2014-8-10: **Version 0.8.1**. See the `download page `__. Due to bugs in 0.8.0, this release is the first announced from the 0.8 series. Highlights since 0.7.1: - Full support for Python 3. This includes being run from Python 3 and generating packages for Python 3. The default is to build Python 3 packages when run with Python 3 and to build Python 2 packages when run from Python 2. Command line options can be used to build packages for the other Python interpreter, too. - Build .changes file for source package. While this still must be signed for upload to a PPA, for example, it should still be useful in some cases. - Switch to Debian source format 3.0 (quilt). Practically speaking, the .diff.gz file that used to come with a source package is now replaced by a .debian.tar.gz file. - Verify SSL certificates when talking to PyPI using Requests. (Verification requires Requests >= 0.8.8.) - Many bugfixes. * 2014-05-05: **Version 0.7.1**. See the `download page `__. Highlights for this release (you may also wish to consult the full `changelog `__). Due to bugs in 0.7.0, this release is the first announced from the 0.7 series. Highlights since 0.6.0: - New commands: pypi-download and pypi-install to directly download and install packages from PyPI, respectively. py2dsc-deb directly creates a .deb file from a source tarball. - New distutils command: install_deb lets you directly install a python package as a standard system package. - Many bugfixes, including the new URL for PyPI. - Automated runs of test suite, thanks to Travis CI - Thanks to many, especially Piotr Ożarowski for help with stdeb. * 2010-06-18: **Version 0.6.0**. See the `download page `__. Highlights for this release (you may also wish to consult the full `changelog `__): - A new ``debianize`` command to build a ``debian/`` directory alongside your setup.py file. - Bugfixes. * 2010-01-09: **Version 0.5.1**. Bugfix release. See the `download page `__, the `changelog `__ and `release notes `__. * 2009-12-30: **Version 0.5.0**. See the `download page `__. Highlights for this release (you may also wish to consult the full `changelog `__): - A new ``pypi-install`` script will automatically download, make a .deb, and install packages from the `Python Package Index (PyPI)`_. - Removal of the setuptools dependency. - New option (`--guess-conflicts-provides-replaces`) to query original Debian packages for Conflicts/Provides/Replaces information. - As a result of these changes and to fix a couple bugs/warts, some minor backwards incompatible changes and deprecations were made. Please check the `release notes `__. * 2009-12-28: Version 0.4.3 Released. See the `download page`__. See the `changelog`__ and `release notes`__. * 2009-11-02: Version 0.4.2 Released. See the `download page`__. See the `changelog`__ and `release notes`__. * 2009-10-04: Version 0.4.1 Released. See the `download page`__. See the `changelog`__ and `release notes`__. * 2009-09-27: Version 0.4 Released. See the `download page`__. This version switches to debhelper 7. See the `Changelog for 0.4`__. __ http://pypi.python.org/pypi/stdeb/0.4.3 __ http://github.com/astraw/stdeb/blob/release-0.4.3/CHANGELOG.txt __ http://github.com/astraw/stdeb/blob/release-0.4.3/RELEASE_NOTES.txt __ http://pypi.python.org/pypi/stdeb/0.4.2 __ http://github.com/astraw/stdeb/blob/release-0.4.2/CHANGELOG.txt __ http://github.com/astraw/stdeb/blob/release-0.4.2/RELEASE_NOTES.txt __ http://pypi.python.org/pypi/stdeb/0.4.1 __ http://github.com/astraw/stdeb/blob/release-0.4.1/CHANGELOG.txt __ http://github.com/astraw/stdeb/blob/release-0.4.1/RELEASE_NOTES.txt __ http://pypi.python.org/pypi/stdeb/0.4 __ http://github.com/astraw/stdeb/blob/release-0.4/CHANGELOG.txt Releases up to and including 0.3.2 are compatible with Ubuntu Hardy. * 2009-10-04: Version 0.3.2 Released. See the `download page`__. See the `Changelog for 0.3.2`__ * 2009-09-27: Version 0.3.1 Released. See the `download page`__. See the `Changelog for 0.3.1`__ * 2009-03-21: Version 0.3 Released. See the `download page`__. See the `Changelog for 0.3`__ * 2009-02-17: Version 0.2.3 Released. See the `download page`__. See the `Changelog for 0.2.3`__ * 2009-01-29: Version 0.2.2 Released. See the `download page`__. See the `Changelog for 0.2.2`__ * 2008-04-26: Version 0.2.1 Released. See the `download page`__. See the `Changelog for 0.2.1`__ * 2008-04-26: Version 0.2 Released. See the `download page`__. See the `Changelog for 0.2`__ * 2007-04-02: Version 0.2.a1 Released. See the `old download page`_. * 2006-06-19: Version 0.1 Released. See the `old download page`_. __ http://pypi.python.org/pypi/stdeb/0.3.2 __ http://github.com/astraw/stdeb/blob/release-0.3.2/CHANGELOG.txt __ http://pypi.python.org/pypi/stdeb/0.3.1 __ http://github.com/astraw/stdeb/blob/release-0.3.1/CHANGELOG.txt __ http://pypi.python.org/pypi/stdeb/0.3 __ http://github.com/astraw/stdeb/blob/release-0.3/CHANGELOG.txt __ http://pypi.python.org/pypi/stdeb/0.2.3 __ http://github.com/astraw/stdeb/blob/release-0.2.3/CHANGELOG.txt __ http://pypi.python.org/pypi/stdeb/0.2.2 __ http://github.com/astraw/stdeb/blob/release-0.2.2/CHANGELOG.txt __ http://pypi.python.org/pypi/stdeb/0.2.1 __ http://github.com/astraw/stdeb/blob/release-0.2.1/CHANGELOG.txt __ http://pypi.python.org/pypi/stdeb/0.2 __ http://github.com/astraw/stdeb/blob/release-0.2/CHANGELOG.txt The commands ------------ pypi-download, command-line command ``````````````````````````````````` ``pypi-download`` takes a package name, queries PyPI for it and downloads it:: pypi-download [options] mypackage pypi-install, command-line command `````````````````````````````````` ``pypi-install`` takes a package name, queries PyPI for it, downloads it, builds a Debian source package and then .deb from it, and this installs it:: pypi-install [options] mypackage py2dsc, command-line command ```````````````````````````` ``py2dsc`` takes a .tar.gz source package and build a Debian source package from it:: py2dsc [options] mypackage-0.1.tar.gz # uses pre-built Python source package py2dsc-deb, command-line command ```````````````````````````````` ``py2dsc-deb`` takes a .tar.gz source package and build a Debian source package and then a .deb file from it:: py2dsc-deb [options] mypackage-0.1.tar.gz # uses pre-built Python source package sdist_dsc, distutils command ```````````````````````````` All methods eventually result in a call to the ``sdist_dsc`` distutils command. You may prefer to do so directly:: python setup.py --command-packages=stdeb.command sdist_dsc A Debian source package is produced from unmodified Python packages. The following files are produced in a newly created subdirectory ``deb_dist``: * ``packagename_versionname.orig.tar.gz`` * ``packagename_versionname-debianversion.dsc`` * ``packagename_versionname-debianversion.diff.gz`` These can then be compiled into binary packages using the standard Debian machinery (e.g. dpkg-buildpackage). bdist_deb, distutils command ```````````````````````````` A ``bdist_deb`` distutils command is installed. This calls the sdist_dsc command and then runs dpkg-buildpackage on the result:: python setup.py --command-packages=stdeb.command bdist_deb install_deb, distutils command `````````````````````````````` The ``install_deb`` distutils command calls the bdist_deb command and then installs the result. You need to run this with superuser privilege:: sudo python setup.py --command-packages=stdeb.command install_deb debianize, distutils command ```````````````````````````` The ``debianize`` distutils command builds the same ``debian/`` directory as used in the previous command, but the output is placed directly in the project's root folder (alongside setup.py). This is useful for customizing the Debian package directly (rather than using the various stdeb options to tune the generated package). :: python setup.py --command-packages=stdeb.command debianize A note about telling distutils to use the stdeb distutils commands `````````````````````````````````````````````````````````````````` Distutils command packages can also be specified in distutils configuration files (rather than using the ``--command-packages`` command line argument to ``setup.py``), as specified in the `distutils documentation `_. Specifically, you could include this in your ``~/.pydistutils.cfg`` file:: [global] command-packages: stdeb.command Examples -------- These all assume you have stdeb installed in your system Python path. stdeb also works from a non-system Python path (e.g. a `virtualenv `_). Quickstart 1: Install something from PyPI now, I don't care about anything else ``````````````````````````````````````````````````````````````````````````````` Do this from the command line:: pypi-install mypackage **Warning: Despite doing its best, there is absolutely no way stdeb can guarantee all the Debian package dependencies will be properly fulfilled without manual intervention. Using pypi-install bypasses your ability to customize stdeb's behavior. Read the rest of this document to understand how to make better packages.** Quickstart 2: Just tell me the fastest way to make a .deb ````````````````````````````````````````````````````````` (First, install stdeb as you normally install Python packages.) Do this from the directory with your `setup.py` file:: python setup.py --command-packages=stdeb.command bdist_deb This will make a Debian source package (.dsc, .orig.tar.gz and .diff.gz files) and then compile it to a Debian binary package (.deb) for your current system. The result will be in ``deb_dist``. **Warning: installing the .deb file on other versions of Ubuntu or Debian than the one on which it was compiled will result in undefined behavior. If you have extension modules, they will probably break. Even in the absence of extension modules, bad stuff will likely happen.** For this reason, it is much better to build the Debian source package and then compile that (e.g. using `Ubuntu's PPA`__) for each target version of Debian or Ubuntu. __ https://help.launchpad.net/Packaging/PPA Quickstart 3: I read the warning, so show me how to make a source package, then compile it `````````````````````````````````````````````````````````````````````````````````````````` This generates a source package:: wget http://pypi.python.org/packages/source/R/Reindent/Reindent-0.1.0.tar.gz py2dsc Reindent-0.1.0.tar.gz This turns it into a .deb using the standard Debian tools. (Do *this* on the same source package for each target distribution):: cd deb_dist/reindent-0.1.0/ dpkg-buildpackage -rfakeroot -uc -us This installs it:: cd .. sudo dpkg -i python-reindent_0.1.0-1_all.deb Quickstart 4: Install from a Python package direct to a debian system package ````````````````````````````````````````````````````````````````````````````` (First, install stdeb as you normally install Python packages.) Do this from the directory with your `setup.py` file:: python setup.py --command-packages=stdeb.command install_deb This will make a Debian source package (.dsc, .orig.tar.gz and .diff.gz files), compile it to a Debian binary package (.deb) for your current system and then install it using ``dpkg``. Another example, with more explanation `````````````````````````````````````` This example is more useful if you don't have a Python source package (.tar.gz file generated by ``python setup.py sdist``). For the sake of illustration, we do download such a tarball, but immediately unpack it (alternatively, use a version control system to grab the unpacked source of a package):: wget http://pypi.python.org/packages/source/R/Reindent/Reindent-0.1.0.tar.gz tar xzf Reindent-0.1.0.tar.gz cd Reindent-0.1.0 The following will generate a directory ``deb_dist`` containing the files ``reindent_0.1.0-1.dsc``, ``reindent_0.1.0.orig.tar.gz`` and ``reindent_0.1.0-1.diff.gz``, which, together, are a debian source package:: python setup.py --command-packages=stdeb.command sdist_dsc The source generated in the above way is also extracted (using ``dpkg-source -x``) and placed in the ``deb_dist`` subdirectory. To continue the example above:: cd deb_dist/reindent-0.1.0 dpkg-buildpackage -rfakeroot -uc -us Finally, the generated package can be installed:: cd .. sudo dpkg -i python-reindent_0.1.0-1_all.deb For yet another example of use, with still more explanation, see `allmydata-tahoe ticket 251`_. .. _allmydata-tahoe ticket 251: http://allmydata.org/trac/tahoe/ticket/251 Download -------- Files are available at the `download page`_ (for ancient releases, see the `old download page`_). .. _download page: https://pypi.python.org/pypi/stdeb .. _old download page: http://stdeb.python-hosting.com/wiki/Download The git repository is available at http://github.com/astraw/stdeb Install (or, using stdeb to create an stdeb installer) ------------------------------------------------------ For a bit of fun, here's how to install stdeb using stdeb. Note that stdeb is also in Debian and Ubuntu, so this recipe is only necessary to install a more recent stdeb. :: STDEB_VERSION="0.8.5" # Download stdeb wget http://pypi.python.org/packages/source/s/stdeb/stdeb-$STDEB_VERSION.tar.gz # Extract it tar xzf stdeb-$STDEB_VERSION.tar.gz # Enter extracted source package cd stdeb-$STDEB_VERSION # Build .deb (making use of stdeb package directory in sys.path). python setup.py --command-packages=stdeb.command bdist_deb # Install it sudo dpkg -i deb_dist/python-stdeb_$STDEB_VERSION-1_all.deb Background ---------- For the average Python package, its source distribution (python_package.tar.gz created with ``python setup.py sdist``) contains nearly everything necessary to make a Debian source package. This near-equivalence encouraged me to write this distutils extension, which executes the setup.py file to extract relevant information. `setuptools `_ may optionally be used. I wrote this initially to Debianize several Python packages of my own, but I have the feeling it could be generally useful. It appears similar, at least in theory, to easydeb_, `Logilab's Devtools`_, bdist_dpkg_, bdist_deb_, pkgme_ and `dh-virtualenv `__. .. _easydeb: http://easy-deb.sourceforge.net/ .. _Logilab's DevTools: http://www.logilab.org/projects/devtools .. _bdist_dpkg: http://svn.python.org/view/sandbox/trunk/Lib/bdist_dpkg.py .. _bdist_deb: http://bugs.python.org/issue1054967 .. _pkgme: https://launchpad.net/pkgme Features -------- * Create a package for all Python versions supported by python-support. (Limiting this range is possible with the ``XS-Python-Version:`` config option.) * Automatic conversion of Python package names into valid Debian package names. * Attempt to automatically convert version numbers such that ordering is maintained. See also the config option ``Forced-Upstream-Version``. * Fine grained control of version numbers. (``Debian-Version``, ``Forced-Upstream-Version``, ``Upstream-Version-Prefix``, ``Upstream-Version-Suffix`` config options.) * Install .desktop files. (``MIME-Desktop-Files`` config option.) * Install .mime and .sharedmimeinfo files. (``MIME-File`` and ``Shared-MIME-File`` config options.) * Install copyright files. (``Copyright-File`` config option.) * Apply patches to upstream sources. (``Stdeb-Patch-File`` config option.) * Pass environment variables to setup.py script. (``Setup-Env-Vars`` config option.) Customizing the produced Debian source package (config options) --------------------------------------------------------------- stdeb will attempt to provide reasonable defaults, but these are only guesses. There are two ways to customize the Debian source package produced by stdeb. First, you may provide options to the distutils commands. Second, you may provide an ``stdeb.cfg`` file. stdeb distutils command options ``````````````````````````````` The sdist_dsc command takes command-line options to the distutils command. For example:: python setup.py --command-packages=stdeb.command sdist_dsc --debian-version 0MyName1 This creates a Debian package with the Debian version set to "0MyName1". These options can also be set via distutils configuration files. (These are the ``setup.cfg`` file alongside ``setup.py`` and the ~/.pydistutils.cfg file.) In that case, put the arguments in the ``[sdist_dsc]`` section. For example, a project's ``~/.setup.cfg`` file might have this:: [sdist_dsc] debian-version: 0MyName1 To pass these commands to sdist_dsc when calling bdist_deb, do this:: python setup.py sdist_dsc --debian-version 0MyName1 bdist_deb ====================================== ========================================= Command line option Effect ====================================== ========================================= --with-python2 build Python 2 package (default=True) --with-python3 build Python 3 package (default=False) --no-python2-scripts disable installation of Python 2 scripts (default=False) --no-python3-scripts disable installation of Python 3 scripts (default=False) --force-x-python3-version Override default minimum python3:any dependency with value from x-python3- version --allow-virtualenv-install-location Allow installing into /some/random/virtualenv-path --dist-dir (-d) directory to put final built distributions in (default='deb_dist') --patch-already-applied (-a) patch was already applied (used when py2dsc calls sdist_dsc) --default-distribution deprecated (see --suite) --suite (-z) distribution name to use if not specified in .cfg (default='unstable') --default-maintainer deprecated (see --maintainer) --maintainer (-m) maintainer name and email to use if not specified in .cfg (default from setup.py) --extra-cfg-file (-x) additional .cfg file (in addition to stdeb.cfg if present) --patch-file (-p) patch file applied before setup.py called (incompatible with file specified in .cfg) --patch-level (-l) patch file applied before setup.py called (incompatible with file specified in .cfg) --patch-posix (-q) apply the patch with --posix mode --remove-expanded-source-dir (-r) remove the expanded source directory --ignore-install-requires (-i) ignore the requirements from requires.txt in the egg-info directory --no-backwards-compatibility This option has no effect, is here for backwards compatibility, and may be removed someday. --guess-conflicts-provides-replaces If True, attempt to guess Conflicts/Provides/Replaces in debian/control based on apt-cache output. (Default=False). --use-premade-distfile (-P) use .zip or .tar.gz file already made by sdist command --source debian/control Source: (Default: ) --package debian/control Package: (Default: python-) --suite suite (e.g. stable, lucid) in changelog (Default: unstable) --maintainer debian/control Maintainer: (Default: ) --debian-version debian version (Default: 1) --section debian/control Section: (Default: python) --epoch version epoch --forced-upstream-version forced upstream version --upstream-version-prefix upstream version prefix --upstream-version-suffix upstream version suffix --uploaders uploaders --copyright-file copyright file --build-depends debian/control Build-Depends: --build-conflicts debian/control Build-Conflicts: --stdeb-patch-file file containing patches for stdeb to apply --stdeb-patch-level patch level provided to patch command --depends debian/control Depends: --suggests debian/control Suggests: --recommends debian/control Recommends: --xs-python-version debian/control XS-Python-Version: --x-python3-version debian/control X-Python3-Version: --dpkg-shlibdeps-params parameters passed to dpkg-shlibdeps --conflicts debian/control Conflicts: --provides debian/control Provides: --replaces debian/control Replaces: --mime-desktop-files MIME desktop files --mime-file MIME file --shared-mime-file shared MIME file --setup-env-vars environment variables passed to setup.py --udev-rules file with rules to install to udev ====================================== ========================================= You may also pass any arguments described below for the stdeb.cfg file via distutils options. Passing the arguments this way (either on the command line, or in the ``[sdist_dsc]`` section of a distutils .cfg file) will take precedence. The option name should be given in lower case. stdeb.cfg configuration file ```````````````````````````` You may write config files of the format understood by `ConfigParser `_. When building each package, stdeb looks for the existance of a ``stdeb.cfg`` in the directory with ``setup.py``. You may specify an additional config file with the command-line option --extra-cfg-file. The section should should either be [DEFAULT] or [package_name], which package_name is specified as the name argument to the setup() command. An example stdeb.cfg file is:: [DEFAULT] Depends: python-numpy XS-Python-Version: >= 2.6 All available options: ====================================== ========================================= Config file option Effect ====================================== ========================================= Source debian/control Source: (Default: ) Package debian/control Package: (Default: python-) Suite suite (e.g. stable, lucid) in changelog (Default: unstable) Maintainer debian/control Maintainer: (Default: ) Debian-Version debian version (Default: 1) Section debian/control Section: (Default: python) Epoch version epoch Forced-Upstream-Version forced upstream version Upstream-Version-Prefix upstream version prefix Upstream-Version-Suffix upstream version suffix Uploaders uploaders Copyright-File copyright file Build-Depends debian/control Build-Depends: Build-Conflicts debian/control Build-Conflicts: Stdeb-Patch-File file containing patches for stdeb to apply Stdeb-Patch-Level patch level provided to patch command Depends debian/control Depends: Depends3 debian/control Depends: for python3 Suggests debian/control Suggests: Suggests3 debian/control Suggests: for python3 Recommends debian/control Recommends: Recommends3 debian/control Recommends: for python3 XS-Python-Version debian/control XS-Python-Version: X-Python3-Version debian/control X-Python3-Version: Dpkg-Shlibdeps-Params parameters passed to dpkg-shlibdeps Conflicts debian/control Conflicts: Conflicts3 debian/control Conflicts: for python3 Provides debian/control Provides: Provides3 debian/control Provides: for python3 Replaces debian/control Replaces: Replaces3 debian/control Replaces: for python3 MIME-Desktop-Files MIME desktop files MIME-File MIME file Shared-MIME-File shared MIME file Setup-Env-Vars environment variables passed to setup.py Udev-Rules file with rules to install to udev ====================================== ========================================= The option names in stdeb.cfg files are not case sensitive. Prerequisites ------------- * Python 2.7 or Python 3.x * Standard Debian utilities such as ``date``, ``dpkg-source`` and Debhelper 7 (use stdeb 0.3.x if you need to support older distributions without dh7) * If your setup.py uses the setuptools features ``setup_requires`` or ``install_requires``, you must run ``apt-file update`` prior to running any stdeb command. TODO ---- * Make output meet `Debian Python Policy`_ specifications or the `new python policy`_. This will include several things, among which are: - the ability to make custom changelogs - the ability to include project-supplied documentation as a -doc package - include license information in debian/copyright - the ability to include project-supplied examples, tests, and data as a separate package - much more not listed * Create (better) documentation * Log output using standard distutils mechanisms * Refactor the source code to have a simpler, more sane design .. _debian python policy: http://www.debian.org/doc/packaging-manuals/python-policy/ .. _new python policy: http://wiki.debian.org/DebianPython/NewPolicy Call for volunteers ------------------- I don't have a lot of time for this. This project stands a very real chance of being only a shadow of its potential self unless people step up and contribute. There are numerous ways in which people could help. In particular, I'd be interested in finding a co-maintainer or maintainer if the project generates any interest. Secondarily, I would appreciate advice from Debian developers or Ubuntu MOTUs about the arcane details of Python packaging. Mailing list ------------ Please address all questions to the distutils-SIG_ .. _distutils-SIG: http://mail.python.org/mailman/listinfo/distutils-sig License ------- MIT-style license. Copyright (c) 2006-2015 stdeb authors. See the LICENSE.txt file provided with the source distribution for full details. Authors ------- * Andrew Straw * Pedro Algarvio, aka, s0undt3ch * Gerry Reno (initial bdist_deb implementation) Additional Credits ------------------ * Zooko O'Whielacronx for the autofind-depends patch. * Brett (last name unknown) for the --ignore-install-requires patch. * Ximin Luo for a bug fix. * Alexander D. Sedov for bug fixes and suggestions. * Michele Mattioni for bug fix. * Alexander V. Nikolaev for the debhelper buildsystem specification. * Roland Sommer for the description field bugfix. * Barry Warsaw for suggesting the debianize command. * Asheesh Laroia for updating the PyPI URL. * Piotr Ożarowski for implementing dh_python2 support. * Nikita Burtsev for unicode tests and fixes * Mikołaj Siedlarek for a bugfix * Dirk Thomas for --force-x-python3-version and X-Python3-Version * Louis for Recommends3, Suggests3, Provides3 and Replaces3 support * kzwin for interop with virtualenv * GitHub_ for hosting services. * WebFaction_ (aka `python-hosting`_) for previous hosting services. * TravisCI_ for continuous integration .. _GitHub: http://github.com/ .. _WebFaction: http://webfaction.com/ .. _python-hosting: http://python-hosting.com/ .. _TravisCI: http://travis-ci.org/ Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: Intended Audience :: System Administrators Classifier: License :: OSI Approved :: MIT License Classifier: Operating System :: POSIX :: Linux Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 stdeb-0.8.5/README.rst0000644000076500000240000010343312471220204014575 0ustar strawstaff00000000000000.. image:: https://travis-ci.org/astraw/stdeb.png?branch=master :target: https://travis-ci.org/astraw/stdeb stdeb - Python to Debian source package conversion utility ========================================================== `stdeb `_ produces Debian source packages from Python packages via a new distutils command, ``sdist_dsc``. Automatic defaults are provided for the Debian package, but many aspects of the resulting package can be customized (see the customizing section, below). An additional command, ``bdist_deb``, creates a Debian binary package, a .deb file. The ``install_deb`` command installs this .deb file. The ``debianize`` command builds a ``debian/`` directory directly alongside your setup.py. Several convenience utilities are also provided: * ``pypi-download`` will query the `Python Package Index (PyPI) `_ for a package and download it. * ``pypi-install`` will query the `Python Package Index (PyPI) `_ for a package, download it, create a .deb from it, and then install the .deb. * ``py2dsc`` will convert a distutils-built source tarball into a Debian source package. * ``py2dsc-deb`` will convert a distutils-built source tarball into a Debian source package and then use the Debian machinery to build a .deb file from this. .. contents:: Python 3 support ---------------- As explained in more detail below, the heart of stdeb is the sdist_dsc distutils command. This command runs once to generate a Debian source package. This Debian source package can specify building packages for Python 2, Python 3, or both. Furthermore, this generation can be done with the Python 2 or Python 3 interpreter. By default, only packages are built for the version of Python being used. To override this, use ``--with-python2=True`` or ``--with-python3=True`` as an argument to the sdist_dsc distutils command (or use both to be sure). For example, to build only a Python 3 package using the Python 3 interpreter:: python3 setup.py --command-packages=stdeb.command bdist_deb To build both Python 2 and Python 3 packages using the Python 3 interpreter (and only the Python3 package installs scripts):: python3 setup.py --command-packages=stdeb.command sdist_dsc --with-python2=True --with-python3=True --no-python2-scripts=True bdist_deb News ---- * 2015-02-18: **Version 0.8.5**. See the `download page `__. Bugfixes: reverted change that installed into virtualenv when built in virtualenv. Improvements: Added `--allow-virtualenv-install-location` to allow installing into virtualenv location. Supports Debian Squeeze (6), Debian Wheezy (7), Ubuntu Precise (12.04), Ubuntu Trusty (14.04) and later releases. * 2015-02-16: **Version 0.8.4**. See the `download page `__. Bugfixes: works on Python 3.4 (e.g. Ubuntu Trusty) again. Improvements: Improved customization for Python 3 (Dirk Thomas added `force-x-python3-version` and `X-Python3-Version` and Louis for `Recommends3`, `Suggests3`, `Provides3` and `Replaces3` support. Supports Debian Squeeze (6), Debian Wheezy (7), Ubuntu Precise (12.04), Ubuntu Trusty (14.04) and later releases. * 2015-02-14: **Version 0.8.3**. See the `download page `__. This is a bugfix release which fixes several aspects of Unicode support. Tests pass on Debian Squeeze (6), Debian Wheezy (7), and Ubuntu Precise (12.04). Support for Python 3.4 (e.g. Ubuntu Trusty 14.04) was mistakenly broken and was fixed in the 0.8.3 release. * 2014-8-14: **Version 0.8.2**. See the `download page `__. This is a bugfix release fixing a serious issue that would cause a Python 2 package to be built if only a Python 3 package was requested in some circumstances. * 2014-8-10: **Version 0.8.1**. See the `download page `__. Due to bugs in 0.8.0, this release is the first announced from the 0.8 series. Highlights since 0.7.1: - Full support for Python 3. This includes being run from Python 3 and generating packages for Python 3. The default is to build Python 3 packages when run with Python 3 and to build Python 2 packages when run from Python 2. Command line options can be used to build packages for the other Python interpreter, too. - Build .changes file for source package. While this still must be signed for upload to a PPA, for example, it should still be useful in some cases. - Switch to Debian source format 3.0 (quilt). Practically speaking, the .diff.gz file that used to come with a source package is now replaced by a .debian.tar.gz file. - Verify SSL certificates when talking to PyPI using Requests. (Verification requires Requests >= 0.8.8.) - Many bugfixes. * 2014-05-05: **Version 0.7.1**. See the `download page `__. Highlights for this release (you may also wish to consult the full `changelog `__). Due to bugs in 0.7.0, this release is the first announced from the 0.7 series. Highlights since 0.6.0: - New commands: pypi-download and pypi-install to directly download and install packages from PyPI, respectively. py2dsc-deb directly creates a .deb file from a source tarball. - New distutils command: install_deb lets you directly install a python package as a standard system package. - Many bugfixes, including the new URL for PyPI. - Automated runs of test suite, thanks to Travis CI - Thanks to many, especially Piotr Ożarowski for help with stdeb. * 2010-06-18: **Version 0.6.0**. See the `download page `__. Highlights for this release (you may also wish to consult the full `changelog `__): - A new ``debianize`` command to build a ``debian/`` directory alongside your setup.py file. - Bugfixes. * 2010-01-09: **Version 0.5.1**. Bugfix release. See the `download page `__, the `changelog `__ and `release notes `__. * 2009-12-30: **Version 0.5.0**. See the `download page `__. Highlights for this release (you may also wish to consult the full `changelog `__): - A new ``pypi-install`` script will automatically download, make a .deb, and install packages from the `Python Package Index (PyPI)`_. - Removal of the setuptools dependency. - New option (`--guess-conflicts-provides-replaces`) to query original Debian packages for Conflicts/Provides/Replaces information. - As a result of these changes and to fix a couple bugs/warts, some minor backwards incompatible changes and deprecations were made. Please check the `release notes `__. * 2009-12-28: Version 0.4.3 Released. See the `download page`__. See the `changelog`__ and `release notes`__. * 2009-11-02: Version 0.4.2 Released. See the `download page`__. See the `changelog`__ and `release notes`__. * 2009-10-04: Version 0.4.1 Released. See the `download page`__. See the `changelog`__ and `release notes`__. * 2009-09-27: Version 0.4 Released. See the `download page`__. This version switches to debhelper 7. See the `Changelog for 0.4`__. __ http://pypi.python.org/pypi/stdeb/0.4.3 __ http://github.com/astraw/stdeb/blob/release-0.4.3/CHANGELOG.txt __ http://github.com/astraw/stdeb/blob/release-0.4.3/RELEASE_NOTES.txt __ http://pypi.python.org/pypi/stdeb/0.4.2 __ http://github.com/astraw/stdeb/blob/release-0.4.2/CHANGELOG.txt __ http://github.com/astraw/stdeb/blob/release-0.4.2/RELEASE_NOTES.txt __ http://pypi.python.org/pypi/stdeb/0.4.1 __ http://github.com/astraw/stdeb/blob/release-0.4.1/CHANGELOG.txt __ http://github.com/astraw/stdeb/blob/release-0.4.1/RELEASE_NOTES.txt __ http://pypi.python.org/pypi/stdeb/0.4 __ http://github.com/astraw/stdeb/blob/release-0.4/CHANGELOG.txt Releases up to and including 0.3.2 are compatible with Ubuntu Hardy. * 2009-10-04: Version 0.3.2 Released. See the `download page`__. See the `Changelog for 0.3.2`__ * 2009-09-27: Version 0.3.1 Released. See the `download page`__. See the `Changelog for 0.3.1`__ * 2009-03-21: Version 0.3 Released. See the `download page`__. See the `Changelog for 0.3`__ * 2009-02-17: Version 0.2.3 Released. See the `download page`__. See the `Changelog for 0.2.3`__ * 2009-01-29: Version 0.2.2 Released. See the `download page`__. See the `Changelog for 0.2.2`__ * 2008-04-26: Version 0.2.1 Released. See the `download page`__. See the `Changelog for 0.2.1`__ * 2008-04-26: Version 0.2 Released. See the `download page`__. See the `Changelog for 0.2`__ * 2007-04-02: Version 0.2.a1 Released. See the `old download page`_. * 2006-06-19: Version 0.1 Released. See the `old download page`_. __ http://pypi.python.org/pypi/stdeb/0.3.2 __ http://github.com/astraw/stdeb/blob/release-0.3.2/CHANGELOG.txt __ http://pypi.python.org/pypi/stdeb/0.3.1 __ http://github.com/astraw/stdeb/blob/release-0.3.1/CHANGELOG.txt __ http://pypi.python.org/pypi/stdeb/0.3 __ http://github.com/astraw/stdeb/blob/release-0.3/CHANGELOG.txt __ http://pypi.python.org/pypi/stdeb/0.2.3 __ http://github.com/astraw/stdeb/blob/release-0.2.3/CHANGELOG.txt __ http://pypi.python.org/pypi/stdeb/0.2.2 __ http://github.com/astraw/stdeb/blob/release-0.2.2/CHANGELOG.txt __ http://pypi.python.org/pypi/stdeb/0.2.1 __ http://github.com/astraw/stdeb/blob/release-0.2.1/CHANGELOG.txt __ http://pypi.python.org/pypi/stdeb/0.2 __ http://github.com/astraw/stdeb/blob/release-0.2/CHANGELOG.txt The commands ------------ pypi-download, command-line command ``````````````````````````````````` ``pypi-download`` takes a package name, queries PyPI for it and downloads it:: pypi-download [options] mypackage pypi-install, command-line command `````````````````````````````````` ``pypi-install`` takes a package name, queries PyPI for it, downloads it, builds a Debian source package and then .deb from it, and this installs it:: pypi-install [options] mypackage py2dsc, command-line command ```````````````````````````` ``py2dsc`` takes a .tar.gz source package and build a Debian source package from it:: py2dsc [options] mypackage-0.1.tar.gz # uses pre-built Python source package py2dsc-deb, command-line command ```````````````````````````````` ``py2dsc-deb`` takes a .tar.gz source package and build a Debian source package and then a .deb file from it:: py2dsc-deb [options] mypackage-0.1.tar.gz # uses pre-built Python source package sdist_dsc, distutils command ```````````````````````````` All methods eventually result in a call to the ``sdist_dsc`` distutils command. You may prefer to do so directly:: python setup.py --command-packages=stdeb.command sdist_dsc A Debian source package is produced from unmodified Python packages. The following files are produced in a newly created subdirectory ``deb_dist``: * ``packagename_versionname.orig.tar.gz`` * ``packagename_versionname-debianversion.dsc`` * ``packagename_versionname-debianversion.diff.gz`` These can then be compiled into binary packages using the standard Debian machinery (e.g. dpkg-buildpackage). bdist_deb, distutils command ```````````````````````````` A ``bdist_deb`` distutils command is installed. This calls the sdist_dsc command and then runs dpkg-buildpackage on the result:: python setup.py --command-packages=stdeb.command bdist_deb install_deb, distutils command `````````````````````````````` The ``install_deb`` distutils command calls the bdist_deb command and then installs the result. You need to run this with superuser privilege:: sudo python setup.py --command-packages=stdeb.command install_deb debianize, distutils command ```````````````````````````` The ``debianize`` distutils command builds the same ``debian/`` directory as used in the previous command, but the output is placed directly in the project's root folder (alongside setup.py). This is useful for customizing the Debian package directly (rather than using the various stdeb options to tune the generated package). :: python setup.py --command-packages=stdeb.command debianize A note about telling distutils to use the stdeb distutils commands `````````````````````````````````````````````````````````````````` Distutils command packages can also be specified in distutils configuration files (rather than using the ``--command-packages`` command line argument to ``setup.py``), as specified in the `distutils documentation `_. Specifically, you could include this in your ``~/.pydistutils.cfg`` file:: [global] command-packages: stdeb.command Examples -------- These all assume you have stdeb installed in your system Python path. stdeb also works from a non-system Python path (e.g. a `virtualenv `_). Quickstart 1: Install something from PyPI now, I don't care about anything else ``````````````````````````````````````````````````````````````````````````````` Do this from the command line:: pypi-install mypackage **Warning: Despite doing its best, there is absolutely no way stdeb can guarantee all the Debian package dependencies will be properly fulfilled without manual intervention. Using pypi-install bypasses your ability to customize stdeb's behavior. Read the rest of this document to understand how to make better packages.** Quickstart 2: Just tell me the fastest way to make a .deb ````````````````````````````````````````````````````````` (First, install stdeb as you normally install Python packages.) Do this from the directory with your `setup.py` file:: python setup.py --command-packages=stdeb.command bdist_deb This will make a Debian source package (.dsc, .orig.tar.gz and .diff.gz files) and then compile it to a Debian binary package (.deb) for your current system. The result will be in ``deb_dist``. **Warning: installing the .deb file on other versions of Ubuntu or Debian than the one on which it was compiled will result in undefined behavior. If you have extension modules, they will probably break. Even in the absence of extension modules, bad stuff will likely happen.** For this reason, it is much better to build the Debian source package and then compile that (e.g. using `Ubuntu's PPA`__) for each target version of Debian or Ubuntu. __ https://help.launchpad.net/Packaging/PPA Quickstart 3: I read the warning, so show me how to make a source package, then compile it `````````````````````````````````````````````````````````````````````````````````````````` This generates a source package:: wget http://pypi.python.org/packages/source/R/Reindent/Reindent-0.1.0.tar.gz py2dsc Reindent-0.1.0.tar.gz This turns it into a .deb using the standard Debian tools. (Do *this* on the same source package for each target distribution):: cd deb_dist/reindent-0.1.0/ dpkg-buildpackage -rfakeroot -uc -us This installs it:: cd .. sudo dpkg -i python-reindent_0.1.0-1_all.deb Quickstart 4: Install from a Python package direct to a debian system package ````````````````````````````````````````````````````````````````````````````` (First, install stdeb as you normally install Python packages.) Do this from the directory with your `setup.py` file:: python setup.py --command-packages=stdeb.command install_deb This will make a Debian source package (.dsc, .orig.tar.gz and .diff.gz files), compile it to a Debian binary package (.deb) for your current system and then install it using ``dpkg``. Another example, with more explanation `````````````````````````````````````` This example is more useful if you don't have a Python source package (.tar.gz file generated by ``python setup.py sdist``). For the sake of illustration, we do download such a tarball, but immediately unpack it (alternatively, use a version control system to grab the unpacked source of a package):: wget http://pypi.python.org/packages/source/R/Reindent/Reindent-0.1.0.tar.gz tar xzf Reindent-0.1.0.tar.gz cd Reindent-0.1.0 The following will generate a directory ``deb_dist`` containing the files ``reindent_0.1.0-1.dsc``, ``reindent_0.1.0.orig.tar.gz`` and ``reindent_0.1.0-1.diff.gz``, which, together, are a debian source package:: python setup.py --command-packages=stdeb.command sdist_dsc The source generated in the above way is also extracted (using ``dpkg-source -x``) and placed in the ``deb_dist`` subdirectory. To continue the example above:: cd deb_dist/reindent-0.1.0 dpkg-buildpackage -rfakeroot -uc -us Finally, the generated package can be installed:: cd .. sudo dpkg -i python-reindent_0.1.0-1_all.deb For yet another example of use, with still more explanation, see `allmydata-tahoe ticket 251`_. .. _allmydata-tahoe ticket 251: http://allmydata.org/trac/tahoe/ticket/251 Download -------- Files are available at the `download page`_ (for ancient releases, see the `old download page`_). .. _download page: https://pypi.python.org/pypi/stdeb .. _old download page: http://stdeb.python-hosting.com/wiki/Download The git repository is available at http://github.com/astraw/stdeb Install (or, using stdeb to create an stdeb installer) ------------------------------------------------------ For a bit of fun, here's how to install stdeb using stdeb. Note that stdeb is also in Debian and Ubuntu, so this recipe is only necessary to install a more recent stdeb. :: STDEB_VERSION="0.8.5" # Download stdeb wget http://pypi.python.org/packages/source/s/stdeb/stdeb-$STDEB_VERSION.tar.gz # Extract it tar xzf stdeb-$STDEB_VERSION.tar.gz # Enter extracted source package cd stdeb-$STDEB_VERSION # Build .deb (making use of stdeb package directory in sys.path). python setup.py --command-packages=stdeb.command bdist_deb # Install it sudo dpkg -i deb_dist/python-stdeb_$STDEB_VERSION-1_all.deb Background ---------- For the average Python package, its source distribution (python_package.tar.gz created with ``python setup.py sdist``) contains nearly everything necessary to make a Debian source package. This near-equivalence encouraged me to write this distutils extension, which executes the setup.py file to extract relevant information. `setuptools `_ may optionally be used. I wrote this initially to Debianize several Python packages of my own, but I have the feeling it could be generally useful. It appears similar, at least in theory, to easydeb_, `Logilab's Devtools`_, bdist_dpkg_, bdist_deb_, pkgme_ and `dh-virtualenv `__. .. _easydeb: http://easy-deb.sourceforge.net/ .. _Logilab's DevTools: http://www.logilab.org/projects/devtools .. _bdist_dpkg: http://svn.python.org/view/sandbox/trunk/Lib/bdist_dpkg.py .. _bdist_deb: http://bugs.python.org/issue1054967 .. _pkgme: https://launchpad.net/pkgme Features -------- * Create a package for all Python versions supported by python-support. (Limiting this range is possible with the ``XS-Python-Version:`` config option.) * Automatic conversion of Python package names into valid Debian package names. * Attempt to automatically convert version numbers such that ordering is maintained. See also the config option ``Forced-Upstream-Version``. * Fine grained control of version numbers. (``Debian-Version``, ``Forced-Upstream-Version``, ``Upstream-Version-Prefix``, ``Upstream-Version-Suffix`` config options.) * Install .desktop files. (``MIME-Desktop-Files`` config option.) * Install .mime and .sharedmimeinfo files. (``MIME-File`` and ``Shared-MIME-File`` config options.) * Install copyright files. (``Copyright-File`` config option.) * Apply patches to upstream sources. (``Stdeb-Patch-File`` config option.) * Pass environment variables to setup.py script. (``Setup-Env-Vars`` config option.) Customizing the produced Debian source package (config options) --------------------------------------------------------------- stdeb will attempt to provide reasonable defaults, but these are only guesses. There are two ways to customize the Debian source package produced by stdeb. First, you may provide options to the distutils commands. Second, you may provide an ``stdeb.cfg`` file. stdeb distutils command options ``````````````````````````````` The sdist_dsc command takes command-line options to the distutils command. For example:: python setup.py --command-packages=stdeb.command sdist_dsc --debian-version 0MyName1 This creates a Debian package with the Debian version set to "0MyName1". These options can also be set via distutils configuration files. (These are the ``setup.cfg`` file alongside ``setup.py`` and the ~/.pydistutils.cfg file.) In that case, put the arguments in the ``[sdist_dsc]`` section. For example, a project's ``~/.setup.cfg`` file might have this:: [sdist_dsc] debian-version: 0MyName1 To pass these commands to sdist_dsc when calling bdist_deb, do this:: python setup.py sdist_dsc --debian-version 0MyName1 bdist_deb ====================================== ========================================= Command line option Effect ====================================== ========================================= --with-python2 build Python 2 package (default=True) --with-python3 build Python 3 package (default=False) --no-python2-scripts disable installation of Python 2 scripts (default=False) --no-python3-scripts disable installation of Python 3 scripts (default=False) --force-x-python3-version Override default minimum python3:any dependency with value from x-python3- version --allow-virtualenv-install-location Allow installing into /some/random/virtualenv-path --dist-dir (-d) directory to put final built distributions in (default='deb_dist') --patch-already-applied (-a) patch was already applied (used when py2dsc calls sdist_dsc) --default-distribution deprecated (see --suite) --suite (-z) distribution name to use if not specified in .cfg (default='unstable') --default-maintainer deprecated (see --maintainer) --maintainer (-m) maintainer name and email to use if not specified in .cfg (default from setup.py) --extra-cfg-file (-x) additional .cfg file (in addition to stdeb.cfg if present) --patch-file (-p) patch file applied before setup.py called (incompatible with file specified in .cfg) --patch-level (-l) patch file applied before setup.py called (incompatible with file specified in .cfg) --patch-posix (-q) apply the patch with --posix mode --remove-expanded-source-dir (-r) remove the expanded source directory --ignore-install-requires (-i) ignore the requirements from requires.txt in the egg-info directory --no-backwards-compatibility This option has no effect, is here for backwards compatibility, and may be removed someday. --guess-conflicts-provides-replaces If True, attempt to guess Conflicts/Provides/Replaces in debian/control based on apt-cache output. (Default=False). --use-premade-distfile (-P) use .zip or .tar.gz file already made by sdist command --source debian/control Source: (Default: ) --package debian/control Package: (Default: python-) --suite suite (e.g. stable, lucid) in changelog (Default: unstable) --maintainer debian/control Maintainer: (Default: ) --debian-version debian version (Default: 1) --section debian/control Section: (Default: python) --epoch version epoch --forced-upstream-version forced upstream version --upstream-version-prefix upstream version prefix --upstream-version-suffix upstream version suffix --uploaders uploaders --copyright-file copyright file --build-depends debian/control Build-Depends: --build-conflicts debian/control Build-Conflicts: --stdeb-patch-file file containing patches for stdeb to apply --stdeb-patch-level patch level provided to patch command --depends debian/control Depends: --suggests debian/control Suggests: --recommends debian/control Recommends: --xs-python-version debian/control XS-Python-Version: --x-python3-version debian/control X-Python3-Version: --dpkg-shlibdeps-params parameters passed to dpkg-shlibdeps --conflicts debian/control Conflicts: --provides debian/control Provides: --replaces debian/control Replaces: --mime-desktop-files MIME desktop files --mime-file MIME file --shared-mime-file shared MIME file --setup-env-vars environment variables passed to setup.py --udev-rules file with rules to install to udev ====================================== ========================================= You may also pass any arguments described below for the stdeb.cfg file via distutils options. Passing the arguments this way (either on the command line, or in the ``[sdist_dsc]`` section of a distutils .cfg file) will take precedence. The option name should be given in lower case. stdeb.cfg configuration file ```````````````````````````` You may write config files of the format understood by `ConfigParser `_. When building each package, stdeb looks for the existance of a ``stdeb.cfg`` in the directory with ``setup.py``. You may specify an additional config file with the command-line option --extra-cfg-file. The section should should either be [DEFAULT] or [package_name], which package_name is specified as the name argument to the setup() command. An example stdeb.cfg file is:: [DEFAULT] Depends: python-numpy XS-Python-Version: >= 2.6 All available options: ====================================== ========================================= Config file option Effect ====================================== ========================================= Source debian/control Source: (Default: ) Package debian/control Package: (Default: python-) Suite suite (e.g. stable, lucid) in changelog (Default: unstable) Maintainer debian/control Maintainer: (Default: ) Debian-Version debian version (Default: 1) Section debian/control Section: (Default: python) Epoch version epoch Forced-Upstream-Version forced upstream version Upstream-Version-Prefix upstream version prefix Upstream-Version-Suffix upstream version suffix Uploaders uploaders Copyright-File copyright file Build-Depends debian/control Build-Depends: Build-Conflicts debian/control Build-Conflicts: Stdeb-Patch-File file containing patches for stdeb to apply Stdeb-Patch-Level patch level provided to patch command Depends debian/control Depends: Depends3 debian/control Depends: for python3 Suggests debian/control Suggests: Suggests3 debian/control Suggests: for python3 Recommends debian/control Recommends: Recommends3 debian/control Recommends: for python3 XS-Python-Version debian/control XS-Python-Version: X-Python3-Version debian/control X-Python3-Version: Dpkg-Shlibdeps-Params parameters passed to dpkg-shlibdeps Conflicts debian/control Conflicts: Conflicts3 debian/control Conflicts: for python3 Provides debian/control Provides: Provides3 debian/control Provides: for python3 Replaces debian/control Replaces: Replaces3 debian/control Replaces: for python3 MIME-Desktop-Files MIME desktop files MIME-File MIME file Shared-MIME-File shared MIME file Setup-Env-Vars environment variables passed to setup.py Udev-Rules file with rules to install to udev ====================================== ========================================= The option names in stdeb.cfg files are not case sensitive. Prerequisites ------------- * Python 2.7 or Python 3.x * Standard Debian utilities such as ``date``, ``dpkg-source`` and Debhelper 7 (use stdeb 0.3.x if you need to support older distributions without dh7) * If your setup.py uses the setuptools features ``setup_requires`` or ``install_requires``, you must run ``apt-file update`` prior to running any stdeb command. TODO ---- * Make output meet `Debian Python Policy`_ specifications or the `new python policy`_. This will include several things, among which are: - the ability to make custom changelogs - the ability to include project-supplied documentation as a -doc package - include license information in debian/copyright - the ability to include project-supplied examples, tests, and data as a separate package - much more not listed * Create (better) documentation * Log output using standard distutils mechanisms * Refactor the source code to have a simpler, more sane design .. _debian python policy: http://www.debian.org/doc/packaging-manuals/python-policy/ .. _new python policy: http://wiki.debian.org/DebianPython/NewPolicy Call for volunteers ------------------- I don't have a lot of time for this. This project stands a very real chance of being only a shadow of its potential self unless people step up and contribute. There are numerous ways in which people could help. In particular, I'd be interested in finding a co-maintainer or maintainer if the project generates any interest. Secondarily, I would appreciate advice from Debian developers or Ubuntu MOTUs about the arcane details of Python packaging. Mailing list ------------ Please address all questions to the distutils-SIG_ .. _distutils-SIG: http://mail.python.org/mailman/listinfo/distutils-sig License ------- MIT-style license. Copyright (c) 2006-2015 stdeb authors. See the LICENSE.txt file provided with the source distribution for full details. Authors ------- * Andrew Straw * Pedro Algarvio, aka, s0undt3ch * Gerry Reno (initial bdist_deb implementation) Additional Credits ------------------ * Zooko O'Whielacronx for the autofind-depends patch. * Brett (last name unknown) for the --ignore-install-requires patch. * Ximin Luo for a bug fix. * Alexander D. Sedov for bug fixes and suggestions. * Michele Mattioni for bug fix. * Alexander V. Nikolaev for the debhelper buildsystem specification. * Roland Sommer for the description field bugfix. * Barry Warsaw for suggesting the debianize command. * Asheesh Laroia for updating the PyPI URL. * Piotr Ożarowski for implementing dh_python2 support. * Nikita Burtsev for unicode tests and fixes * Mikołaj Siedlarek for a bugfix * Dirk Thomas for --force-x-python3-version and X-Python3-Version * Louis for Recommends3, Suggests3, Provides3 and Replaces3 support * kzwin for interop with virtualenv * GitHub_ for hosting services. * WebFaction_ (aka `python-hosting`_) for previous hosting services. * TravisCI_ for continuous integration .. _GitHub: http://github.com/ .. _WebFaction: http://webfaction.com/ .. _python-hosting: http://python-hosting.com/ .. _TravisCI: http://travis-ci.org/ stdeb-0.8.5/RELEASE_NOTES.txt0000644000076500000240000000700612471220204015676 0ustar strawstaff00000000000000Release 0.8.5 ============= Building package in a virtual environment does not install in a virtual environment (restores 0.8.3 behavior). Release 0.8.4 ============= Building package in a virtual environment installs in a virtual environment. Release 0.8.3 ============= Fixes various Unicode handling bugs. Release 0.8.2 ============= Fixes a bug. Release 0.8.1 ============= Fixes documentation bugs. Release 0.8.0 ============= Removed "--force-buildsystem" option. Release 0.7.1 ============= Fixes several bugs. Release 0.7.0 ============= stdeb uses dh_python2 instead of dh_pysupport (thanks to Piotr Ożarowski). A long time passed between releases, so there are probably backwards incompatible changes that have crept in. Release 0.6.0 ============= A new ``debianize`` command was added. This command builds a ``debian/`` directory alongside your setup.py file. No backwards incompatible changes were made with this release. Release 0.5.1 ============= This is a bugfix release. This fixes a bug that caused the debian/control Description: field to be wrong. No backwards incompatible changes were made with this release. Release 0.5.0 ============= The following backwards incompatible changes were made: * The --process-dependencies option to py2dsc was dropped, because this functionality went beyond the scope of the py2dsc script. The functionality could be added to a new script if desired. * The ability to pass command options to sdist_dsc by specifying them to bdist_deb was removed. In other words, if you did this in the past:: python setup.py bdist_deb --no-backwards-compatibility You must now do this:: python setup.py sdist_dsc --no-backwards-compatibility bdist_deb The deprecations were made: * The stdeb.cfg file location has been moved from the .egg-info directory into the directory holding setup.py. The old location will work, but is deprecated and will be removed sometime in the future. * Some options to the sdist_dsc command have now changed. (--default-maintiner should now be --maintainer, --default-distribution should now be --suite), although the old way will still work, as it is only deprecated for now. Release 0.4.3 ============= This is a bugfix release. The most significant change is that by default the "DH_OPTIONS=--buildsystem=python_distutils" environment variable is passed to debhelper. This causes debhelper to ignore Makefiles and forces use of "python setup.py install". No backwards incompatible changes were made with this release. Release 0.4.2 ============= This is a bugfix release fixing a couple issues. The most significant fix is that if a package specified "XS-Python-Version" in stdeb.cfg, the binary package wouldn't install the Python packages. No backwards incompatible changes were made with this release. Release 0.4.1 ============= This release maintains backward compatibility with old versions of stdeb and debhelper, but stdeb now allows packages that don't carry the cruft of backward compatibility. To disable all backwards compatibility, specify the --no-backwards-compatibility flag. This will set --pycentral-backwards-compatibility=False and --workaround-548392=False. You may set these flags individually if desired. By "maintains backward compatibility with stdeb", I mean that newer packages made with newer stdeb (0.4.1 and up) will properly upgrade from older package made with older versions of stdeb (less than 0.4.0). The problem, in particular, is the migration from python-central. See Debian bug #479852 for more information. stdeb-0.8.5/scripts/0000755000076500000240000000000012471220353014576 5ustar strawstaff00000000000000stdeb-0.8.5/scripts/py2dsc0000755000076500000240000000051212471220204015721 0ustar strawstaff00000000000000#!/usr/bin/env python USAGE = """\ usage: py2dsc [options] distfile or: py2dsc --help where distfile is a .zip or .tar.gz file built with the sdist command of distutils. """ import stdeb.cli_runner import sys def main(): sys.exit(stdeb.cli_runner.runit(cmd='sdist_dsc',usage=USAGE)) if __name__=='__main__': main() stdeb-0.8.5/scripts/py2dsc-deb0000755000076500000240000000052212471220204016452 0ustar strawstaff00000000000000#!/usr/bin/env python USAGE = """\ usage: py2dsc-deb [options] distfile or: py2dsc-deb --help where distfile is a .zip or .tar.gz file built with the sdist command of distutils. """ import stdeb.cli_runner import sys def main(): sys.exit(stdeb.cli_runner.runit(cmd='bdist_deb',usage=USAGE)) if __name__=='__main__': main() stdeb-0.8.5/scripts/pypi-download0000755000076500000240000000220412471220204017303 0ustar strawstaff00000000000000#!/usr/bin/env python import sys from optparse import OptionParser from stdeb.downloader import myprint, get_source_tarball def main(): usage = '%prog PACKAGE_NAME [options]' parser = OptionParser(usage) parser.add_option('--verbose', type='int', help='verbosity level', default=0) parser.add_option('--release', type='str', help='specify a particular release', default=None) parser.add_option('--allow-unsafe-download', action='store_true', default=False, help='allow unsafe downloads') (options, args) = parser.parse_args() if len(args) != 1: myprint('need exactly one PACKAGE_NAME',file=sys.stderr) parser.print_help() sys.exit(1) package_name = args[0] tarball_fname = get_source_tarball(package_name,verbose=options.verbose, release=options.release, allow_unsafe_download=options.allow_unsafe_download) myprint('OK: %s' % tarball_fname) if __name__=='__main__': main() stdeb-0.8.5/scripts/pypi-install0000755000076500000240000000445712471220204017156 0ustar strawstaff00000000000000#!/usr/bin/env python import sys, os, shutil import subprocess import argparse from stdeb.downloader import myprint, get_source_tarball import tempfile def main(): parser = argparse.ArgumentParser(usage='%(prog)s PACKAGE_NAME [options] [py2dsc-deb options]') parser.add_argument('--verbose', type=int, help='verbosity level', default=0) parser.add_argument('--release', type=str, help='specify a particular release', default=None) parser.add_argument('--keep', action='store_true', default=False, help='do not remove temporary files') parser.add_argument('--allow-unsafe-download', action='store_true', default=False, help='allow unsafe downloads') (options, args) = parser.parse_known_args() if os.geteuid() != 0: myprint('%s must be run as root'%os.path.basename(sys.argv[0]),file=sys.stderr) sys.exit(1) if len(args) < 1: myprint('need exactly one PACKAGE_NAME',file=sys.stderr) parser.print_help() sys.exit(1) package_name = args[0] py2dsc_args = args[1:] if package_name.startswith('-'): myprint('PACKAGE_NAME must be first argument',file=sys.stderr) parser.print_help() sys.exit(1) orig_dir = os.path.abspath( os.curdir ) tmpdir = os.path.abspath(tempfile.mkdtemp()) try: if options.verbose >= 2: myprint('downloading to %s'%tmpdir) os.chdir( tmpdir ) tarball_fname = get_source_tarball(package_name,verbose=options.verbose, release=options.release, allow_unsafe_download=options.allow_unsafe_download) cmd = ' '.join(['py2dsc-deb'] + py2dsc_args + [tarball_fname]) if options.verbose >= 2: myprint('executing: %s'%cmd) subprocess.check_call(cmd, shell=True) os.chdir( 'deb_dist' ) cmd = 'dpkg -i *.deb' if options.verbose >= 2: myprint('executing: %s'%cmd) subprocess.check_call(cmd, shell=True) finally: os.chdir( orig_dir ) if not options.keep: shutil.rmtree(tmpdir) if __name__=='__main__': main() stdeb-0.8.5/setup.py0000644000076500000240000000212712471220204014616 0ustar strawstaff00000000000000from distutils.core import setup import codecs with codecs.open('README.rst', encoding='utf-8') as file: long_description = file.read() setup(name='stdeb', # Keep version in sync with stdeb/__init__.py and install section # of README.rst. version='0.8.5', author='Andrew Straw', author_email='strawman@astraw.com', description='Python to Debian source package conversion utility', long_description=long_description, license='MIT', url='http://github.com/astraw/stdeb', packages=['stdeb','stdeb.command'], scripts=['scripts/py2dsc', 'scripts/py2dsc-deb', 'scripts/pypi-download', 'scripts/pypi-install', ], classifiers=[ 'Development Status :: 5 - Production/Stable', 'Intended Audience :: Developers', 'Intended Audience :: System Administrators', 'License :: OSI Approved :: MIT License', 'Operating System :: POSIX :: Linux', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', ], ) stdeb-0.8.5/stdeb/0000755000076500000240000000000012471220353014210 5ustar strawstaff00000000000000stdeb-0.8.5/stdeb/__init__.py0000644000076500000240000000045012471220204016313 0ustar strawstaff00000000000000import logging __version__ = '0.8.5' # keep in sync with ../setup.py log = logging.getLogger('stdeb') log.setLevel(logging.INFO) handler = logging.StreamHandler() handler.setLevel(logging.INFO) formatter = logging.Formatter('%(message)s') handler.setFormatter(formatter) log.addHandler(handler) stdeb-0.8.5/stdeb/cli_runner.py0000644000076500000240000001244312471220204016721 0ustar strawstaff00000000000000from __future__ import print_function import sys, os, shutil, subprocess try: # python 2.x from ConfigParser import SafeConfigParser except ImportError as err: # python 3.x from configparser import SafeConfigParser from distutils.util import strtobool from distutils.fancy_getopt import FancyGetopt, translate_longopt from stdeb.util import stdeb_cmdline_opts, stdeb_cmd_bool_opts from stdeb.util import expand_sdist_file, apply_patch from stdeb import log from pkg_resources import Requirement, Distribution class OptObj: pass def runit(cmd,usage): if cmd not in ['sdist_dsc','bdist_deb']: raise ValueError('unknown command %r'%cmd) # process command-line options bool_opts = map(translate_longopt, stdeb_cmd_bool_opts) parser = FancyGetopt(stdeb_cmdline_opts+[ ('help', 'h', "show detailed help message"), ]) optobj = OptObj() args = parser.getopt(object=optobj) for option in optobj.__dict__: value = getattr(optobj,option) is_string = type(value) == str if option in bool_opts and is_string: setattr(optobj, option, strtobool(value)) if hasattr(optobj,'help'): print(usage) parser.set_option_table(stdeb_cmdline_opts) parser.print_help("Options:") return 0 if len(args)!=1: log.error('not given single argument (distfile), args=%r', args) print(usage) return 1 sdist_file = args[0] final_dist_dir = optobj.__dict__.get('dist_dir','deb_dist') tmp_dist_dir = os.path.join(final_dist_dir,'tmp_py2dsc') if os.path.exists(tmp_dist_dir): shutil.rmtree(tmp_dist_dir) os.makedirs(tmp_dist_dir) if not os.path.isfile(sdist_file): log.error("Package %s not found."%sdist_file) sys.exit(1) patch_file = optobj.__dict__.get('patch_file',None) patch_level = int(optobj.__dict__.get('patch_level',0)) patch_posix = int(optobj.__dict__.get('patch_posix',0)) expand_dir = os.path.join(tmp_dist_dir,'stdeb_tmp') if os.path.exists(expand_dir): shutil.rmtree(expand_dir) if not os.path.exists(tmp_dist_dir): os.mkdir(tmp_dist_dir) os.mkdir(expand_dir) expand_sdist_file(os.path.abspath(sdist_file),cwd=expand_dir) # now the sdist package is expanded in expand_dir expanded_root_files = os.listdir(expand_dir) assert len(expanded_root_files)==1 repackaged_dirname = expanded_root_files[0] fullpath_repackaged_dirname = os.path.join(tmp_dist_dir,repackaged_dirname) base_dir = os.path.join(expand_dir,expanded_root_files[0]) if os.path.exists(fullpath_repackaged_dirname): # prevent weird build errors if this dir exists shutil.rmtree(fullpath_repackaged_dirname) os.renames(base_dir, fullpath_repackaged_dirname) del base_dir # no longer useful ############################################## if patch_file is not None: log.info('py2dsc applying patch %s', patch_file) apply_patch(patch_file, posix=patch_posix, level=patch_level, cwd=fullpath_repackaged_dirname) patch_already_applied = 1 else: patch_already_applied = 0 ############################################## abs_dist_dir = os.path.abspath(final_dist_dir) extra_args = [] for long in parser.long_opts: if long in ['dist-dir=','patch-file=']: continue # dealt with by this invocation attr = parser.get_attr_name(long).rstrip('=') if hasattr(optobj,attr): val = getattr(optobj,attr) if attr=='extra_cfg_file': val = os.path.abspath(val) if long in bool_opts or long.replace('-', '_') in bool_opts: extra_args.append('--%s' % long) else: extra_args.append('--'+long+str(val)) if patch_already_applied == 1: extra_args.append('--patch-already-applied') if cmd=='bdist_deb': extra_args.append('bdist_deb') args = [sys.executable,'setup.py','--command-packages','stdeb.command', 'sdist_dsc','--dist-dir=%s'%abs_dist_dir, '--use-premade-distfile=%s'%os.path.abspath(sdist_file)]+extra_args log.info('-='*35 + '-') # print >> sys.stderr, '-='*20 # print >> sys.stderr, "Note that the .cfg file(s), if present, have not "\ # "been read at this stage. If options are necessary, pass them from "\ # "the command line" log.info("running the following command in directory: %s\n%s", fullpath_repackaged_dirname, ' '.join(args)) log.info('-='*35 + '-') try: returncode = subprocess.call( args,cwd=fullpath_repackaged_dirname, ) except: log.error('ERROR running: %s', ' '.join(args)) log.error('ERROR in %s', fullpath_repackaged_dirname) raise if returncode: log.error('ERROR running: %s', ' '.join(args)) log.error('ERROR in %s', fullpath_repackaged_dirname) #log.error(' stderr: %s'res.stderr.read()) #print >> sys.stderr, 'ERROR running: %s'%(' '.join(args),) #print >> sys.stderr, res.stderr.read() return returncode #raise RuntimeError('returncode %d'%returncode) #result = res.stdout.read().strip() shutil.rmtree(tmp_dist_dir) return returncode stdeb-0.8.5/stdeb/command/0000755000076500000240000000000012471220353015626 5ustar strawstaff00000000000000stdeb-0.8.5/stdeb/command/__init__.py0000644000076500000240000000007612471220204017735 0ustar strawstaff00000000000000__all__ = ['sdist_dsc','bdist_deb','install_deb','debianize'] stdeb-0.8.5/stdeb/command/bdist_deb.py0000644000076500000240000000264212471220204020116 0ustar strawstaff00000000000000import os import stdeb.util as util from distutils.core import Command __all__ = ['bdist_deb'] class bdist_deb(Command): description = 'distutils command to create debian binary package' user_options = [] boolean_options = [] def initialize_options (self): pass def finalize_options (self): pass def run(self): # generate .dsc source pkg self.run_command('sdist_dsc') # get relevant options passed to sdist_dsc sdist_dsc = self.get_finalized_command('sdist_dsc') dsc_tree = sdist_dsc.dist_dir # execute system command and read output (execute and read output of find cmd) target_dirs = [] for entry in os.listdir(dsc_tree): fulldir = os.path.join(dsc_tree,entry) if os.path.isdir(fulldir): if entry == 'tmp_py2dsc': continue target_dirs.append( fulldir ) if len(target_dirs)>1: raise ValueError('More than one directory in deb_dist. ' 'Unsure which is source directory. All: %r'%( target_dirs,)) if len(target_dirs)==0: raise ValueError('could not find debian source directory') # define system command to execute (gen .deb binary pkg) syscmd = ['dpkg-buildpackage','-rfakeroot','-uc','-b'] util.process_command(syscmd,cwd=target_dirs[0]) stdeb-0.8.5/stdeb/command/common.py0000644000076500000240000002243512471220204017471 0ustar strawstaff00000000000000import sys, os, shutil from stdeb import log from distutils.core import Command from distutils.errors import DistutilsModuleError from stdeb.util import DebianInfo, build_dsc, stdeb_cmdline_opts, \ stdeb_cmd_bool_opts, stdeb_cfg_options class common_debian_package_command(Command): def initialize_options (self): self.patch_already_applied = 0 self.remove_expanded_source_dir = 0 self.patch_posix = 0 self.dist_dir = None self.extra_cfg_file = None self.patch_file = None self.patch_level = None self.ignore_install_requires = None self.debian_version = None self.no_backwards_compatibility = None self.guess_conflicts_provides_replaces = None if sys.version_info[0]==2: self.with_python2 = 'True' self.with_python3 = 'False' else: assert sys.version_info[0]==3 self.with_python2 = 'False' self.with_python3 = 'True' self.no_python2_scripts = 'False' self.no_python3_scripts = 'False' self.force_x_python3_version = False self.allow_virtualenv_install_location = False # deprecated options self.default_distribution = None self.default_maintainer = None # make distutils happy by filling in default values for longopt, shortopt, description in stdeb_cfg_options: assert longopt.endswith('=') name = longopt[:-1] name = name.replace('-','_') setattr( self, name, None ) def finalize_options(self): def str_to_bool(mystr): if mystr.lower() == 'false': return False elif mystr.lower() == 'true': return True else: raise ValueError('bool string "%s" is not "true" or "false"'%mystr) if self.dist_dir is None: self.dist_dir = 'deb_dist' if self.patch_level is not None: self.patch_level = int(self.patch_level) if self.guess_conflicts_provides_replaces is None: # the default self.guess_conflicts_provides_replaces = False else: self.guess_conflicts_provides_replaces = str_to_bool( self.guess_conflicts_provides_replaces) self.with_python2 = str_to_bool(self.with_python2) self.with_python3 = str_to_bool(self.with_python3) self.no_python2_scripts = str_to_bool(self.no_python2_scripts) self.no_python3_scripts = str_to_bool(self.no_python3_scripts) if self.maintainer is not None: # Get the locale specifying the encoding in sys.argv import locale, codecs fs_enc = codecs.lookup(locale.getpreferredencoding()).name if hasattr(os,'fsencode'): # this exists only in Python 3 m = os.fsencode(self.maintainer) # convert to original raw bytes # Now, convert these raw bytes into unicode. m = m.decode(fs_enc) # Set your locale if you get errors here self.maintainer = m else: # Python 2 if hasattr(self.maintainer,'decode'): self.maintainer = self.maintainer.decode(fs_enc) def get_debinfo(self): ############################################### # 1. setup initial variables # A. create config defaults module_name = self.distribution.get_name() if 1: # set default maintainer if (self.distribution.get_maintainer() != 'UNKNOWN' and self.distribution.get_maintainer_email() != 'UNKNOWN'): guess_maintainer = "%s <%s>"%( self.distribution.get_maintainer(), self.distribution.get_maintainer_email()) elif (self.distribution.get_author() != 'UNKNOWN' and self.distribution.get_author_email() != 'UNKNOWN'): guess_maintainer = "%s <%s>"%( self.distribution.get_author(), self.distribution.get_author_email()) else: guess_maintainer = "unknown " if self.default_maintainer is not None: log.warn('Deprecation warning: you are using the ' '--default-maintainer option. ' 'Switch to the --maintainer option.') guess_maintainer = self.default_maintainer if hasattr(guess_maintainer,'decode'): # python 2 : convert (back to) unicode guess_maintainer = guess_maintainer.decode('utf-8') # B. find config files (if any) cfg_files = [] if self.extra_cfg_file is not None: cfg_files.append(self.extra_cfg_file) use_setuptools = True try: ei_cmd = self.distribution.get_command_obj('egg_info') except DistutilsModuleError as err: use_setuptools = False have_script_entry_points = None config_fname = 'stdeb.cfg' # Distutils fails if not run from setup.py dir, so this is OK. if os.path.exists(config_fname): cfg_files.append(config_fname) if use_setuptools: self.run_command('egg_info') egg_info_dirname = ei_cmd.egg_info # Pickup old location of stdeb.cfg config_fname = os.path.join(egg_info_dirname,'stdeb.cfg') if os.path.exists(config_fname): log.warn('Deprecation warning: stdeb detected old location of ' 'stdeb.cfg in %s. This file will be used, but you ' 'should move it alongside setup.py.' %egg_info_dirname) cfg_files.append(config_fname) egg_module_name = egg_info_dirname[:egg_info_dirname.index('.egg-info')] egg_module_name = egg_module_name.split(os.sep)[-1] if 1: # determine whether script specifies setuptools entry_points ep_fname = os.path.join(egg_info_dirname,'entry_points.txt') if os.path.exists(ep_fname): entry_points = open(ep_fname,'rU').readlines() else: entry_points = '' entry_points = [ep.strip() for ep in entry_points] if ('[console_scripts]' in entry_points or '[gui_scripts]' in entry_points): have_script_entry_points = True else: # We don't have setuptools, so guess egg_info_dirname to # find old stdeb.cfg. entries = os.listdir(os.curdir) for entry in entries: if not (entry.endswith('.egg-info') and os.path.isdir(entry)): continue # Pickup old location of stdeb.cfg config_fname = os.path.join(entry,'stdeb.cfg') if os.path.exists(config_fname): log.warn('Deprecation warning: stdeb detected ' 'stdeb.cfg in %s. This file will be used, but you ' 'should move it alongside setup.py.' % entry) cfg_files.append(config_fname) if have_script_entry_points is None: have_script_entry_points = self.distribution.has_scripts() upstream_version = self.distribution.get_version() bad_chars = ':_' for bad_char in bad_chars: if bad_char in upstream_version: raise ValueError("Illegal character (%r) detected in version. " "This will break the debian tools."%bad_char) description = self.distribution.get_description() if hasattr(description,'decode'): # python 2 : convert (back to) unicode description = description.decode('utf-8') description = description[:60] long_description = self.distribution.get_long_description() if hasattr(long_description,'decode'): # python 2 : convert (back to) unicode long_description = long_description.decode('utf-8') long_description = long_description debinfo = DebianInfo( cfg_files=cfg_files, module_name = module_name, default_distribution=self.default_distribution, guess_maintainer=guess_maintainer, upstream_version = upstream_version, has_ext_modules = self.distribution.has_ext_modules(), description = description, long_description = long_description, patch_file = self.patch_file, patch_level = self.patch_level, debian_version = self.debian_version, have_script_entry_points = have_script_entry_points, setup_requires = (), # XXX How do we get the setup_requires? use_setuptools = use_setuptools, guess_conflicts_provides_replaces=self.guess_conflicts_provides_replaces, sdist_dsc_command = self, with_python2 = self.with_python2, with_python3 = self.with_python3, no_python2_scripts = self.no_python2_scripts, no_python3_scripts = self.no_python3_scripts, force_x_python3_version=self.force_x_python3_version, allow_virtualenv_install_location=self.allow_virtualenv_install_location, ) return debinfo stdeb-0.8.5/stdeb/command/debianize.py0000644000076500000240000000144412471220204020130 0ustar strawstaff00000000000000from distutils.core import Command from stdeb.command.common import common_debian_package_command from stdeb.util import build_dsc, stdeb_cmdline_opts, \ stdeb_cmd_bool_opts, stdeb_cfg_options class debianize(common_debian_package_command): description = "distutils command to create a debian directory" user_options = stdeb_cmdline_opts + stdeb_cfg_options boolean_options = stdeb_cmd_bool_opts def run(self): debinfo = self.get_debinfo() if debinfo.patch_file != '': raise RuntimeError('Patches cannot be applied in debianize command') dist_dir = None repackaged_dirname = None build_dsc(debinfo, dist_dir, repackaged_dirname, debian_dir_only=True, ) stdeb-0.8.5/stdeb/command/install_deb.py0000644000076500000240000000201512471220204020451 0ustar strawstaff00000000000000import os, glob import stdeb.util as util from distutils.core import Command __all__ = ['install_deb'] class install_deb(Command): description = 'distutils command to install debian binary package' user_options = [] boolean_options = [] def initialize_options (self): pass def finalize_options (self): pass def run(self): # generate .deb file self.run_command('bdist_deb') # get relevant options passed to sdist_dsc sdist_dsc = self.get_finalized_command('sdist_dsc') # execute system command and read output (execute and read output of find cmd) target_dirs = [] target_debs = glob.glob( os.path.join( sdist_dsc.dist_dir, '*.deb' ) ) if len(target_debs)==0: raise ValueError('could not find .deb file') for target_deb in target_debs: # define system command to execute (install .deb binary pkg) syscmd = ['dpkg','--install',target_deb] util.process_command(syscmd) stdeb-0.8.5/stdeb/command/sdist_dsc.py0000644000076500000240000001364112471220204020157 0ustar strawstaff00000000000000import sys, os, shutil, tempfile from stdeb import log from stdeb.util import expand_sdist_file, recursive_hardlink from stdeb.util import build_dsc, stdeb_cmdline_opts, \ stdeb_cmd_bool_opts, stdeb_cfg_options from stdeb.util import repack_tarball_with_debianized_dirname from stdeb.command.common import common_debian_package_command __all__ = ['sdist_dsc'] class sdist_dsc(common_debian_package_command): description = "distutils command to create a debian source distribution" user_options = stdeb_cmdline_opts + [ ('use-premade-distfile=','P', 'use .zip or .tar.gz file already made by sdist command'), ] + stdeb_cfg_options boolean_options = stdeb_cmd_bool_opts def initialize_options(self): self.use_premade_distfile = None common_debian_package_command.initialize_options(self) def run(self): debinfo = self.get_debinfo() if debinfo.patch_file != '' and self.patch_already_applied: raise RuntimeError('A patch was already applied, but another ' 'patch is requested.') repackaged_dirname = debinfo.source+'-'+debinfo.upstream_version fullpath_repackaged_dirname = os.path.join(self.dist_dir, repackaged_dirname) cleanup_dirs = [] if self.use_premade_distfile is None: # generate original tarball sdist_cmd = self.distribution.get_command_obj('sdist') self.run_command('sdist') source_tarball = None for archive_file in sdist_cmd.get_archive_files(): if archive_file.endswith('.tar.gz'): source_tarball = archive_file if source_tarball is None: raise RuntimeError('sdist did not produce .tar.gz file') # make copy of source tarball in deb_dist/ local_source_tarball = os.path.split(source_tarball)[-1] shutil.copy2( source_tarball, local_source_tarball ) source_tarball = local_source_tarball self.use_premade_distfile = source_tarball else: source_tarball = self.use_premade_distfile # Copy source tree assuming that package-0.1.tar.gz contains # single top-level path 'package-0.1'. The contents of this # directory are then used. if os.path.exists(fullpath_repackaged_dirname): shutil.rmtree(fullpath_repackaged_dirname) tmpdir = tempfile.mkdtemp() expand_sdist_file( os.path.abspath(source_tarball), cwd=tmpdir ) expanded_base_files = os.listdir(tmpdir) assert len(expanded_base_files)==1 actual_package_dirname = expanded_base_files[0] expected_package_dirname = debinfo.module_name + '-' + debinfo.upstream_version shutil.move( os.path.join( tmpdir, actual_package_dirname ), fullpath_repackaged_dirname) # ensure premade sdist can actually be used self.use_premade_distfile = os.path.abspath(self.use_premade_distfile) expand_dir = os.path.join(self.dist_dir,'tmp_sdist_dsc') cleanup_dirs.append(expand_dir) if os.path.exists(expand_dir): shutil.rmtree(expand_dir) if not os.path.exists(self.dist_dir): os.mkdir(self.dist_dir) os.mkdir(expand_dir) expand_sdist_file(self.use_premade_distfile,cwd=expand_dir) is_tgz=False if self.use_premade_distfile.lower().endswith('.tar.gz'): is_tgz=True # now the sdist package is expanded in expand_dir expanded_root_files = os.listdir(expand_dir) assert len(expanded_root_files)==1 distname_in_premade_distfile = expanded_root_files[0] debianized_dirname = repackaged_dirname original_dirname = os.path.split(distname_in_premade_distfile)[-1] do_repack=False if is_tgz: source_tarball = self.use_premade_distfile else: log.warn('WARNING: .orig.tar.gz will be generated from sdist ' 'archive ("%s") because it is not a .tar.gz file', self.use_premade_distfile) do_repack=True if do_repack: tmp_dir = os.path.join(self.dist_dir, 'tmp_repacking_dir' ) os.makedirs( tmp_dir ) cleanup_dirs.append(tmp_dir) source_tarball = os.path.join(tmp_dir,'repacked_sdist.tar.gz') repack_tarball_with_debianized_dirname(self.use_premade_distfile, source_tarball, debianized_dirname, original_dirname ) if source_tarball is not None: # Because we deleted all .pyc files above, if the # original source dist has them, we will have # (wrongly) deleted them. So, quit loudly rather # than fail silently. for root, dirs, files in os.walk(fullpath_repackaged_dirname): for name in files: if name.endswith('.pyc'): raise RuntimeError('original source dist cannot ' 'contain .pyc files') ############################################### # 3. Find all directories for pkgdir in self.distribution.packages or []: debinfo.dirlist += ' ' + pkgdir.replace('.', '/') ############################################### # 4. Build source tree and rename it to be in self.dist_dir build_dsc(debinfo, self.dist_dir, repackaged_dirname, orig_sdist=source_tarball, patch_posix = self.patch_posix, remove_expanded_source_dir=self.remove_expanded_source_dir, ) for rmdir in cleanup_dirs: shutil.rmtree(rmdir) stdeb-0.8.5/stdeb/downloader.py0000644000076500000240000001216112471220204016714 0ustar strawstaff00000000000000from __future__ import print_function import os try: # Python 2.x import xmlrpclib except ImportError: # Python 3.x import xmlrpc.client as xmlrpclib from functools import partial import requests import hashlib import warnings import stdeb from stdeb.transport import RequestsTransport myprint=print USER_AGENT = 'pypi-install/%s ( https://github.com/astraw/stdeb )'%stdeb.__version__ def find_tar_gz(package_name, pypi_url = 'https://pypi.python.org/pypi', verbose=0, release=None): transport = RequestsTransport() transport.user_agent = USER_AGENT if pypi_url.startswith('https://'): transport.use_https = True pypi = xmlrpclib.ServerProxy(pypi_url, transport=transport) download_url = None expected_md5_digest = None if verbose >= 2: myprint( 'querying PyPI (%s) for package name "%s"' % (pypi_url, package_name) ) show_hidden=True all_releases = pypi.package_releases(package_name,show_hidden) if release is not None: # A specific release is requested. if verbose >= 2: myprint( 'found all available releases: %s' % (', '.join(all_releases),) ) if release not in all_releases: raise ValueError('your desired release %r is not among available ' 'releases %r'%(release,all_releases)) version = release else: default_releases = pypi.package_releases(package_name) if len(default_releases)!=1: raise RuntimeError('Expected one and only one release. ' 'Non-hidden: %r. All: %r'%( default_releases,all_releases)) default_release = default_releases[0] if verbose >= 2: myprint( 'found default release: %s' % (', '.join(default_releases),) ) version = default_release urls = pypi.release_urls( package_name,version) for url in urls: if url['packagetype']=='sdist': assert url['python_version']=='source', 'how can an sdist not be a source?' if url['url'].endswith('.tar.gz'): download_url = url['url'] if 'md5_digest' in url: expected_md5_digest = url['md5_digest'] break if download_url is None: # PyPI doesn't have package. Is download URL provided? result = pypi.release_data(package_name,version) if result['download_url'] != 'UNKNOWN': download_url = result['download_url'] # no download URL provided, see if PyPI itself has download urls = pypi.release_urls( result['name'], result['version'] ) if download_url is None: raise ValueError('no package "%s" was found'%package_name) return download_url, expected_md5_digest def md5sum(filename): # from http://stackoverflow.com/questions/7829499/using-hashlib-to-compute-md5-digest-of-a-file-in-python-3 with open(filename, mode='rb') as f: d = hashlib.md5() for buf in iter(partial(f.read, 128), b''): d.update(buf) return d.hexdigest() def get_source_tarball(package_name,verbose=0,allow_unsafe_download=False, release=None): download_url, expected_md5_digest = find_tar_gz(package_name, verbose=verbose, release=release) if not download_url.startswith('https://'): if allow_unsafe_download: warnings.warn('downloading from unsafe url: %r' % download_url) else: raise ValueError('PYPI returned unsafe url: %r' % download_url) fname = download_url.split('/')[-1] if expected_md5_digest is not None: if os.path.exists(fname): actual_md5_digest = md5sum(fname) if actual_md5_digest == expected_md5_digest: if verbose >= 1: myprint( 'Download URL: %s' % download_url ) myprint( 'File "%s" already exists with correct checksum.' % fname ) return fname else: raise ValueError('File "%s" exists but has wrong checksum.'%fname) if verbose >= 1: myprint( 'downloading %s' % download_url ) headers = {'User-Agent': USER_AGENT } r = requests.get(download_url, headers=headers) r.raise_for_status() package_tar_gz = r.content if verbose >= 1: myprint( 'done downloading %d bytes.' % ( len(package_tar_gz), ) ) if expected_md5_digest is not None: m = hashlib.md5() m.update(package_tar_gz) actual_md5_digest = m.hexdigest() if verbose >= 2: myprint( 'md5: actual %s\n expected %s' % (actual_md5_digest, expected_md5_digest)) if actual_md5_digest != expected_md5_digest: raise ValueError('actual and expected md5 digests do not match') else: warnings.warn('no md5 digest found -- cannot verify source file') fd = open(fname,mode='wb') fd.write( package_tar_gz ) fd.close() return fname stdeb-0.8.5/stdeb/transport.py0000644000076500000240000000573412471220204016622 0ustar strawstaff00000000000000# -*- coding: utf-8 -*- """ A replacement transport for Python xmlrpc library. Usage: >>> import xmlrpclib >>> from transport import RequestsTransport >>> s = xmlrpclib.ServerProxy('http://yoursite.com/xmlrpc', transport=RequestsTransport()) >>> s.demo.sayHello() Hello! """ try: import xmlrpc.client as xmlrpc except ImportError: import xmlrpclib as xmlrpc import requests import requests.utils import sys from distutils.version import StrictVersion import warnings class RequestsTransport(xmlrpc.Transport): """ Drop in Transport for xmlrpclib that uses Requests instead of httplib """ # change our user agent to reflect Requests user_agent = "Python XMLRPC with Requests (python-requests.org)" # override this if you'd like to https use_https = False def request(self, host, handler, request_body, verbose): """ Make an xmlrpc request. """ headers = {'User-Agent': self.user_agent, 'Content-Type': 'text/xml', } url = self._build_url(host, handler) kwargs = {} if StrictVersion(requests.__version__) >= StrictVersion('0.8.8'): kwargs['verify']=True else: if self.use_https: warnings.warn('using https transport but no certificate ' 'verification. (Hint: upgrade requests package.)') try: resp = requests.post(url, data=request_body, headers=headers, **kwargs) except ValueError: raise except Exception: raise # something went wrong else: try: resp.raise_for_status() except requests.RequestException as e: raise xmlrpc.ProtocolError(url, resp.status_code, str(e), resp.headers) else: return self.parse_response(resp) def parse_response(self, resp): """ Parse the xmlrpc response. """ p, u = self.getparser() if hasattr(resp,'text'): # modern requests will do this for us text = resp.text # this is unicode(py2)/str(py3) else: encoding = requests.utils.get_encoding_from_headers(resp.headers) if encoding is None: encoding='utf-8' # FIXME: what to do here? if sys.version_info[0]==2: text = unicode(resp.content, encoding, errors='replace') else: assert sys.version_info[0]==3 text = str(resp.content, encoding, errors='replace') p.feed(text) p.close() return u.close() def _build_url(self, host, handler): """ Build a url for our request based on the host, handler and use_http property """ scheme = 'https' if self.use_https else 'http' return '%s://%s/%s' % (scheme, host, handler)stdeb-0.8.5/stdeb/util.py0000644000076500000240000016557012471220204015550 0ustar strawstaff00000000000000# # This module contains most of the code of stdeb. # import re, sys, os, shutil, select import codecs try: # Python 2.x import ConfigParser except ImportError: # Python 3.x import configparser as ConfigParser import subprocess import tempfile import stdeb from stdeb import log, __version__ as __stdeb_version__ if hasattr(os,'link'): link_func = os.link else: # matplotlib deletes link from os namespace, expected distutils workaround link_func = shutil.copyfile __all__ = ['DebianInfo','build_dsc','expand_tarball','expand_zip', 'stdeb_cmdline_opts','stdeb_cmd_bool_opts','recursive_hardlink', 'apply_patch','repack_tarball_with_debianized_dirname', 'expand_sdist_file','stdeb_cfg_options'] DH_MIN_VERS = '7' # Fundamental to stdeb >= 0.4 DH_IDEAL_VERS = '7.4.3' # fixes Debian bug 548392 PYTHON_ALL_MIN_VERS = '2.6.6-3' try: # Python 2.x from exceptions import Exception except ImportError: # Python 3.x pass class CalledProcessError(Exception): pass class CantSatisfyRequirement(Exception): pass def check_call(*popenargs, **kwargs): retcode = subprocess.call(*popenargs, **kwargs) if retcode == 0: return raise CalledProcessError(retcode) if sys.version_info[0]==2: help_str_py2='If True, build package for python 2. (Default=True).' help_str_py3='If True, build package for python 3. (Default=False).' else: assert sys.version_info[0]==3 help_str_py2='If True, build package for python 2. (Default=False).' help_str_py3='If True, build package for python 3. (Default=True).' stdeb_cmdline_opts = [ ('dist-dir=', 'd', "directory to put final built distributions in (default='deb_dist')"), ('patch-already-applied','a', 'patch was already applied (used when py2dsc calls sdist_dsc)'), ('default-distribution=', None, "deprecated (see --suite)"), ('suite=', 'z', "distribution name to use if not specified in .cfg (default='unstable')"), ('default-maintainer=', None, 'deprecated (see --maintainer)'), ('maintainer=', 'm', 'maintainer name and email to use if not specified in .cfg ' '(default from setup.py)'), ('extra-cfg-file=','x', 'additional .cfg file (in addition to stdeb.cfg if present)'), ('patch-file=','p', 'patch file applied before setup.py called ' '(incompatible with file specified in .cfg)'), ('patch-level=','l', 'patch file applied before setup.py called ' '(incompatible with file specified in .cfg)'), ('patch-posix','q', 'apply the patch with --posix mode'), ('remove-expanded-source-dir','r', 'remove the expanded source directory'), ('ignore-install-requires', 'i', 'ignore the requirements from requires.txt in the egg-info directory'), ('pycentral-backwards-compatibility=',None, 'This option has no effect, is here for backwards compatibility, and may ' 'be removed someday.'), ('workaround-548392=',None, 'This option has no effect, is here for backwards compatibility, and may ' 'be removed someday.'), ('no-backwards-compatibility',None, 'This option has no effect, is here for backwards compatibility, and may ' 'be removed someday.'), ('guess-conflicts-provides-replaces=',None, 'If True, attempt to guess Conflicts/Provides/Replaces in debian/control ' 'based on apt-cache output. (Default=False).'), ('with-python2=',None, help_str_py2), ('with-python3=',None, help_str_py3), ('no-python2-scripts=',None, 'If True, do not install scripts for python 2. (Default=False).'), ('no-python3-scripts=',None, 'If True, do not install scripts for python 3. (Default=False).'), ('force-x-python3-version',None, 'Override default minimum python3:any dependency with value from ' 'x-python3-version'), ('allow-virtualenv-install-location',None, 'Allow installing into /some/random/virtualenv-path'), ] # old entries from stdeb.cfg: # These should be settable as distutils command options, but in case # we want to support other packaging methods, they should also be # settable outside distutils. Consequently, we keep the ability to # parse ConfigParser files (specified with --extra-cfg-file). TODO: # Also, some (most, in fact) of the above options should also be # settable in the ConfigParser file. stdeb_cfg_options = [ # With defaults ('source=',None, 'debian/control Source: (Default: )'), ('package=',None, 'debian/control Package: (Default: python-)'), ('package3=',None, 'debian/control Package: (Default: python3-)'), ('suite=',None, 'suite (e.g. stable, lucid) in changelog (Default: unstable)'), ('maintainer=',None, 'debian/control Maintainer: (Default: )'), ('debian-version=',None,'debian version (Default: 1)'), ('section=',None,'debian/control Section: (Default: python)'), # With no defaults ('epoch=',None,'version epoch'), ('forced-upstream-version=',None,'forced upstream version'), ('upstream-version-prefix=',None,'upstream version prefix'), ('upstream-version-suffix=',None,'upstream version suffix'), ('uploaders=',None,'uploaders'), ('copyright-file=',None,'copyright file'), ('build-depends=',None,'debian/control Build-Depends:'), ('build-conflicts=',None,'debian/control Build-Conflicts:'), ('stdeb-patch-file=',None,'file containing patches for stdeb to apply'), ('stdeb-patch-level=',None,'patch level provided to patch command'), ('depends=',None,'debian/control Depends:'), ('depends3=',None,'debian/control Depends:'), ('suggests=',None,'debian/control Suggests:'), ('suggests3=',None,'debian/control Suggests:'), ('recommends=',None,'debian/control Recommends:'), ('recommends3=',None,'debian/control Recommends:'), ('xs-python-version=',None,'debian/control XS-Python-Version:'), ('x-python3-version=',None,'debian/control X-Python3-Version:'), ('dpkg-shlibdeps-params=',None,'parameters passed to dpkg-shlibdeps'), ('conflicts=',None,'debian/control Conflicts:'), ('conflicts3=',None,'debian/control Conflicts:'), ('provides=',None,'debian/control Provides:'), ('provides3=',None,'debian/control Provides3:'), ('replaces=',None,'debian/control Replaces:'), ('replaces3=',None,'debian/control Replaces3:'), ('mime-desktop-files=',None,'MIME desktop files'), ('mime-file=',None,'MIME file'), ('shared-mime-file=',None,'shared MIME file'), ('setup-env-vars=',None,'environment variables passed to setup.py'), ('udev-rules=',None,'file with rules to install to udev'), ] stdeb_cmd_bool_opts = [ 'patch-already-applied', 'remove-expanded-source-dir', 'patch-posix', 'ignore-install-requires', 'no-backwards-compatibility', 'force-x-python3-version', 'allow-virtualenv-install-location', ] class NotGiven: pass def process_command(args, cwd=None): if not isinstance(args, (list, tuple)): raise RuntimeError("args passed must be in a list") check_call(args, cwd=cwd) def recursive_hardlink(src,dst): dst = os.path.abspath(dst) orig_dir = os.path.abspath(os.curdir) os.chdir(src) try: for root,dirs,files in os.walk(os.curdir): for file in files: fullpath = os.path.normpath(os.path.join(root,file)) dirname, fname = os.path.split(fullpath) dstdir = os.path.normpath(os.path.join(dst,dirname)) if not os.path.exists(dstdir): os.makedirs(dstdir) newpath = os.path.join(dstdir,fname) if os.path.exists(newpath): if os.path.samefile(fullpath,newpath): continue else: os.unlink(newpath) #print 'linking %s -> %s'%(fullpath,newpath) link_func(fullpath,newpath) finally: os.chdir(orig_dir) def debianize_name(name): "make name acceptable as a Debian (binary) package name" name = name.replace('_','-') name = name.lower() return name def source_debianize_name(name): "make name acceptable as a Debian source package name" name = name.replace('_','-') name = name.replace('.','-') name = name.lower() return name def debianize_version(name): "make name acceptable as a Debian package name" # XXX should use setuptools' version sorting and do this properly: name = name.replace('.dev','~dev') name = name.lower() return name def dpkg_compare_versions(v1,op,v2): args = ['/usr/bin/dpkg','--compare-versions',v1,op,v2] cmd = subprocess.Popen(args) returncode = cmd.wait() if returncode: return False else: return True def get_cmd_stdout(args): cmd = subprocess.Popen(args,stdout=subprocess.PIPE) returncode = cmd.wait() if returncode: log.error('ERROR running: %s', ' '.join(args)) raise RuntimeError('returncode %d', returncode) return cmd.stdout.read() def normstr(s): try: # Python 3.x result = str(s,'utf-8') except TypeError: # Python 2.x result = s return result def get_date_822(): """return output of 822-date command""" cmd = '/bin/date' if not os.path.exists(cmd): raise ValueError('%s command does not exist.'%cmd) args = [cmd,'-R'] result = get_cmd_stdout(args).strip() result = normstr(result) return result def get_version_str(pkg): args = ['/usr/bin/dpkg-query','--show', '--showformat=${Version}',pkg] stdout = get_cmd_stdout(args) return stdout.strip().decode('ascii') def load_module(name,fname): import imp suffix = '.py' found = False for description in imp.get_suffixes(): if description[0]==suffix: found = True break assert found fd = open(fname,mode='r') try: module = imp.load_module(name,fd,fname,description) finally: fd.close() return module def get_deb_depends_from_setuptools_requires(requirements, on_failure="warn"): """ Suppose you can't confidently figure out a .deb which satisfies a given requirement. If on_failure == 'warn', then log a warning. If on_failure == 'raise' then raise CantSatisfyRequirement exception. If on_failure == 'guess' then guess that python-$FOO will satisfy the dependency and that the Python version numbers will apply to the Debian packages (in addition to logging a warning message). """ assert on_failure in ("raise", "warn", "guess"), on_failure import pkg_resources depends = [] # This will be the return value from this function. parsed_reqs=[] for extra,reqs in pkg_resources.split_sections(requirements): if extra: continue parsed_reqs.extend(pkg_resources.parse_requirements(reqs)) if not parsed_reqs: return depends if not os.path.exists('/usr/bin/apt-file'): raise ValueError('apt-file not in /usr/bin. Please install ' 'with: sudo apt-get install apt-file') # Ask apt-file for any packages which have a .egg-info file by # these names. # Note that apt-file appears to think that some packages # e.g. setuptools itself have "foo.egg-info/BLAH" files but not a # "foo.egg-info" directory. egginfore=("(/(%s)(?:-[^/]+)?(?:-py[0-9]\.[0-9.]+)?\.egg-info)" % '|'.join(req.project_name.replace('-', '_') for req in parsed_reqs)) args = ["apt-file", "search", "--ignore-case", "--regexp", egginfore] if 1: # do dry run on apt-file dry_run_args = args[:] + ['--dummy','--non-interactive'] cmd = subprocess.Popen(dry_run_args,stderr=subprocess.PIPE) returncode = cmd.wait() if returncode: err_output = cmd.stderr.read() raise RuntimeError('Error running "apt-file search": ' + err_output.strip()) try: cmd = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, universal_newlines=True) except Exception as le: # TODO: catch rc=1 and "E: The cache directory is empty. You need to # run 'apt-file update' first.", and tell the user to follow those # instructions. log.error('ERROR running: %s', ' '.join(args)) raise RuntimeError('exception %s from subprocess %s' % (le,args)) returncode = cmd.wait() if returncode: log.error('ERROR running: %s', ' '.join(args)) raise RuntimeError('returncode %d from subprocess %s' % (returncode, args)) inlines = cmd.stdout.readlines() dd = {} # {pydistname: {pydist: set(debpackagename)}} E=re.compile(egginfore, re.I) D=re.compile("^([^:]*):", re.I) eggsndebs = set() for l in inlines: if l: emo = E.search(l) assert emo, l dmo = D.search(l) assert dmo, l eggsndebs.add((emo.group(1), dmo.group(1))) for (egginfo, debname) in eggsndebs: pydist = pkg_resources.Distribution.from_filename(egginfo) try: dd.setdefault( pydist.project_name.lower(), {}).setdefault( pydist, set()).add(debname) except ValueError as le: log.warn("I got an error parsing a .egg-info file named \"%s\" " "from Debian package \"%s\" as a pkg_resources " "Distribution: %s" % (egginfo, debname, le,)) pass # Now for each requirement, see if a Debian package satisfies it. ops = {'<':'<<','>':'>>','==':'=','<=':'<=','>=':'>='} for req in parsed_reqs: reqname = req.project_name.lower() gooddebs = set() for pydist, debs in dd.get(reqname, {}).iteritems(): if pydist in req: ## log.info("I found Debian packages \"%s\" which provides " ## "Python package \"%s\", version \"%s\", which " ## "satisfies our version requirements: \"%s\"" ## % (', '.join(debs), req.project_name, ver, req) gooddebs |= (debs) else: log.info("I found Debian packages \"%s\" which provides " "Python package \"%s\" which " "does not satisfy our version requirements: " "\"%s\" -- ignoring." % (', '.join(debs), req.project_name, req)) if not gooddebs: if on_failure == 'warn': log.warn( "I found no Debian package which provides the required " "Python package \"%s\" with version requirements " "\"%s\"."% (req.project_name, req.specs)) elif on_failure == "raise": raise CantSatisfyRequirement( "I found no Debian package which " "provides the required Python package \"%s\" with version " "requirements \"%s\"." % (req.project_name, req.specs), req) elif on_failure == "guess": log.warn("I found no Debian package which provides the " "required Python package \"%s\" with version " "requirements \"%s\". Guessing blindly that the " "name \"python-%s\" will be it, and that the Python " "package version number requirements will apply to " "the Debian package." % (req.project_name, req.specs, reqname)) gooddebs.add("python-" + reqname) elif len(gooddebs) == 1: log.info("I found a Debian package which provides the require " "Python package. Python package: \"%s\", " "Debian package: \"%s\"; adding Depends specifications " "for the following version(s): \"%s\"" % (req.project_name, tuple(gooddebs)[0], req.specs)) else: log.warn("I found multiple Debian packages which provide the " "Python distribution required. I'm listing them all " "as alternates. Candidate debs which claim to provide " "the Python package \"%s\" are: \"%s\"" % (req.project_name, ', '.join(gooddebs),)) alts = [] for deb in gooddebs: added_any_alt = False for spec in req.specs: # Here we blithely assume that the Debian package # versions are enough like the Python package versions # that the requirement can be ported straight over... alts.append("%s (%s %s)" % (deb, ops[spec[0]], spec[1])) added_any_alt = True if not added_any_alt: # No alternates were added, but we have the name of a # good package. alts.append("%s"%deb) if len(alts): depends.append(' | '.join(alts)) return depends def make_tarball(tarball_fname,directory,cwd=None): "create a tarball from a directory" if tarball_fname.endswith('.gz'): opts = 'czf' else: opts = 'cf' args = ['/bin/tar',opts,tarball_fname,directory] process_command(args, cwd=cwd) def expand_tarball(tarball_fname,cwd=None): "expand a tarball" if tarball_fname.endswith('.gz'): opts = 'xzf' elif tarball_fname.endswith('.bz2'): opts = 'xjf' else: opts = 'xf' args = ['/bin/tar',opts,tarball_fname] process_command(args, cwd=cwd) def expand_zip(zip_fname,cwd=None): "expand a zip" unzip_path = '/usr/bin/unzip' if not os.path.exists(unzip_path): log.error('ERROR: {} does not exist'.format(unzip_path)) sys.exit(1) args = [unzip_path, zip_fname] # Does it have a top dir res = subprocess.Popen( [args[0], '-l', args[1]], cwd=cwd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) contents = [] for line in res.stdout.readlines()[3:-2]: contents.append(line.split()[-1]) commonprefix = os.path.commonprefix(contents) if not commonprefix: extdir = os.path.join(cwd, os.path.basename(zip_fname[:-4])) args.extend(['-d', os.path.abspath(extdir)]) process_command(args, cwd=cwd) def expand_sdist_file(sdist_file,cwd=None): lower_sdist_file = sdist_file.lower() if lower_sdist_file.endswith('.zip'): expand_zip(sdist_file,cwd=cwd) elif lower_sdist_file.endswith('.tar.bz2'): expand_tarball(sdist_file,cwd=cwd) elif lower_sdist_file.endswith('.tar.gz'): expand_tarball(sdist_file,cwd=cwd) else: raise RuntimeError('could not guess format of original sdist file') def repack_tarball_with_debianized_dirname( orig_sdist_file, repacked_sdist_file, debianized_dirname, original_dirname ): working_dir = tempfile.mkdtemp() expand_sdist_file( orig_sdist_file, cwd=working_dir ) fullpath_original_dirname = os.path.join(working_dir,original_dirname) fullpath_debianized_dirname = os.path.join(working_dir,debianized_dirname) # ensure sdist looks like sdist: assert os.path.exists( fullpath_original_dirname ) assert len(os.listdir(working_dir))==1 if fullpath_original_dirname != fullpath_debianized_dirname: # rename original dirname to debianized dirname os.rename(fullpath_original_dirname, fullpath_debianized_dirname) make_tarball(repacked_sdist_file,debianized_dirname,cwd=working_dir) shutil.rmtree(working_dir) def dpkg_source(b_or_x,arg1,cwd=None): "call dpkg-source -b|x arg1 [arg2]" assert b_or_x in ['-b','-x'] args = ['/usr/bin/dpkg-source',b_or_x,arg1] process_command(args, cwd=cwd) def dpkg_genchanges(cwd=None): args = ['/usr/bin/dpkg-buildpackage', '-rfakeroot', '-uc', # unsigned changes '-us', # unsigned source '-S', # source package '-sa', # with original source archive ] process_command(args,cwd=cwd) def apply_patch(patchfile,cwd=None,posix=False,level=0): """call 'patch -p[level] [--posix] < arg1' posix mode is sometimes necessary. It keeps empty files so that dpkg-source removes their contents. """ if not os.path.exists(patchfile): raise RuntimeError('patchfile "%s" does not exist'%patchfile) fd = open(patchfile,mode='r') level_str = '-p%d'%level args = ['/usr/bin/patch',level_str] if posix: args.append('--posix') log.info('PATCH COMMAND: %s < %s', ' '.join(args), patchfile) log.info(' PATCHING in dir: %s', cwd) # print >> sys.stderr, 'PATCH COMMAND:',' '.join(args),'<',patchfile # print >> sys.stderr, ' PATCHING in dir:',cwd res = subprocess.Popen( args, cwd=cwd, stdin=fd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) returncode=None while returncode is None: returncode = res.poll() ready = select.select( [res.stdout,res.stderr],[],[],0.1) # XXX figure out how to do this without reading byte-by-byte if res.stdout in ready[0]: sys.stdout.write(res.stdout.read(1)) sys.stdout.flush() if res.stderr in ready[0]: sys.stderr.write(res.stderr.read(1)) sys.stderr.flush() # finish outputting file sys.stdout.write(res.stdout.read()) sys.stdout.flush() sys.stderr.write(res.stderr.read()) sys.stderr.flush() if returncode: log.error('ERROR running: %s', ' '.join(args)) log.error('ERROR in %s', cwd) # print >> sys.stderr, 'ERROR running: %s'%(' '.join(args),) # print >> sys.stderr, 'ERROR in',cwd raise RuntimeError('returncode %d'%returncode) def parse_vals(cfg,section,option): """parse comma separated values in debian control file style from .cfg""" try: vals = cfg.get(section,option) except ConfigParser.NoSectionError as err: if section != 'DEFAULT': vals = cfg.get('DEFAULT',option) else: raise err vals = vals.split('#')[0] vals = vals.strip() vals = vals.split(',') vals = [v.strip() for v in vals] vals = [v for v in vals if len(v)] return vals def parse_val(cfg,section,option): """extract a single value from .cfg""" vals = parse_vals(cfg,section,option) if len(vals)==0: return '' else: assert len(vals)==1, (section, option, vals, type(vals)) return vals[0] def apt_cache_info(apt_cache_cmd,package_name): if apt_cache_cmd not in ('showsrc','show'): raise NotImplementedError( "don't know how to run apt-cache command '%s'"%apt_cache_cmd) result_list = [] args = ["apt-cache", apt_cache_cmd, package_name] cmd = subprocess.Popen(args, stdin=subprocess.PIPE, stderr=subprocess.PIPE, stdout=subprocess.PIPE) returncode = cmd.wait() if returncode: errline = cmd.stderr.read() if not (returncode == 100 and errline == "E: You must put some 'source' URIs in your sources.list\n"): log.error('ERROR running: %s', ' '.join(args)) raise RuntimeError('returncode %d from subprocess %s' % (returncode, args)) inlines = cmd.stdout.read() version_blocks = inlines.split('\n\n') for version_block in version_blocks: block_dict = {} if len(version_block)==0: continue version_lines = version_block.split('\n') assert version_lines[0].startswith('Package: ') block_dict['Package'] = version_lines[0][ len('Package: '): ] if apt_cache_cmd == 'showsrc': assert version_lines[1].startswith('Binary: ') block_dict['Binary'] = version_lines[1][ len('Binary: '): ] block_dict['Binary'] = block_dict['Binary'].split(', ') elif apt_cache_cmd == 'show': for start in ('Provides: ','Conflicts: ','Replaces: '): key = start[:-2] for line in version_lines[2:]: if line.startswith(start): unsplit_line_result = line[ len(start): ] split_result = unsplit_line_result.split(', ') block_dict[key] = split_result if key not in block_dict: block_dict[key] = [] result_list.append(block_dict) return result_list def check_cfg_files(cfg_files,module_name): """check if the configuration files actually specify something If config files are given, give warning if they don't contain information. This may indicate a wrong module name name, for example. """ cfg = ConfigParser.SafeConfigParser() cfg.read(cfg_files) if cfg.has_section(module_name): section_items = cfg.items(module_name) else: section_items = [] default_items = cfg.items('DEFAULT') n_items = len(section_items) + len(default_items) if n_items==0: log.warn('configuration files were specified, but no options were ' 'found in "%s" or "DEFAULT" sections.' % (module_name,) ) class DebianInfo: """encapsulate information for Debian distribution system""" def __init__(self, cfg_files=NotGiven, module_name=NotGiven, default_distribution=NotGiven, guess_maintainer=NotGiven, upstream_version=NotGiven, has_ext_modules=NotGiven, description=NotGiven, long_description=NotGiven, patch_file=None, patch_level=None, setup_requires=None, debian_version=None, have_script_entry_points = None, use_setuptools = False, guess_conflicts_provides_replaces = False, sdist_dsc_command = None, with_python2 = None, with_python3 = None, no_python2_scripts = None, no_python3_scripts = None, force_x_python3_version=False, allow_virtualenv_install_location=False, ): if cfg_files is NotGiven: raise ValueError("cfg_files must be supplied") if module_name is NotGiven: raise ValueError( "module_name must be supplied") if default_distribution is NotGiven: raise ValueError( "default_distribution must be supplied") if guess_maintainer is NotGiven: raise ValueError( "guess_maintainer must be supplied") if upstream_version is NotGiven: raise ValueError( "upstream_version must be supplied") if has_ext_modules is NotGiven: raise ValueError( "has_ext_modules must be supplied") if description is NotGiven: raise ValueError( "description must be supplied") if long_description is NotGiven: raise ValueError( "long_description must be supplied") cfg_defaults = self._make_cfg_defaults( module_name=module_name, default_distribution=default_distribution, guess_maintainer=guess_maintainer, ) if len(cfg_files): check_cfg_files(cfg_files,module_name) cfg = ConfigParser.SafeConfigParser(cfg_defaults) for cfg_file in cfg_files: with codecs.open( cfg_file, mode='r', encoding='utf-8') as fd: cfg.readfp(fd) if sdist_dsc_command is not None: # Allow distutils commands to override config files (this lets # command line options beat file options). for longopt, shortopt, desc in stdeb_cfg_options: opt_name = longopt[:-1] name = opt_name.replace('-','_') value = getattr( sdist_dsc_command, name ) if value is not None: if not cfg.has_section(module_name): cfg.add_section(module_name) cfg.set( module_name, opt_name, value ) self.stdeb_version = __stdeb_version__ self.module_name = module_name self.source = parse_val(cfg,module_name,'Source') self.package = parse_val(cfg,module_name,'Package') self.package3 = parse_val(cfg,module_name,'Package3') forced_upstream_version = parse_val(cfg,module_name, 'Forced-Upstream-Version') if forced_upstream_version == '': upstream_version_prefix = parse_val(cfg,module_name, 'Upstream-Version-Prefix') upstream_version_suffix = parse_val(cfg,module_name, 'Upstream-Version-Suffix') self.upstream_version = (upstream_version_prefix+ debianize_version(upstream_version)+ upstream_version_suffix) else: if (debianize_version(forced_upstream_version) != forced_upstream_version): raise ValueError('forced upstream version ("%s") not a ' 'Debian-compatible version (e.g. "%s")'%( forced_upstream_version, debianize_version(forced_upstream_version))) self.upstream_version = forced_upstream_version self.epoch = parse_val(cfg,module_name,'Epoch') if self.epoch != '' and not self.epoch.endswith(':'): self.epoch = self.epoch + ':' self.packaging_version = parse_val(cfg,module_name,'Debian-Version') if debian_version is not None: # command-line arg overrides file self.packaging_version = debian_version self.dsc_version = '%s-%s'%( self.upstream_version, self.packaging_version) self.full_version = '%s%s-%s'%( self.epoch, self.upstream_version, self.packaging_version) self.distname = parse_val(cfg,module_name,'Suite') self.maintainer = ', '.join(parse_vals(cfg,module_name,'Maintainer')) self.uploaders = parse_vals(cfg,module_name,'Uploaders') self.date822 = get_date_822() build_deps = [] if use_setuptools: if with_python2: build_deps.append('python-setuptools (>= 0.6b3)') if with_python3: build_deps.append('python3-setuptools') if setup_requires is not None and len(setup_requires): build_deps.extend( get_deb_depends_from_setuptools_requires(setup_requires)) depends = ['${misc:Depends}', '${python:Depends}'] depends3 = ['${misc:Depends}', '${python3:Depends}'] need_custom_binary_target = False if has_ext_modules: self.architecture = 'any' if with_python2: build_deps.append('python-all-dev (>= %s)'%PYTHON_ALL_MIN_VERS) depends.append('${shlibs:Depends}') self.architecture3 = 'any' if with_python3: build_deps.append('python3-all-dev') depends3.append('${shlibs:Depends}') else: self.architecture = 'all' if with_python2: build_deps.append('python-all (>= %s)'%PYTHON_ALL_MIN_VERS) self.architecture3 = 'all' if with_python3: build_deps.append('python3-all') self.copyright_file = parse_val(cfg,module_name,'Copyright-File') self.mime_file = parse_val(cfg,module_name,'MIME-File') self.shared_mime_file = parse_val(cfg,module_name,'Shared-MIME-File') if self.mime_file == '' and self.shared_mime_file == '': self.dh_installmime_indep_line = '' else: need_custom_binary_target = True self.dh_installmime_indep_line = '\tdh_installmime' mime_desktop_files = parse_vals(cfg,module_name,'MIME-Desktop-Files') if len(mime_desktop_files): need_custom_binary_target = True self.dh_desktop_indep_line = '\tdh_desktop' else: self.dh_desktop_indep_line = '' # E. any mime .desktop files self.install_file_lines = [] for mime_desktop_file in mime_desktop_files: self.install_file_lines.append( '%s usr/share/applications'%mime_desktop_file) depends.extend(parse_vals(cfg,module_name,'Depends') ) depends3.extend(parse_vals(cfg,module_name,'Depends3') ) self.depends = ', '.join(depends) self.depends3 = ', '.join(depends3) self.debian_section = parse_val(cfg,module_name,'Section') self.description = re.sub('\s+', ' ', description).strip() if long_description != 'UNKNOWN': ld2=[] for line in long_description.split('\n'): ls = line.strip() if len(ls): ld2.append(' '+line) else: ld2.append(' .') ld2 = ld2[:20] self.long_description = '\n'.join(ld2) else: self.long_description = '' if have_script_entry_points: build_deps.append( 'debhelper (>= %s)'%DH_IDEAL_VERS ) else: build_deps.append( 'debhelper (>= %s)'%DH_MIN_VERS ) build_deps.extend( parse_vals(cfg,module_name,'Build-Depends') ) self.build_depends = ', '.join(build_deps) suggests = ', '.join( parse_vals(cfg,module_name,'Suggests') ) suggests3 = ', '.join( parse_vals(cfg,module_name,'Suggests3') ) recommends = ', '.join( parse_vals(cfg,module_name,'Recommends') ) recommends3 = ', '.join( parse_vals(cfg,module_name,'Recommends3') ) self.source_stanza_extras = '' build_conflicts = parse_vals(cfg,module_name,'Build-Conflicts') if len(build_conflicts): self.source_stanza_extras += ('Build-Conflicts: '+ ', '.join( build_conflicts )+'\n') self.patch_file = parse_val(cfg,module_name,'Stdeb-Patch-File') if patch_file is not None: if self.patch_file != '': raise RuntimeError('A patch file was specified on the command ' 'line and in .cfg file.') else: self.patch_file = patch_file self.patch_level = parse_val(cfg,module_name,'Stdeb-Patch-Level') if self.patch_level != '': if patch_level is not None: raise RuntimeError('A patch level was specified on the command ' 'line and in .cfg file.') else: self.patch_level = int(self.patch_level) else: if patch_level is not None: self.patch_level = patch_level else: self.patch_level = 0 xs_python_version = parse_vals(cfg,module_name,'XS-Python-Version') if len(xs_python_version)!=0: self.source_stanza_extras += ('X-Python-Version: '+ ', '.join(xs_python_version)+'\n') x_python3_version = parse_vals(cfg,module_name,'X-Python3-Version') x_python3_version = [v.strip('"') for v in x_python3_version] if len(x_python3_version)!=0: self.source_stanza_extras += ('X-Python3-Version: '+ ', '.join(x_python3_version)+'\n') dpkg_shlibdeps_params = parse_val( cfg,module_name,'dpkg-shlibdeps-params') if dpkg_shlibdeps_params: need_custom_binary_target = True self.dh_binary_arch_lines = """\tdh binary-arch --before dh_shlibdeps \tdh_shlibdeps -a --dpkg-shlibdeps-params=%s \tdh binary --after dh_shlibdeps"""%dpkg_shlibdeps_params else: self.dh_binary_arch_lines = '\tdh binary-arch' self.dh_binary_indep_lines = '\tdh binary-indep' conflicts = parse_vals(cfg,module_name,'Conflicts') conflicts3 = parse_vals(cfg,module_name,'Conflicts3') provides = parse_vals(cfg,module_name,'Provides') provides3 = parse_vals(cfg,module_name,'Provides3') replaces = parse_vals(cfg,module_name,'Replaces') replaces3 = parse_vals(cfg,module_name,'Replaces3') if guess_conflicts_provides_replaces: # Find list of binaries which we will conflict/provide/replace. cpr_binaries = set() # Get original Debian information for the package named the same. for version_info in apt_cache_info('showsrc',self.package): # Remember each of the binary packages produced by the Debian source for binary in version_info['Binary']: cpr_binaries.add(binary) # TODO: do this for every version available , just the # first, or ??? break # Descend each of the original binaries and see what # packages they conflict/ provide/ replace: for orig_binary in cpr_binaries: for version_info in apt_cache_info('show',orig_binary): provides.extend( version_info['Provides']) provides3.extend( version_info['Provides']) conflicts.extend(version_info['Conflicts']) conflicts3.extend(version_info['Conflicts']) replaces.extend( version_info['Replaces']) replaces3.extend( version_info['Replaces']) if self.package in cpr_binaries: cpr_binaries.remove(self.package) # don't include ourself cpr_binaries = list(cpr_binaries) # convert to list conflicts.extend( cpr_binaries ) conflicts3.extend( cpr_binaries ) provides.extend( cpr_binaries ) provides3.extend( cpr_binaries ) replaces.extend( cpr_binaries ) replaces3.extend( cpr_binaries ) # round-trip through set to get unique entries conflicts = list(set(conflicts)) conflicts3 = list(set(conflicts3)) provides = list(set(provides)) provides3 = list(set(provides3)) replaces = list(set(replaces)) replaces3 = list(set(replaces3)) self.package_stanza_extras = '' self.package_stanza_extras3 = '' if len(conflicts): self.package_stanza_extras += ('Conflicts: '+ ', '.join( conflicts )+'\n') if len(conflicts3): self.package_stanza_extras3 += ('Conflicts: '+ ', '.join( conflicts3 )+'\n') if len(provides): self.package_stanza_extras += ('Provides: '+ ', '.join( provides )+'\n') if len(provides3): self.package_stanza_extras3 += ('Provides: '+ ', '.join( provides3 )+'\n') if len(replaces): self.package_stanza_extras += ('Replaces: ' + ', '.join( replaces )+'\n') if len(replaces3): self.package_stanza_extras3 += ('Replaces: ' + ', '.join( replaces3 )+'\n') if len(recommends): self.package_stanza_extras += ('Recommends: '+recommends+'\n') if len(recommends3): self.package_stanza_extras3 += ('Recommends: '+recommends3+'\n') if len(suggests): self.package_stanza_extras += ('Suggests: '+suggests+'\n') if len(suggests3): self.package_stanza_extras3 += ('Suggests: '+suggests3+'\n') self.dirlist = "" if not (with_python2 or with_python3): raise RuntimeError('nothing to do - neither Python 2 or 3.') sequencer_with = [] if with_python2: sequencer_with.append('python2') if with_python3: sequencer_with.append('python3') num_binary_packages = len(sequencer_with) no_script_lines=[] if no_python2_scripts: # install to a location where debian tools do not find them self.no_python2_scripts_cli_args = '--install-scripts=/trash' no_script_lines.append( 'rm -rf debian/%s/trash'%(self.package,)) else: self.no_python2_scripts_cli_args = '' if no_python3_scripts: # install to a location where debian tools do not find them self.no_python3_scripts_cli_args = '--install-scripts=/trash' no_script_lines.append( 'rm -rf debian/%s/trash'%(self.package3,)) else: self.no_python3_scripts_cli_args = '' self.scripts_cleanup = '\n'.join([' '+s for s in no_script_lines]) if sys.prefix != '/usr': if not allow_virtualenv_install_location: # virtualenv will set distutils # --prefix=/path/to/virtualenv, but unless explicitly # requested, we want to install into /usr. self.install_prefix = '--prefix=/usr' else: self.install_prefix = '--prefix=%s' % sys.prefix else: self.install_prefix = '' rules_override_clean_target_pythons = [] rules_override_build_target_pythons = [] rules_override_install_target_pythons = [] if with_python2: rules_override_clean_target_pythons.append( RULES_OVERRIDE_CLEAN_TARGET_PY2%self.__dict__ ) rules_override_build_target_pythons.append( RULES_OVERRIDE_BUILD_TARGET_PY2%self.__dict__ ) rules_override_install_target_pythons.append( RULES_OVERRIDE_INSTALL_TARGET_PY2%self.__dict__ ) if with_python3: rules_override_clean_target_pythons.append( RULES_OVERRIDE_CLEAN_TARGET_PY3%self.__dict__ ) rules_override_build_target_pythons.append( RULES_OVERRIDE_BUILD_TARGET_PY3%self.__dict__ ) rules_override_install_target_pythons.append( RULES_OVERRIDE_INSTALL_TARGET_PY3%self.__dict__ ) self.rules_override_clean_target_pythons = '\n'.join(rules_override_clean_target_pythons) self.rules_override_build_target_pythons = '\n'.join(rules_override_build_target_pythons) self.rules_override_install_target_pythons = '\n'.join(rules_override_install_target_pythons) self.override_dh_auto_clean = RULES_OVERRIDE_CLEAN_TARGET%self.__dict__ self.override_dh_auto_build = RULES_OVERRIDE_BUILD_TARGET%self.__dict__ self.override_dh_auto_install = RULES_OVERRIDE_INSTALL_TARGET%self.__dict__ if force_x_python3_version and with_python3 and x_python3_version and \ x_python3_version[0]: # override dh_python3 target to modify the dependencies # to ensure that the passed minimum X-Python3-Version is usedby version = x_python3_version[0] if not version.endswith('~'): version += '~' self.override_dh_python3 = RULES_OVERRIDE_PYTHON3%{ 'scripts': ( ' sed -i ' + '"s/\([ =]python3:any (\)>= [^)]*\()\)/\\1%s\\2/g" ' + 'debian/%s.substvars') % (version, self.package3) } else: self.override_dh_python3 = '' sequencer_options = ['--with '+','.join(sequencer_with)] sequencer_options.append('--buildsystem=python_distutils') self.sequencer_options = ' '.join(sequencer_options) setup_env_vars = parse_vals(cfg,module_name,'Setup-Env-Vars') self.exports = "" if len(setup_env_vars): self.exports += '\n' self.exports += '#exports specified using stdeb Setup-Env-Vars:\n' self.exports += '\n'.join(['export %s'%v for v in setup_env_vars]) self.exports += '\n' self.udev_rules = parse_val(cfg,module_name,'Udev-Rules') if need_custom_binary_target: if self.architecture == 'all': self.binary_target_lines = ( \ RULES_BINARY_ALL_TARGET%self.__dict__ + \ RULES_BINARY_INDEP_TARGET%self.__dict__ ) else: self.binary_target_lines = ( \ RULES_BINARY_TARGET%self.__dict__ + \ RULES_BINARY_INDEP_TARGET%self.__dict__ + \ RULES_BINARY_ARCH_TARGET%self.__dict__ ) else: self.binary_target_lines = '' if with_python2: self.control_py2_stanza = CONTROL_PY2_STANZA%self.__dict__ else: self.control_py2_stanza = '' if with_python3: self.control_py3_stanza = CONTROL_PY3_STANZA%self.__dict__ else: self.control_py3_stanza = '' self.with_python2 = with_python2 self.with_python3 = with_python3 self.no_python2_scripts = no_python2_scripts self.no_python3_scripts = no_python3_scripts def _make_cfg_defaults(self, module_name=NotGiven, default_distribution=NotGiven, guess_maintainer=NotGiven, ): defaults = {} default_re = re.compile(r'^.* \(Default: (.*)\)$') for longopt,shortopt,description in stdeb_cfg_options: assert longopt.endswith('=') assert longopt.lower() == longopt key = longopt[:-1] matchobj = default_re.search( description ) if matchobj is not None: # has a default value groups = matchobj.groups() assert len(groups)==1 value = groups[0] # A few special cases if value == '': assert key=='source' value = source_debianize_name(module_name) elif value == 'python-': assert key=='package' value = 'python-' + debianize_name(module_name) elif value == 'python3-': assert key=='package3' value = 'python3-' + debianize_name(module_name) elif value == '': assert key=='maintainer' value = guess_maintainer if key=='suite': if default_distribution is not None: value = default_distribution log.warn('Deprecation warning: you are using the ' '--default-distribution option. ' 'Switch to the --suite option.') else: # no default value value = '' defaults[key] = value return defaults def build_dsc(debinfo, dist_dir, repackaged_dirname, orig_sdist=None, patch_posix=0, remove_expanded_source_dir=0, debian_dir_only=False, ): """make debian source package""" # A. Find new dirname and delete any pre-existing contents # dist_dir is usually 'deb_dist' # the location of the copied original source package (it was # re-recreated in dist_dir) if debian_dir_only: fullpath_repackaged_dirname = os.path.abspath(os.curdir) else: fullpath_repackaged_dirname = os.path.join(dist_dir,repackaged_dirname) ############################################### # 1. make temporary original source tarball # Note that, for the final tarball, best practices suggest # using "dpkg-source -b". See # http://www.debian.org/doc/developers-reference/ch-best-pkging-practices.en.html # Create the name of the tarball that qualifies as the upstream # source. If the original was specified, we'll link to # it. Otherwise, we generate our own .tar.gz file from the output # of "python setup.py sdist" (done above) so that we avoid # packaging .svn directories, for example. if not debian_dir_only: repackaged_orig_tarball = ('%(source)s_%(upstream_version)s.orig.tar.gz'% debinfo.__dict__) repackaged_orig_tarball_path = os.path.join(dist_dir, repackaged_orig_tarball) if orig_sdist is not None: if os.path.exists(repackaged_orig_tarball_path): os.unlink(repackaged_orig_tarball_path) link_func(orig_sdist,repackaged_orig_tarball_path) else: make_tarball(repackaged_orig_tarball, repackaged_dirname, cwd=dist_dir) # apply patch if debinfo.patch_file != '': apply_patch(debinfo.patch_file, posix=patch_posix, level=debinfo.patch_level, cwd=fullpath_repackaged_dirname) for fname in ['Makefile','makefile']: if os.path.exists(os.path.join(fullpath_repackaged_dirname,fname)): sys.stderr.write('*'*1000 + '\n') sys.stderr.write('WARNING: a Makefile exists in this package. ' 'stdeb will tell debhelper 7 to use setup.py ' 'to build and install the package, and the ' 'Makefile will be ignored.\n') sys.stderr.write('*'*1000 + '\n') ############################################### # 2. create debian/ directory and contents debian_dir = os.path.join(fullpath_repackaged_dirname,'debian') if not os.path.exists(debian_dir): os.mkdir(debian_dir) # A. debian/changelog changelog = CHANGELOG_FILE%debinfo.__dict__ with codecs.open( os.path.join(debian_dir,'changelog'), mode='w', encoding='utf-8') as fd: fd.write(changelog) # B. debian/control if debinfo.uploaders: debinfo.uploaders = 'Uploaders: %s\n' % ', '.join(debinfo.uploaders) else: debinfo.uploaders = '' control = CONTROL_FILE%debinfo.__dict__ with codecs.open( os.path.join(debian_dir,'control'), mode='w', encoding='utf-8') as fd: fd.write(control) # C. debian/rules debinfo.percent_symbol = '%' rules = RULES_MAIN%debinfo.__dict__ rules = rules.replace(' ','\t') rules_fname = os.path.join(debian_dir,'rules') with codecs.open( rules_fname, mode='w', encoding='utf-8') as fd: fd.write(rules) os.chmod(rules_fname,0o755) # D. debian/compat fd = open( os.path.join(debian_dir,'compat'), mode='w') fd.write('7\n') fd.close() # E. debian/package.mime if debinfo.mime_file != '': if not os.path.exists(debinfo.mime_file): raise ValueError( 'a MIME file was specified, but does not exist: %s'%( debinfo.mime_file,)) link_func( debinfo.mime_file, os.path.join(debian_dir,debinfo.package+'.mime')) if debinfo.shared_mime_file != '': if not os.path.exists(debinfo.shared_mime_file): raise ValueError( 'a shared MIME file was specified, but does not exist: %s'%( debinfo.shared_mime_file,)) link_func( debinfo.shared_mime_file, os.path.join(debian_dir, debinfo.package+'.sharedmimeinfo')) # F. debian/copyright if debinfo.copyright_file != '': link_func( debinfo.copyright_file, os.path.join(debian_dir,'copyright')) # H. debian/.install if len(debinfo.install_file_lines): fd = open( os.path.join(debian_dir,'%s.install'%debinfo.package), mode='w') fd.write('\n'.join(debinfo.install_file_lines)+'\n') fd.close() # I. debian/.udev if debinfo.udev_rules != '': fname = debinfo.udev_rules if not os.path.exists(fname): raise ValueError('udev rules file specified, but does not exist') link_func(fname, os.path.join(debian_dir,'%s.udev'%debinfo.package)) # J. debian/source/format os.mkdir(os.path.join(debian_dir,'source')) fd = open( os.path.join(debian_dir,'source','format'), mode='w') fd.write('3.0 (quilt)\n') fd.close() fd = open( os.path.join(debian_dir,'source','options'), mode='w') fd.write('extend-diff-ignore="\.egg-info$"') fd.close() if debian_dir_only: return ############################################### # 3. unpack original source tarball debianized_package_dirname = fullpath_repackaged_dirname+'.debianized' if os.path.exists(debianized_package_dirname): raise RuntimeError('debianized_package_dirname exists: %s' % debianized_package_dirname) # A. move debianized tree away os.rename(fullpath_repackaged_dirname, debianized_package_dirname ) if orig_sdist is not None: # B. expand repackaged original tarball tmp_dir = os.path.join(dist_dir,'tmp-expand') os.mkdir(tmp_dir) try: expand_tarball(orig_sdist,cwd=tmp_dir) orig_tarball_top_contents = os.listdir(tmp_dir) # make sure original tarball has exactly one directory assert len(orig_tarball_top_contents)==1 orig_dirname = orig_tarball_top_contents[0] fullpath_orig_dirname = os.path.join(tmp_dir,orig_dirname) # C. remove original repackaged tree shutil.rmtree(fullpath_orig_dirname) finally: shutil.rmtree(tmp_dir) if 1: # check versions of debhelper and python-all debhelper_version_str = get_version_str('debhelper') if len(debhelper_version_str)==0: log.warn('This version of stdeb requires debhelper >= %s, but you ' 'do not have debhelper installed. ' 'Could not check compatibility.'%DH_MIN_VERS) else: if not dpkg_compare_versions( debhelper_version_str, 'ge', DH_MIN_VERS ): log.warn('This version of stdeb requires debhelper >= %s. ' 'Use stdeb 0.3.x to generate source packages ' 'compatible with older versions of debhelper.'%( DH_MIN_VERS,)) python_defaults_version_str = get_version_str('python-all') if len(python_defaults_version_str)==0: log.warn('This version of stdeb requires python-all >= %s, ' 'but you do not have this package installed. ' 'Could not check compatibility.'%PYTHON_ALL_MIN_VERS) else: if not dpkg_compare_versions( python_defaults_version_str, 'ge', PYTHON_ALL_MIN_VERS): log.warn('This version of stdeb requires python-all >= %s. ' 'Use stdeb 0.6.0 or older to generate source packages ' 'that use python-support.'%( PYTHON_ALL_MIN_VERS,)) # D. restore debianized tree os.rename(fullpath_repackaged_dirname+'.debianized', fullpath_repackaged_dirname) # Re-generate tarball using best practices see # http://www.debian.org/doc/developers-reference/ch-best-pkging-practices.en.html # call "dpkg-source -b new_dirname orig_dirname" log.info('CALLING dpkg-source -b %s %s (in dir %s)'%( repackaged_dirname, repackaged_orig_tarball, dist_dir)) dpkg_source('-b',repackaged_dirname, cwd=dist_dir) dpkg_genchanges(cwd=fullpath_repackaged_dirname) if 1: shutil.rmtree(fullpath_repackaged_dirname) if not remove_expanded_source_dir: # expand the debian source package dsc_name = debinfo.source + '_' + debinfo.dsc_version + '.dsc' dpkg_source('-x',dsc_name, cwd=dist_dir) CHANGELOG_FILE = """\ %(source)s (%(full_version)s) %(distname)s; urgency=low * source package automatically created by stdeb %(stdeb_version)s -- %(maintainer)s %(date822)s\n""" CONTROL_FILE = """\ Source: %(source)s Maintainer: %(maintainer)s %(uploaders)sSection: %(debian_section)s Priority: optional Build-Depends: %(build_depends)s Standards-Version: 3.9.1 %(source_stanza_extras)s %(control_py2_stanza)s %(control_py3_stanza)s """ CONTROL_PY2_STANZA = """ Package: %(package)s Architecture: %(architecture)s Depends: %(depends)s %(package_stanza_extras)sDescription: %(description)s %(long_description)s """ CONTROL_PY3_STANZA = """ Package: %(package3)s Architecture: %(architecture3)s Depends: %(depends3)s %(package_stanza_extras3)sDescription: %(description)s %(long_description)s """ RULES_MAIN = """\ #!/usr/bin/make -f # This file was automatically generated by stdeb %(stdeb_version)s at # %(date822)s %(exports)s %(percent_symbol)s: dh $@ %(sequencer_options)s %(override_dh_auto_clean)s %(override_dh_auto_build)s %(override_dh_auto_install)s override_dh_python2: dh_python2 --no-guessing-versions %(override_dh_python3)s %(binary_target_lines)s """ RULES_OVERRIDE_CLEAN_TARGET_PY2 = " python setup.py clean -a" RULES_OVERRIDE_CLEAN_TARGET_PY3 = " python3 setup.py clean -a" RULES_OVERRIDE_CLEAN_TARGET = """ override_dh_auto_clean: %(rules_override_clean_target_pythons)s find . -name \*.pyc -exec rm {} \; """ RULES_OVERRIDE_BUILD_TARGET_PY2 = " python setup.py build --force" RULES_OVERRIDE_BUILD_TARGET_PY3 = " python3 setup.py build --force" RULES_OVERRIDE_BUILD_TARGET = """ override_dh_auto_build: %(rules_override_build_target_pythons)s """ RULES_OVERRIDE_INSTALL_TARGET_PY2 = " python setup.py install --force --root=debian/%(package)s --no-compile -O0 --install-layout=deb %(install_prefix)s %(no_python2_scripts_cli_args)s" RULES_OVERRIDE_INSTALL_TARGET_PY3 = " python3 setup.py install --force --root=debian/%(package3)s --no-compile -O0 --install-layout=deb %(install_prefix)s %(no_python3_scripts_cli_args)s" RULES_OVERRIDE_INSTALL_TARGET = """ override_dh_auto_install: %(rules_override_install_target_pythons)s %(scripts_cleanup)s """ RULES_OVERRIDE_PYTHON3 = """ override_dh_python3: dh_python3 %(scripts)s """ RULES_BINARY_TARGET = """ binary: binary-arch binary-indep """ RULES_BINARY_ALL_TARGET = """ binary: binary-indep """ RULES_BINARY_ARCH_TARGET = """ binary-arch: build %(dh_binary_arch_lines)s """ RULES_BINARY_INDEP_TARGET = """ binary-indep: build %(dh_binary_indep_lines)s %(dh_installmime_indep_line)s %(dh_desktop_indep_line)s """ stdeb-0.8.5/stdeb.cfg0000644000076500000240000000022112471220204014657 0ustar strawstaff00000000000000[stdeb] Depends: apt-file, dpkg-dev, python-pkg-resources, python-requests Depends3: apt-file, dpkg-dev, python3-pkg-resources, python3-requests stdeb-0.8.5/test-pypi-install.sh0000755000076500000240000000173312471220204017047 0ustar strawstaff00000000000000#!/bin/bash set -e if [ "$UID" -ne "0" ]; then echo "$0 must be run as root" exit 1 fi # Package with source tarball on PyPI: pypi-install pyflakes --verbose=2 dpkg --purge python-pyflakes # This test fails on Ubuntu 12.04 due to what looks like a bug with # "dh_auto_clean -O--buildsystem=python_distutils" not changing into the # directory with setup.py and thus its "import prober" fails. That's not # an stdeb bug. We could run this test on later versions of Debian/Ubuntu. # # Package with no source tarball on PyPI: (v 0.6.2, 2009-12-30) #pypi-install posix_ipc --release=0.6.2 --verbose=2 --allow-unsafe-download #dpkg --purge python-posixipc echo "skipping known failure tests" exit 0 # A pure python package with source tarball on PyPI. (This fails if # the Debian/Ubuntu original "pyro" package is already # installed. This should use apt-file to find that binary package is # "pyro".) apt-get install pyro # get upstream version pypi-install Pyro --verbose=2 stdeb-0.8.5/test.sh0000755000076500000240000000757512471220204014436 0ustar strawstaff00000000000000#!/bin/bash set -e # setup tests ## remove old build results rm -rf deb_dist # setup paths if [ "${PYEXE}" == "" ]; then PYEXE=`which python`; fi echo "using Python at ${PYEXE}" PY2DSC_LOC=`which py2dsc` PY2DSC_DEB_LOC=`which py2dsc-deb` PYPI_DOWNLOAD_LOC=`which pypi-download` PYPI_INSTALL_LOC=`which pypi-install` PY2DSC="${PYEXE} ${PY2DSC_LOC}" PY2DSC_DEB="${PYEXE} ${PY2DSC_DEB_LOC}" PYPI_DOWNLOAD="${PYEXE} ${PYPI_DOWNLOAD_LOC}" PYPI_INSTALL="${PYEXE} ${PYPI_INSTALL_LOC}" # Run tests ## Test some basic tests. Just make sure these don't fail. ${PY2DSC} --help > /dev/null ${PY2DSC_DEB} --help > /dev/null ${PYPI_DOWNLOAD} --help > /dev/null ${PYPI_INSTALL} --help > /dev/null ## Run test cases on each of the following packages # Set an upper bound on the size of the compressed deb_specific. We are not # applying any patches here so this should be pretty small. MAX_DEB_SPECIFIC_SIZE=5000 for i in `seq 1 3`; do if [ $i -eq "1" ]; then SOURCE_PACKAGE=requests SOURCE_RELEASE=2.2.1 SOURCE_TARBALL_DIR=${SOURCE_PACKAGE}-${SOURCE_RELEASE} SOURCE_TARBALL=${SOURCE_TARBALL_DIR}.tar.gz DEBSOURCE=${SOURCE_TARBALL_DIR} elif [ $i -eq "2" ]; then SOURCE_PACKAGE=Reindent SOURCE_RELEASE=0.1.1 SOURCE_TARBALL_DIR=${SOURCE_PACKAGE}-${SOURCE_RELEASE} SOURCE_TARBALL=${SOURCE_TARBALL_DIR}.tar.gz DEBSOURCE=reindent-${SOURCE_RELEASE} elif [ $i -eq "3" ]; then SOURCE_PACKAGE=psycopg2 SOURCE_RELEASE=2.5 SOURCE_TARBALL_DIR=${SOURCE_PACKAGE}-${SOURCE_RELEASE} SOURCE_TARBALL=${SOURCE_TARBALL_DIR}.tar.gz DEBSOURCE=${SOURCE_TARBALL_DIR} else echo "unknown case" exit 1 fi # get a file to work with # ============================================================== ${PYPI_DOWNLOAD} ${SOURCE_PACKAGE} --release ${SOURCE_RELEASE} # case 1: build from pre-existing source tarball with py2dsc # ============================================================== ${PY2DSC} $SOURCE_TARBALL cd deb_dist/$DEBSOURCE dpkg-buildpackage -rfakeroot -uc -us cd ../.. for DEBFILE in deb_dist/*.deb; do echo "contents of $DEBFILE from $SOURCE_TARBALL in case 1:" dpkg --contents $DEBFILE done DEB_SPECIFIC_SIZE=$(stat -c '%s' deb_dist/*.debian.tar.?z) if ((${DEB_SPECIFIC_SIZE}>${MAX_DEB_SPECIFIC_SIZE})); then echo "ERROR: debian specific file larger than expected" exit 1 else echo "${SOURCE_PACKAGE} case 1: deb_specific size ${DEB_SPECIFIC_SIZE}" fi #cleanup case 1 rm -rf deb_dist # case 2: build from pre-existing source tarball using distutils # ============================================================== tar xzf $SOURCE_TARBALL cd $SOURCE_TARBALL_DIR which python python -c "import sys; print('sys.version',sys.version)" python setup.py --command-packages=stdeb.command sdist_dsc cd deb_dist/$DEBSOURCE dpkg-buildpackage -rfakeroot -uc -us cd ../.. for DEBFILE in deb_dist/*.deb; do echo "contents of $DEBFILE from $SOURCE_TARBALL in case 2:" dpkg --contents $DEBFILE done DEB_SPECIFIC_SIZE=$(stat -c '%s' deb_dist/*.debian.tar.?z) if ((${DEB_SPECIFIC_SIZE}>${MAX_DEB_SPECIFIC_SIZE})); then echo "ERROR: debian specific file larger than expected" exit 1 else echo "${SOURCE_PACKAGE} case 2: deb_specific size ${DEB_SPECIFIC_SIZE}" fi cd .. #cleanup case 2 # ============================================================== rm -rf $SOURCE_TARBALL_DIR # case 3: build from pre-existing source tarball with py2dsc # ============================================================== ${PY2DSC_DEB} $SOURCE_TARBALL for DEBFILE in deb_dist/*.deb; do echo "contents of $DEBFILE from $SOURCE_TARBALL in case 3:" dpkg --contents $DEBFILE done DEB_SPECIFIC_SIZE=$(stat -c '%s' deb_dist/*.debian.tar.?z) if ((${DEB_SPECIFIC_SIZE}>${MAX_DEB_SPECIFIC_SIZE})); then echo "ERROR: debian specific file larger than expected" exit 1 else echo "${SOURCE_PACKAGE} case 3: deb_specific size ${DEB_SPECIFIC_SIZE}" fi #cleanup case 3 rm -rf deb_dist #cleanup original tarball rm -rf $SOURCE_TARBALL done echo "All tests passed." stdeb-0.8.5/test2and3.sh0000755000076500000240000000604412471220204015254 0ustar strawstaff00000000000000#!/bin/bash set -e export DO_PY2=true export DO_PY3=true # setup paths if [ "${PY2EXE}" == "" ]; then PY2EXE=`which python2` || echo if [ "${PY2EXE}" == "" ]; then PY2EXE=`which python` || export DO_PY2=false fi fi if [ "${PY3EXE}" == "" ]; then PY3EXE=`which python3` || export DO_PY3=false fi # check that stdeb is actually installed cd test_data # do test in path without stdeb source if [ "$DO_PY2" = true ]; then ${PY2EXE} -c "import stdeb; print stdeb.__version__,stdeb.__file__" || export DO_PY2=false fi if [ "$DO_PY3" = true ]; then ${PY3EXE} -c "import stdeb; print(stdeb.__version__,stdeb.__file__)" || export DO_PY3=false fi cd .. # -------------- PYTHONS="" if [ "$DO_PY2" = true ]; then PYTHONS="${PYTHONS} ${PY2EXE}" fi if [ "$DO_PY3" = true ]; then PYTHONS="${PYTHONS} ${PY3EXE}" fi ## ---------------------------- # Test unicode in CLI args and .cfg file for MAINTAINER_ARGS in cli none cfgfile; do for PYTHON in ${PYTHONS}; do echo ${PYTHON} MAINTAINER_ARGS ${MAINTAINER_ARGS} if [ "$MAINTAINER_ARGS" = cli ]; then M1="--maintainer" M2="Herr Unicöde " M3="${M1},${M2}" else M3="" fi rm -f test_data/simple_pkg/stdeb.cfg if [ "$MAINTAINER_ARGS" = cfgfile ]; then cat > test_data/simple_pkg/stdeb.cfg < EOF fi cd test_data/simple_pkg IFS=, ${PYTHON} setup.py --command-packages stdeb.command sdist_dsc ${M3} bdist_deb unset IFS cd ../.. done done ## ------------------------- ## Tell Python that we do not have e.g. UTF-8 file encodings and thus ## force everything to be very explicit. export LC_ALL="C" ## Test very basic py2 and py3 packages ------ if [ "$DO_PY2" = true ]; then echo "using Python 2 at ${PY2EXE}" cd test_data/py2_only_pkg # test the "debianize" command rm -rf debian ${PY2EXE} setup.py --command-packages stdeb.command debianize rm -rf debian # test the "sdist_dsc" and "bdist_deb" commands ${PY2EXE} setup.py --command-packages stdeb.command sdist_dsc --with-python2=true --with-python3=false bdist_deb cd ../.. else echo "skipping Python 2 test" fi if [ "$DO_PY3" = true ]; then # Due to http://bugs.python.org/issue9561 (fixed in Py 3.2) we skip this test in 3.0 and 3.1. ${PY3EXE} -c "import sys; ec=0 if sys.version_info[1]>=2 else 1; sys.exit(ec)" && rc=$? || rc=$? if [ "$rc" == 0 ]; then echo "using Python 3 at ${PY3EXE}" cd test_data/py3_only_pkg # test the "debianize" command rm -rf debian ${PY3EXE} setup.py --command-packages stdeb.command debianize rm -rf debian # test the "sdist_dsc" and "bdist_deb" commands ${PY3EXE} setup.py --command-packages stdeb.command sdist_dsc --with-python3=true --with-python2=false bdist_deb cd ../.. else echo "skipping Python >= 3.2 test" fi else echo "skipping Python 3 test" fi stdeb-0.8.5/test_data/0000755000076500000240000000000012471220353015057 5ustar strawstaff00000000000000stdeb-0.8.5/test_data/py2_only_pkg/0000755000076500000240000000000012471220353017473 5ustar strawstaff00000000000000stdeb-0.8.5/test_data/py2_only_pkg/py2_only_pkg/0000755000076500000240000000000012471220353022107 5ustar strawstaff00000000000000stdeb-0.8.5/test_data/py2_only_pkg/py2_only_pkg/__init__.py0000644000076500000240000000000012471220204024201 0ustar strawstaff00000000000000stdeb-0.8.5/test_data/py2_only_pkg/py2_only_pkg/py2_module.py0000644000076500000240000000027612471220204024540 0ustar strawstaff00000000000000def my_py2_function( value ): """this is a function that works only in python 2""" if False: raise Exception, 'this is a SyntaxError in py3 but not 2' return value+value stdeb-0.8.5/test_data/py2_only_pkg/setup.py0000644000076500000240000000123512471220204021201 0ustar strawstaff00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- from distutils.core import setup from distutils.command.build import build import sys class my_build(build): """ensure (at runtime) we are running python 2""" def __init__(self,*args,**kwargs): assert sys.version_info[0]==2 build.__init__(self,*args,**kwargs) setup(name='py2_only_pkg', packages=['py2_only_pkg'], version='0.1', cmdclass={'build':my_build}, author='Mister Unicodé', author_email='mister.unicode@example.tld', description='Python 2 package with Unicodé fields', long_description='This is a Python 2 package with Unicodé data.', ) stdeb-0.8.5/test_data/py3_only_pkg/0000755000076500000240000000000012471220353017474 5ustar strawstaff00000000000000stdeb-0.8.5/test_data/py3_only_pkg/py3_only_pkg/0000755000076500000240000000000012471220353022111 5ustar strawstaff00000000000000stdeb-0.8.5/test_data/py3_only_pkg/py3_only_pkg/py3_module.py0000644000076500000240000000024012471220204024532 0ustar strawstaff00000000000000def my_py3_function( value : int = 2 ) -> int: # SyntaxError in py2 (but not 3) """this is a function that works only in python 3""" return value+value stdeb-0.8.5/test_data/py3_only_pkg/setup.py0000644000076500000240000000123612471220204021203 0ustar strawstaff00000000000000#!/usr/bin/env python3 # -*- coding: utf-8 -*- from distutils.core import setup from distutils.command.build import build import sys class my_build(build): """ensure (at runtime) we are running python 3""" def __init__(self,*args,**kwargs): assert sys.version_info[0]==3 build.__init__(self,*args,**kwargs) setup(name='py3_only_pkg', packages=['py3_only_pkg'], version='0.1', cmdclass={'build':my_build}, author='Mister Unicodé', author_email='mister.unicode@example.tld', description='Python 3 package with Unicodé fields', long_description='This is a Python 3 package with Unicodé data.', ) stdeb-0.8.5/test_data/simple_pkg/0000755000076500000240000000000012471220353017211 5ustar strawstaff00000000000000stdeb-0.8.5/test_data/simple_pkg/setup.py0000644000076500000240000000060112471220204020713 0ustar strawstaff00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- from distutils.core import setup import sys setup(name='simple_pkg', packages=['simple_pkg'], version='0.1', author='Mister Unicodé', author_email='mister.unicode@example.tld', description='Python package with Unicodé fields', long_description='This is a Python package with Unicodé data.', ) stdeb-0.8.5/test_data/simple_pkg/simple_pkg/0000755000076500000240000000000012471220353021343 5ustar strawstaff00000000000000stdeb-0.8.5/test_data/simple_pkg/simple_pkg/__init__.py0000644000076500000240000000000012471220204023435 0ustar strawstaff00000000000000stdeb-0.8.5/Vagrantfile.debian-7-wheezy.rb0000644000076500000240000000330412471220204020567 0ustar strawstaff00000000000000# encoding: utf-8 # -*- mode: ruby -*- # vi: set ft=ruby : Vagrant::Config.run do |config| config.vm.box_url = "https://dl.dropboxusercontent.com/s/3jz559mjz2aw4gs/debian-wheezy-64-vanilla.box" config.vm.box = "debian-wheezy-64-vanilla" # install prerequisites for stdeb and tests config.vm.provision :shell, :inline => "apt-get update" config.vm.provision :shell, :inline => <<-SH export DEBIAN_FRONTEND=noninteractive apt-get install --yes debhelper python-all-dev python-setuptools apt-file python-requests python3-all-dev python3-setuptools libpq-dev wget http://debs.strawlab.org/precise/python3-requests_2.3.0-0ads1_all.deb -O python3-requests_2.3.0-0ads1_all.deb dpkg -i python3-requests_2.3.0-0ads1_all.deb SH # We need to copy files to a new dir to prevent vagrant filesystem issues. config.vm.provision :shell, :inline => "cp -a /vagrant /tmp/vagrant_copy" # Install stdeb config.vm.provision :shell, :inline => "rm -rf /tmp/vagrant_copy/deb_dist" config.vm.provision :shell, :inline => "cd /tmp/vagrant_copy && python setup.py --command-packages=stdeb.command sdist_dsc --with-python2=True --with-python3=True --no-python3-scripts=True install_deb" # Run tests. config.vm.provision :shell, :inline => "cd /tmp/vagrant_copy && ./test.sh" config.vm.provision :shell, :inline => "cd /tmp/vagrant_copy && ./test-pypi-install.sh" # Run tests on Python 3. config.vm.provision :shell, :inline => "cd /tmp/vagrant_copy && PYEXE=/usr/bin/python3 ./test.sh" config.vm.provision :shell, :inline => "cd /tmp/vagrant_copy && PYEXE=/usr/bin/python3 ./test-pypi-install.sh" # Run more tests config.vm.provision :shell, :inline => "cd /tmp/vagrant_copy && ./test2and3.sh" end stdeb-0.8.5/Vagrantfile.debian-8-jessie.rb0000644000076500000240000000327312471220204020544 0ustar strawstaff00000000000000# encoding: utf-8 # -*- mode: ruby -*- # vi: set ft=ruby : Vagrant::Config.run do |config| config.vm.box_url = "https://downloads.sourceforge.net/project/vagrantboxjessie/debian80.box" config.vm.box = "debian80" # install prerequisites for stdeb and tests config.vm.provision :shell, :inline => "apt-get update" config.vm.provision :shell, :inline => <<-SH export DEBIAN_FRONTEND=noninteractive apt-get install --yes build-essential debhelper python-all-dev python-setuptools apt-file python-requests python3-all-dev python3-setuptools libpq-dev wget http://debs.strawlab.org/precise/python3-requests_2.3.0-0ads1_all.deb -O python3-requests_2.3.0-0ads1_all.deb dpkg -i python3-requests_2.3.0-0ads1_all.deb SH # We need to copy files to a new dir to prevent vagrant filesystem issues. config.vm.provision :shell, :inline => "cp -a /vagrant /tmp/vagrant_copy" # Install stdeb config.vm.provision :shell, :inline => "rm -rf /tmp/vagrant_copy/deb_dist" config.vm.provision :shell, :inline => "cd /tmp/vagrant_copy && python setup.py --command-packages=stdeb.command sdist_dsc --with-python2=True --with-python3=True --no-python3-scripts=True install_deb" # Run tests. config.vm.provision :shell, :inline => "cd /tmp/vagrant_copy && ./test.sh" config.vm.provision :shell, :inline => "cd /tmp/vagrant_copy && ./test-pypi-install.sh" # Run tests on Python 3. config.vm.provision :shell, :inline => "cd /tmp/vagrant_copy && PYEXE=/usr/bin/python3 ./test.sh" config.vm.provision :shell, :inline => "cd /tmp/vagrant_copy && PYEXE=/usr/bin/python3 ./test-pypi-install.sh" # Run more tests config.vm.provision :shell, :inline => "cd /tmp/vagrant_copy && ./test2and3.sh" end stdeb-0.8.5/Vagrantfile.ubuntu-12.04-precise.rb0000644000076500000240000000321512471220204021305 0ustar strawstaff00000000000000# encoding: utf-8 # -*- mode: ruby -*- # vi: set ft=ruby : Vagrant::Config.run do |config| config.vm.box = "precise64" config.vm.box_url = "http://files.vagrantup.com/precise64.box" # install prerequisites for stdeb and tests config.vm.provision :shell, :inline => "apt-get update" config.vm.provision :shell, :inline => <<-SH export DEBIAN_FRONTEND=noninteractive apt-get install --yes debhelper python-all-dev python-setuptools apt-file python-requests python3-all-dev python3-setuptools libpq-dev wget http://debs.strawlab.org/precise/python3-requests_2.3.0-0ads1_all.deb -O python3-requests_2.3.0-0ads1_all.deb dpkg -i python3-requests_2.3.0-0ads1_all.deb SH # We need to copy files to a new dir to prevent vagrant filesystem issues. config.vm.provision :shell, :inline => "cp -a /vagrant /tmp/vagrant_copy" # Install stdeb config.vm.provision :shell, :inline => "rm -rf /tmp/vagrant_copy/deb_dist" config.vm.provision :shell, :inline => "cd /tmp/vagrant_copy && python setup.py --command-packages=stdeb.command sdist_dsc --with-python2=True --with-python3=True --no-python3-scripts=True install_deb" # Run tests. config.vm.provision :shell, :inline => "cd /tmp/vagrant_copy && ./test.sh" config.vm.provision :shell, :inline => "cd /tmp/vagrant_copy && ./test-pypi-install.sh" # Run tests on Python 3. config.vm.provision :shell, :inline => "cd /tmp/vagrant_copy && PYEXE=/usr/bin/python3 ./test.sh" config.vm.provision :shell, :inline => "cd /tmp/vagrant_copy && PYEXE=/usr/bin/python3 ./test-pypi-install.sh" # Run more tests config.vm.provision :shell, :inline => "cd /tmp/vagrant_copy && ./test2and3.sh" end stdeb-0.8.5/Vagrantfile.ubuntu-14.04-trusty.rb0000644000076500000240000000335212471220204021231 0ustar strawstaff00000000000000# encoding: utf-8 # -*- mode: ruby -*- # vi: set ft=ruby : Vagrant::Config.run do |config| config.vm.box_url = "http://cloud-images.ubuntu.com/vagrant/trusty/current/trusty-server-cloudimg-amd64-vagrant-disk1.box" config.vm.box = "trusty-server-cloudimg-amd64-vagrant-disk1" # install prerequisites for stdeb and tests config.vm.provision :shell, :inline => "apt-get update" config.vm.provision :shell, :inline => <<-SH export DEBIAN_FRONTEND=noninteractive apt-get install --yes debhelper python-all-dev python-setuptools apt-file python-requests python3-all-dev python3-setuptools libpq-dev wget http://debs.strawlab.org/precise/python3-requests_2.3.0-0ads1_all.deb -O python3-requests_2.3.0-0ads1_all.deb dpkg -i python3-requests_2.3.0-0ads1_all.deb SH # We need to copy files to a new dir to prevent vagrant filesystem issues. config.vm.provision :shell, :inline => "cp -a /vagrant /tmp/vagrant_copy" # Install stdeb config.vm.provision :shell, :inline => "rm -rf /tmp/vagrant_copy/deb_dist" config.vm.provision :shell, :inline => "cd /tmp/vagrant_copy && python setup.py --command-packages=stdeb.command sdist_dsc --with-python2=True --with-python3=True --no-python3-scripts=True install_deb" # Run tests. config.vm.provision :shell, :inline => "cd /tmp/vagrant_copy && ./test.sh" config.vm.provision :shell, :inline => "cd /tmp/vagrant_copy && ./test-pypi-install.sh" # Run tests on Python 3. config.vm.provision :shell, :inline => "cd /tmp/vagrant_copy && PYEXE=/usr/bin/python3 ./test.sh" config.vm.provision :shell, :inline => "cd /tmp/vagrant_copy && PYEXE=/usr/bin/python3 ./test-pypi-install.sh" # Run more tests config.vm.provision :shell, :inline => "cd /tmp/vagrant_copy && ./test2and3.sh" end