././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1603948288.7720127 stdeb-0.10.0/0000775000175000017500000000000000000000000014014 5ustar00dthomasdthomas00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1583192886.3750048 stdeb-0.10.0/.gitignore0000644000175000017500000000027200000000000016003 0ustar00dthomasdthomas00000000000000build 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 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1603905368.7757373 stdeb-0.10.0/.travis.yml0000664000175000017500000000224600000000000016131 0ustar00dthomasdthomas00000000000000# http://travis-ci.org/#!/astraw/stdeb language: python python: - "2.7_with_system_site_packages" - "3.5_with_system_site_packages" before_install: - sudo apt-get update - sudo apt-get install fakeroot 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 - pip install flake8 - flake8 --extend-ignore D scripts/* stdeb/ test_data/ `python -c "import sys;sys.stdout.write('--extend-exclude py3_module.py') if sys.version_info[0] == 2 else sys"` ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1583192886.3750048 stdeb-0.10.0/CHANGELOG.txt0000644000175000017500000002303400000000000016044 0ustar00dthomasdthomas00000000000000Since (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. ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1583192886.3750048 stdeb-0.10.0/LICENSE.txt0000644000175000017500000000204700000000000015640 0ustar00dthomasdthomas00000000000000Copyright (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. ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1583192886.3750048 stdeb-0.10.0/MANIFEST.in0000644000175000017500000000025100000000000015546 0ustar00dthomasdthomas00000000000000include *.txt include *.rst include *.sh include stdeb.cfg include MANIFEST.in include .gitignore include .travis.yml include Vagrantfile* recursive-include test_data * ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1603948288.7720127 stdeb-0.10.0/PKG-INFO0000664000175000017500000013301500000000000015114 0ustar00dthomasdthomas00000000000000Metadata-Version: 1.1 Name: stdeb Version: 0.10.0 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 ---- * 2020-10-28: **Version 0.10.0**. See the `download page `__. * Bugfixes: * add sleep between PyPI API calls to avoid rate limit (#173) * Improvements: * use SOURCE_DATE_EPOCH if set for timestamp in generated changelog to generate reproducbile artifacts (#166) * update debhelper compat version from 7 to 9 (#158) * added flag --with-dh-systemd (#162) * add support for DEBEMAIL envvar (#168) * use setuptools "url" field for "Homepage" field in debian/control (#169) * dh_virtualenv: specify Python version (#165) * added compat flag to modify Debian compatibility level (#163) * Cosmetic: * remove excess newlines from debian/control and rules file (#167) * use flake8 to check style in Travis CI, update code to comply (#171) * 2020-06-11: **Version 0.9.1**. See the `download page `__. * Bugfixes: * handle path with spaces in zip tarball (#150) * fix map() iterator issue in Python 3 (#152) * fix checking for python3-all (instead of python-all) when using only Python 3 (#154) * Improvements: * get date in Python, avoiding requiring ``date`` on macOS (#115) * add configuration file option ``Python2-Depends-Name`` (#156) * add an option ``--with-dh-virtualenv`` (#155) * add an option named ``ignore-source-changes`` (#151) * 2019-12-09: **Version 0.9.0**. See the `download page `__. * Bugfixes: * fix applying patch files under Python 3 * Improvements: * add ``--sign-results`` to sdist_dsc and bdist_deb command * add ``--debian-version`` to CLI program options * add support for ``Breaks`` / ``Breaks3`` in debian/control * add support for ``Suite3`` option * support zip files in pypi-install * Breaking changes: * remove deprecated ``dh_desktop`` call * 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.10.0" # 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 --with-dh-virtualenv Build the package using dh_virtualenv, so all dependencies are embedded into the packages. --with-dh-systemd Add the systemd addon that will add dh_systemd_enable and dh_systemd_start helpers at the correct time during build. --sign-results Use gpg to sign the resulting .dsc and .changes file --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) --compat debian compatibility level (default=9) --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 --ignore-source-changes ignore all changes on source when building source package (add -i.* option to dpkg-source) --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 existence 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-) Package3 debian/control Package: for python3 (Default: python3-) Suite suite (e.g. stable, lucid) in changelog (Default: unstable) Suite3 suite (e.g. stable, lucid) for python3 (Default: uses value of Suite option) 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 Breaks debian/control Breaks: Breaks3 debian/control Breaks: 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 Python2-Depends-Name override Python 2 Debian package name in ${python:Depends} ====================================== ========================================= The option names in stdeb.cfg files are not case sensitive. Reproducible builds ------------------- By default stdeb uses the current time for the the timestamp in the generated changelog file. This results in a non-reproducible build since every invocation generates a different changelog / ``.deb``. The environment variable ``SOURCE_DATE_EPOCH`` can be set to a fixed timestamp (e.g. when the version was tagged or of the last commit was made) which will be used in the changelog instead. This will ensure that the produced ``.deb`` is reproducible on repeated invocations. For more information about reproducible builds and this specific environment variable please see https://reproducible-builds.org/docs/source-date-epoch/ 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/ .. image:: https://badges.gitter.im/Join%20Chat.svg :alt: Join the chat at https://gitter.im/astraw/stdeb :target: https://gitter.im/astraw/stdeb?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge 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 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1603947976.0086424 stdeb-0.10.0/README.rst0000664000175000017500000011367200000000000015515 0ustar00dthomasdthomas00000000000000.. 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 ---- * 2020-10-28: **Version 0.10.0**. See the `download page `__. * Bugfixes: * add sleep between PyPI API calls to avoid rate limit (#173) * Improvements: * use SOURCE_DATE_EPOCH if set for timestamp in generated changelog to generate reproducbile artifacts (#166) * update debhelper compat version from 7 to 9 (#158) * added flag --with-dh-systemd (#162) * add support for DEBEMAIL envvar (#168) * use setuptools "url" field for "Homepage" field in debian/control (#169) * dh_virtualenv: specify Python version (#165) * added compat flag to modify Debian compatibility level (#163) * Cosmetic: * remove excess newlines from debian/control and rules file (#167) * use flake8 to check style in Travis CI, update code to comply (#171) * 2020-06-11: **Version 0.9.1**. See the `download page `__. * Bugfixes: * handle path with spaces in zip tarball (#150) * fix map() iterator issue in Python 3 (#152) * fix checking for python3-all (instead of python-all) when using only Python 3 (#154) * Improvements: * get date in Python, avoiding requiring ``date`` on macOS (#115) * add configuration file option ``Python2-Depends-Name`` (#156) * add an option ``--with-dh-virtualenv`` (#155) * add an option named ``ignore-source-changes`` (#151) * 2019-12-09: **Version 0.9.0**. See the `download page `__. * Bugfixes: * fix applying patch files under Python 3 * Improvements: * add ``--sign-results`` to sdist_dsc and bdist_deb command * add ``--debian-version`` to CLI program options * add support for ``Breaks`` / ``Breaks3`` in debian/control * add support for ``Suite3`` option * support zip files in pypi-install * Breaking changes: * remove deprecated ``dh_desktop`` call * 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.10.0" # 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 --with-dh-virtualenv Build the package using dh_virtualenv, so all dependencies are embedded into the packages. --with-dh-systemd Add the systemd addon that will add dh_systemd_enable and dh_systemd_start helpers at the correct time during build. --sign-results Use gpg to sign the resulting .dsc and .changes file --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) --compat debian compatibility level (default=9) --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 --ignore-source-changes ignore all changes on source when building source package (add -i.* option to dpkg-source) --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 existence 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-) Package3 debian/control Package: for python3 (Default: python3-) Suite suite (e.g. stable, lucid) in changelog (Default: unstable) Suite3 suite (e.g. stable, lucid) for python3 (Default: uses value of Suite option) 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 Breaks debian/control Breaks: Breaks3 debian/control Breaks: 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 Python2-Depends-Name override Python 2 Debian package name in ${python:Depends} ====================================== ========================================= The option names in stdeb.cfg files are not case sensitive. Reproducible builds ------------------- By default stdeb uses the current time for the the timestamp in the generated changelog file. This results in a non-reproducible build since every invocation generates a different changelog / ``.deb``. The environment variable ``SOURCE_DATE_EPOCH`` can be set to a fixed timestamp (e.g. when the version was tagged or of the last commit was made) which will be used in the changelog instead. This will ensure that the produced ``.deb`` is reproducible on repeated invocations. For more information about reproducible builds and this specific environment variable please see https://reproducible-builds.org/docs/source-date-epoch/ 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/ .. image:: https://badges.gitter.im/Join%20Chat.svg :alt: Join the chat at https://gitter.im/astraw/stdeb :target: https://gitter.im/astraw/stdeb?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1603947976.0086424 stdeb-0.10.0/RELEASE_NOTES.txt0000664000175000017500000000764000000000000016614 0ustar00dthomasdthomas00000000000000See the News section in the README for more details. Release 0.10.0 ============== The default Debian compat version has been changed from 7 to 9 as well as new options and features. Release 0.9.1 ============= A few improvements for Python 3 as well as new options. Release 0.9.0 ============= The following backwards incompatible changes were made: * The deprecated call dh_desktop has been removed. Release 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. ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1583192886.3750048 stdeb-0.10.0/Vagrantfile.debian-7-wheezy.rb0000644000175000017500000000330400000000000021477 0ustar00dthomasdthomas00000000000000# 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 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1583192886.3750048 stdeb-0.10.0/Vagrantfile.debian-8-jessie.rb0000644000175000017500000000327300000000000021454 0ustar00dthomasdthomas00000000000000# 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 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1583192886.3750048 stdeb-0.10.0/Vagrantfile.ubuntu-12.04-precise.rb0000644000175000017500000000321500000000000022215 0ustar00dthomasdthomas00000000000000# 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 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1583192886.3750048 stdeb-0.10.0/Vagrantfile.ubuntu-14.04-trusty.rb0000644000175000017500000000335200000000000022141 0ustar00dthomasdthomas00000000000000# 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 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1603948288.7720127 stdeb-0.10.0/scripts/0000775000175000017500000000000000000000000015503 5ustar00dthomasdthomas00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1603905368.7757373 stdeb-0.10.0/scripts/py2dsc0000775000175000017500000000052000000000000016632 0ustar00dthomasdthomas00000000000000#!/usr/bin/env python import stdeb.cli_runner import sys USAGE = """\ usage: py2dsc [options] distfile or: py2dsc --help where distfile is a .zip or .tar.gz file built with the sdist command of distutils. """ def main(): sys.exit(stdeb.cli_runner.runit(cmd='sdist_dsc', usage=USAGE)) if __name__ == '__main__': main() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1603905368.7757373 stdeb-0.10.0/scripts/py2dsc-deb0000775000175000017500000000053000000000000017363 0ustar00dthomasdthomas00000000000000#!/usr/bin/env python import stdeb.cli_runner import sys 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. """ def main(): sys.exit(stdeb.cli_runner.runit(cmd='bdist_deb', usage=USAGE)) if __name__ == '__main__': main() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1603905368.7757373 stdeb-0.10.0/scripts/pypi-download0000775000175000017500000000212500000000000020217 0ustar00dthomasdthomas00000000000000#!/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() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1603905368.7757373 stdeb-0.10.0/scripts/pypi-install0000775000175000017500000000435000000000000020060 0ustar00dthomasdthomas00000000000000#!/usr/bin/env python import os import shutil import sys 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() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1603947976.0086424 stdeb-0.10.0/setup.py0000664000175000017500000000206000000000000015524 0ustar00dthomasdthomas00000000000000from 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.10.0', 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', ], ) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1603948288.7720127 stdeb-0.10.0/stdeb/0000775000175000017500000000000000000000000015115 5ustar00dthomasdthomas00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1603947976.0086424 stdeb-0.10.0/stdeb/__init__.py0000664000175000017500000000045200000000000017227 0ustar00dthomasdthomas00000000000000import logging __version__ = '0.10.0' # 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) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1603905368.7757373 stdeb-0.10.0/stdeb/cli_runner.py0000664000175000017500000001265700000000000017642 0ustar00dthomasdthomas00000000000000from __future__ import print_function import os import shutil import subprocess import sys try: # python 2.x from ConfigParser import SafeConfigParser # noqa: F401 except ImportError: # python 3.x from configparser import SafeConfigParser # noqa: F401 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 # noqa: F401 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 = list(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 Exception: 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 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1603948288.7720127 stdeb-0.10.0/stdeb/command/0000775000175000017500000000000000000000000016533 5ustar00dthomasdthomas00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1603905368.7757373 stdeb-0.10.0/stdeb/command/__init__.py0000664000175000017500000000010100000000000020634 0ustar00dthomasdthomas00000000000000__all__ = ['sdist_dsc', 'bdist_deb', 'install_deb', 'debianize'] ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1603905368.7797375 stdeb-0.10.0/stdeb/command/bdist_deb.py0000664000175000017500000000407600000000000021033 0ustar00dthomasdthomas00000000000000import 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 = [ ('sign-results', None, 'Use gpg to sign the resulting .dsc and .changes file'), ('ignore-source-changes', None, 'Ignore all changes on source when building source package ' '(add -i.* option to dpkg-source'), ] boolean_options = [ 'sign-results', 'ignore-source-changes', ] def initialize_options(self): self.sign_results = False self.ignore_source_changes = False def finalize_options(self): self.sign_results = bool(self.sign_results) self.ignore_source_changes = bool(self.ignore_source_changes) 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', '-b'] if not self.sign_results: syscmd.append('-uc') if self.ignore_source_changes: syscmd.append('-i.*') util.process_command(syscmd, cwd=target_dirs[0]) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1603905368.7797375 stdeb-0.10.0/stdeb/command/common.py0000664000175000017500000002230400000000000020376 0ustar00dthomasdthomas00000000000000import os import sys from stdeb import log from distutils.core import Command from distutils.errors import DistutilsModuleError from stdeb.util import DebianInfo, DH_DEFAULT_VERS, 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 self.with_dh_virtualenv = False self.with_dh_systemd = False self.sign_results = False self.ignore_source_changes = False self.compat = DH_DEFAULT_VERS # 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 codecs import locale fs_enc = codecs.lookup(locale.getpreferredencoding()).name if hasattr(os, 'fsencode'): # this exists only in Python 3 m = os.fsencode(self.maintainer) # convert to orig 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 os.environ.get('DEBEMAIL'): guess_maintainer = "%s <%s>" % ( os.environ.get('DEBFULLNAME', os.environ['DEBEMAIL']), os.environ['DEBEMAIL']) elif ( 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: use_setuptools = False 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] 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) 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, homepage=self.distribution.get_url(), patch_file=self.patch_file, patch_level=self.patch_level, debian_version=self.debian_version, 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), compat=self.compat, with_dh_virtualenv=self.with_dh_virtualenv, with_dh_systemd=self.with_dh_systemd, ) return debinfo ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1603905368.7797375 stdeb-0.10.0/stdeb/command/debianize.py0000664000175000017500000000150400000000000021037 0ustar00dthomasdthomas00000000000000from distutils.core import Command # noqa: F401 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, ) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1603905368.7797375 stdeb-0.10.0/stdeb/command/install_deb.py0000664000175000017500000000200300000000000021360 0ustar00dthomasdthomas00000000000000import glob import os 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_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) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1603905368.7797375 stdeb-0.10.0/stdeb/command/sdist_dsc.py0000664000175000017500000001366000000000000021072 0ustar00dthomasdthomas00000000000000import os import shutil import tempfile from stdeb import log from stdeb.util import expand_sdist_file 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] 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, sign_dsc=self.sign_results, ignore_source_changes=self.ignore_source_changes, ) for rmdir in cleanup_dirs: shutil.rmtree(rmdir) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1603913789.6868215 stdeb-0.10.0/stdeb/downloader.py0000664000175000017500000001311400000000000017625 0ustar00dthomasdthomas00000000000000from __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 import time myprint = print USER_AGENT = 'pypi-install/%s ( https://github.com/astraw/stdeb )' % \ stdeb.__version__ def find_tar_gz(package_name, pypi_url='https://pypi.org', 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 = _call(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 = _call(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 = _call(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', '.zip')): 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 = _call(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 = _call(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 _call(callable_, *args, **kwargs): try: return callable_(*args, **kwargs) except xmlrpclib.Fault as e: if not e.faultString.startswith('HTTPTooManyRequests'): raise time.sleep(1) # try again after rate limit return callable_(*args, **kwargs) 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 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1603905368.7797375 stdeb-0.10.0/stdeb/transport.py0000664000175000017500000000600100000000000017520 0ustar00dthomasdthomas00000000000000# -*- 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( # noqa: F821 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) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1603905368.7797375 stdeb-0.10.0/stdeb/util.py0000664000175000017500000017711200000000000016455 0ustar00dthomasdthomas00000000000000# # This module contains most of the code of stdeb. # import calendar import os import re import select import shutil import sys import time import codecs try: # Python 2.x import ConfigParser except ImportError: # Python 3.x import configparser as ConfigParser import subprocess import tempfile import stdeb # noqa: F401 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 = '9' # Fundamental to stdeb >= 0.10 DH_DEFAULT_VERS = 9 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)'), ('debian-version=', None, 'debian version (Default: 1)'), ('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'), ('compat=', 'c', 'Debian compatibility level (Default={})'.format(DH_DEFAULT_VERS)), ('with-dh-virtualenv', None, 'Use dh_virtualenv to build the package instead of python_distutils. ' 'This is useful to embed an application with all its dependencies ' 'and dont touch to the system libraries.'), ('with-dh-systemd', None, 'Adds the systemd addon that will dh_systemd_enable and' 'dh_systemd_start helpers at the correct time during build.'), ('sign-results', None, 'Use gpg to sign the resulting .dsc and .changes file'), ('ignore-source-changes', None, 'Ignore all changes on source when building source package (add -i.* ' 'option to dpkg-source)'), ] # 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)'), ('suite3=', None, 'suite3 Suites used when building with python3 only (Default: ' ')'), ('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:'), ('breaks=', None, 'debian/control Breaks:'), ('breaks3=', None, 'debian/control Breaks:'), ('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'), ('python2-depends-name=', None, 'Python 2 Debian package name used in ${python:Depends}'), ] 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', 'with-dh-virtualenv', 'with-dh-systemd', 'sign-results', 'ignore-source-changes', ] 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 get_date_822(): """return output of 822-date command""" source_date_epoch = os.environ.get('SOURCE_DATE_EPOCH', None) if source_date_epoch: t = time.gmtime(int(source_date_epoch)) else: t = time.localtime() return time.strftime( calendar.day_abbr[t.tm_wday] + ", %d " + calendar.month_abbr[t.tm_mon] + " %Y %H:%M:%S %z", t) 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 = (r"(/(%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 line in inlines: if line: emo = E.search(line) assert emo, line dmo = D.search(line) assert dmo, line 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(None, 3)[-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_buildpackage(*args, **kwargs): cwd = kwargs.pop('cwd', None) if len(kwargs) != 0: raise ValueError('only kwarg can be "cwd"') "call dpkg-buildpackage [arg1] [...] [argN]" args = ['/usr/bin/dpkg-buildpackage']+list(args) process_command(args, cwd=cwd) 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 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, universal_newlines=True ) 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, homepage=NotGiven, patch_file=None, patch_level=None, setup_requires=None, debian_version=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, compat=DH_DEFAULT_VERS, with_dh_virtualenv=False, with_dh_systemd=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") if homepage is NotGiven: raise ValueError("homepage 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.compat = compat 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.distname3 = parse_val(cfg, module_name, 'Suite3') 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 # 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(r'\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 = '' 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 = '' if homepage != 'UNKNOWN': self.source_stanza_extras += 'Homepage: %s\n' % homepage 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 python2_depends_name = parse_val( cfg, module_name, 'Python2-Depends-Name') 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') breaks = parse_vals(cfg, module_name, 'Breaks') breaks3 = parse_vals(cfg, module_name, 'Breaks3') 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(breaks): self.package_stanza_extras += ( 'Breaks: ' + ', '.join(breaks)+'\n') if len(breaks3): self.package_stanza_extras3 += ( 'Breaks: ' + ', '.join(breaks3)+'\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') 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__ scripts = '' if with_python2 and python2_depends_name: scripts = ( ' sed -i ' + r'"s/\([ =]\)python[0-9]\?\(\(:any\)\? (\)/\\1%s\\2/g" ' + 'debian/%s.substvars') % (python2_depends_name, self.package) self.override_dh_python2 = RULES_OVERRIDE_PYTHON2 % { 'scripts': scripts } 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 ' + r'"s/\([ =]python3:any (\)>= [^)]*\()\)/\\1%s\\2/g" ' + 'debian/%s.substvars') % (version, self.package3) } else: self.override_dh_python3 = '' sequencer_options = ['--with '+','.join(sequencer_with)] if with_dh_virtualenv: if with_python2: self.override_dh_virtualenv_py = \ RULES_OVERRIDE_DH_VIRTUALENV_PY2 % self.__dict__ if with_python3: self.override_dh_virtualenv_py = \ RULES_OVERRIDE_DH_VIRTUALENV_PY3 % self.__dict__ sequencer_options.append('--with python-virtualenv') else: sequencer_options.append('--buildsystem=python_distutils') self.override_dh_virtualenv_py = '' if with_dh_systemd: sequencer_options.append('--with systemd') 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 = '' self.changelog_distname = CHANGELOG_PY2_DISTNAME % self.__dict__ 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__ if self.distname3 and self.distname3 != self.distname: if with_python2: raise ValueError( "Suites are shared between versions. To use a " "different value for Suite3 run --with-python3 true " "--with-python2 false only.") self.changelog_distname = \ CHANGELOG_PY3_DISTNAME % 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 elif value == '': assert key == 'suite3' # Set to empty string so value of suite is used. value = '' 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, sign_dsc=False, ignore_source_changes=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__ control = re.sub('\n{3,}', '\n\n', control) 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 = re.sub('\n{3,}', '\n\n', rules) 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('{}\n'.format(str(debinfo.compat))) 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(r'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.9.x to generate source packages ' 'compatible with older versions of debhelper.' % ( DH_MIN_VERS,)) if debinfo.with_python2: 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,)) if debinfo.with_python3: python3_defaults_version_str = get_version_str('python3-all') if len(python3_defaults_version_str) == 0: log.warn('This version of stdeb requires python3-all, ' 'but you do not have this package installed.') # 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 args = ['-S', '-sa'] if not sign_dsc: args += ['-uc', '-us'] if ignore_source_changes: args.append('-i.*') dpkg_buildpackage(*args, 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_PY2_DISTNAME = '%(distname)s' CHANGELOG_PY3_DISTNAME = '%(distname3)s' CHANGELOG_FILE = """\ %(source)s (%(full_version)s) %(changelog_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)s %(override_dh_python3)s %(override_dh_virtualenv_py)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 = r""" 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" # noqa: E501 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" # noqa: E501 RULES_OVERRIDE_INSTALL_TARGET = """ override_dh_auto_install: %(rules_override_install_target_pythons)s %(scripts_cleanup)s """ RULES_OVERRIDE_PYTHON2 = """ override_dh_python2: dh_python2 --no-guessing-versions %(scripts)s """ RULES_OVERRIDE_PYTHON3 = """ override_dh_python3: dh_python3 %(scripts)s """ RULES_OVERRIDE_DH_VIRTUALENV_PY2 = """ override_dh_virtualenv: dh_virtualenv --python python2 """ RULES_OVERRIDE_DH_VIRTUALENV_PY3 = """ override_dh_virtualenv: dh_virtualenv --python python3 """ 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 """ ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1583192886.3750048 stdeb-0.10.0/stdeb.cfg0000644000175000017500000000022100000000000015567 0ustar00dthomasdthomas00000000000000[stdeb] Depends: apt-file, dpkg-dev, python-pkg-resources, python-requests Depends3: apt-file, dpkg-dev, python3-pkg-resources, python3-requests ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1583192886.3790047 stdeb-0.10.0/test-pypi-install.sh0000755000175000017500000000173300000000000017757 0ustar00dthomasdthomas00000000000000#!/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 ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1602883704.548625 stdeb-0.10.0/test.sh0000775000175000017500000000766500000000000015350 0ustar00dthomasdthomas00000000000000#!/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.6.0 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.7 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 export DEB_BUILD_OPTIONS=nocheck # psycopg2 tests fail # 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." ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1583192886.3790047 stdeb-0.10.0/test2and3.sh0000755000175000017500000000604400000000000016164 0ustar00dthomasdthomas00000000000000#!/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 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1603948288.7720127 stdeb-0.10.0/test_data/0000775000175000017500000000000000000000000015764 5ustar00dthomasdthomas00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1603948288.7720127 stdeb-0.10.0/test_data/py2_only_pkg/0000775000175000017500000000000000000000000020400 5ustar00dthomasdthomas00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1603948288.7720127 stdeb-0.10.0/test_data/py2_only_pkg/py2_only_pkg/0000775000175000017500000000000000000000000023014 5ustar00dthomasdthomas00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1583192886.3790047 stdeb-0.10.0/test_data/py2_only_pkg/py2_only_pkg/__init__.py0000644000175000017500000000000000000000000025111 0ustar00dthomasdthomas00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1603905368.7797375 stdeb-0.10.0/test_data/py2_only_pkg/py2_only_pkg/py2_module.py0000664000175000017500000000030400000000000025442 0ustar00dthomasdthomas00000000000000def 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' # noqa return value+value ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1603905368.7797375 stdeb-0.10.0/test_data/py2_only_pkg/setup.py0000664000175000017500000000122700000000000022114 0ustar00dthomasdthomas00000000000000#!/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.', ) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1603948288.7720127 stdeb-0.10.0/test_data/py3_only_pkg/0000775000175000017500000000000000000000000020401 5ustar00dthomasdthomas00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1603948288.7720127 stdeb-0.10.0/test_data/py3_only_pkg/py3_only_pkg/0000775000175000017500000000000000000000000023016 5ustar00dthomasdthomas00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1603905368.7797375 stdeb-0.10.0/test_data/py3_only_pkg/py3_only_pkg/py3_module.py0000664000175000017500000000023600000000000025451 0ustar00dthomasdthomas00000000000000def 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 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1603905368.7797375 stdeb-0.10.0/test_data/py3_only_pkg/setup.py0000664000175000017500000000123000000000000022107 0ustar00dthomasdthomas00000000000000#!/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.', ) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1603948288.7720127 stdeb-0.10.0/test_data/simple_pkg/0000775000175000017500000000000000000000000020116 5ustar00dthomasdthomas00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1603905368.7797375 stdeb-0.10.0/test_data/simple_pkg/setup.py0000664000175000017500000000056600000000000021637 0ustar00dthomasdthomas00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- from distutils.core import setup 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.', ) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1603948288.7720127 stdeb-0.10.0/test_data/simple_pkg/simple_pkg/0000775000175000017500000000000000000000000022250 5ustar00dthomasdthomas00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1583192886.3790047 stdeb-0.10.0/test_data/simple_pkg/simple_pkg/__init__.py0000644000175000017500000000000000000000000024345 0ustar00dthomasdthomas00000000000000