summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoradmin <yuhuan.yang@samsung.com>2016-05-17 23:30:59 +0800
committerSoonKyu Park <sk7.park@samsung.com>2016-12-27 17:33:59 +0900
commitfecf6e401aff9c6a27cdad41e86818497ec5f471 (patch)
tree5c17cebd1f598836886b3d52e7cc85321e33d628
parent95e4a1a9f12135f89ad4801890eedcedfb3efac8 (diff)
downloadpython-support-submit/trunk/20191017.233826.tar.gz
python-support-submit/trunk/20191017.233826.tar.bz2
python-support-submit/trunk/20191017.233826.zip
-rw-r--r--COPYING510
-rw-r--r--README225
-rw-r--r--debhelper/dh_pysupport384
-rw-r--r--debhelper/postinst-python-support3
-rw-r--r--debhelper/prerm-python-support3
-rw-r--r--debian/changelog776
-rw-r--r--debian/compat1
-rw-r--r--debian/control24
-rw-r--r--debian/copyright26
-rw-r--r--debian/dirs2
-rw-r--r--debian/install7
-rw-r--r--debian/manpages3
-rw-r--r--debian/postinst20
-rw-r--r--debian/postrm12
-rw-r--r--debian/prerm9
-rw-r--r--debian/python-support.lintian-overrides1
-rwxr-xr-xdebian/rules28
-rw-r--r--debian/source/format1
-rw-r--r--debian/triggers1
-rwxr-xr-xmovemodules237
-rwxr-xr-xparseversions103
-rw-r--r--pysupport.py55
-rw-r--r--python-support.private1
-rwxr-xr-xruntime/python-support.rtinstall3
-rwxr-xr-xruntime/python-support.rtremove6
-rwxr-xr-xruntime/python-support.rtupdate6
-rw-r--r--tests/testparseversions.leading-newline.control6
-rw-r--r--tests/testparseversions.missing.control3
-rw-r--r--tests/testparseversions.nonexported.control4
-rwxr-xr-xtests/testparseversions.py40
-rw-r--r--tests/testparseversions.pycbin0 -> 2148 bytes
-rw-r--r--tests/testparseversions.regular.control4
-rw-r--r--tests/testparseversions.second-paragraph.control4
-rw-r--r--tests/testparseversions.spaces.control4
-rwxr-xr-xupdate-python-modules502
-rw-r--r--update-python-modules.884
36 files changed, 3098 insertions, 0 deletions
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..2d2d780
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,510 @@
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations
+below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it
+becomes a de-facto standard. To achieve this, non-free programs must
+be allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control
+compilation and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at least
+ three years, to give the same user the materials specified in
+ Subsection 6a, above, for a charge no more than the cost of
+ performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply, and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License
+may add an explicit geographical distribution limitation excluding those
+countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms
+of the ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library.
+It is safest to attach them to the start of each source file to most
+effectively convey the exclusion of warranty; and each file should
+have at least the "copyright" line and a pointer to where the full
+notice is found.
+
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or
+your school, if any, to sign a "copyright disclaimer" for the library,
+if necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James
+ Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/README b/README
new file mode 100644
index 0000000..d12cd16
--- /dev/null
+++ b/README
@@ -0,0 +1,225 @@
+Python-support is a tool to handle byte-compilation of python modules
+when there are several python versions installed on the system.
+
+QUICK GUIDE FOR MAINTAINERS
+===========================
+
+ * If necessary, describe the supported versions in debian/pyversions.
+ * If your package is arch-all:
+ - Build it using its standard build system.
+ - Build-depend on python and python-support.
+ * If your package is arch-any:
+ - Build it once for every supported Python version (loop over
+ `pyversions -vr`).
+ - Build-depend on python-all-dev and python-support.
+ * Install files to the *standard* locations.
+ * Call dh_pysupport in the binary-* target.
+ * Add ${python:Depends} to the dependencies.
+
+And that’s all. Anything else is likely superfluous. If your package
+works correctly by doing that (and this is the case of 99% packages),
+you can stop reading this file here.
+
+
+How does it work?
+=================
+Python-support looks for modules in /usr/share/python-support.
+ * Private modules (.py files that shouldn't be installed in the default
+ sys.path) are handled through a foo.private file, which contains a list
+ of files to bytecompile. If the header of the foo.private file contains
+ a "pyversion=..." field, they will be bytecompiled with the Python
+ version described here, otherwise the current Python version will be
+ used.
+ * Public modules (.py files that should be installed in the default
+ sys.path) are handled through a foo.public file, which contains a
+ list of files to install. The files are normally installed in
+ /usr/share/pyshared/. They will be installed and bytecompiled in each
+ Python specific directory: /usr/lib/pymodules/pythonX.Y/. If the header
+ of the foo.public file contains a "pyversions=..." field, it will be
+ parsed for the list of python versions the module supports. It should
+ look like e.g.:
+ 2.2,2.4-
+ for a package supporting python2.2, and all versions starting from
+ python2.4.
+ * Public extensions (.so files) are handled just like public modules:
+ they are listed in the foo.public file. However, extensions for each
+ pythonX.Y will be located in /usr/lib/pyshared/pythonX.Y/, while they
+ are installed in /usr/lib/pymodules/pythonX.Y together with the
+ corresponding modules.
+
+How to make a package using it?
+===============================
+All the work is done using dh_pysupport. For most packages, using the
+standard build system then calling dh_pysupport should be enough.
+However, if the package builds binary extensions, it should be changed
+to build the extensions for all python versions in a single package.
+While not mandatory, it is highly recommended.
+
+*** You don't need X[BS]-Python-Version fields. You don't need ***
+*** debian/pycompat. You don't need to call dh_python after ***
+*** dh_pysupport. Just remove all of these. ***
+
+Of course, don't forget the dependency fields:
+ Build-Depends: python-support (>= 0.90), debhelper(>= 5)
+ Depends: ${python:Depends}
+
+If you're including public modules or extensions *and* if some other
+packages are expected to need them for a specific (non-default) Python
+version, you can also add the field:
+ Provides: ${python:Provides}
+
+However, if you do that, you need to be very careful. Especially, if
+you're depending on another python module, you should not declare it in
+the Depends field, but like this:
+ Python-Depends: python-bar (>= some.version)
+The appropriate dependencies on python2.X-bar will automatically be
+added.
+
+ For a package with only private modules
+ ---------------------------------------
+In this case, the rules file will probably look like this:
+
+build:
+ make ...
+
+install:
+ make install DESTDIR=debian/foo/
+
+binary-indep:
+ ...
+ dh_pysupport
+ dh_installdeb
+ ...
+
+If the private modules are not in a default directory (like
+/usr/share/$package or /usr/lib/$package) you should pass the directory
+to dh_pysupport:
+ dh_pysupport /usr/share/someframework/foo
+
+If the modules need a specific python version (like e.g. for Zope), you can
+pass the -V argument to dh_pysupport.
+ dh_pysupport -V2.4
+
+ For a package with public modules
+ ---------------------------------
+If the module doesn't work with all python versions, you should setup a
+debian/pyversions file. If the package needs python >= 2.3, it will look
+like :
+ 2.3-
+
+The rules file will look like this:
+
+build:
+ ...
+ python setup.py build
+
+install:
+ ...
+ python setup.py install --root=$(CURDIR)/debian/python-foo
+
+binary-indep:
+ ...
+ dh_pysupport
+ dh_installdeb
+ ...
+
+ For a package with public C extensions:
+ ---------------------------------------
+First of all, you should build-depend on python-all-dev.
+
+If you want to build the extension only for some python versions, you
+should create a debian/pyversions file as described earlier, and set in
+the rules file:
+PYVERS=$(shell pyversions -vr)
+You need to build-depend on python (>= 2.3.5-11) for this to work.
+
+Otherwise, you can just build the extensions for all supported python
+versions:
+PYVERS=$(shell pyversions -vs)
+
+The rest of the rules file will look like:
+
+build: $(PYVERS:%=build-python%)
+ touch $@
+build-python%:
+ python$* setup.py build
+ touch $@
+
+install: build $(PYVERS:%=install-python%)
+install-python%:
+ python$* setup.py install --root $(CURDIR)/debian/python-foo
+
+binary-arch:
+ ...
+ dh_pysupport
+ dh_installdeb
+ ...
+
+Specific cases
+==============
+ Packages hardcoding the path to their modules
+ ---------------------------------------------
+Some packages installing their modules in /usr/lib/python2.X expect
+to find them explicitly at that place at runtime. Fortunately this is
+uncommon as distutils doesn't allow that, but in this case the module
+will stop functioning with python-support. The solution is to install
+the files explicitly to /usr/lib/pymodules. Python-support will then
+automatically move them to the appropriate place.
+
+build-%/configure-stamp:
+ mkdir build-$*
+ cd build-$* && PYTHON=/usr/bin/python$* ../configure --prefix=/usr
+ touch $@
+
+build: $(PYVERS:%=build-%/build-stamp)
+build-%/build-stamp: build-%/configure-stamp
+ $(MAKE) -C build-$* pyexecdir=/usr/lib/pymodules/python$*
+ touch $@
+
+install: build $(PYVERS:%=install-%)
+install-%: build-%/build-stamp
+ $(MAKE) -C build-$* install pyexecdir=/usr/lib/pymodules/python$* DESTDIR=$(CURDIR)/debian/tmp
+
+binary-arch:
+ ...
+ dh_pysupport
+ dh_installdeb
+
+ Namespace packages
+ ------------------
+Namespace packages are empty __init__.py files that are necessary for
+other .py files to be considered as Python modules by the interpreter.
+To avoid this being a problem, python-support will add them automatically
+as needed. However, this will be done later than the update-python-modules
+call when dpkg installs the package, because this is, like
+byte-compilation, a time-consuming operation.
+
+What this means is, if you need a namespace package or depend on a
+package that needs it, *and* that you need to use it during the
+postinst phase (e.g. for a daemon), you will have to add the following
+command in the postinst before starting your daemon:
+ update-python-modules -p
+
+ Namespace packages and broken modules
+ -------------------------------------
+Some Python modules like Twisted rely on the fact that there is no
+__init__.py file in some directories. THESE PACKAGES ARE BROKEN. You
+should try to fix the package first to not rely on such implementation
+details.
+
+However, if it turns out not to be possible, you can, as a workaround,
+create a file named ".noinit" in the directories where you don't want
+__init__.py to be created. In this case, update-python-modules will not
+create the namespace package.
+
+
+Note : Legacy locations
+=======================
+Packages used to ship files in the following way:
+ * /usr/share/python-support/$package contained the public modules.
+ * /usr/lib/python-support/pythonX.Y/$package contained the public
+ extensions.
+ * /usr/share/python-support/$package.dirs contained a list of directories
+ to handle for byte-compilation (for private modules).
+These locations are still supported, but deprecated. New packages should
+not be using them.
diff --git a/debhelper/dh_pysupport b/debhelper/dh_pysupport
new file mode 100644
index 0000000..606510c
--- /dev/null
+++ b/debhelper/dh_pysupport
@@ -0,0 +1,384 @@
+#!/usr/bin/perl -w
+
+=head1 NAME
+
+dh_pysupport - use the python-support framework to handle Python modules
+
+=cut
+
+use strict;
+use File::Find;
+use Debian::Debhelper::Dh_Lib;
+
+=head1 SYNOPSIS
+
+B<dh_pysupport> [I<debhelper options>] [-V I<X.Y>] [-X I<item> [...]] [-n] [I<module dirs ...>]
+
+=head1 DESCRIPTION
+
+dh_pysupport is a debhelper program that will scan your package, detect
+public modules in I</usr/lib/pythonX.Y/site-packages>, and move them to
+the shared Python modules location. It will generate appropriate
+postinst/prerm scripts to byte-compile modules installed there for all
+available python versions.
+
+It will also look for private Python modules and will byte-compile them
+with the current Python version. You may have to list the directories
+containing private Python modules.
+
+If a file named I<debian/pyversions> exists, it is used to determine the
+python versions with which the package can work.
+
+Appropriate dependencies on python-support, python and pythonI<X.Y> are
+put in ${python:Depends}. The ${python:Versions} and ${python:Provides}
+optional substitution variables are made available as well.
+
+=head1 OPTIONS
+
+=over 4
+
+=item I<module dirs>
+
+If your package installs private python modules in non-standard directories, you
+can make dh_pysupport check those directories by passing their names on the
+command line. By default, it will check /usr/lib/$PACKAGE,
+/usr/share/$PACKAGE, /usr/lib/games/$PACKAGE and /usr/share/games/$PACKAGE
+
+=item B<-n>, B<--noscripts>
+
+Do not modify postinst/postrm scripts.
+
+=item B<-d>
+
+This option is deprecated.
+
+=item B<-V> I<X.Y>
+
+Force private modules to be bytecompiled with the specific I<X.Y> python version, regardless of the default python version on the system.
+
+=item B<-X> I<item>, B<--exclude=>I<item>
+
+Exclude files that contain "item" anywhere in their filename from being
+taken into account to generate the python dependency. It also excludes
+them from byte-compilation. You may use this option multiple times to
+build up a list of things to exclude.
+
+=back
+
+=head1 CONFORMS TO
+
+Python policy as of 2006-08-10
+
+=cut
+
+init();
+
+warning("This program is deprecated, you should use dh_python2 instead. Migration guide: http://deb.li/dhs2p");
+
+sub next_minor_version {
+ my $version = shift;
+ # Handles 2.10 -> 2.11 gracefully
+ my @items = split(/\./, $version);
+ $items[1] += 1;
+ $version = join(".", @items);
+ return $version;
+}
+
+sub specified_deps_in_package {
+ my $package = shift;
+ my $curpackage = 0;
+ my @deps = ();
+ open (CONTROL, 'debian/control') || error("cannot read debian/control: $!\n");
+ while (<CONTROL>) {
+ chomp;
+ s/\s+$//;
+ if (/^Package:\s*(.*)$/ && $package eq $1) {
+ $curpackage = 1;
+ }
+ if ($curpackage == 2) {
+ if (/^\s+(.*)$/) {
+ push @deps, split ",",$1;
+ if ($1 !~ /,$/) {
+ return @deps;
+ }
+ } else {
+ return @deps;
+ }
+ }
+ if ($curpackage && /^Python-Depends:\s*(.*)$/) {
+ @deps = split ",",$1;
+ if ($1 =~ /,$/) {
+ $curpackage = 2;
+ } else {
+ return @deps;
+ }
+ }
+ }
+ return @deps;
+}
+
+sub trim {
+ my $tmp = shift;
+ $tmp =~ s/^\s+//;
+ $tmp =~ s/\s+$//;
+ return $tmp;
+}
+
+# The current default python version
+my $default=`readlink /usr/bin/python`;
+$default =~ s/^python//;
+chomp $default;
+
+# Versions supported by python-defaults
+my @debian_pysupported = split(/ /, `/usr/bin/pyversions -sv`);
+chomp @debian_pysupported;
+
+my $privdir="/usr/share/python-support/private";
+# All supported versions
+my $allversions_string=`$privdir/parseversions --all`;
+chomp $allversions_string;
+my @allversions=split " ", $allversions_string;
+
+if (! grep { $_ eq $default } @allversions) {
+ error("Cannot detect default Python version");
+}
+
+# Use a specific version for private modules (doesn't affect public modules)
+my $useversion;
+if($dh{V_FLAG_SET}) {
+ $useversion = $dh{V_FLAG};
+ if (! grep { $_ eq $useversion } @allversions) {
+ error("Unknown python version $useversion");
+ }
+}
+
+foreach my $package (@{$dh{DOPACKAGES}}) {
+ next if ($package =~ /^python3-/); # ignore Python 3 packages
+ my $tmp = tmpdir($package);
+ my $need_pydep=0; # This variable tells whether we need a Python dependency
+ # regardless of the rest
+ my $have_pydep=0; # This variable tells whether we have added some dependency
+ # on python one way or another.
+ my @specified_deps = specified_deps_in_package ($package);
+ my $do_scripts = "";
+
+ # 1) Handle public python modules
+ # Move them to the python-support directories
+ my $verfile = "debian/pyversions";
+ my $versions = "";
+ if (open (VERFILE, $verfile)) {
+ # read first non-empty line
+ local $/ = "";
+ $versions = <VERFILE>;
+ chomp $versions;
+ close (VERFILE);
+ $versions = trim $versions;
+ # TODO: debian/package.pyversions ?
+ } else {
+ my $doko_versions=`$privdir/parseversions --raw --pycentral debian/control`;
+ chomp $doko_versions;
+ if ($doko_versions !~ /not found/) {
+ $versions=$doko_versions;
+ }
+ }
+ if ($versions) {
+ doit (("$privdir/movemodules","-V", $versions, $tmp))
+ } else {
+ doit (("$privdir/movemodules",$tmp));
+ }
+
+ # Then look for what the script found
+ foreach my $list_file (glob("$tmp/usr/share/python-support/*.public")) {
+ if (-f $list_file) {
+ my $supported=`$privdir/parseversions --minmax $list_file`;
+
+ # Add the packages explicitly asked by the maintainer
+ foreach my $dep (@specified_deps) {
+ $dep = trim $dep;
+ addsubstvar($package, "python:Depends", $dep);
+ }
+ my @ar=split "\n",$supported;
+ my @provides=split " ",$ar[0];
+ foreach my $pyversion (@provides) {
+ # Skip the substvars part for versions that might not
+ # be provided by packages depended upon.
+ next if (! grep { $_ eq $pyversion } @debian_pysupported);
+
+ # Generate the useless versions field
+ addsubstvar($package, "python:Versions", $pyversion);
+ # ... and the provides field
+ if ($package =~ /^python-/) {
+ my $virtual = $package;
+ $virtual =~ s/^python-/python$pyversion-/;
+ addsubstvar($package, "python:Provides", $virtual);
+ }
+ # Use the provides fields in packages dependended upon
+ foreach my $dep (@specified_deps) {
+ $dep = trim $dep;
+ # I have no idea why this wouldn't be the case, but well
+ if ($dep =~ /^python-(\S+)/) {
+ addsubstvar($package, "python:Depends", "python$pyversion-$1");
+ }
+ }
+ }
+ my @minmax=split " ",$ar[1];
+ my $minversion=$minmax[0];
+ if ( grep { $_ eq $default } @provides ) {
+ # The default version is in the supported versions
+ if ($minversion ne "None") {
+ addsubstvar($package, "python:Depends", "python (>= $minversion)");
+ $have_pydep=1;
+ }
+ } elsif ($minversion ne "None") {
+ # The default version is less than all supported versions
+ addsubstvar($package, "python:Depends", "python (>= $minversion) | python$minversion");
+ $have_pydep=1;
+ } else {
+ error("The default python version is greater than all supported versions");
+ }
+ my $maxversion=$minmax[1];
+ if ($maxversion ne "None") {
+ $maxversion = next_minor_version($maxversion);
+ addsubstvar($package, "python:Depends", "python (<< $maxversion)");
+ $have_pydep=1;
+ }
+ $list_file =~ s,^.*/,,;
+ $do_scripts = "$do_scripts $list_file";
+
+ $need_pydep = 1;
+ }
+ }
+
+ # 2) Look for private python modules
+ my @dirs = ("/usr/lib/$package", "/usr/share/$package",
+ "/usr/lib/games/$package", "/usr/share/games/$package", @ARGV );
+ @dirs = grep -d, map "$tmp$_", @dirs;
+ my @filelist;
+ my $file;
+ my $has_module = 0;
+ my $has_extension = 0;
+ my $strong_pydep=0;
+ my %need_verdep = ();
+ foreach (@allversions) {
+ $need_verdep{$_} = 0;
+ }
+ if (@dirs) {
+ foreach my $curdir (@dirs) {
+ find sub {
+ return unless -f;
+ return if excludefile($File::Find::name);
+ if (/\.py$/) {
+ $has_module=1;
+ doit(("rm","-f",$_."c",$_."o"));
+ ( $file=$File::Find::name ) =~ s%^$tmp%%;
+ if (! grep { $_ eq $file } @filelist) {
+ push @filelist, $file;
+ }
+ }
+ if (/\.so$/ &&
+ `nm -Du "$_" | grep "U Py_InitModule"` &&
+ ! `objdump -p "$_" | grep "NEEDED *libpython"`) {
+ $has_extension=1;
+ }
+ }, $curdir ;
+ }
+ }
+
+ if ( ($has_module or $has_extension) ) {
+ if ( $useversion ) {
+ $need_verdep{$useversion}=1;
+ } else {
+ $need_pydep=1;
+ $strong_pydep=1 if $has_extension;
+ }
+ }
+
+ if (@filelist) {
+ # We have private python modules
+ # Use python-support to ensure that they are always
+ # byte-compiled for the current version
+ doit("mkdir", "-p", "-m", "755", "$tmp/usr/share/python-support");
+ open(FILELIST, "> $tmp/usr/share/python-support/$package.private") ||
+ error("Can't create $tmp/usr/share/python-support/$package.private: $!");
+ if ( $useversion ) {
+ print FILELIST "pyversion=$useversion\n\n";
+ }
+ print FILELIST map "$_\n", @filelist;
+ close(FILELIST);
+ $do_scripts = "$do_scripts $package.private";
+ }
+
+ # 3) Add python-support dependency depending on what we found
+ if (-d "$tmp/usr/share/python-support") {
+ addsubstvar($package, "python:Depends", "python-support (>= 0.90.0)");
+ }
+
+ # 4) Look for python scripts
+ find sub {
+ return unless -f and -x;
+ return if excludefile($File::Find::name);
+ local *F;
+ return unless open F, $_;
+ if (read F, local $_, 32 and m%^#!\s*/usr/bin/(env\s+)?(python(\d+\.\d+)?)\s%) {
+ if ( "python" eq $2 ) {
+ $need_pydep=1;
+ } elsif (defined $need_verdep{$3}) {
+ $need_verdep{$3}=1;
+ }
+ }
+ close F;
+ }, $tmp;
+
+ # 5) Generate remaining dependencies
+ foreach my $version (@allversions) {
+ if ($need_verdep{$version}) {
+ addsubstvar($package, "python:Depends", "python$version");
+ }
+ }
+ if (not $have_pydep) {
+ if ($strong_pydep) {
+ addsubstvar($package, "python:Depends", "python (>= $default)");
+ my $maxversion = next_minor_version($default);
+ addsubstvar($package, "python:Depends", "python (<< $maxversion)");
+ $have_pydep=1;
+ } elsif ($need_pydep and $versions) {
+ my $supported=`echo $versions | $privdir/parseversions --minmax`;
+ my @ar=split "\n",$supported;
+ my @minmax=split " ",$ar[1];
+ my $minversion=$minmax[0];
+ if ($minversion ne "None") {
+ addsubstvar($package, "python:Depends", "python (>= $minversion)");
+ $have_pydep=1;
+ }
+ my $maxversion=$minmax[1];
+ if ($maxversion ne "None") {
+ $maxversion = next_minor_version($maxversion);
+ addsubstvar($package, "python:Depends", "python (<< $maxversion)");
+ $have_pydep=1;
+ }
+ }
+ }
+ # If nothing has added a python dependency yet, add it
+ if ($need_pydep and not $have_pydep) {
+ addsubstvar($package, "python:Depends", "python");
+ }
+
+ # 6) Generate the scripts
+ if ($do_scripts && ! $dh{NOSCRIPTS}) {
+ autoscript($package, "postinst", "postinst-python-support", "s,#ARGS#,$do_scripts,");
+ autoscript($package, "prerm", "prerm-python-support", "s,#ARGS#,$do_scripts,");
+ }
+}
+
+=head1 SEE ALSO
+
+L<debhelper(7)>
+
+This program is a part of python-support but is made to work with debhelper.
+
+=head1 AUTHORS
+
+Josselin Mouette <joss@debian.org>,
+Raphael Hertzog <hertzog@debian.org>
+
+=cut
diff --git a/debhelper/postinst-python-support b/debhelper/postinst-python-support
new file mode 100644
index 0000000..0969b1d
--- /dev/null
+++ b/debhelper/postinst-python-support
@@ -0,0 +1,3 @@
+if which update-python-modules >/dev/null 2>&1; then
+ update-python-modules #ARGS#
+fi
diff --git a/debhelper/prerm-python-support b/debhelper/prerm-python-support
new file mode 100644
index 0000000..f0a39a5
--- /dev/null
+++ b/debhelper/prerm-python-support
@@ -0,0 +1,3 @@
+if which update-python-modules >/dev/null 2>&1; then
+ update-python-modules -c #ARGS#
+fi
diff --git a/debian/changelog b/debian/changelog
new file mode 100644
index 0000000..b55737b
--- /dev/null
+++ b/debian/changelog
@@ -0,0 +1,776 @@
+python-support (1.0.15) unstable; urgency=low
+
+ [ Jakub Wilk ]
+ * parseversions:
+ + Make comparison of field names case-insensitive.
+ + Recognize X-Python-Version.
+
+ [ Piotr Ożarowski ]
+ * update-python-modules manpage: fix --install option's description
+ (closes: #671942)
+ * movemodules:
+ - doesn't raise string exceptions anymore (closes: #585332)
+ * Standards version is 3.9.3, no changes required
+
+ -- Piotr Ożarowski <piotr@debian.org> Sat, 30 Jun 2012 19:20:00 +0200
+
+python-support (1.0.14) unstable; urgency=low
+
+ * update-python-modules: remove directory if it's replaced with a file
+ (often happens with .egg-info file/dirs)
+ * Add deprecation warning: dh_python2 (from python package) should be used
+ instead. Migration guide is available on wiki page:
+ http://wiki.debian.org/Python/PythonSupportToDHPython2
+ * Vcs-* fields now point to anonscm.debian.org
+ * Standards version is 3.9.2, no changes required.
+
+ -- Piotr Ożarowski <piotr@debian.org> Mon, 27 Jun 2011 20:22:56 +0200
+
+python-support (1.0.13) unstable; urgency=low
+
+ [ LoĂ¯c Minier ]
+ * tests/testparseversions.py: don't hardcode expected versions; instead,
+ compare with pyversions' output.
+ * pysupport.py: don't hardcode supported and old versions; instead, parse
+ debian_defaults; NB: this removes some very old python versions from the
+ list (2.1 and 2.2), but these weren't ever support and aren't supported in
+ the previous stable release anyway. Depend on python-minimal as
+ debian_defaults is accessed directly.
+
+ [ Piotr Ożarowski ]
+ * Upload to unstable (closes: #622906)
+ * Add lintian override for depends-on-python-minimal
+
+ -- Piotr Ożarowski <piotr@debian.org> Fri, 15 Apr 2011 21:14:04 +0200
+
+python-support (1.0.12) experimental; urgency=low
+
+ * Add support for python2.7.
+ * Move python2.4 to old versions.
+
+ -- Piotr Ożarowski <piotr@debian.org> Mon, 18 Oct 2010 19:51:21 +0200
+
+python-support (1.0.11) unstable; urgency=low
+
+ * Move python2.4 to old versions.
+
+ -- Piotr Ożarowski <piotr@debian.org> Tue, 19 Oct 2010 17:20:22 +0200
+
+python-support (1.0.10) unstable; urgency=low
+
+ * Binary packages with name starting with "python3-" are now ignored by
+ dh_pysupport
+ * Standards version is 3.9.1, no changes required.
+
+ -- Piotr Ożarowski <piotr@debian.org> Tue, 14 Sep 2010 19:05:58 +0200
+
+python-support (1.0.9) unstable; urgency=low
+
+ * dh_pysupport: generates correct dependencies if multiple packages need
+ pythonX.Y (closes: #576517, thanks to Jakub Wilk for the patch)
+ * update-python-modules:
+ - remove /usr/lib/pymodules files symlinked to /usr/share/pyshared that
+ no longer belong to any python-support based package
+ - doesn't raise string exceptions anymore (closes: #585332)
+
+ -- Piotr Ożarowski <piotr@debian.org> Sun, 27 Jun 2010 15:12:52 +0200
+
+python-support (1.0.8) unstable; urgency=low
+
+ [ Jakub Wilk ]
+ * movemodules: ignore indentation and trailing whitespace when comparing
+ PKG-INFO and *.egg-info files. This is work-around for bug #575377.
+
+ [ Piotr Ożarowski ]
+ * Standards version is 3.8.4, no changes required.
+ * Use 3.0 (native) source package format
+
+ -- Piotr Ożarowski <piotr@debian.org> Tue, 20 Apr 2010 20:11:54 +0200
+
+python-support (1.0.7) unstable; urgency=low
+
+ [ LoĂ¯c Minier ]
+ * Fix stripping of empty lines in debian/pyversions; LP: #437593;
+ closes: #568171.
+ * Only search for XS-Python-Version in the debian/control general paragraph
+ (the first one, for the source package); see Debian #567941;
+ closes: #568173.
+ * Add tests for parseversions.
+ * Use ./parseversions --all --long to list supported versions during build
+ instead of poking pysupport.py_supported directly.
+ * Cleanup shell snippet / tabs in rules.
+ * Explicitly strip spaces after parsing debian/pyversions.
+
+ [ Josselin Mouette ]
+ * dh_pysupport: fix syntax errors in previous patch.
+ * README: document that only python is required for arch: all
+ packages, not python-dev. Also talk about python-support itself.
+ Closes: #563749.
+ * dh_pysupport: print an error if the default Python version cannot be
+ found. Closes: #572155.
+ * parseversions: I hate regexes.
+ * dh_pysupport: ensure there is a Python dependency even when no
+ specific versions are required. Closes: #568811.
+
+ -- Josselin Mouette <joss@debian.org> Thu, 11 Mar 2010 23:17:19 +0100
+
+python-support (1.0.6.1) unstable; urgency=low
+
+ * Non-maintainer upload.
+ * update-python-modules: set umask to 022. Closes: #567811.
+
+ -- Matt Kraai <kraai@debian.org> Tue, 23 Feb 2010 03:14:38 -0800
+
+python-support (1.0.6) unstable; urgency=low
+
+ * movemodules: do not touch symlinks that merely point to another
+ place in the module tree. Closes: #539187.
+
+ -- Josselin Mouette <joss@debian.org> Fri, 04 Dec 2009 09:26:17 +0100
+
+python-support (1.0.5) unstable; urgency=low
+
+ [ Piotr Ożarowski ]
+ * Rename .egg-info files the same way .egg-info directories are renamed
+
+ [ Josselin Mouette ]
+ * dh_pysupport: use mkdir -p instead of the Perl mkdir function.
+ Closes: #558392.
+
+ -- Josselin Mouette <joss@debian.org> Sat, 28 Nov 2009 20:17:55 +0100
+
+python-support (1.0.4) unstable; urgency=low
+
+ [ Josselin Mouette ]
+ * README: fix small but confusing mistake about public extensions.
+ * update-python-modules.8: fix typo, thanks Nacho Barrientos.
+ * Add Bernd and Piotr to uploaders.
+ * dh_pysupport: fix a variable getting included in a regexp.
+ Closes: #549283.
+ * dh_pysupport: patch by Luca Falavigna to not generate substvars for
+ Python versions not supported by python-defaults. Closes: #549713.
+
+ [ Piotr Ożarowski ]
+ * control: add Vcs-Browser and Vcs-Svn fields
+
+ -- Josselin Mouette <joss@debian.org> Thu, 08 Oct 2009 22:39:22 +0200
+
+python-support (1.0.3) unstable; urgency=low
+
+ * update-python-modules: be resilient against broken directories in
+ /usr/share/python-support. Closes: #528130.
+
+ -- Josselin Mouette <joss@debian.org> Tue, 12 May 2009 21:46:05 +0200
+
+python-support (1.0.2) unstable; urgency=low
+
+ * dh_pysupport: remove warning about compatibility mode.
+ * movemodules: list files in /usr/share/pyshared, so that this place
+ can be used as a destination for stuff installed by hand.
+ * Switch to debhelper compatibility mode 7.
+
+ -- Josselin Mouette <joss@debian.org> Wed, 15 Apr 2009 16:25:13 +0200
+
+python-support (1.0.1) unstable; urgency=low
+
+ * update-python-modules:
+ + Use the warning() function for all warnings. Closes: #522856.
+ * movemodules:
+ + Read links destinations instead of their contents, so that we can
+ support dangling symbolic links. Closes: #523033.
+
+ -- Josselin Mouette <joss@debian.org> Wed, 08 Apr 2009 12:23:23 +0200
+
+python-support (1.0.0) unstable; urgency=low
+
+ * Upload to unstable.
+
+ -- Josselin Mouette <joss@debian.org> Mon, 06 Apr 2009 13:22:14 +0200
+
+python-support (0.90.5) experimental; urgency=low
+
+ * movemodules:
+ + Better handling of files from multiple sources, used for files
+ being installed in different directories for python2.5 and 2.6.
+ + Add /usr/local/lib/pythonX.Y/dist-packages as a source for
+ modules.
+ + Use hashlib instead of md5. Closes: #519189.
+ * Require python 2.5 for the hashlib module.
+
+ -- Josselin Mouette <joss@debian.org> Thu, 26 Mar 2009 19:09:31 +0100
+
+python-support (0.90.4) experimental; urgency=low
+
+ * movemodules:
+ + When moving relative symbolic links, handle the case where we move
+ several of them.
+ + Support dist-packages as a source for modules.
+ * rules: install the .pth in dist-packages for python2.6.
+ Closes: #518826.
+ * update-python-modules: fix a crash occurring when a package drops
+ some supported versions. Closes: #518973.
+
+ -- Josselin Mouette <joss@debian.org> Tue, 24 Mar 2009 16:24:12 +0100
+
+python-support (0.90.3) experimental; urgency=low
+
+ * Add a quick guide for maintainers on top of the README. Maybe it
+ will prevent maintainers from doing useless things they thought were
+ necessary by reading the rest.
+ * movemodules:
+ + Now that we have the /var/lib/python-support symlink, also move
+ files from that directory at build time, this will avoid to change
+ a couple of packages.
+ + Preserve relative symbolic links when moving them to a different
+ level
+
+ -- Josselin Mouette <joss@debian.org> Fri, 27 Feb 2009 00:39:41 +0100
+
+python-support (0.90.2) experimental; urgency=low
+
+ * dh_pysupport: match /\.py$/ instead of /.py$/.
+ * movemodules: completely remove empty __init__.py files, they are
+ added at installation time by update-python-modules.
+ * post{inst,rm}: add a symbolic link in /var/lib/python-support,
+ otherwise the upgrade will be a big failure for several packages.
+
+ -- Josselin Mouette <joss@debian.org> Fri, 20 Feb 2009 16:42:52 +0100
+
+python-support (0.90.1) experimental; urgency=low
+
+ * Update priority to match the override.
+ * update-python-modules: add a consistency check for the case when no
+ packages using python-support are installed.
+ * dh_pysupport: avoid duplicates when handling private modules.
+ * movemodules: correctly support the case where
+ /usr/lib/pyshared/pythonX.Y is used but more Python versions are
+ supported.
+
+ -- Josselin Mouette <joss@debian.org> Thu, 19 Feb 2009 19:16:49 +0100
+
+python-support (0.90.0) experimental; urgency=low
+
+ * Major changes to the installed packages format. The old format is
+ still supported at runtime, but will not be generated anymore.
+ * Private modules now ship foo.private files, containing the metadata
+ and file listing for the package.
+ * Public modules now ship foo.public files for metadata and listing,
+ and files go to /usr/{share,lib}/pyshared. Closes: #478178.
+ * The modules installation path was changed to /usr/lib/pymodules.
+ * The private directory has moved to
+ /usr/share/python-support/private. The specific scripts are now
+ installed in here.
+ * Important documentation updates.
+ * copyright: point to the correct LGPL location.
+ * Add support for python2.6.
+
+ -- Josselin Mouette <joss@debian.org> Wed, 18 Feb 2009 21:44:25 +0100
+
+python-support (0.8.7) unstable; urgency=low
+
+ * update-python-modules (install_modules):
+ + Make the error message more useful.
+
+ -- Josselin Mouette <joss@debian.org> Mon, 27 Oct 2008 09:02:41 +0100
+
+python-support (0.8.6) unstable; urgency=low
+
+ * update-python-modules (create_dotpath):
+ + Completely ignore lines starting with "import", as they would be
+ executed by python upon startup.
+
+ -- Josselin Mouette <joss@debian.org> Fri, 29 Aug 2008 22:31:43 +0200
+
+python-support (0.8.5) unstable; urgency=low
+
+ * update-python-modules (post_change_stuff):
+ + Don't create a namespace package if there is a file named .noinit
+ in the same directory. Closes: #459468.
+ * dh_pysupport: add correct dependencies when there is such a file.
+ * README: document how to do that and that you shouldn't.
+
+ -- Josselin Mouette <joss@debian.org> Thu, 24 Jul 2008 14:30:01 +0200
+
+python-support (0.8.4) unstable; urgency=medium
+
+ * update-python-modules (post_change_stuff):
+ + Remove symbolic links to files in packages not supported by the
+ current python version anymore. Closes: #485740
+ * Standards version is 3.8.0, no changes required.
+
+ -- Josselin Mouette <joss@debian.org> Mon, 30 Jun 2008 13:07:07 +0200
+
+python-support (0.8.3) unstable; urgency=low
+
+ * update-python-modules:
+ + Integrate a part of the Ubuntu change for LP#208961, fixes a
+ crash that might occur if a dangling symbolic link to an old
+ version of the file in a removed package is found.
+ * README:
+ + Document the specific case of daemons needing namespace packages.
+ This should be very rare, but you never know.
+
+ -- Josselin Mouette <joss@debian.org> Mon, 23 Jun 2008 11:07:50 +0200
+
+python-support (0.8.2) unstable; urgency=low
+
+ * Fix typo in 0.8.1 changelog entry.
+ * update-python-modules:
+ + Call dpkg-trigger explicitly when we need it. This should prevent
+ the trigger from being run *before* the actual installation.
+ Closes: #486516.
+ * triggers: declare interest on the "pysupport" trigger.
+
+ -- Josselin Mouette <joss@debian.org> Mon, 23 Jun 2008 02:35:41 +0200
+
+python-support (0.8.1) unstable; urgency=low
+
+ * update-python-modules:
+ + Handle the case where a daemon package uses a module that ships a
+ .pth file. In this case, it is needed at once and we cannot wait
+ for the trigger.
+ * Depend on dpkg 1.14.19 to not get hit by #479850.
+ * Fix minor issue in README.
+
+ -- Josselin Mouette <joss@debian.org> Tue, 13 May 2008 10:48:00 +0200
+
+python-support (0.8.0) experimental; urgency=low
+
+ * update-python-modules:
+ + Don't do anything when called with -c for public modules. This
+ will allow modules to remain available while being upgraded.
+ + Don't byte-compile public modules when called without -p, either.
+ This should reduce the time consumed during upgrades.
+ + Support a new --post-install/-p option, that byte-compiles public
+ modules and removes any dangling symbolic links left by a package
+ removal or upgrade.
+ + Indentation fixes.
+ * triggers: register triggers on /usr/share/python-support and
+ /usr/lib/python-support.
+ * postinst:
+ + Always byte-compile python-support.dirs.
+ + Launch update-python-support --post-install to enforce
+ byte-compilation.
+ + Launch only this command when triggered.
+ * control: build-depend on debhelper 5.0.59 for triggers support.
+ * pysupport.py: deprecate python2.3.
+ * control: depend on python >= 2.4 to match the change.
+
+ -- Josselin Mouette <joss@debian.org> Wed, 07 May 2008 00:18:55 +0200
+
+python-support (0.7.7) unstable; urgency=low
+
+ * update-python-modules:
+ + Correctly handle the clean mode when called with an unknown
+ directory as argument. Closes: #468848.
+ + Fail when a package tries to provide an extension provided by
+ another one (the previous code only worked for modules).
+ * README: document that you shouldn't remove the
+ /usr/share/python-support/foo directory.
+ * control: properly capitalize Python.
+
+ -- Josselin Mouette <joss@debian.org> Wed, 12 Mar 2008 00:07:04 +0100
+
+python-support (0.7.6) unstable; urgency=low
+
+ * dh_pysupport: allow the Python-Depends field to be wrapped.
+ Closes: #458737.
+ * Standards version is 3.7.3; no changes.
+
+ -- Josselin Mouette <joss@debian.org> Sat, 05 Jan 2008 13:04:30 +0100
+
+python-support (0.7.5) unstable; urgency=low
+
+ * dh_pysupport:
+ + Cut out some unused code.
+ + Unify script generation, cutting obsolete -i and -b options.
+ * {postinst,prerm}-python-support:
+ + Update snippets accordingly.
+ + Launch the postinst in all cases, not only in the configure case.
+ Closes: #446730.
+
+ -- Josselin Mouette <joss@debian.org> Wed, 31 Oct 2007 18:51:10 +0100
+
+python-support (0.7.4) unstable; urgency=low
+
+ * dh_pysupport: don't treat .so files linking to libpython* as
+ extensions. This will avoid adding spurious dependencies.
+ * Fix some wrong changelog entries talking about dh_python.
+
+ -- Josselin Mouette <joss@debian.org> Thu, 04 Oct 2007 14:22:36 +0200
+
+python-support (0.7.3) unstable; urgency=low
+
+ * dh_pysupport: fix an annoying bug sometimes leading to an invalid
+ substvars file when using Python-Depends.
+
+ -- Josselin Mouette <joss@debian.org> Sat, 22 Sep 2007 12:15:34 +0200
+
+python-support (0.7.2) unstable; urgency=low
+
+ * Upload to unstable.
+ * dh_pysupport: bump the generated dependencies to version 0.7.1. Modules
+ which need namespace packages will need to build-depend on that
+ version, and will get a dependency on it.
+
+ -- Josselin Mouette <joss@debian.org> Thu, 20 Sep 2007 23:07:44 +0200
+
+python-support (0.7.1) experimental; urgency=low
+
+ * update-python-modules:
+ + Exclude __init__.py files already provided by the package by
+ looking at whether they are symbolic links.
+ + Minor cleanups.
+ + Use shutil.rmtree instead of rm -rf.
+
+ -- Josselin Mouette <joss@debian.org> Wed, 27 Jun 2007 19:13:32 +0200
+
+python-support (0.7) experimental; urgency=low
+
+ * Make the package priority standard.
+ * update-python-modules: add support for namespace packages, by
+ creating and removing automatically empty __init__.py files where
+ appropriate. Thanks Gustavo Noronha Silva for the initial idea and
+ precious input.
+
+ -- Josselin Mouette <joss@debian.org> Sun, 10 Jun 2007 00:45:37 +0200
+
+python-support (0.6.4) unstable; urgency=low
+
+ * update-python-modules: only warn on missing files if we're in
+ cleaning mode (prerm). Closes: #422568.
+ * pysupport-movemodules: merge .egg-info directories by stripping the
+ -py$vers part from them. Based on a patch by Cyril Brulebois,
+ closes: #422436.
+
+ -- Josselin Mouette <joss@debian.org> Tue, 08 May 2007 18:48:31 +0200
+
+python-support (0.6.3) unstable; urgency=low
+
+ * dh_pysupport: trim strings in the Python-Depends field.
+
+ -- Josselin Mouette <joss@debian.org> Wed, 28 Mar 2007 22:50:41 +0200
+
+python-support (0.6.2) unstable; urgency=low
+
+ * pysupport-movemodules: remove .a and .la files, which are useless
+ cruft generated by libtool (closes: #412477).
+ * Upload to unstable.
+
+ -- Josselin Mouette <joss@debian.org> Wed, 21 Mar 2007 22:16:20 +0100
+
+python-support (0.6.1) experimental; urgency=low
+
+ * pysupport-movemodules:
+ + Fix a case where the original installation directory was not
+ removed.
+ + Move modules from /var/lib/python-support as well. This allows
+ to handle packages that hardcode the path to the modules
+ (closes: #397895).
+ * README:
+ + Document the procedure for such packages.
+ + Also document the Python-Depends field.
+
+ -- Josselin Mouette <joss@debian.org> Sat, 24 Feb 2007 13:04:23 +0100
+
+python-support (0.6) experimental; urgency=low
+
+ * dh_pysupport:
+ + Generate the useless ${python:Versions} field (closes: #403366).
+ + Parse a new control field, Python-Depends, which contains
+ dependencies on other python packages. Add to ${python:Depends}
+ the virtual dependencies needed for all python versions.
+ + Remove useless spaces at the end of python-support dependencies.
+
+ -- Josselin Mouette <joss@debian.org> Sat, 17 Feb 2007 13:10:27 +0100
+
+python-support (0.5.6) unstable; urgency=medium
+
+ * pysupport-parseversions, dh_pysupport: remove the remaining calls to
+ pyversions, thanks Pawel Tecza.
+ * This allows to loosen dependencies on python to 2.3.
+ * update-python-modules: only show a warning when byte-compilation
+ fails, but don't stop the whole process, thanks Raphaël Hertzog
+ (closes: #400001).
+ * pysupport-parseversions: fix parsing of XS-Python-Version field.
+
+ -- Josselin Mouette <joss@debian.org> Thu, 23 Nov 2006 22:34:58 +0100
+
+python-support (0.5.5) unstable; urgency=high
+
+ * dh_pysupport, pysupport-movemodules, debian/rules,
+ pysupport-parseversions, pysupport.py: do not rely on pyversions to
+ obtain the list of installed python versions, because it is not a
+ reliable way to do so, see #396840.
+ * This brings back support for python2.3, and allows support for
+ python2.5.
+
+ -- Josselin Mouette <joss@debian.org> Tue, 14 Nov 2006 21:25:16 +0100
+
+python-support (0.5.4) unstable; urgency=high
+
+ * dh_pysupport: patch from Raphaël Hertzog to correctly depend on
+ python when there is no minimum nor maximum version
+ (closes: #391689).
+
+ -- Josselin Mouette <joss@debian.org> Thu, 12 Oct 2006 19:38:41 +0200
+
+python-support (0.5.3) unstable; urgency=low
+
+ * dh_pysupport: always generate dependencies.
+ * Conflict with debhelper (<< 5.0.38).
+
+ -- Josselin Mouette <joss@debian.org> Sun, 1 Oct 2006 19:58:09 +0200
+
+python-support (0.5.2) unstable; urgency=low
+
+ * update-python-modules:
+ + Remove some useless code.
+ + Small fix in short help.
+ + Handle the case of broken symlinks needing to be overwritten.
+ * dh_pysupport.1: reference README and policy, thanks Tomas Pospisek
+ (closes: #388171).
+
+ -- Josselin Mouette <joss@debian.org> Fri, 22 Sep 2006 21:14:15 +0200
+
+python-support (0.5.1) unstable; urgency=low
+
+ * dh_pysupport:
+ + Generate ${python:Provides} when no debian/pyversions file exists.
+ + Barf when /usr/lib/python-support/$package is lacking an existing
+ python version (closes: #387040).
+
+ -- Josselin Mouette <joss@debian.org> Mon, 11 Sep 2006 23:51:49 +0200
+
+python-support (0.5) unstable; urgency=low
+
+ * update-python-modules: be much stricter in what is accepted on the
+ command line. Only .dirs files are accepted with the -i option,
+ while directories in /usr/share/python-support are accepted with the
+ -b option. It is now possible to pass both kinds of arguments on the
+ command line. Closes: #386830.
+ * update-python-modules: abandon compatibility with version 0.1
+ entirely. The warnings have been prominent enough.
+
+ -- Josselin Mouette <joss@debian.org> Sun, 10 Sep 2006 19:39:21 +0200
+
+python-support (0.4.3) unstable; urgency=medium
+
+ * update-python-modules: check for .path presence when checking for
+ newly installed python versions, otherwise stuff might not be
+ compiled for it (closes: #383799, medium-urgency fix).
+ * update-python-modules: handle symbolic links to directories
+ (closes: #378853).
+
+ -- Josselin Mouette <joss@debian.org> Thu, 31 Aug 2006 21:11:19 +0200
+
+python-support (0.4.2) unstable; urgency=low
+
+ * dh_pysupport: add a python dependency even when there is already a
+ dependency on python-support (closes: #383958).
+ * pysupport.py: strip all unnecessary whitespace (closes: #385105).
+ * pysupport-movemodules: force the umask to avoid getting wrong
+ permissions in the final package (closes: #382755).
+
+ -- Josselin Mouette <joss@debian.org> Thu, 31 Aug 2006 20:01:10 +0200
+
+python-support (0.4.1) unstable; urgency=low
+
+ * dh_pysupport:
+ + Implement the -X option to exclude files from being searched to
+ generate the dependencies.
+ + Detect private extensions as .so files calling Py_InitModule*. In
+ this case, a strict dependency on python (>= X.Y), python (<<
+ X.Y+1) is generated.
+
+ -- Josselin Mouette <joss@debian.org> Thu, 10 Aug 2006 14:03:48 +0200
+
+python-support (0.4.0) unstable; urgency=low
+
+ * dh_pysupport:
+ + Handle dependencies for packages that only ship modules for
+ non-default python versions.
+ + Always generate dependencies when debian/pycompat isn't found.
+ + Add missing newline at the end of the .dirs files.
+ + Avoid obtaining a double leading / in .dirs files.
+ + Avoid duplicate entries in .dirs files.
+ + Create .pyversion in private module directories when the -V option
+ is used. Require python-support 0.4 in this case.
+ + Handle python dependencies for private modules.
+ + Handle script dependencies.
+ + Improve comments in the code.
+ + Remove .py[co] files in the private module directories.
+ * update-python-modules:
+ + Don't call compileall.py on non-existing directories
+ (closes: #378773).
+ + Bytecompilation of private modules for non-default python
+ versions, using the .pyversion file.
+ * README:
+ + Document all these changes.
+ + Document that using dh_python is not recommended.
+
+ -- Josselin Mouette <joss@debian.org> Wed, 9 Aug 2006 00:26:42 +0200
+
+python-support (0.3.9) unstable; urgency=low
+
+ * python-support.rtupdate: only run the script when called with the
+ "rtupdate" argument.
+ * pysupport-movemodules: keep foo.so.3 files in /usr/lib, but print a
+ warning.
+ * dh_pysupport:
+ + Fix typo in documentation (closes: #375934).
+ + Fix --noscripts usage (closes: #378421).
+ * README: a few clarifications from CĂ©dric Delfosse
+ (closes: #378161).
+
+ -- Josselin Mouette <joss@debian.org> Wed, 2 Aug 2006 13:23:44 +0200
+
+python-support (0.3.8) unstable; urgency=low
+
+ * update-python-modules: fix upgrade path from pre-0.3.4 versions
+ (closes: #375608).
+
+ -- Josselin Mouette <joss@debian.org> Tue, 27 Jun 2006 10:00:38 +0200
+
+python-support (0.3.7) unstable; urgency=low
+
+ * debian/prerm: in the case update-python-modules fails, cleanup by
+ hand and exit gracefully. This should make upgrades from broken
+ versions work.
+
+ -- Josselin Mouette <joss@debian.org> Sun, 25 Jun 2006 15:50:47 +0200
+
+python-support (0.3.6) unstable; urgency=low
+
+ * update-python-modules: Fix a case where the .path file wasn't
+ cleaned up automatically upon package removal.
+
+ -- Josselin Mouette <joss@debian.org> Sun, 25 Jun 2006 15:17:56 +0200
+
+python-support (0.3.5) unstable; urgency=low
+
+ * update-python-modules: don't try to generate a .path file if the
+ directory doesn't exist. Thanks Bastian Blank for noticing this.
+
+ -- Josselin Mouette <joss@debian.org> Sun, 25 Jun 2006 15:08:12 +0200
+
+python-support (0.3.4) unstable; urgency=low
+
+ * update-python-modules: handle .pth files correctly, by concatenating
+ them into ".path".
+ * rules: python-support.pth is now a symbolic link to this .path.
+ * dh_pysupport: make packages depend on python-support 0.3.4 to avoid
+ hitting the bug.
+
+ -- Josselin Mouette <joss@debian.org> Sat, 24 Jun 2006 18:23:21 +0200
+
+python-support (0.3.3) unstable; urgency=low
+
+ * pysupport-movemodules: fix directory creation in the case there is
+ no .py at all in the package.
+
+ -- Josselin Mouette <joss@debian.org> Sat, 24 Jun 2006 11:54:24 +0200
+
+python-support (0.3.2) unstable; urgency=low
+
+ * dh_pysupport: fix typo affecting dependency generation.
+ * README: recommend using pyversions -vr now it works.
+
+ -- Josselin Mouette <joss@debian.org> Fri, 23 Jun 2006 19:46:53 +0200
+
+python-support (0.3.1) unstable; urgency=low
+
+ * README: add correct documentation (closes: #370515).
+ * pysupport-movemodules: remove .pyc and .pyo files if some are
+ generated.
+
+ -- Josselin Mouette <joss@debian.org> Wed, 21 Jun 2006 10:41:19 +0200
+
+python-support (0.3.0) unstable; urgency=low
+
+ * Acknowledge NMU (closes: #372774).
+ * Increase minimal dependency to 0.2 in the helper script.
+ + Make it 0.3 in the case where /usr/lib/python-support exists.
+ * rules: cdbs already provides DEB_VERSION, no need to re-compute it.
+ * install: install dh_pysupport in /usr/bin.
+ * Don't build-depend on perl.
+
+ * Standards-version is 3.7.2.
+ * Add more warnings and errors for package making wrong uses of
+ python-support or using the python-support 0.1 compatibility mode.
+ * Use "pyversions -s to get the list of python versions.
+ + Depend on python 2.3.5-6.
+ * Improve a bit the manual page.
+ * Fail if a package tries to overwrite a file provided by another
+ package (closes: #373753).
+ * Support extensions, by searching
+ /usr/lib/python-support/$package/$version for files specific to a
+ python version.
+ * New command: pysupport-movemodules, to move modules from
+ /usr/lib/python2.X trees to the python-support hierarchies.
+ * Call this command in dh_pysupport.
+ * Add the ability to generate a .version in dh_pysupport, by copying
+ debian/pyversions.
+ * Add the possibility for automatic generation of ${python:Depends}
+ and ${python:Provides}, when calling dh_pysupport -d.
+ * Provide python-support.rt* scripts to provide hooks when python
+ versions are installed or removed.
+ + The dependency on python (<< 2.4) can be removed.
+ * New command: pysupport-parseversions. It parses
+ debian/package.pyversions files to display the list of supported
+ versions that are included in the version list described here.
+
+ -- Josselin Mouette <joss@debian.org> Mon, 19 Jun 2006 14:18:29 +0200
+
+python-support (0.2.3) unstable; urgency=low
+
+ * Non-maintainer upload.
+ * Integrate dh_pysupport and generate the corresponding man-page.
+ Closes: #372774
+
+ -- Raphael Hertzog <hertzog@debian.org> Mon, 12 Jun 2006 17:59:47 +0200
+
+python-support (0.2.2) unstable; urgency=low
+
+ * Rewrite the version parser to correctly handle the "-2.x" version
+ string.
+ * Remove support for python2.1 and python2.2.
+ * Purge directories for old python versions.
+ * Standards-version is 3.7.0.
+
+ -- Josselin Mouette <joss@debian.org> Wed, 3 May 2006 18:54:10 +0200
+
+python-support (0.2.1) unstable; urgency=low
+
+ * Include /usr/share/python-support in the package (closes: #365550).
+
+ -- Josselin Mouette <joss@debian.org> Mon, 1 May 2006 04:26:25 +0200
+
+python-support (0.2) unstable; urgency=low
+
+ * Link the .py files (closes: #365111, #348596, #363505).
+ * Support /usr/share/python-support/foo/.version to list the python
+ versions for which the package is known to work.
+ * Make python-support entirely stateless. We now rely on
+ /usr/share/python-support/*/ for directories to install and on
+ /usr/share/python-support/*.dirs for directories to bytecompile in
+ situ.
+ * Improve performance by byte-compiling for non-default python
+ versions in a single run.
+ * Treat relative paths in arguments as belonging to
+ /usr/share/python-support.
+ * Support python 2.5.
+
+ -- Josselin Mouette <joss@debian.org> Sat, 29 Apr 2006 23:29:40 +0200
+
+python-support (0.1.1) unstable; urgency=low
+
+ * Create /var/lib/python-support first.
+
+ -- Josselin Mouette <joss@debian.org> Fri, 6 Jan 2006 11:25:20 +0100
+
+python-support (0.1) unstable; urgency=low
+
+ * Initial release (closes: #345638).
+
+ -- Josselin Mouette <joss@debian.org> Mon, 2 Jan 2006 14:52:42 +0100
diff --git a/debian/compat b/debian/compat
new file mode 100644
index 0000000..7f8f011
--- /dev/null
+++ b/debian/compat
@@ -0,0 +1 @@
+7
diff --git a/debian/control b/debian/control
new file mode 100644
index 0000000..9e1f36b
--- /dev/null
+++ b/debian/control
@@ -0,0 +1,24 @@
+Source: python-support
+Section: python
+Priority: optional
+Maintainer: Josselin Mouette <joss@debian.org>
+Uploaders: Bernd Zeimetz <bzed@debian.org>, Piotr Ożarowski <piotr@debian.org>
+Build-Depends: debhelper (>= 7), cdbs
+Build-Depends-Indep: python (>= 2.5)
+Standards-Version: 3.9.3
+Vcs-Svn: svn://anonscm.debian.org/collab-maint/deb-maint/python-support/trunk
+Vcs-Browser: http://anonscm.debian.org/viewvc/collab-maint/deb-maint/python-support/trunk/
+
+Package: python-support
+Architecture: all
+Depends: python (>= 2.5), python-minimal, dpkg (>= 1.14.19), ${misc:Depends}
+Conflicts: debhelper (<< 5.0.38)
+Description: automated rebuilding support for Python modules
+ This package contains the 'update-python-modules' script, which takes
+ care of byte-compilation of Python-only modules.
+ .
+ Private modules are automatically rebuilt upon major Python upgrades,
+ avoiding the need for strong dependencies.
+ .
+ Public modules are automatically made available for all installed
+ Python versions.
diff --git a/debian/copyright b/debian/copyright
new file mode 100644
index 0000000..785f205
--- /dev/null
+++ b/debian/copyright
@@ -0,0 +1,26 @@
+This is python-support, written and maintained by Josselin Mouette
+<joss@debian.org> on Mon, 2 Jan 2006 14:57:00 +0100.
+
+The original source can always be found at:
+ ftp://ftp.debian.org/debian/pool/main/p/python-support/
+
+Copyright (c) 2006 Josselin Mouette <joss@debian.org>
+
+License:
+
+ This package is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License.
+
+ This package is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this package; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+On Debian systems, the complete text of the GNU Lesser General
+Public License can be found in `/usr/share/common-licenses/LGPL-2.1'.
diff --git a/debian/dirs b/debian/dirs
new file mode 100644
index 0000000..e0103bd
--- /dev/null
+++ b/debian/dirs
@@ -0,0 +1,2 @@
+/usr/share/python-support
+/usr/lib/pymodules
diff --git a/debian/install b/debian/install
new file mode 100644
index 0000000..f021cbb
--- /dev/null
+++ b/debian/install
@@ -0,0 +1,7 @@
+update-python-modules /usr/sbin/
+movemodules parseversions /usr/share/python-support/private/
+*.py /usr/share/python-support/private/
+python-support.private /usr/share/python-support/
+debhelper/dh_pysupport /usr/bin/
+debhelper/*-python-support /usr/share/debhelper/autoscripts/
+runtime/* /usr/share/python/runtime.d/
diff --git a/debian/manpages b/debian/manpages
new file mode 100644
index 0000000..afe6099
--- /dev/null
+++ b/debian/manpages
@@ -0,0 +1,3 @@
+update-python-modules.8
+debhelper/*.1
+pysupport-*.1
diff --git a/debian/postinst b/debian/postinst
new file mode 100644
index 0000000..e0364ac
--- /dev/null
+++ b/debian/postinst
@@ -0,0 +1,20 @@
+#! /bin/sh
+set -e
+
+if [ "$1" = "triggered" ]; then
+ update-python-modules --post-install
+ exit 0
+fi
+
+# Remove the old directory.
+if [ "$1" = configure ] && dpkg --compare-versions "$2" lt-nl 0.90; then
+ rm -rf /var/lib/python-support
+fi
+
+if ! [ -e /var/lib/python-support ]; then
+ ln -sf /usr/lib/pymodules /var/lib/python-support
+fi
+
+#DEBHELPER#
+
+update-python-modules --post-install python-support.private
diff --git a/debian/postrm b/debian/postrm
new file mode 100644
index 0000000..84e953d
--- /dev/null
+++ b/debian/postrm
@@ -0,0 +1,12 @@
+#! /bin/sh
+set -e
+
+#DEBHELPER#
+
+if [ -L /var/lib/python-support ]; then
+ rm -f /var/lib/python-support
+fi
+
+if [ "$1" = "purge" ]; then
+ rm -rf /usr/lib/pymodules
+fi
diff --git a/debian/prerm b/debian/prerm
new file mode 100644
index 0000000..ccde9c3
--- /dev/null
+++ b/debian/prerm
@@ -0,0 +1,9 @@
+#! /bin/sh
+set -e
+
+#DEBHELPER#
+
+# Don't fail if this command fails, it's not important enough.
+# In this case, make the cleanup by hand.
+update-python-modules -c -b python-support.private || \
+ rm -f /usr/share/python-support/private/*.pyc
diff --git a/debian/python-support.lintian-overrides b/debian/python-support.lintian-overrides
new file mode 100644
index 0000000..84c72ac
--- /dev/null
+++ b/debian/python-support.lintian-overrides
@@ -0,0 +1 @@
+python-support: depends-on-python-minimal depends
diff --git a/debian/rules b/debian/rules
new file mode 100755
index 0000000..5a373a0
--- /dev/null
+++ b/debian/rules
@@ -0,0 +1,28 @@
+#!/usr/bin/make -f
+
+include /usr/share/cdbs/1/rules/debhelper.mk
+
+SUPP := $(shell ./parseversions --all --long)
+
+clean::
+ rm -f debhelper/dh_pysupport.1 *.pyc
+
+check:
+ dh_testdir
+ cd tests && PATH=$(CURDIR):$$PATH ./testparseversions.py
+
+maybe_check = $(if $(findstring nocheck,$(DEB_BUILD_OPTIONS)),,check)
+
+build/python-support::
+ cd debhelper && pod2man -c "python-support" -r "$(DEB_VERSION)" dh_pysupport dh_pysupport.1
+
+binary-install/python-support:: $(maybe_check)
+ for ver in $(SUPP); do \
+ subdir=dist-packages; \
+ if dpkg --compare-versions $$ver lt python2.6; then \
+ subdir=site-packages; \
+ fi; \
+ mkdir -p debian/python-support/usr/lib/$$ver/$$subdir; \
+ ln -s ../../pymodules/$$ver/.path debian/python-support/usr/lib/$$ver/$$subdir/python-support.pth; \
+ done
+
diff --git a/debian/source/format b/debian/source/format
new file mode 100644
index 0000000..89ae9db
--- /dev/null
+++ b/debian/source/format
@@ -0,0 +1 @@
+3.0 (native)
diff --git a/debian/triggers b/debian/triggers
new file mode 100644
index 0000000..cd4df7c
--- /dev/null
+++ b/debian/triggers
@@ -0,0 +1 @@
+interest pysupport
diff --git a/movemodules b/movemodules
new file mode 100755
index 0000000..61a6e4f
--- /dev/null
+++ b/movemodules
@@ -0,0 +1,237 @@
+#! /usr/bin/python
+#
+# copyright (c) 2006 Josselin Mouette <joss@debian.org>
+# Licensed under the GNU Lesser General Public License, version 2.1
+# See COPYING for details
+
+from optparse import OptionParser
+import os,os.path,re,sys
+from hashlib import md5
+
+sourcepath='usr/share/python-support'
+modulepath='usr/share/pyshared'
+extensionpath='usr/lib/pyshared'
+installedpath='usr/lib/pymodules'
+
+parser = OptionParser(usage="usage: %prog [options] [directory [...]]")
+
+parser.add_option("-v", "--verbose", action="store_true", dest="verbose",
+ help="verbose output", default=False)
+parser.add_option("-p", "--package", dest="package")
+parser.add_option("-V", "--version-info", dest="version")
+
+(options, args) = parser.parse_args()
+
+sys.path.append("/usr/share/python-support/private/")
+from pysupport import py_supported,py_supported_short
+
+# Set the umask so that directories are created with correct permissions
+os.umask(022)
+
+if not args:
+ parser.error("No directory to process.")
+
+for basedir in args:
+ if not os.path.isdir(basedir):
+ parser.error("%s is not a directory."%basedir)
+
+class filelist:
+ def __init__(self):
+ self.d={}
+ self.pylist=set()
+ def addsum(self,file,pyver,sum):
+ if file not in self.d:
+ self.d[file]={}
+ elif pyver in self.d[file] and self.d[file][pyver] != sum:
+ sys.stderr.write("WARNING: %s exists in multiple versions\n"%file)
+ self.d[file][pyver]=sum
+ def addpyver(self,pyver):
+ self.pylist.add(pyver)
+ def isallthesame(self,file):
+ if file.endswith(".so"):
+ # If there is a .so, no need to even check, it must be moved
+ return False
+ elif re.search('\.so(?:\.\d+){0,3}$', file):
+ sys.stderr.write("WARNING: %s: versioned shared object\n"%file)
+ return False
+ try:
+ s=[ self.d[file][pyver] for pyver in self.pylist ]
+ except KeyError:
+ return False
+ return (s.count(s[0]) == len(self.pylist))
+ def list(self,file):
+ return self.d[file].keys()
+ def __iter__(self):
+ return iter(self.d)
+
+# Rename by preserving relative links
+def rename_subtle (source, destination, sourcedir):
+ if os.path.islink (source):
+ linkdest = os.readlink (source)
+ if not os.path.isabs (linkdest):
+ linkdest = os.path.normpath(os.path.join(os.path.dirname(source),linkdest))
+ if not linkdest.startswith(sourcedir+'/'):
+ prefix = os.path.dirname(os.path.commonprefix((linkdest, destination)))
+ linkdest = os.path.normpath(destination)[len(prefix)+1:].count('/') * '../' + \
+ linkdest[len(prefix)+1:]
+ destdir = os.path.dirname(destination)
+ if not os.path.isdir (destdir):
+ os.makedirs (destdir)
+ if os.path.lexists (destination):
+ os.remove (destination)
+ os.symlink (linkdest, destination)
+ os.remove (source)
+ try:
+ os.removedirs(os.path.dirname(source))
+ except OSError:
+ pass
+ return
+ os.renames (source, destination)
+
+def do_simple_move (basedir, sourcedir):
+ fileset = set()
+ absdir=os.path.join(basedir, sourcedir)
+ for dir, dirs, files in os.walk (absdir):
+ reldir = dir[len(absdir):].lstrip("/")
+ for curfile in files:
+ rename_subtle (os.path.join(absdir, reldir, curfile), os.path.join(basedir, modulepath, reldir, curfile), absdir)
+ fileset.add(os.path.join("/", modulepath, reldir, curfile))
+ return fileset
+
+def do_move (basedir, tuples):
+ file_dict=filelist()
+ for (pybasedir, suffixdir) in tuples:
+ for pyvers in py_supported:
+ pydir=os.path.join(basedir,pybasedir,pyvers,suffixdir)
+ if not os.path.isdir(pydir):
+ continue
+ file_dict.addpyver(pyvers)
+ for dir, dirs, files in os.walk(pydir):
+ reldir = dir[len(pydir):].lstrip('/')
+ for curfile in files:
+ relfile = os.path.join(reldir,curfile)
+ absfile = os.path.join(pydir,relfile)
+ # remove bytecompiled files and libtool cruft
+ if relfile.split('.')[-1] in ["pyc", "pyo", "a", "la"]:
+ os.remove(absfile)
+ elif os.path.islink(absfile):
+ file_dict.addsum(relfile,pyvers,os.readlink(absfile))
+ elif absfile.endswith('/PKG-INFO') or absfile.endswith('.egg-info'):
+ # work-around for bug #575377
+ file_dict.addsum(relfile,pyvers,md5(''.join(line.strip()+'\n' for line in file(absfile))).digest())
+ else:
+ file_dict.addsum(relfile,pyvers,md5(file(absfile).read()).digest())
+
+ files = set()
+ pyversions = set()
+ for relfile in file_dict:
+ splitfile=not file_dict.isallthesame(relfile)
+ destdir=modulepath
+ for pyver in file_dict.list(relfile):
+ for (pybasedir, suffixdir) in tuples:
+ sourcedir=os.path.join(basedir,pybasedir,pyver,suffixdir)
+ sourcefile=os.path.join(sourcedir,relfile)
+ if not os.path.lexists(sourcefile):
+ continue
+ if splitfile:
+ destdir=os.path.join(extensionpath,pyver)
+ pyversions.add(pyver)
+ if sourcefile.endswith("/__init__.py") and not os.path.getsize(sourcefile):
+ # Remove namespace packages, they will be added automatically
+ # by update-python-modules.
+ # This will avoid file conflicts at the dpkg level.
+ os.remove(sourcefile)
+ try:
+ os.removedirs(os.path.dirname(sourcefile))
+ except OSError:
+ pass
+ else:
+ rename_subtle(sourcefile,os.path.join(basedir,destdir,relfile),sourcedir)
+ files.add(os.path.join("/",destdir,relfile))
+ if pyversions:
+ # If we have some versions that appear in the extension path
+ # BUT that more versions were originally supported
+ # We must add these versions to the list of supported versions
+ pyversions.update(file_dict.pylist)
+ return files, pyversions
+
+def do_listonly (basedir):
+ fileset = set()
+ absdir=os.path.join(basedir, modulepath)
+ for dir, dirs, files in os.walk (absdir):
+ reldir = dir[len(basedir):].lstrip("/")
+ for curfile in files:
+ fileset.add(os.path.join("/",reldir,curfile))
+ return fileset
+
+# Remove the -py$(VERSION) part of the egg directories
+def do_eggrename (basedir, pybasedir, suffixdir=""):
+ for vers in py_supported_short:
+ pydir=os.path.join(basedir,pybasedir,"python"+vers,suffixdir)
+ suffix="-py"+vers+".egg-info"
+ if not os.path.isdir(pydir):
+ continue
+ for item in os.listdir(pydir):
+ item=os.path.join(pydir,item)
+ if item.endswith(suffix):
+ new_item = item[:-len(suffix)]+".egg-info"
+ if not os.path.exists(new_item): # You never know
+ os.rename(item, new_item)
+
+for basedir in args:
+ basedir=basedir.rstrip('/')
+ package=options.package
+ if not package:
+ package=os.path.split(basedir)[1]
+ if not package:
+ raise Exception("Unable to extract the package name.")
+
+ public_file = os.path.join(basedir,sourcepath,package+".public")
+ if os.path.isfile (public_file):
+ # movemodules was already run, do nothing
+ sys.exit(0)
+
+ # /usr/share/pyshared (files installed by hand)
+ files = do_listonly (basedir)
+
+ # /usr/lib/pythonX.Y/site-packages (python <= 2.5)
+ # /usr/lib/pythonX.Y/dist-packages (python >= 2.6 with deb layout)
+ # /usr/local/lib/pythonX.Y/dist-packages (python >= 2.6 without deb layout)
+ do_eggrename (basedir, "usr/lib", "site-packages")
+ do_eggrename (basedir, "usr/lib", "dist-packages")
+ do_eggrename (basedir, "usr/local/lib", "dist-packages")
+ files2, pyversions = do_move (basedir, [("usr/lib", "site-packages"),
+ ("usr/lib", "dist-packages"),
+ ("usr/local/lib", "dist-packages")])
+ files.update(files2)
+
+ # /var/lib/python-support/pythonX.Y
+ do_eggrename (basedir, "var/lib/python-support")
+ files2, pyversions2 = do_move (basedir, [("var/lib/python-support", "")])
+ files.update(files2)
+ pyversions.update(pyversions2)
+
+ # /usr/lib/pymodules/pythonX.Y
+ do_eggrename (basedir, extensionpath)
+ files2, pyversions2 = do_move (basedir, [(installedpath, "")])
+ files.update(files2)
+ pyversions.update(pyversions2)
+
+ # /usr/share/python-support/$package
+ if os.path.isdir(os.path.join(basedir,"usr/share/python-support")):
+ for ent in os.listdir(os.path.join(basedir,"usr/share/python-support")):
+ if os.path.isdir(os.path.join(basedir, "usr/share/python-support", ent)):
+ files.update(do_simple_move(basedir, os.path.join("usr/share/python-support", ent)))
+
+ if files:
+ if not os.path.isdir(os.path.join(basedir,sourcepath)):
+ os.makedirs(os.path.join(basedir,sourcepath))
+ out=file(public_file, "w")
+ if pyversions:
+ out.write("pyversions=%s\n\n"%(','.join(x.replace('python','') for x in sorted(pyversions))))
+ elif options.version:
+ out.write("pyversions=%s\n\n"%options.version)
+ for filename in sorted(files):
+ out.write(filename+"\n")
+ out.close()
+
diff --git a/parseversions b/parseversions
new file mode 100755
index 0000000..896d129
--- /dev/null
+++ b/parseversions
@@ -0,0 +1,103 @@
+#! /usr/bin/python
+#
+# copyright (c) 2006 Josselin Mouette <joss@debian.org>
+# Licensed under the GNU Lesser General Public License, version 2.1
+# See COPYING for details
+
+from optparse import OptionParser
+import sys,os.path
+sys.path.append("/usr/share/python-support/private/")
+import pysupport
+
+parser = OptionParser(usage="usage: %prog [options] file.pyversions")
+
+parser.add_option ("--minmax", action="store_true", dest="minmax", help="display minimum and maximum python versions described by the file", default=False)
+parser.add_option ("-l", "--long", action="store_true", dest="long", help='prepend versions with "python"',default=False)
+parser.add_option ("--pycentral", action="store_true", dest="pycentral", help="Parse a pycentral-type version string instead",default=False)
+parser.add_option ("--raw", action="store_true", dest="raw", help="Output the raw input string (useful with --pycentral)",default=False)
+parser.add_option ("--all", action="store_true", dest="all", help="List all supported versions instead of parsing a file",default=False)
+
+(options, args) = parser.parse_args()
+
+if options.all:
+ f=iter(['-'])
+else:
+ if len(args) < 1:
+ f=sys.stdin
+ else:
+ f=file(args[0])
+
+if options.pycentral:
+ import re
+ l=None
+ paraborder=True
+ for line in f:
+ line=line.strip()
+ if line.startswith('#') or not line: # Empty line or comment
+ if paraborder==True:
+ # We're at the beginning of debian/control
+ continue
+ # We reached the end of the first paragraph, don't keep on reading
+ break
+ paraborder=False
+ if line.lower().startswith(("xs-python-version:", "x-python-version:")):
+ l=line.split(':')[1]
+ break
+ if not l:
+ print "X(S)-Python-Version header not found."
+ sys.exit(1)
+ min=max=""
+ out=[]
+ for elem in l.split(','):
+ elem=elem.strip()
+ if elem=="all":
+ min=max=""
+ out=["-"]
+ break
+ if elem=="current":
+ out.append(os.readlink("/usr/bin/python")[6:])
+ continue
+ a=re.match(">=\s*([\d\.]+)",elem)
+ if a:
+ min=a.group(1)
+ continue
+ a=re.match("<<\s*([\d\.]+)",elem)
+ if a:
+ try:
+ max=a.group(1).split(".")
+ max[1]=`int(max[1])-1`
+ max='.'.join(max)
+ except IndexError:
+ max=""
+ continue
+ a=re.match("^[\d\.]+$",elem)
+ if a:
+ out.append(elem)
+ if min or max:
+ out.append(min+"-"+max)
+ stringtoparse=','.join(out)
+else:
+ stringtoparse=f.next()
+ if stringtoparse.startswith("pyversions") and "=" in stringtoparse:
+ # Case of a .public file with version info
+ stringtoparse = stringtoparse.split("=",1)[1]
+ elif stringtoparse.startswith("/"):
+ # Case of a .public file without version info
+ stringtoparse = "-"
+
+if options.raw:
+ print stringtoparse.rstrip('\n')
+ sys.exit(0)
+
+v=pysupport.version_list(stringtoparse)
+if options.long:
+ print ' '.join(v)
+else:
+ print ' '.join(v.verlist)
+
+if options.minmax:
+ min=v.min
+ if options.long and min: min="python"+min
+ max=v.max
+ if options.long and max: max="python"+max
+ print min, max
diff --git a/pysupport.py b/pysupport.py
new file mode 100644
index 0000000..4666f4b
--- /dev/null
+++ b/pysupport.py
@@ -0,0 +1,55 @@
+import os
+from ConfigParser import SafeConfigParser
+
+config = SafeConfigParser()
+config.readfp(file('/usr/share/python/debian_defaults'))
+versions = config.get('DEFAULT', 'supported-versions')
+py_supported = [s.strip() for s in versions.split(',')]
+versions = config.get('DEFAULT', 'old-versions')
+py_oldversions = [s.strip() for s in versions.split(',')]
+
+py_installed = [ ver for ver in py_supported if os.access('/usr/bin/'+ver,os.X_OK) ]
+py_supported_short = [ a.replace("python","") for a in py_supported ]
+
+def version_cmp(ver1,ver2):
+ v1=[int(i) for i in ver1.split('.')]
+ v2=[int(i) for i in ver2.split('.')]
+ return cmp(v1,v2)
+
+# Parse the version format from .version files
+class version_list(list):
+ def __init__(self,version_info):
+ self.verlist=[]
+ dummylist=[]
+ for item in version_info.rstrip('\n').split(','):
+ v=[i.strip() for i in item.split('-')]
+ if len(v)>1:
+ if v[0]:
+ dummylist.append(v[0])
+ else:
+ v[0] = py_supported_short[0]
+ dummylist.append("0")
+ if v[1]:
+ dummylist.append(v[1])
+ else:
+ v[1] = py_supported_short[-1]
+ dummylist.append("100")
+ for ver in py_supported_short:
+ try:
+ if version_cmp(ver,v[0]) >= 0 and version_cmp(ver,v[1]) <= 0:
+ self.verlist.append(ver)
+ except ValueError:
+ pass
+ else:
+ dummylist.append(v[0])
+ if v[0] in py_supported_short:
+ self.verlist.append(v[0])
+ self.verlist.sort(version_cmp)
+ dummylist.sort(version_cmp)
+ self.min=dummylist[0]
+ if self.min=="0": self.min=None
+ self.max=dummylist[-1]
+ if self.max=="100": self.max=None
+ for i in self.verlist:
+ self.append('python'+i)
+
diff --git a/python-support.private b/python-support.private
new file mode 100644
index 0000000..030ce0b
--- /dev/null
+++ b/python-support.private
@@ -0,0 +1 @@
+/usr/share/python-support/private/pysupport.py
diff --git a/runtime/python-support.rtinstall b/runtime/python-support.rtinstall
new file mode 100755
index 0000000..a84f8fc
--- /dev/null
+++ b/runtime/python-support.rtinstall
@@ -0,0 +1,3 @@
+#! /bin/sh
+set -e
+exec /usr/sbin/update-python-modules
diff --git a/runtime/python-support.rtremove b/runtime/python-support.rtremove
new file mode 100755
index 0000000..692ff1c
--- /dev/null
+++ b/runtime/python-support.rtremove
@@ -0,0 +1,6 @@
+#! /bin/sh
+set -e
+
+pyversion="$2"
+
+rm -rf /usr/lib/pymodules/"$2"
diff --git a/runtime/python-support.rtupdate b/runtime/python-support.rtupdate
new file mode 100755
index 0000000..4f1b431
--- /dev/null
+++ b/runtime/python-support.rtupdate
@@ -0,0 +1,6 @@
+#! /bin/sh
+set -e
+
+if [ "$1" = rtupdate ]; then
+ exec /usr/sbin/update-python-modules -a
+fi
diff --git a/tests/testparseversions.leading-newline.control b/tests/testparseversions.leading-newline.control
new file mode 100644
index 0000000..b0b5a10
--- /dev/null
+++ b/tests/testparseversions.leading-newline.control
@@ -0,0 +1,6 @@
+# comment
+
+Source: source
+XS-Python-Version: >= 2.6
+
+Package: package
diff --git a/tests/testparseversions.missing.control b/tests/testparseversions.missing.control
new file mode 100644
index 0000000..cf6b7fc
--- /dev/null
+++ b/tests/testparseversions.missing.control
@@ -0,0 +1,3 @@
+Source: source
+
+Package: package
diff --git a/tests/testparseversions.nonexported.control b/tests/testparseversions.nonexported.control
new file mode 100644
index 0000000..a8681ff
--- /dev/null
+++ b/tests/testparseversions.nonexported.control
@@ -0,0 +1,4 @@
+Source: source
+X-Python-Version: >= 2.6
+
+Package: package
diff --git a/tests/testparseversions.py b/tests/testparseversions.py
new file mode 100755
index 0000000..4da7084
--- /dev/null
+++ b/tests/testparseversions.py
@@ -0,0 +1,40 @@
+#!/usr/bin/python
+
+import unittest
+import subprocess
+
+class TestParseVersions(unittest.TestCase):
+ @staticmethod
+ def get_output(args):
+ subp = subprocess.Popen(args, stdout=subprocess.PIPE)
+ output = subp.communicate()[0]
+ if subp.returncode != 0:
+ raise RuntimeError, subp.returncode
+ return output
+
+ def pv_output(self, control):
+ return TestParseVersions.get_output(["parseversions", "--pycentral", control])
+
+ def test_regular(self):
+ self.assertEqual(self.pv_output('testparseversions.regular.control'),
+ TestParseVersions.get_output(['pyversions', '--supported', '-v']))
+
+ def test_nonexported(self):
+ self.assertEqual(self.pv_output('testparseversions.nonexported.control'),
+ TestParseVersions.get_output(['pyversions', '--supported', '-v']))
+
+ def test_leading_newline(self):
+ self.assertEqual(self.pv_output('testparseversions.leading-newline.control'),
+ TestParseVersions.get_output(['pyversions', '--supported', '-v']))
+
+ def test_missing(self):
+ self.assertRaises(RuntimeError, self.pv_output, 'testparseversions.missing.control')
+
+ def test_second_paragraph(self):
+ self.assertRaises(RuntimeError, self.pv_output, 'testparseversions.second-paragraph.control')
+
+ def test_spaces(self):
+ self.assertRaises(RuntimeError, self.pv_output, 'testparseversions.spaces.control')
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/testparseversions.pyc b/tests/testparseversions.pyc
new file mode 100644
index 0000000..a67f9bc
--- /dev/null
+++ b/tests/testparseversions.pyc
Binary files differ
diff --git a/tests/testparseversions.regular.control b/tests/testparseversions.regular.control
new file mode 100644
index 0000000..549d386
--- /dev/null
+++ b/tests/testparseversions.regular.control
@@ -0,0 +1,4 @@
+Source: source
+XS-Python-Version: >= 2.6
+
+Package: package
diff --git a/tests/testparseversions.second-paragraph.control b/tests/testparseversions.second-paragraph.control
new file mode 100644
index 0000000..6d205a6
--- /dev/null
+++ b/tests/testparseversions.second-paragraph.control
@@ -0,0 +1,4 @@
+Source: source
+
+Package: package
+XS-Python-Version: >= 2.6
diff --git a/tests/testparseversions.spaces.control b/tests/testparseversions.spaces.control
new file mode 100644
index 0000000..f19eea3
--- /dev/null
+++ b/tests/testparseversions.spaces.control
@@ -0,0 +1,4 @@
+Source: source
+
+XS-Python-Version: >= 2.4
+Package: package
diff --git a/update-python-modules b/update-python-modules
new file mode 100755
index 0000000..ddbeaab
--- /dev/null
+++ b/update-python-modules
@@ -0,0 +1,502 @@
+#! /usr/bin/python
+#
+# copyright (c) 2006 Josselin Mouette <joss@debian.org>
+# Licensed under the GNU Lesser General Public License, version 2.1
+# See COPYING for details
+
+# Everything prefixed by old_ is compatibility code with older versions
+# Modules used to lie in /usr/{lib,share}/python-support/$package
+# They now lie in /usr/{lib,share}/pyshared
+
+import sys,os,shutil
+from optparse import OptionParser
+from subprocess import call
+from py_compile import compile, PyCompileError
+sys.path.append("/usr/share/python-support/private/")
+import pysupport
+from pysupport import py_supported,py_installed,py_oldversions
+
+basepath='/usr/lib/pymodules'
+sourcepath='/usr/share/python-support'
+old_extensionpath='/usr/lib/python-support'
+shared_path='/usr/share/pyshared'
+shared_extensionpath='/usr/lib/pyshared'
+
+parser = OptionParser(usage="usage: %prog [-v] [-c] package_directory [...]\n"+
+ " %prog [-v] [-c] package.dirs [...]\n"+
+ " %prog [-v] [-a|-f|-p]")
+parser.add_option("-v", "--verbose", action="store_true", dest="verbose",
+ help="verbose output", default=False)
+parser.add_option("-c", "--clean", action="store_true", dest="clean_mode",
+ help="clean modules instead of compiling them",
+ default=False)
+parser.add_option("-a", "--rebuild-all", action="store_true",
+ dest="rebuild_all", default=False,
+ help="rebuild all private modules for a new default python version")
+parser.add_option("-f", "--force-rebuild-all", action="store_true",
+ dest="rebuild_everything", default=False,
+ help="rebuild all modules, including public modules for all python versions")
+parser.add_option("-p", "--post-install", action="store_true", dest="post_install",
+ help="run post-installation operations, common to many packages",
+ default=False)
+parser.add_option("-b", "--bytecompile", action="store_true", dest="force_private",
+ help="[deprecated] byte-compilation mode: only handle private modules",
+ default=False)
+parser.add_option("-i", "--install", action="store_true", dest="force_public",
+ help="[deprecated] installation mode: only handle public modules",
+ default=False)
+(options, args) = parser.parse_args()
+
+def debug(x):
+ if(options.verbose):
+ print x
+
+def warning(x):
+ sys.stderr.write("WARNING: %s\n"%x)
+
+def isect(l1,l2):
+ return [i for i in l1 if i in l2]
+
+def concat(l1,l2):
+ return l1 + [i for i in l2 if i not in l1]
+
+
+# Abstract class implementing the methods related to public modules
+class _PublicList (list):
+ pyversions = py_supported
+ def install (self, versions):
+ versions = isect (self.pyversions, versions)
+ for filename in self:
+ version = None
+ rng = versions
+ try:
+ if filename.startswith (shared_path+"/"):
+ # New layout, module
+ relname = filename[len(shared_path)+1:]
+ elif filename.startswith (shared_extensionpath+"/python"):
+ # New layout, extension
+ [ version, relname ] = filename[len(shared_extensionpath)+1:].split("/", 1)
+ elif filename.startswith (sourcepath+"/"):
+ [ package, relname ] = filename[len(sourcepath)+1:].split("/",1)
+ elif filename.startswith (old_extensionpath+"/"):
+ [ package, version, relname ] = filename[len(old_extensionpath)+1:].split("/",2)
+ else:
+ raise ValueError
+ except ValueError:
+ warning ("%s contains an invalid filename (%s)"%(self.name, filename))
+ continue
+ if version:
+ if version not in versions:
+ continue
+ rng = [version]
+ for pyversion in rng:
+ destpath = os.path.join (basepath, pyversion, relname)
+ try:
+ os.makedirs(os.path.dirname(destpath))
+ except OSError:
+ pass
+ if filename[-4:] not in ['.pyc', '.pyo']:
+ debug("link "+destpath)
+ # os.path.exists returns False for broken symbolic links
+ if os.path.exists(destpath) or os.path.islink(destpath):
+ if file!="__init__.py" or (os.path.exists(destpath) and os.path.getsize(destpath)):
+ # The file is already here, probably from the previous version.
+ # No need to check for conflicts, dpkg catches them earlier now
+ debug("overwrite "+destpath)
+ else:
+ debug("overwrite namespace "+destpath)
+ if os.path.isdir(destpath):
+ shutil.rmtree(destpath)
+ else:
+ os.remove(destpath)
+ os.symlink(filename,destpath)
+
+
+# Abstract class implementing the methods related to private modules
+class _PrivateList (list):
+ pyversion = None
+ def bytecompile (self):
+ if self.pyversion:
+ debug("Byte-compilation of whole %s with python%s..."%(self.name,self.pyversion))
+ call(['/usr/bin/python'+self.pyversion,
+ os.path.join('/usr/lib','python'+self.pyversion,'py_compile.py')]
+ + self)
+ else:
+ for filename in self:
+ debug("compile "+filename+'c')
+ try:
+ # Note that compile doesn't raise PyCompileError by default
+ compile(filename, doraise=True)
+ except IOError, (errno, strerror):
+ warning("I/O error while trying to byte-compile %s (%s): %s" % (filename, errno, strerror))
+ except PyCompileError, inst:
+ warning("compile error while trying to byte-compile %s: %s" % (filename, inst.msg))
+ except:
+ warning("unexpected error while trying to byte-compile %s: %s" % (filename, sys.exc_info()[0]))
+ def clean(self):
+ for filename in self:
+ for ext in ['c', 'o']:
+ fullpath=filename+ext
+ if os.path.exists(fullpath):
+ debug("remove "+fullpath)
+ os.remove(fullpath)
+
+
+# Abstract class for PrivateFileList and SharedFileList
+class _FileList(list):
+ def __init__ (self, path):
+ self.name = path
+ for line in file(path):
+ line = line.strip()
+ if (not line) or line.startswith('#'):
+ continue
+ if line.startswith('/'):
+ self.append(line)
+ continue
+ line = [x.strip() for x in line.split('=',1)]
+ if len(line) != 2:
+ warning("Parse error in %s"%path)
+ continue
+ self.parse_option(*line)
+
+# This class represents a file list as provided in the /usr/share/python-support/$package.public
+# Useful for public modules and extensions
+class SharedFileList(_FileList, _PublicList):
+ def parse_option (self, arg, value):
+ if arg=='pyversions':
+ self.pyversions = pysupport.version_list(value)
+ # Ignore unknown arguments for extensivity
+
+# This class represents a file list as provided in the /usr/share/python-support/$package.private
+# Useful for private modules
+class PrivateFileList(_FileList, _PrivateList):
+ def parse_option (self, arg, value):
+ if arg=='pyversion':
+ self.pyversion = value
+
+# This is a helper generator that goes through files of interest in a given directory
+def allfiles(path, onlypy=False):
+ for root, dirs, files in os.walk(path):
+ for f in files:
+ if (onlypy and not f.endswith(".py")) or f== ".version":
+ continue
+ yield os.path.join(root,f)
+ if not onlypy:
+ for d in dirs:
+ d = os.path.join(root, d)
+ if os.path.islink(d):
+ yield d
+
+# This class emulates the file listing as provided by /usr/share/python-support/$package.public
+# with the deprecated layout /usr/{lib,share}/python-support/$package/
+class SharedDirList(_PublicList):
+ def __init__ (self, path):
+ self.name = path
+ # Add all files to the file listing
+ self.extend(allfiles(path))
+ verfile=os.path.join(path,'.version')
+ extdir=path.replace(sourcepath,old_extensionpath,1)
+ if os.path.isfile(verfile):
+ # If we have a .version, use it
+ self.pyversions = pysupport.version_list(file(verfile).readline())
+ elif os.path.isdir(extdir):
+ # Try to obtain the list of supported versions
+ # from the extensions in /usr/lib
+ self.pyversions = isect(py_supported,os.listdir(extdir))
+ else:
+ # Otherwise, support all versions
+ pass
+
+ if os.path.isdir(extdir):
+ # Add the extensions to the file listing
+ for version in self.pyversions:
+ self.extend(allfiles(os.path.join(extdir,version)))
+
+# This class emulates the file listing as provided by /usr/share/python-support/$package.private
+# with the deprecated layout /usr/share/python-support/$package.dirs
+class PrivateDirList(_PrivateList):
+ def __init__ (self, path):
+ self.name = path
+ self.extend(allfiles(path, onlypy=True))
+ versionfile = os.path.join(path, ".pyversion")
+ if os.path.isfile(versionfile):
+ self.pyversion = file(versionfile).readline().strip()
+
+
+class CachedFileList(dict):
+ def __getitem__ (self, name):
+ if name in self and dict.__getitem__(self, name) == None:
+ if name.startswith("/"):
+ # The case of old-style private directories
+ self[name] = PrivateDirList (name)
+ else:
+ path = os.path.join (sourcepath, name)
+ if name.endswith(".public"):
+ self[name] = SharedFileList (path)
+ elif name.endswith(".private"):
+ self[name] = PrivateFileList (path)
+ elif os.path.isdir(path):
+ self[name] = SharedDirList (path)
+ else:
+ raise Exception("[Internal Error] I don't know what to do with this path: %s"%path)
+ return dict.__getitem__(self, name)
+
+
+def bytecompile_all(py,path=None):
+ if not path:
+ path=os.path.join(basepath,py)
+ if not os.path.isdir(path):
+ return
+ debug("Byte-compilation of whole %s..."%path)
+ os.spawnl(os.P_WAIT, '/usr/bin/'+py, py,
+ os.path.join('/usr/lib/',py,'compileall.py'), '-q', path)
+
+# A function to create the ".path" at the root of the installed directory
+# Returns the list of affected directories
+def create_dotpath(py):
+ path=os.path.join(basepath,py)
+ if not os.path.isdir(path):
+ return
+ pathfile=os.path.join(path,".path")
+ debug("Generation of %s..."%pathfile)
+ pathlist=[path]
+ ret=[]
+ for f in os.listdir(path):
+ f=os.path.join(path,f)
+ if f.endswith(".pth") and os.path.isfile(f):
+ for l in file(f):
+ l=l.rstrip('\n')
+ if l.startswith('import'):
+ # Do not ship lines starting with "import", they are executed! (complete WTF)
+ continue
+ pathlist.append(l)
+ l2=os.path.join(path,l)
+ pathlist.append(l2)
+ ret.append(l2)
+ fd=file(pathfile,"w")
+ fd.writelines([l+'\n' for l in pathlist])
+ fd.close()
+ return ret
+
+def post_change_stuff(py):
+ # All the changes that need to be done after anything has changed
+ # in a /usr/lib/pymodules/pythonX.Y directory
+ # * Cleanup of all dangling symlinks that are left out after a package
+ # is upgraded/removed.
+ # * The namespace packages are here because python doesn't consider a
+ # directory to be able to contain packages if there is no __init__.py
+ # file (yes, this is completely stupid).
+ # * The .path file must be created by concatenating all those .pth
+ # files that extend sys.path (this also badly sucks).
+ # * Byte-compilation of all .py files that haven't already been
+ path=os.path.join(basepath,py)
+ if not os.path.isdir(path):
+ return
+ # First, remove any dangling symlinks.
+ # In the same loop, we find which directories may need a namespace package
+ dirhash={}
+ for dir, dirs, files in os.walk(path):
+ dirhash[dir]=False
+ files.sort() # We need the .py to appear before the .pyc
+ for f in files+dirs:
+ # We also examine dirs as some symlinks are dirs
+ abspath=os.path.join(dir,f)
+ islink=os.path.islink(abspath)
+ if islink:
+ if not os.path.exists(abspath):
+ # We refer to a file that was removed
+ debug("remove "+abspath)
+ os.remove(abspath)
+ continue
+ srcfile = os.readlink (abspath)
+ # Remove links left here after a change in the supported python versions for a package
+ removed = False
+ for package in public_packages:
+ if srcfile in public_packages[package]:
+ if py not in public_packages[package].pyversions:
+ debug("remove "+abspath)
+ os.remove(abspath)
+ removed = True
+ break
+ else:
+ # Remove files provided by packages that do not use python-support anymore
+ debug("remove "+abspath)
+ os.remove(abspath)
+ removed = True
+ if removed:
+ # Do not go further, the file was removed
+ continue
+ if f[-4:] in ['.pyc', '.pyo']:
+ if not os.path.exists(abspath[:-1]):
+ debug("remove "+abspath)
+ os.remove(abspath)
+ continue
+ elif f[-3:] in ['.py', '.so']:
+ if islink or f!='__init__.py':
+ # List the directory as maybe needing a namespace packages
+ d=dir
+ while dirhash.has_key(d) and not dirhash[d]:
+ dirhash[d]=True
+ d=os.path.dirname(d)
+ # Remove the directory if it is empty after our crazy removals
+ try:
+ os.removedirs(dir)
+ except OSError:
+ pass
+ dirhash[path]=False
+ # Then, find which directories belong in a .pth file
+ # These directories don't need a namespace package, so we
+ # set them to False in dirhash
+ for p in create_dotpath (py):
+ dirhash[p] = False
+ # Finally, create/remove namespace packages
+ for dir in dirhash:
+ initfile=os.path.join(dir,"__init__.py")
+ noinitfile=os.path.join(dir,".noinit")
+ if dirhash[dir] and not os.path.exists(noinitfile):
+ if not os.path.exists(initfile):
+ debug("create namespace "+initfile)
+ file(initfile,"w").close()
+ else:
+ for e in ['','c','o']:
+ if os.path.exists(initfile+e):
+ debug('remove namespace '+initfile+e)
+ os.remove(initfile+e)
+ try:
+ os.removedirs(dir)
+ except OSError:
+ pass
+ bytecompile_all(py)
+
+
+# A helper function for older $package.dirs files
+def dirlist_file(f):
+ return [ l.rstrip('\n') for l in file(f) if len(l)>1 ]
+
+# End of function definitions - Start of the script itself
+
+# Ensure that the umask is sane
+os.umask(022)
+
+# Read all modules listing
+public_packages = CachedFileList()
+private_packages = CachedFileList()
+dirlisting = os.listdir(sourcepath)
+for name in dirlisting:
+ path=os.path.join(sourcepath,name)
+ if name == "private":
+ continue
+ ext = name.split(".")[-1]
+ if os.path.isdir(path):
+ if ext in ["public", "private", "dirs"]:
+ # Presumably a bogus directory, see #528130
+ warning("%s is a directory"%name)
+ else:
+ public_packages[name] = None
+ continue
+ if not os.path.isfile(path):
+ # Ignore whatever is not a file, like dangling symlinks
+ continue
+ if ext == "public":
+ public_packages[name] = None
+ elif ext == "private":
+ private_packages[name] = None
+ elif ext == "dirs":
+ for dirname in dirlist_file (path):
+ private_packages[dirname] = None
+ # Just ignore all other files
+
+# Parse arguments
+do_public=[]
+do_private=[]
+for arg in args:
+ if arg.startswith(sourcepath):
+ arg = arg[len(sourcepath):].lstrip("/")
+ if arg.endswith(".dirs") and arg in dirlisting:
+ for dirname in dirlist_file(os.path.join(sourcepath, arg)):
+ do_private.append(private_packages[dirname])
+ elif arg in public_packages:
+ do_public.append(public_packages[arg])
+ elif arg in private_packages:
+ do_private.append(private_packages[arg])
+ else:
+ if options.clean_mode:
+ warning("%s does not exist.\n Some bytecompiled files may be left behind."%arg)
+ else:
+ parser.error("%s is not a recognized python-support module."%arg)
+
+# Check consistency options (although these ones should not exist anymore)
+if do_private and options.force_public:
+ parser.error("Option -i cannot be used with a .private module file.")
+if do_public and options.force_private:
+ parser.error("Option -b cannot be used with a .public module file.")
+
+if options.rebuild_everything:
+ options.rebuild_all = True
+ for pyver in py_supported:
+ dir = os.path.join(basepath,pyver)
+ if os.path.isdir(dir):
+ shutil.rmtree(dir)
+
+# Check for changes in installed python versions
+need_postinstall = []
+for pyver in py_oldversions+py_supported:
+ dir = os.path.join(basepath,pyver)
+ # Check for ".path" because sometimes the directory already exists
+ # while the python version isn't installed, because of some .so's.
+ if pyver not in py_installed and os.path.isdir(dir):
+ debug("Removing obsolete directory %s..."%(dir))
+ shutil.rmtree(dir)
+ if pyver in py_installed and not os.path.isfile(os.path.join(dir,".path")):
+ need_postinstall.append(pyver)
+if need_postinstall:
+ debug("Building all modules for %s..."%(" ".join(need_postinstall)))
+ for package in public_packages:
+ public_packages[package].install(need_postinstall)
+ for pyver in need_postinstall:
+ # Here we need to launch create_dotpath because otherwise we could
+ # end up without the .path file that is checked 6 lines earlier
+ create_dotpath(pyver)
+
+if options.rebuild_all:
+ for package in private_packages:
+ private_packages[package].bytecompile()
+
+
+# Now for the processing of what was handed on the command line
+for package in do_private:
+ if not options.clean_mode:
+ package.bytecompile()
+ else:
+ package.clean()
+
+need_dotpath = False
+for package in do_public:
+ need_postinstall = concat (need_postinstall, isect(package.pyversions,py_installed))
+ if options.clean_mode:
+ continue
+ package.install(py_installed)
+ for f in package:
+ if f.endswith(".pth"):
+ need_dotpath = True
+
+# Only do the funny and time-consuming things when the -p option is
+# given, e.g when python-support is triggered.
+if need_postinstall and 'DPKG_RUNNING_VERSION' in os.environ and not options.post_install:
+ ret = os.spawnlp(os.P_WAIT, 'dpkg-trigger', 'dpkg-trigger', '--no-await', 'pysupport')
+ if ret:
+ sys.stderr.write("ERROR: dpkg-trigger failed\n")
+ sys.exit(1)
+ if need_dotpath:
+ for py in need_postinstall:
+ create_dotpath (py)
+ need_postinstall = []
+
+if options.post_install:
+ # The trigger has been activated; do it for all installed versions
+ need_postinstall = py_installed
+if need_postinstall:
+ need_dotpath = False
+ for py in need_postinstall:
+ post_change_stuff(py)
+
diff --git a/update-python-modules.8 b/update-python-modules.8
new file mode 100644
index 0000000..ca8f269
--- /dev/null
+++ b/update-python-modules.8
@@ -0,0 +1,84 @@
+.TH UPDATE-PYTHON-MODULES 8 "18 Feb 2009"
+.\" Please adjust this date whenever revising the manpage.
+.SH NAME
+update-python-modules \- byte-compile python modules
+.SH SYNOPSIS
+.B update-python-modules
+.RI [ options "] [" package.public " [...]]"
+.SH DESCRIPTION
+The
+.B update-python-modules
+command is part of the
+.B python-support
+bundle.
+.PP
+.B update-python-modules
+is responsible for the byte-compilation of python modules. When used in
+byte-compilation mode, it will byte-compile modules references in the
+files given on the command line. When used in installation mode, it will
+byte-compile them once for each installed python version, and will make
+them available for all of them.
+.PP
+At each invocation, with or without arguments,
+.B update-python-modules
+will check for installed python versions, and will build or remove
+modules according to new or removed versions since the last time it was
+run.
+.SH ARGUMENTS
+Arguments must be files or directories located in the
+.I /usr/share/python-support
+directory. Depending on their extension, they are treated differently.
+.TP
+.IR package .public
+A file listing public modules to install for each version. These modules
+must lie in
+.I /usr/share/pyshared
+or
+.IR /usr/lib/pyshared .
+.TP
+.IR package .private
+A file listing private modules to byte-compile for one Python version.
+.TP
+.IR package /
+A legacy directory hierarchy of public modules. The C extensions and
+portions that change with the Python version are to be found in
+.IR /usr/lib/python-support/python X.Y / package / .
+.TP
+.IR package.dirs
+A legacy file listing directories where to find private modules.
+.SH OPTIONS
+.TP
+.B \-h, \-\-help
+Show summary of options.
+.TP
+.B \-v, \-\-verbose
+Detail all actions while they are performed.
+.TP
+.B \-b, \-\-bytecompile
+Only accept to work on private modules. When given this option,
+.B update-python-modules
+will fail if passed references to public modules.
+.TP
+.B \-i, \-\-install
+Only accept to work on public modules. When given this option,
+.B update-python-modules
+will fail if passed references to public modules.
+.TP
+.B \-c, \-\-clean
+Clean modules instead of installing them.
+.TP
+.B \-a, \-\-rebuild\-all
+Rebuild all private modules. This is necessary when the default python
+version was changed, for example.
+\.TP
+.B \-f, \-\-force\-rebuild\-all
+Clean all modules (public and private), and rebuild them.
+.SH FILES
+.TP
+.IR /usr/lib/pymodules/python X.Y /
+These directories contain the byte-compiled modules for version
+.RI python X.Y .
+.SH SEE ALSO
+/usr/share/doc/python-support/README.gz
+.SH AUTHOR
+Josselin Mouette <joss@debian.org>.