summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCoprDistGit <infra@openeuler.org>2025-02-04 07:51:09 +0000
committerCoprDistGit <infra@openeuler.org>2025-02-04 07:51:09 +0000
commit7e40c2d2d98727867a250dba5c962b78727eef26 (patch)
tree594d7e5e1978d504523028946a1adfaf07673f7e
parent2970a8685236bf3143f35d221bab53a4dd988e25 (diff)
automatic import of python-rpm-generatorsopeneuler24.03_LTS_SP1
-rw-r--r--COPYING842
-rw-r--r--python-rpm-generators.spec65
-rw-r--r--python.attr31
-rwxr-xr-xpythonbundles.py94
-rw-r--r--pythondist.attr3
-rw-r--r--pythondistdeps.py626
-rw-r--r--sources0
7 files changed, 1661 insertions, 0 deletions
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..3ffa0ab
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,842 @@
+RPM and it's source code are covered under two separate licenses.
+
+The entire code base may be distributed under the terms of the GNU General
+Public License (GPL), which appears immediately below. Alternatively,
+all of the source code in the lib subdirectory of the RPM source code
+distribution as well as any code derived from that code may instead be
+distributed under the GNU Library General Public License (LGPL), at the
+choice of the distributor. The complete text of the LGPL appears
+at the bottom of this file.
+
+This alternatively is allowed to enable applications to be linked against
+the RPM library (commonly called librpm) without forcing such applications
+to be distributed under the GPL.
+
+Any questions regarding the licensing of RPM should be addressed to
+rpm-maint@lists.rpm.org
+
+---------------------------------------------------------------------------
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, 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 or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+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 give any other recipients of the Program a copy of this License
+along with the Program.
+
+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 Program or any portion
+of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+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 Program, 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 Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) 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; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, 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 executable. However, as a
+special exception, the source code 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.
+
+If distribution of executable or 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 counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program 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.
+
+ 5. 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 Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program 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 to
+this License.
+
+ 7. 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 Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program 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 Program.
+
+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.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program 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.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the 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 Program
+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 Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, 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
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), 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 Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. 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 program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
+
+---------------------------------------------------------------------------
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, 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 library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ 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 Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it. You can use it for
+your libraries, too.
+
+ When we speak of free software, we are referring to freedom, 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 or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the 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 a program 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.
+
+ Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library. If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software. To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs. This
+license, the GNU Library General Public License, applies to certain
+designated libraries. This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+ The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it. Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program. However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+ Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries. We
+concluded that weaker conditions might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them. (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.) The hope is that this
+will lead to faster development of free libraries.
+
+ 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, while the latter only
+works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+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 compile 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) 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.
+
+ c) 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.
+
+ d) 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 source code 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 to
+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 Library 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
+
+ Appendix: 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 Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, 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/python-rpm-generators.spec b/python-rpm-generators.spec
new file mode 100644
index 0000000..048578e
--- /dev/null
+++ b/python-rpm-generators.spec
@@ -0,0 +1,65 @@
+Name: python-rpm-generators
+Version: 14
+Release: 1
+Summary: Dependency generators for Python RPMs
+
+License: GPL-2.0-or-later AND LGPL-2.1-or-later
+URL: https://src.fedoraproject.org/rpms/python-rpm-generators
+Source0: https://raw.githubusercontent.com/rpm-software-management/rpm/102eab50b3d0d6546dfe082eac0ade21e6b3dbf1/COPYING
+Source1: python.attr
+Source2: pythondist.attr
+# This one is also originally from RPM, but it has its own license declaration: LGPL-2.1-or-later
+Source3: pythondistdeps.py
+Source4: pythonbundles.py
+
+BuildArch: noarch
+
+%description
+Fedora's dependency generators for Python RPMS.
+
+%package -n python3-rpm-generators
+Summary: %{summary}
+Requires: python3-packaging
+Requires: rpm > 4.15.90
+Conflicts: rpm-build < 4.13.0.1-2
+Conflicts: python-rpm-macros < 3-35
+
+%description -n python3-rpm-generators
+Fedora's dependency generators for Python RPMS.
+
+%prep
+%autosetup -c -T
+cp -a %{sources} .
+
+%install
+install -Dpm0644 -t %{buildroot}%{_fileattrsdir} *.attr
+install -Dpm0755 -t %{buildroot}%{_rpmconfigdir} *.py
+
+%files -n python3-rpm-generators
+%license COPYING
+%{_fileattrsdir}/python.attr
+%{_fileattrsdir}/pythondist.attr
+%{_rpmconfigdir}/pythondistdeps.py
+%{_rpmconfigdir}/pythonbundles.py
+
+%changelog
+* Fri Jan 03 2025 Funda Wang <fundawang@yeah.net> - 14-1
+- update to latest upstream version
+
+* Tue Aug 06 2024 chenhuihan <chenhuihan@huawei.com> - 9-5
+- Fix python provide and requires
+
+* Sun Apr 23 2023 caodongxia <caodongxia@h-partners.com> - 9-4
+- Fix the python3 version cannot be found when pyproject.toml is used for building
+
+* Thu Oct 27 2022 zhangruifang <zhangruifang1@h-partners.com> - 9-3
+- Rebuild for next release
+
+* Fri Jan 07 2022 shixuantong <shixuantong@huawei.com> - 9-2
+- downgrade version to 9
+
+* Thu Dec 09 2021 liudabo <liudabo1@huawei.com> - 12-1
+- upgrade version to 12
+
+* Tue Sep 17 2019 openEuler Buildteam <buildteam@openeuler.org> - 9-1
+- Package init
diff --git a/python.attr b/python.attr
new file mode 100644
index 0000000..cf5ae39
--- /dev/null
+++ b/python.attr
@@ -0,0 +1,31 @@
+%__python_provides() %{lua:
+ -- Match buildroot/payload paths of the form
+ -- /PATH/OF/BUILDROOT/usr/bin/pythonMAJOR.MINOR
+ -- generating a line of the form
+ -- python(abi) = MAJOR.MINOR
+ -- (Don't match against -config tools e.g. /usr/bin/python2.6-config)
+ local path = rpm.expand('%1')
+ -- Use /usr prefix by default, and /app for flatpak builds
+ local prefix = rpm.expand('%{?!flatpak:/usr}%{?flatpak:/app}')
+ if path:match(prefix .. '/bin/python%d+%.%d+$') then
+ local provides = path:gsub('.*' .. prefix .. '/bin/python(%d+%.%d+)', 'python(abi) = %1')
+ print(provides)
+ end
+}
+
+%__python_requires() %{lua:
+ -- Match buildroot paths of the form
+ -- /PATH/OF/BUILDROOT/usr/lib/pythonMAJOR.MINOR/ and
+ -- /PATH/OF/BUILDROOT/usr/lib64/pythonMAJOR.MINOR/
+ -- generating a line of the form:
+ -- python(abi) = MAJOR.MINOR
+ local path = rpm.expand('%1')
+ -- Use /usr prefix by default, and /app for flatpak builds
+ local prefix = rpm.expand('%{?!flatpak:/usr}%{?flatpak:/app}')
+ if path:match(prefix .. '/lib%d*/python%d+%.%d+/.*') then
+ local requires = path:gsub('.*' .. prefix .. '/lib%d*/python(%d+%.%d+)/.*', 'python(abi) = %1')
+ print(requires)
+ end
+}
+
+%__python_path ^((%{?!flatpak:/usr}%{?flatpak:/app}/lib(64)?/python[[:digit:]]+\\.[[:digit:]]+/.*\\.(py[oc]?|so))|(%{_bindir}/python[[:digit:]]+\\.[[:digit:]]+))$
diff --git a/pythonbundles.py b/pythonbundles.py
new file mode 100755
index 0000000..b0e5ecf
--- /dev/null
+++ b/pythonbundles.py
@@ -0,0 +1,94 @@
+#!/usr/bin/python3 -sB
+# (imports pythondistdeps from /usr/lib/rpm, hence -B)
+#
+# This program is free software.
+#
+# It is placed in the public domain or under the CC0-1.0-Universal license,
+# whichever you choose.
+#
+# Alternatively, it may be redistributed and/or modified under the terms of
+# the LGPL version 2.1 (or later) or GPL version 2 (or later).
+#
+# Use this script to generate bundled provides, e.g.:
+# ./pythonbundles.py setuptools-47.1.1/pkg_resources/_vendor/vendored.txt
+
+import pathlib
+import sys
+
+from packaging import requirements
+
+import pythondistdeps
+
+def generate_bundled_provides(paths, namespace):
+ provides = set()
+
+ for path in paths:
+ for line in path.read_text().splitlines():
+ line, _, comment = line.partition('#')
+ if comment.startswith('egg='):
+ # not a real comment
+ # e.g. git+https://github.com/monty/spam.git@master#egg=spam&...
+ egg, *_ = comment.strip().partition(' ')
+ egg, *_ = egg.strip().partition('&')
+ name = pythondistdeps.normalize_name(egg[4:])
+ provides.add(f'Provides: bundled({namespace}({name}))')
+ continue
+ line = line.strip()
+ if line:
+ requirement = requirements.Requirement(line)
+ for spec in requirement.specifier:
+ if spec.operator == '==':
+ version = spec.version
+ break
+ else:
+ raise ValueError('pythonbundles.py only handles exactly one == requirement')
+ name = pythondistdeps.normalize_name(requirement.name)
+ bundled_name = f"bundled({namespace}({name}))"
+ python_provide = pythondistdeps.convert(bundled_name, '==', version)
+ provides.add(f'Provides: {python_provide}')
+
+ return provides
+
+
+def compare(expected, given):
+ stripped = (l.strip() for l in given)
+ no_comments = set(l for l in stripped if not l.startswith('#'))
+ no_comments.discard('')
+ if expected == no_comments:
+ return True
+ extra_expected = expected - no_comments
+ extra_given = no_comments - expected
+ if extra_expected:
+ print('Missing expected provides:', file=sys.stderr)
+ for provide in sorted(extra_expected):
+ print(f' - {provide}', file=sys.stderr)
+ if extra_given:
+ print('Redundant unexpected provides:', file=sys.stderr)
+ for provide in sorted(extra_given):
+ print(f' + {provide}', file=sys.stderr)
+ return False
+
+
+if __name__ == '__main__':
+ import argparse
+
+ parser = argparse.ArgumentParser(prog=sys.argv[0],
+ formatter_class=argparse.ArgumentDefaultsHelpFormatter)
+ parser.add_argument('vendored', metavar='VENDORED.TXT', nargs='+', type=pathlib.Path,
+ help='Upstream information about vendored libraries')
+ parser.add_argument('-c', '--compare-with', action='store',
+ help='A string value to compare with and verify')
+ parser.add_argument('-n', '--namespace', action='store',
+ help='What namespace of provides will used', default='python3dist')
+ args = parser.parse_args()
+
+ provides = generate_bundled_provides(args.vendored, args.namespace)
+
+ if args.compare_with:
+ given = args.compare_with.splitlines()
+ same = compare(provides, given)
+ if not same:
+ sys.exit(1)
+ else:
+ for provide in sorted(provides):
+ print(provide)
diff --git a/pythondist.attr b/pythondist.attr
new file mode 100644
index 0000000..7efbe88
--- /dev/null
+++ b/pythondist.attr
@@ -0,0 +1,3 @@
+%__pythondist_provides %{_rpmconfigdir}/pythondistdeps.py --provides --normalized-names-format legacy-dots --normalized-names-provide-both --package-name %{name} --majorver-provides %{?!_python_dist_allow_version_zero:--fail-if-zero}
+%__pythondist_requires %{_rpmconfigdir}/pythondistdeps.py --requires --normalized-names-format legacy-dots --normalized-names-provide-both --package-name %{name} %{?!_python_no_extras_requires:--require-extras-subpackages} --console-scripts-nodep-setuptools-since 3.10
+%__pythondist_path ^%{?!flatpak:/usr}%{?flatpak:/app}/lib(64)?/python[3-9]\\.[[:digit:]]+/site-packages/[^/]+\\.(dist-info|egg-info|egg-link)$
diff --git a/pythondistdeps.py b/pythondistdeps.py
new file mode 100644
index 0000000..b43ed39
--- /dev/null
+++ b/pythondistdeps.py
@@ -0,0 +1,626 @@
+#!/usr/bin/python3 -s
+# -*- coding: utf-8 -*-
+#
+# Copyright 2010 Per Øyvind Karlsen <proyvind@moondrake.org>
+# Copyright 2015 Neal Gompa <ngompa13@gmail.com>
+# Copyright 2020 SUSE LLC
+#
+# This program is free software. It may be redistributed and/or modified under
+# the terms of the LGPL version 2.1 (or later).
+#
+# RPM python dependency generator, using .egg-info/.egg-link/.dist-info data
+#
+
+from __future__ import print_function
+import argparse
+from os.path import dirname, sep
+import re
+from sys import argv, stdin, stderr, version_info
+from sysconfig import get_path
+from warnings import warn
+
+from packaging.requirements import Requirement as Requirement_
+from packaging.version import parse
+import packaging.markers
+
+# Monkey patching packaging.markers to handle extras names in a
+# case-insensitive manner:
+# pip considers dnspython[DNSSEC] and dnspython[dnssec] to be equal, but
+# packaging markers treat extras in a case-sensitive manner. To solve this
+# issue, we introduce a comparison operator that compares case-insensitively
+# if both sides of the comparison are strings. And then we inject this
+# operator into packaging.markers to be used when comparing names of extras.
+# Fedora BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1936875
+# Upstream issue: https://discuss.python.org/t/what-extras-names-are-treated-as-equal-and-why/7614
+# - After it's established upstream what is the canonical form of an extras
+# name, we plan to open an issue with packaging to hopefully solve this
+# there without having to resort to monkeypatching.
+def str_lower_eq(a, b):
+ if isinstance(a, str) and isinstance(b, str):
+ return a.lower() == b.lower()
+ else:
+ return a == b
+packaging.markers._operators["=="] = str_lower_eq
+
+try:
+ from importlib.metadata import PathDistribution
+except ImportError:
+ from importlib_metadata import PathDistribution
+
+try:
+ from pathlib import Path
+except ImportError:
+ from pathlib2 import Path
+
+
+def normalize_name(name):
+ """https://www.python.org/dev/peps/pep-0503/#normalized-names"""
+ return re.sub(r'[-_.]+', '-', name).lower()
+
+
+def legacy_normalize_name(name):
+ """Like pkg_resources Distribution.key property"""
+ return re.sub(r'[-_]+', '-', name).lower()
+
+
+class Requirement(Requirement_):
+ def __init__(self, requirement_string):
+ super(Requirement, self).__init__(requirement_string)
+ self.normalized_name = normalize_name(self.name)
+ self.legacy_normalized_name = legacy_normalize_name(self.name)
+
+
+class Distribution(PathDistribution):
+ def __init__(self, path):
+ super(Distribution, self).__init__(Path(path))
+
+ # Check that the initialization went well and metadata are not missing or corrupted
+ # name is the most important attribute, if it doesn't exist, import failed
+ if not self.name or not isinstance(self.name, str):
+ print("*** PYTHON_METADATA_FAILED_TO_PARSE_ERROR___SEE_STDERR ***")
+ print('Error: Python metadata at `{}` are missing or corrupted.'.format(path), file=stderr)
+ exit(65) # os.EX_DATAERR
+
+ self.normalized_name = normalize_name(self.name)
+ self.legacy_normalized_name = legacy_normalize_name(self.name)
+ self.requirements = [Requirement(r) for r in self.requires or []]
+ self.extras = [
+ v.lower() for k, v in self.metadata.items() if k == 'Provides-Extra']
+ self.py_version = self._parse_py_version(path)
+
+ # `name` is defined as a property exactly like this in Python 3.10 in the
+ # PathDistribution class. Due to that we can't redefine `name` as a normal
+ # attribute. So we copied the Python 3.10 definition here into the code so
+ # that it works also on previous Python/importlib_metadata versions.
+ @property
+ def name(self):
+ """Return the 'Name' metadata for the distribution package or None."""
+ return self.metadata.get('Name')
+
+ def _parse_py_version(self, path):
+ # Try to parse the Python version from the path the metadata
+ # resides at (e.g. /usr/lib/pythonX.Y/site-packages/...)
+ res = re.search(r"/python(?P<pyver>\d+\.\d+)/", path)
+ if res:
+ return res.group('pyver')
+ # If that hasn't worked, attempt to parse it from the metadata
+ # directory name
+ res = re.search(r"-py(?P<pyver>\d+.\d+)[.-]egg-info$", path)
+ if res:
+ return res.group('pyver')
+ return None
+
+ def requirements_for_extra(self, extra):
+ extra_deps = []
+ # we are only interested in dependencies with extra == 'our_extra' marker
+ for req in self.requirements:
+ # no marker at all, nothing to evaluate
+ if not req.marker:
+ continue
+ # does the marker include extra == 'our_extra'?
+ # we can only evaluate the marker as a whole,
+ # so we evaluate it twice (using 2 different marker_envs)
+ # and see if it only evaluates to True with our extra
+ if (req.marker.evaluate(get_marker_env(self, extra)) and
+ not req.marker.evaluate(get_marker_env(self, None))):
+ extra_deps.append(req)
+ return extra_deps
+
+ def __repr__(self):
+ return '{} from {}'.format(self.name, self._path)
+
+
+class RpmVersion():
+ def __init__(self, version_id):
+ version = parse(version_id)
+ if isinstance(version._version, str):
+ self.version = version._version
+ else:
+ self.epoch = version._version.epoch
+ self.version = list(version._version.release)
+ self.pre = version._version.pre
+ self.dev = version._version.dev
+ self.post = version._version.post
+ # version.local is ignored as it is not expected to appear
+ # in public releases
+ # https://www.python.org/dev/peps/pep-0440/#local-version-identifiers
+
+ def is_legacy(self):
+ return isinstance(self.version, str)
+
+ def increment(self):
+ self.version[-1] += 1
+ self.pre = None
+ self.dev = None
+ self.post = None
+ return self
+
+ def is_zero(self):
+ return self.__str__() == '0'
+
+ def __str__(self):
+ if self.is_legacy():
+ return self.version
+ if self.epoch:
+ rpm_epoch = str(self.epoch) + ':'
+ else:
+ rpm_epoch = ''
+ while len(self.version) > 1 and self.version[-1] == 0:
+ self.version.pop()
+ rpm_version = '.'.join(str(x) for x in self.version)
+ if self.pre:
+ rpm_suffix = '~{}'.format(''.join(str(x) for x in self.pre))
+ elif self.dev:
+ rpm_suffix = '~~{}'.format(''.join(str(x) for x in self.dev))
+ elif self.post:
+ rpm_suffix = '^post{}'.format(self.post[1])
+ else:
+ rpm_suffix = ''
+ return '{}{}{}'.format(rpm_epoch, rpm_version, rpm_suffix)
+
+
+def convert_compatible(name, operator, version_id):
+ if version_id.endswith('.*'):
+ print("*** INVALID_REQUIREMENT_ERROR___SEE_STDERR ***")
+ print('Invalid requirement: {} {} {}'.format(name, operator, version_id), file=stderr)
+ exit(65) # os.EX_DATAERR
+ version = RpmVersion(version_id)
+ if version.is_legacy():
+ # LegacyVersions are not supported in this context
+ print("*** INVALID_REQUIREMENT_ERROR___SEE_STDERR ***")
+ print('Invalid requirement: {} {} {}'.format(name, operator, version_id), file=stderr)
+ exit(65) # os.EX_DATAERR
+ if len(version.version) == 1:
+ print("*** INVALID_REQUIREMENT_ERROR___SEE_STDERR ***")
+ print('Invalid requirement: {} {} {}'.format(name, operator, version_id), file=stderr)
+ exit(65) # os.EX_DATAERR
+ upper_version = RpmVersion(version_id)
+ upper_version.version.pop()
+ upper_version.increment()
+ return '({} >= {} with {} < {})'.format(
+ name, version, name, upper_version)
+
+
+def convert_equal(name, operator, version_id):
+ if version_id.endswith('.*'):
+ version_id = version_id[:-2] + '.0'
+ return convert_compatible(name, '~=', version_id)
+ version = RpmVersion(version_id)
+ return '{} = {}'.format(name, version)
+
+
+def convert_arbitrary_equal(name, operator, version_id):
+ if version_id.endswith('.*'):
+ print("*** INVALID_REQUIREMENT_ERROR___SEE_STDERR ***")
+ print('Invalid requirement: {} {} {}'.format(name, operator, version_id), file=stderr)
+ exit(65) # os.EX_DATAERR
+ version = RpmVersion(version_id)
+ return '{} = {}'.format(name, version)
+
+
+def convert_not_equal(name, operator, version_id):
+ if version_id.endswith('.*'):
+ version_id = version_id[:-2]
+ version = RpmVersion(version_id)
+ if version.is_legacy():
+ # LegacyVersions are not supported in this context
+ print("*** INVALID_REQUIREMENT_ERROR___SEE_STDERR ***")
+ print('Invalid requirement: {} {} {}'.format(name, operator, version_id), file=stderr)
+ exit(65) # os.EX_DATAERR
+ version_gt = RpmVersion(version_id).increment()
+ version_gt_operator = '>='
+ # Prevent dev and pre-releases from satisfying a < requirement
+ version = '{}~~'.format(version)
+ else:
+ version = RpmVersion(version_id)
+ version_gt = version
+ version_gt_operator = '>'
+ return '({} < {} or {} {} {})'.format(
+ name, version, name, version_gt_operator, version_gt)
+
+
+def convert_ordered(name, operator, version_id):
+ if version_id.endswith('.*'):
+ # PEP 440 does not define semantics for prefix matching
+ # with ordered comparisons
+ # see: https://github.com/pypa/packaging/issues/320
+ # and: https://github.com/pypa/packaging/issues/321
+ # This style of specifier is officially "unsupported",
+ # even though it is processed. Support may be removed
+ # in version 21.0.
+ version_id = version_id[:-2]
+ version = RpmVersion(version_id)
+ if operator == '>':
+ # distutils will allow a prefix match with '>'
+ operator = '>='
+ if operator == '<=':
+ # distutils will not allow a prefix match with '<='
+ operator = '<'
+ else:
+ version = RpmVersion(version_id)
+ # For backwards compatibility, fallback to previous behavior with LegacyVersions
+ if not version.is_legacy():
+ # Prevent dev and pre-releases from satisfying a < requirement
+ if operator == '<' and not version.pre and not version.dev and not version.post:
+ version = '{}~~'.format(version)
+ # Prevent post-releases from satisfying a > requirement
+ if operator == '>' and not version.pre and not version.dev and not version.post:
+ version = '{}.0'.format(version)
+ return '{} {} {}'.format(name, operator, version)
+
+
+OPERATORS = {'~=': convert_compatible,
+ '==': convert_equal,
+ '===': convert_arbitrary_equal,
+ '!=': convert_not_equal,
+ '<=': convert_ordered,
+ '<': convert_ordered,
+ '>=': convert_ordered,
+ '>': convert_ordered}
+
+
+def convert(name, operator, version_id):
+ try:
+ return OPERATORS[operator](name, operator, version_id)
+ except Exception as exc:
+ raise RuntimeError("Cannot process Python package version `{}` for name `{}`".
+ format(version_id, name)) from exc
+
+
+def get_marker_env(dist, extra):
+ # packaging uses a default environment using
+ # platform.python_version to evaluate if a dependency is relevant
+ # based on environment markers [1],
+ # e.g. requirement `argparse;python_version<"2.7"`
+ #
+ # Since we're running this script on one Python version while
+ # possibly evaluating packages for different versions, we
+ # set up an environment with the version we want to evaluate.
+ #
+ # [1] https://www.python.org/dev/peps/pep-0508/#environment-markers
+ return {"python_full_version": dist.py_version,
+ "python_version": dist.py_version,
+ "extra": extra}
+
+
+def main():
+ """To allow this script to be importable (and its classes/functions
+ reused), actions are defined in the main function and are performed only
+ when run as a main script."""
+ parser = argparse.ArgumentParser(prog=argv[0])
+ group = parser.add_mutually_exclusive_group(required=True)
+ group.add_argument('-P', '--provides', action='store_true', help='Print Provides')
+ group.add_argument('-R', '--requires', action='store_true', help='Print Requires')
+ group.add_argument('-r', '--recommends', action='store_true', help='Print Recommends')
+ group.add_argument('-C', '--conflicts', action='store_true', help='Print Conflicts')
+ group.add_argument('-E', '--extras', action='store_true', help='[Unused] Generate spec file snippets for extras subpackages')
+ group_majorver = parser.add_mutually_exclusive_group()
+ group_majorver.add_argument('-M', '--majorver-provides', action='store_true', help='Print extra Provides with Python major version only')
+ group_majorver.add_argument('--majorver-provides-versions', action='append',
+ help='Print extra Provides with Python major version only for listed '
+ 'Python VERSIONS (appended or comma separated without spaces, e.g. 2.7,3.9)')
+ parser.add_argument('-m', '--majorver-only', action='store_true', help='Print Provides/Requires with Python major version only')
+ parser.add_argument('-n', '--normalized-names-format', action='store',
+ default="legacy-dots", choices=["pep503", "legacy-dots"],
+ help='Format of normalized names according to pep503 or legacy format that allows dots [default]')
+ parser.add_argument('--normalized-names-provide-both', action='store_true',
+ help='Provide both `pep503` and `legacy-dots` format of normalized names (useful for a transition period)')
+ parser.add_argument('-L', '--legacy-provides', action='store_true', help='Print extra legacy pythonegg Provides')
+ parser.add_argument('-l', '--legacy', action='store_true', help='Print legacy pythonegg Provides/Requires instead')
+ parser.add_argument('--console-scripts-nodep-setuptools-since', action='store',
+ help='An optional Python version (X.Y), at least 3.8. '
+ 'For that version and any newer version, '
+ 'a dependency on "setuptools" WILL NOT be generated for packages with console_scripts/gui_scripts entry points. '
+ 'By setting this flag, you guarantee that setuptools >= 47.2.0 is used '
+ 'during the build of packages for this and any newer Python version.')
+ parser.add_argument('--require-extras-subpackages', action='store_true',
+ help="If there is a dependency on a package with extras functionality, require the extras subpackage")
+ parser.add_argument('--package-name', action='store', help="Name of the RPM package that's being inspected. Required for extras requires/provides to work.")
+ parser.add_argument('--namespace', action='store', help="Namespace for the printed Requires, Provides, Recommends and Conflicts")
+ parser.add_argument('--fail-if-zero', action='store_true', help='Fail the script if the automatically generated Provides version was 0, which usually indicates a packaging error.')
+ parser.add_argument('files', nargs=argparse.REMAINDER, help="Files from the RPM package that are to be inspected, can also be supplied on stdin")
+ args = parser.parse_args()
+
+ if args.fail_if_zero and not args.provides:
+ raise parser.error('--fail-if-zero only works with --provides')
+
+ py_abi = args.requires
+ py_deps = {}
+
+ if args.majorver_provides_versions:
+ # Go through the arguments (can be specified multiple times),
+ # and parse individual versions (can be comma-separated)
+ args.majorver_provides_versions = [v for vstring in args.majorver_provides_versions
+ for v in vstring.split(",")]
+
+ # If normalized_names_require_pep503 is True we require the pep503
+ # normalized name, if it is False we provide the legacy normalized name
+ normalized_names_require_pep503 = args.normalized_names_format == "pep503"
+
+ # If normalized_names_provide_pep503/legacy is True we provide the
+ # pep503/legacy normalized name, if it is False we don't
+ normalized_names_provide_pep503 = \
+ args.normalized_names_format == "pep503" or args.normalized_names_provide_both
+ normalized_names_provide_legacy = \
+ args.normalized_names_format == "legacy-dots" or args.normalized_names_provide_both
+
+ # At least one type of normalization must be provided
+ assert normalized_names_provide_pep503 or normalized_names_provide_legacy
+
+ if args.console_scripts_nodep_setuptools_since:
+ nodep_setuptools_pyversion = parse(args.console_scripts_nodep_setuptools_since)
+ if nodep_setuptools_pyversion < parse("3.8"):
+ print("Only version 3.8+ is supported in --console-scripts-nodep-setuptools-since", file=stderr)
+ print("*** PYTHON_EXTRAS_ARGUMENT_ERROR___SEE_STDERR ***")
+ exit(65) # os.EX_DATAERR
+ else:
+ nodep_setuptools_pyversion = None
+
+ # Is this script being run for an extras subpackage?
+ extras_subpackage = None
+ if args.package_name and '+' in args.package_name:
+ # The extras names are encoded in the package names after the + sign.
+ # We take the part after the rightmost +, ignoring when empty,
+ # this allows packages like nicotine+ or c++ to work fine.
+ # While packages with names like +spam or foo+bar would break,
+ # names started with the plus sign are not very common
+ # and pluses in the middle can be easily replaced with dashes.
+ # Python extras names don't contain pluses according to PEP 508.
+ package_name_parts = args.package_name.rpartition('+')
+ extras_subpackage = package_name_parts[2].lower() or None
+
+ namespace = (args.namespace + "({})") if args.namespace else "{}"
+
+ for f in (args.files or stdin.readlines()):
+ f = f.strip()
+ lower = f.lower()
+ name = 'python(abi)'
+ # add dependency based on path, versioned if within versioned python directory
+ if py_abi and (lower.endswith('.py') or lower.endswith('.pyc') or lower.endswith('.pyo')):
+ if name not in py_deps:
+ py_deps[name] = []
+ running_python_version = '{}.{}'.format(*version_info[:2])
+ purelib = get_path('purelib').split(running_python_version)[0]
+ platlib = get_path('platlib').split(running_python_version)[0]
+ for lib in (purelib, platlib):
+ if lib in f:
+ spec = ('==', f.split(lib)[1].split(sep)[0])
+ if spec not in py_deps[name]:
+ py_deps[name].append(spec)
+
+ # XXX: hack to workaround RPM internal dependency generator not passing directories
+ lower_dir = dirname(lower)
+ if lower_dir.endswith('.egg') or \
+ lower_dir.endswith('.egg-info') or \
+ lower_dir.endswith('.dist-info'):
+ lower = lower_dir
+ f = dirname(f)
+ # Determine provide, requires, conflicts & recommends based on egg/dist metadata
+ if lower.endswith('.egg') or \
+ lower.endswith('.egg-info') or \
+ lower.endswith('.dist-info'):
+ dist = Distribution(f)
+ if not dist.py_version:
+ warn("Version for {!r} has not been found".format(dist), RuntimeWarning)
+ continue
+
+ # If processing an extras subpackage:
+ # Check that the extras name is declared in the metadata, or
+ # that there are some dependencies associated with the extras
+ # name in the requires.txt (this is an outdated way to declare
+ # extras packages).
+ # - If there is an extras package declared only in requires.txt
+ # without any dependencies, this check will fail. In that case
+ # make sure to use updated metadata and declare the extras
+ # package there.
+ if extras_subpackage and extras_subpackage not in dist.extras and not dist.requirements_for_extra(extras_subpackage):
+ print("*** PYTHON_EXTRAS_NOT_FOUND_ERROR___SEE_STDERR ***")
+ print(f"\nError: The package name contains an extras name `{extras_subpackage}` that was not found in the metadata.\n"
+ "Check if the extras were removed from the project. If so, consider removing the subpackage and obsoleting it from another.\n", file=stderr)
+ exit(65) # os.EX_DATAERR
+
+ if args.majorver_provides or args.majorver_provides_versions or \
+ args.majorver_only or args.legacy_provides or args.legacy:
+ # Get the Python major version
+ pyver_major = dist.py_version.split('.')[0]
+ if args.provides:
+ extras_suffix = f"[{extras_subpackage}]" if extras_subpackage else ""
+ # If egg/dist metadata says package name is python, we provide python(abi)
+ if dist.normalized_name == 'python':
+ name = namespace.format('python(abi)')
+ if name not in py_deps:
+ py_deps[name] = []
+ py_deps[name].append(('==', dist.py_version))
+ if not args.legacy or not args.majorver_only:
+ if normalized_names_provide_legacy:
+ name = namespace.format('python{}dist({}{})').format(dist.py_version, dist.legacy_normalized_name, extras_suffix)
+ if name not in py_deps:
+ py_deps[name] = []
+ if normalized_names_provide_pep503:
+ name_ = namespace.format('python{}dist({}{})').format(dist.py_version, dist.normalized_name, extras_suffix)
+ if name_ not in py_deps:
+ py_deps[name_] = []
+ if args.majorver_provides or args.majorver_only or \
+ (args.majorver_provides_versions and dist.py_version in args.majorver_provides_versions):
+ if normalized_names_provide_legacy:
+ pymajor_name = namespace.format('python{}dist({}{})').format(pyver_major, dist.legacy_normalized_name, extras_suffix)
+ if pymajor_name not in py_deps:
+ py_deps[pymajor_name] = []
+ if normalized_names_provide_pep503:
+ pymajor_name_ = namespace.format('python{}dist({}{})').format(pyver_major, dist.normalized_name, extras_suffix)
+ if pymajor_name_ not in py_deps:
+ py_deps[pymajor_name_] = []
+ if args.legacy or args.legacy_provides:
+ legacy_name = namespace.format('pythonegg({})({})').format(pyver_major, dist.legacy_normalized_name)
+ if legacy_name not in py_deps:
+ py_deps[legacy_name] = []
+ if dist.version:
+ version = dist.version
+ spec = ('==', version)
+ if args.fail_if_zero:
+ if RpmVersion(version).is_zero():
+ print('*** PYTHON_PROVIDED_VERSION_NORMALIZES_TO_ZERO___SEE_STDERR ***')
+ print(f'\nError: The version in the Python package metadata {version} normalizes to zero.\n'
+ 'It\'s likely a packaging error caused by missing version information\n'
+ '(e.g. when using a version control system snapshot as a source).\n'
+ 'Try providing the version information manually when building the Python package,\n'
+ 'for example by setting the SETUPTOOLS_SCM_PRETEND_VERSION environment variable if the package uses setuptools_scm.\n'
+ 'If you are confident that the version of the Python package is intentionally zero,\n'
+ 'you may %define the _python_dist_allow_version_zero macro in the spec file to disable this check.\n', file=stderr)
+ exit(65) # os.EX_DATAERR
+
+ if normalized_names_provide_legacy:
+ if spec not in py_deps[name]:
+ py_deps[name].append(spec)
+ if args.majorver_provides or \
+ (args.majorver_provides_versions and dist.py_version in args.majorver_provides_versions):
+ py_deps[pymajor_name].append(spec)
+ if normalized_names_provide_pep503:
+ if spec not in py_deps[name_]:
+ py_deps[name_].append(spec)
+ if args.majorver_provides or \
+ (args.majorver_provides_versions and dist.py_version in args.majorver_provides_versions):
+ py_deps[pymajor_name_].append(spec)
+ if args.legacy or args.legacy_provides:
+ if spec not in py_deps[legacy_name]:
+ py_deps[legacy_name].append(spec)
+ if args.requires or (args.recommends and dist.extras):
+ name = namespace.format('python(abi)')
+ # If egg/dist metadata says package name is python, we don't add dependency on python(abi)
+ if dist.normalized_name == 'python':
+ py_abi = False
+ if name in py_deps:
+ py_deps.pop(name)
+ elif py_abi and dist.py_version:
+ if name not in py_deps:
+ py_deps[name] = []
+ spec = ('==', dist.py_version)
+ if spec not in py_deps[name]:
+ py_deps[name].append(spec)
+
+ if extras_subpackage:
+ deps = [d for d in dist.requirements_for_extra(extras_subpackage)]
+ else:
+ deps = dist.requirements
+
+ # console_scripts/gui_scripts entry points needed pkg_resources from setuptools
+ # on new Python/setuptools versions, this is no longer required
+ if nodep_setuptools_pyversion is None or parse(dist.py_version) < nodep_setuptools_pyversion:
+ if (dist.entry_points and
+ (lower.endswith('.egg') or
+ lower.endswith('.egg-info'))):
+ groups = {ep.group for ep in dist.entry_points}
+ if {"console_scripts", "gui_scripts"} & groups:
+ # stick them first so any more specific requirement
+ # overrides it
+ deps.insert(0, Requirement('setuptools'))
+ # add requires/recommends based on egg/dist metadata
+ for dep in deps:
+ # Even if we're requiring `foo[bar]`, also require `foo`
+ # to be safe, and to make it discoverable through
+ # `repoquery --whatrequires`
+ extras_suffixes = [""]
+ if args.require_extras_subpackages and dep.extras:
+ # A dependency can have more than one extras,
+ # i.e. foo[bar,baz], so let's go through all of them
+ extras_suffixes += [f"[{e.lower()}]" for e in dep.extras]
+
+ for extras_suffix in extras_suffixes:
+ if normalized_names_require_pep503:
+ dep_normalized_name = dep.normalized_name
+ else:
+ dep_normalized_name = dep.legacy_normalized_name
+
+ if args.legacy:
+ name = namespace.format('pythonegg({})({})').format(pyver_major, dep.legacy_normalized_name)
+ else:
+ if args.majorver_only:
+ name = namespace.format('python{}dist({}{})').format(pyver_major, dep_normalized_name, extras_suffix)
+ else:
+ name = namespace.format('python{}dist({}{})').format(dist.py_version, dep_normalized_name, extras_suffix)
+
+ if dep.marker and not args.recommends and not extras_subpackage:
+ if not dep.marker.evaluate(get_marker_env(dist, '')):
+ continue
+
+ if name not in py_deps:
+ py_deps[name] = []
+ for spec in dep.specifier:
+ if (spec.operator, spec.version) not in py_deps[name]:
+ py_deps[name].append((spec.operator, spec.version))
+
+ # Unused, for automatic sub-package generation based on 'extras' from egg/dist metadata
+ # TODO: implement in rpm later, or...?
+ if args.extras:
+ print(dist.extras)
+ for extra in dist.extras:
+ print('%%package\textras-{}'.format(extra))
+ print('Summary:\t{} extra for {} python package'.format(extra, dist.legacy_normalized_name))
+ print('Group:\t\tDevelopment/Python')
+ for dep in dist.requirements_for_extra(extra):
+ for spec in dep.specifier:
+ if spec.operator == '!=':
+ print('Conflicts:\t{} {} {}'.format(dep.legacy_normalized_name, '==', spec.version))
+ else:
+ print('Requires:\t{} {} {}'.format(dep.legacy_normalized_name, spec.operator, spec.version))
+ print('%%description\t{}'.format(extra))
+ print('{} extra for {} python package'.format(extra, dist.legacy_normalized_name))
+ print('%%files\t\textras-{}\n'.format(extra))
+ if args.conflicts:
+ # Should we really add conflicts for extras?
+ # Creating a meta package per extra with recommends on, which has
+ # the requires/conflicts in stead might be a better solution...
+ for dep in dist.requirements:
+ for spec in dep.specifier:
+ if spec.operator == '!=':
+ if dep.legacy_normalized_name not in py_deps:
+ py_deps[dep.legacy_normalized_name] = []
+ spec = ('==', spec.version)
+ if spec not in py_deps[dep.legacy_normalized_name]:
+ py_deps[dep.legacy_normalized_name].append(spec)
+
+ for name in sorted(py_deps):
+ if py_deps[name]:
+ # Print out versioned provides, requires, recommends, conflicts
+ spec_list = []
+ for spec in py_deps[name]:
+ spec_list.append(convert(name, spec[0], spec[1]))
+ if len(spec_list) == 1:
+ print(spec_list[0])
+ else:
+ # Sort spec_list so that the results can be tested easily
+ print('({})'.format(' with '.join(sorted(spec_list))))
+ else:
+ # Print out unversioned provides, requires, recommends, conflicts
+ print(name)
+
+
+if __name__ == "__main__":
+ """To allow this script to be importable (and its classes/functions
+ reused), actions are performed only when run as a main script."""
+ try:
+ main()
+ except Exception as exc:
+ print("*** PYTHONDISTDEPS_GENERATORS_FAILED ***", flush=True)
+ raise RuntimeError("Error: pythondistdeps.py generator encountered an unhandled exception and was terminated.") from exc
+
diff --git a/sources b/sources
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/sources