diff --git a/.gitignore b/.gitignore index 77e4dbf..0226674 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ build dist *.egg-info *.pyc +.idea/ +.pytest_cache/ diff --git a/COPYING b/COPYING deleted file mode 100644 index cde4efd..0000000 --- a/COPYING +++ /dev/null @@ -1,272 +0,0 @@ - - The GNU General Public License (GPL) - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 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. - - 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 - - diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 43d7b10..0000000 --- a/Dockerfile +++ /dev/null @@ -1,33 +0,0 @@ -FROM centos:7 - -MAINTAINER Brian Stinson - -USER root -RUN yum -y install sudo epel-release -RUN yum -y install koji python2-koji - -# We need this until CentOS releases CR or 7.6.1810 -RUN yum -y install https://kojipkgs.fedoraproject.org//packages/libmodulemd/1.7.0/1.el7/x86_64/libmodulemd-1.7.0-1.el7.x86_64.rpm - -RUN yum -y install git python-devel krb5-devel rpmdevtools python-centos rpm-python python-setuptools @development PyYAML libmodulemd python2-modulemd python2-cccolutils - -RUN git clone -b centpkg-inbound https://pagure.io/forks/bstinson/rpkg.git /src/rpkg -RUN git clone -b develop https://bitbucket.org/bstinsonmhk/centpkg.git /src/centpkg -RUN git clone -b master https://pagure.io/fedpkg.git /src/fedpkg -ADD https://raw.githubusercontent.com/bstinsonmhk/centos-packager/master/SOURCES/cbs-koji.conf /etc/koji.conf.d/cbs-koji.conf - -WORKDIR /src/rpkg -RUN python setup.py install - -WORKDIR /src/centpkg -RUN python setup.py install - -WORKDIR /src/fedpkg -RUN python setup.py install - -RUN useradd -m centpkg-user -RUN echo 'centpkg-user ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/centpkg-user - -USER centpkg-user -WORKDIR /home/centpkg-user -CMD /bin/bash -l diff --git a/README.md b/README.md deleted file mode 100644 index 2d82532..0000000 --- a/README.md +++ /dev/null @@ -1,29 +0,0 @@ -# Centpkg -Centpkg is a wrapper for [rpkg](https://fedorahosted.org/rpkg/) which interacts -with RPM git repositories like the ones hosted at http://git.centos.org. Rpkg also provides -some convenience methods/commands for local builds via mock or rpmbuild, for -interacting with koji, and for generating patches. - -# Centpkg is in pre-alpha state, as of now this is a proof of concept. -For now only a very small subset of rpkg commands are enabled. - -Exception handling at the top level has been disabled for now to get better -tracebacks during development. - -## Current workflow -For a sig working on a package in git.centos.org, the following workflow is -recommended: - - # In this example a member of the virt sig would like to scratch-build a2ps on EL6 - $ centpkg clone -b virt6 a2ps - $ cd a2ps - $ centpkg build --srpm --scratch - - # Tagged builds can be done also - $ centpkg build --srpm - - -## License - -Unless otherwise specified, all files are licensed under GPLv2+. -See COPYING for more license information diff --git a/centpkg.spec b/centpkg.spec deleted file mode 100644 index 80a886a..0000000 --- a/centpkg.spec +++ /dev/null @@ -1,82 +0,0 @@ -%{!?python_sitelib: %global python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())")} - -Name: centpkg -Version: 0.4.6 -Release: 1%{?dist} -Summary: CentOS utility for working with dist-git - -Group: Applications/System -License: GPLv2+ -URL: https://git.centos.org/summary/centpkg.git -Source0: centpkg-%{version}.tar.gz -BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root%(%{__id_u} -n) - -# CentOS Distributed Packages -Requires: redhat-rpm-config -Requires: python-pycurl - -# EPEL Distributed Packages -Requires: pyrpkg >= 1.17 -Requires: koji - -BuildArch: noarch - -# CentOS Distributed build-requires -BuildRequires: python-devel, python-setuptools - -# EPEL Distributed build-requires -BuildRequires: pyrpkg - -%description -Provides the centpkg command for working with dist-git - -%prep -%setup -q -c - - -%build -%{__python} setup.py build - -%install -%{__python} setup.py install -O1 --skip-build --root %{buildroot} - -%clean -rm -rf %{buildroot} - - -%files -%defattr(-,root,root,-) -%doc README.md COPYING -%config %{_sysconfdir}/rpkg/centpkg.conf -%{_bindir}/%{name} -%{python_sitelib}/* - - -%changelog -* Mon Nov 28 2016 brian@bstinson.com 0.4.6-1 -- Tracking updates to rpkg (thanks pavlix) -- Fix the URL building code in the sources method - -* Sat Jan 31 2015 Brian Stinson bstinson@ksu.edu - 0.4.4-1 -- New version correcting the anonymous pull URLs - -* Sun Dec 14 2014 Brian Stinson bstinson@ksu.edu - 0.4.3-1 -- Use the authenticated git url for centpkg pulls - -* Sun Dec 14 2014 Brian Stinson bstinson@ksu.edu - 0.4.2-1 -- Fix the koji config path in centpkg.conf - -* Sun Dec 14 2014 Brian Stinson bstinson@ksu.edu - 0.4.1-1 -- Fix a disttag regression and add a "patch" version number - -* Sat Nov 23 2014 Brian Stinson bstinson@ksu.edu - 0.2-1 -- The srpm workflow to the CBS works now - -* Sat Jul 05 2014 Brian Stinson bstinson@ksu.edu - 0.1-2 -- Update readme and add exception checking when running toplevel commands - -* Sat Jul 05 2014 Brian Stinson bstinson@ksu.edu - 0.1-1 -- Local builds and mockbuilds work - - - diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 0000000..60d2158 --- /dev/null +++ b/poetry.lock @@ -0,0 +1,642 @@ +[[package]] +category = "dev" +description = "Atomic file writes." +marker = "sys_platform == \"win32\"" +name = "atomicwrites" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "1.4.0" + +[[package]] +category = "dev" +description = "Classes Without Boilerplate" +name = "attrs" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "20.1.0" + +[package.extras] +dev = ["coverage (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "sphinx", "sphinx-rtd-theme", "pre-commit"] +docs = ["sphinx", "sphinx-rtd-theme", "zope.interface"] +tests = ["coverage (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface"] + +[[package]] +category = "main" +description = "Kerberos5 Credential Cache Collection Utilities" +name = "cccolutils" +optional = false +python-versions = "*" +version = "1.5" + +[[package]] +category = "main" +description = "Python package for providing Mozilla's CA Bundle." +name = "certifi" +optional = false +python-versions = "*" +version = "2020.6.20" + +[[package]] +category = "main" +description = "Foreign Function Interface for Python calling C code." +name = "cffi" +optional = false +python-versions = "*" +version = "1.14.2" + +[package.dependencies] +pycparser = "*" + +[[package]] +category = "main" +description = "Universal encoding detector for Python 2 and 3" +name = "chardet" +optional = false +python-versions = "*" +version = "3.0.4" + +[[package]] +category = "dev" +description = "Cross-platform colored terminal text." +marker = "sys_platform == \"win32\"" +name = "colorama" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "0.4.3" + +[[package]] +category = "main" +description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." +name = "cryptography" +optional = false +python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*" +version = "3.1" + +[package.dependencies] +cffi = ">=1.8,<1.11.3 || >1.11.3" +six = ">=1.4.1" + +[package.extras] +docs = ["sphinx (>=1.6.5,<1.8.0 || >1.8.0,<3.1.0 || >3.1.0,<3.1.1 || >3.1.1)", "sphinx-rtd-theme"] +docstest = ["doc8", "pyenchant (>=1.6.11)", "twine (>=1.12.0)", "sphinxcontrib-spelling (>=4.0.1)"] +pep8test = ["black", "flake8", "flake8-import-order", "pep8-naming"] +ssh = ["bcrypt (>=3.1.5)"] +test = ["pytest (>=3.6.0,<3.9.0 || >3.9.0,<3.9.1 || >3.9.1,<3.9.2 || >3.9.2)", "pretend", "iso8601", "pytz", "hypothesis (>=1.11.4,<3.79.2 || >3.79.2)"] + +[[package]] +category = "main" +description = "Decorators for Humans" +name = "decorator" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*" +version = "4.4.2" + +[[package]] +category = "main" +description = "Git Object Database" +name = "gitdb" +optional = false +python-versions = ">=3.4" +version = "4.0.5" + +[package.dependencies] +smmap = ">=3.0.1,<4" + +[[package]] +category = "main" +description = "Python Git Library" +name = "gitpython" +optional = false +python-versions = ">=3.4" +version = "3.1.8" + +[package.dependencies] +gitdb = ">=4.0.1,<5" + +[[package]] +category = "main" +description = "Python GSSAPI Wrapper" +name = "gssapi" +optional = false +python-versions = ">=3.6.*" +version = "1.6.9" + +[package.dependencies] +decorator = "*" +six = ">=1.4.0" + +[[package]] +category = "main" +description = "Internationalized Domain Names in Applications (IDNA)" +name = "idna" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "2.10" + +[[package]] +category = "dev" +description = "Read metadata from Python packages" +marker = "python_version < \"3.8\"" +name = "importlib-metadata" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" +version = "1.7.0" + +[package.dependencies] +zipp = ">=0.5" + +[package.extras] +docs = ["sphinx", "rst.linker"] +testing = ["packaging", "pep517", "importlib-resources (>=1.3)"] + +[[package]] +category = "dev" +description = "iniconfig: brain-dead simple config-ini parsing" +name = "iniconfig" +optional = false +python-versions = "*" +version = "1.0.1" + +[[package]] +category = "main" +description = "Koji is a system for building and tracking RPMS. The base package contains shared libraries and the command-line interface." +name = "koji" +optional = false +python-versions = ">=2.6" +version = "1.22.0" + +[package.dependencies] +pyOpenSSL = "*" +python-dateutil = "*" +requests = "*" +requests-gssapi = "*" +six = "*" + +[[package]] +category = "dev" +description = "More routines for operating on iterables, beyond itertools" +name = "more-itertools" +optional = false +python-versions = ">=3.5" +version = "8.5.0" + +[[package]] +category = "dev" +description = "Core utilities for Python packages" +name = "packaging" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "20.4" + +[package.dependencies] +pyparsing = ">=2.0.2" +six = "*" + +[[package]] +category = "dev" +description = "plugin and hook calling mechanisms for python" +name = "pluggy" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "0.13.1" + +[package.dependencies] +[package.dependencies.importlib-metadata] +python = "<3.8" +version = ">=0.12" + +[package.extras] +dev = ["pre-commit", "tox"] + +[[package]] +category = "dev" +description = "library with cross-python path, ini-parsing, io, code, log facilities" +name = "py" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "1.9.0" + +[[package]] +category = "main" +description = "C parser in Python" +name = "pycparser" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "2.20" + +[[package]] +category = "main" +description = "PycURL -- A Python Interface To The cURL library" +name = "pycurl" +optional = false +python-versions = ">=3.5" +version = "7.43.0.6" + +[[package]] +category = "main" +description = "Python wrapper module around the OpenSSL library" +name = "pyopenssl" +optional = false +python-versions = "*" +version = "19.1.0" + +[package.dependencies] +cryptography = ">=2.8" +six = ">=1.5.2" + +[package.extras] +docs = ["sphinx", "sphinx-rtd-theme"] +test = ["flaky", "pretend", "pytest (>=3.0.1)"] + +[[package]] +category = "dev" +description = "Python parsing module" +name = "pyparsing" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +version = "2.4.7" + +[[package]] +category = "dev" +description = "pytest: simple powerful testing with Python" +name = "pytest" +optional = false +python-versions = ">=3.5" +version = "6.0.1" + +[package.dependencies] +atomicwrites = ">=1.0" +attrs = ">=17.4.0" +colorama = "*" +iniconfig = "*" +more-itertools = ">=4.0.0" +packaging = "*" +pluggy = ">=0.12,<1.0" +py = ">=1.8.2" +toml = "*" + +[package.dependencies.importlib-metadata] +python = "<3.8" +version = ">=0.12" + +[package.extras] +checkqa_mypy = ["mypy (0.780)"] +testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"] + +[[package]] +category = "dev" +description = "pytest-sugar is a plugin for pytest that changes the default look and feel of pytest (e.g. progressbar, show tests that fail instantly)." +name = "pytest-sugar" +optional = false +python-versions = "*" +version = "0.9.4" + +[package.dependencies] +packaging = ">=14.1" +pytest = ">=2.9" +termcolor = ">=1.1.0" + +[[package]] +category = "main" +description = "Extensions to the standard Python datetime module" +name = "python-dateutil" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +version = "2.8.1" + +[package.dependencies] +six = ">=1.5" + +[[package]] +category = "main" +description = "YAML parser and emitter for Python" +name = "pyyaml" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "5.3.1" + +[[package]] +category = "main" +description = "Python HTTP for Humans." +name = "requests" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "2.24.0" + +[package.dependencies] +certifi = ">=2017.4.17" +chardet = ">=3.0.2,<4" +idna = ">=2.5,<3" +urllib3 = ">=1.21.1,<1.25.0 || >1.25.0,<1.25.1 || >1.25.1,<1.26" + +[package.extras] +security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)"] +socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7)", "win-inet-pton"] + +[[package]] +category = "main" +description = "A GSSAPI authentication handler for python-requests" +name = "requests-gssapi" +optional = false +python-versions = "*" +version = "1.2.2" + +[package.dependencies] +gssapi = "*" +requests = ">=1.1.0" + +[[package]] +category = "main" +description = "A python library and runtime script for managing RPMpackage sources in a git repository" +name = "rpkg" +optional = false +python-versions = "*" +version = "1.60" + +[package.dependencies] +GitPython = "*" +PyYAML = "*" +cccolutils = ">=1.4" +koji = ">=1.15" +pycurl = ">=7.19" +requests = "*" +six = ">=1.9.0" + +[package.source] +reference = "150cf3830c0f65c10a98a5f678959b1757af9bfd" +type = "git" +url = "https://pagure.io/rpkg.git" + +[[package]] +category = "main" +description = "Placeholder pending proper publication of RPM Python bindings" +name = "rpm" +optional = false +python-versions = "*" +version = "0.0.2" + +[[package]] +category = "main" +description = "Python 2 and 3 compatibility utilities" +name = "six" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +version = "1.15.0" + +[[package]] +category = "main" +description = "A pure Python implementation of a sliding window memory map manager" +name = "smmap" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "3.0.4" + +[[package]] +category = "dev" +description = "ANSII Color formatting for output in terminal." +name = "termcolor" +optional = false +python-versions = "*" +version = "1.1.0" + +[[package]] +category = "dev" +description = "Python Library for Tom's Obvious, Minimal Language" +name = "toml" +optional = false +python-versions = "*" +version = "0.10.1" + +[[package]] +category = "main" +description = "HTTP library with thread-safe connection pooling, file post, and more." +name = "urllib3" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" +version = "1.25.10" + +[package.extras] +brotli = ["brotlipy (>=0.6.0)"] +secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "pyOpenSSL (>=0.14)", "ipaddress"] +socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7,<2.0)"] + +[[package]] +category = "dev" +description = "Backport of pathlib-compatible object wrapper for zip files" +marker = "python_version < \"3.8\"" +name = "zipp" +optional = false +python-versions = ">=3.6" +version = "3.1.0" + +[package.extras] +docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"] +testing = ["jaraco.itertools", "func-timeout"] + +[metadata] +content-hash = "bd73404e786deb9455d3c4d9506e2169c62b010e98ccae365329837c3d2d9224" +python-versions = "^3.6" + +[metadata.files] +atomicwrites = [ + {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"}, + {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"}, +] +attrs = [ + {file = "attrs-20.1.0-py2.py3-none-any.whl", hash = "sha256:2867b7b9f8326499ab5b0e2d12801fa5c98842d2cbd22b35112ae04bf85b4dff"}, + {file = "attrs-20.1.0.tar.gz", hash = "sha256:0ef97238856430dcf9228e07f316aefc17e8939fc8507e18c6501b761ef1a42a"}, +] +cccolutils = [ + {file = "CCColUtils-1.5.tar.gz", hash = "sha256:6332a31b8ddb8916d364ab734941c786dcce7dc65fcc84870c5a25ab3ac18cbf"}, +] +certifi = [ + {file = "certifi-2020.6.20-py2.py3-none-any.whl", hash = "sha256:8fc0819f1f30ba15bdb34cceffb9ef04d99f420f68eb75d901e9560b8749fc41"}, + {file = "certifi-2020.6.20.tar.gz", hash = "sha256:5930595817496dd21bb8dc35dad090f1c2cd0adfaf21204bf6732ca5d8ee34d3"}, +] +cffi = [ + {file = "cffi-1.14.2-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:da9d3c506f43e220336433dffe643fbfa40096d408cb9b7f2477892f369d5f82"}, + {file = "cffi-1.14.2-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:23e44937d7695c27c66a54d793dd4b45889a81b35c0751ba91040fe825ec59c4"}, + {file = "cffi-1.14.2-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:0da50dcbccd7cb7e6c741ab7912b2eff48e85af217d72b57f80ebc616257125e"}, + {file = "cffi-1.14.2-cp27-cp27m-win32.whl", hash = "sha256:76ada88d62eb24de7051c5157a1a78fd853cca9b91c0713c2e973e4196271d0c"}, + {file = "cffi-1.14.2-cp27-cp27m-win_amd64.whl", hash = "sha256:15a5f59a4808f82d8ec7364cbace851df591c2d43bc76bcbe5c4543a7ddd1bf1"}, + {file = "cffi-1.14.2-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:e4082d832e36e7f9b2278bc774886ca8207346b99f278e54c9de4834f17232f7"}, + {file = "cffi-1.14.2-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:57214fa5430399dffd54f4be37b56fe22cedb2b98862550d43cc085fb698dc2c"}, + {file = "cffi-1.14.2-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:6843db0343e12e3f52cc58430ad559d850a53684f5b352540ca3f1bc56df0731"}, + {file = "cffi-1.14.2-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:577791f948d34d569acb2d1add5831731c59d5a0c50a6d9f629ae1cefd9ca4a0"}, + {file = "cffi-1.14.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:8662aabfeab00cea149a3d1c2999b0731e70c6b5bac596d95d13f643e76d3d4e"}, + {file = "cffi-1.14.2-cp35-cp35m-win32.whl", hash = "sha256:837398c2ec00228679513802e3744d1e8e3cb1204aa6ad408b6aff081e99a487"}, + {file = "cffi-1.14.2-cp35-cp35m-win_amd64.whl", hash = "sha256:bf44a9a0141a082e89c90e8d785b212a872db793a0080c20f6ae6e2a0ebf82ad"}, + {file = "cffi-1.14.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:29c4688ace466a365b85a51dcc5e3c853c1d283f293dfcc12f7a77e498f160d2"}, + {file = "cffi-1.14.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:99cc66b33c418cd579c0f03b77b94263c305c389cb0c6972dac420f24b3bf123"}, + {file = "cffi-1.14.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:65867d63f0fd1b500fa343d7798fa64e9e681b594e0a07dc934c13e76ee28fb1"}, + {file = "cffi-1.14.2-cp36-cp36m-win32.whl", hash = "sha256:f5033952def24172e60493b68717792e3aebb387a8d186c43c020d9363ee7281"}, + {file = "cffi-1.14.2-cp36-cp36m-win_amd64.whl", hash = "sha256:7057613efefd36cacabbdbcef010e0a9c20a88fc07eb3e616019ea1692fa5df4"}, + {file = "cffi-1.14.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6539314d84c4d36f28d73adc1b45e9f4ee2a89cdc7e5d2b0a6dbacba31906798"}, + {file = "cffi-1.14.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:672b539db20fef6b03d6f7a14b5825d57c98e4026401fce838849f8de73fe4d4"}, + {file = "cffi-1.14.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:95e9094162fa712f18b4f60896e34b621df99147c2cee216cfa8f022294e8e9f"}, + {file = "cffi-1.14.2-cp37-cp37m-win32.whl", hash = "sha256:b9aa9d8818c2e917fa2c105ad538e222a5bce59777133840b93134022a7ce650"}, + {file = "cffi-1.14.2-cp37-cp37m-win_amd64.whl", hash = "sha256:e4b9b7af398c32e408c00eb4e0d33ced2f9121fd9fb978e6c1b57edd014a7d15"}, + {file = "cffi-1.14.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e613514a82539fc48291d01933951a13ae93b6b444a88782480be32245ed4afa"}, + {file = "cffi-1.14.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:9b219511d8b64d3fa14261963933be34028ea0e57455baf6781fe399c2c3206c"}, + {file = "cffi-1.14.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:c0b48b98d79cf795b0916c57bebbc6d16bb43b9fc9b8c9f57f4cf05881904c75"}, + {file = "cffi-1.14.2-cp38-cp38-win32.whl", hash = "sha256:15419020b0e812b40d96ec9d369b2bc8109cc3295eac6e013d3261343580cc7e"}, + {file = "cffi-1.14.2-cp38-cp38-win_amd64.whl", hash = "sha256:12a453e03124069b6896107ee133ae3ab04c624bb10683e1ed1c1663df17c13c"}, + {file = "cffi-1.14.2.tar.gz", hash = "sha256:ae8f34d50af2c2154035984b8b5fc5d9ed63f32fe615646ab435b05b132ca91b"}, +] +chardet = [ + {file = "chardet-3.0.4-py2.py3-none-any.whl", hash = "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"}, + {file = "chardet-3.0.4.tar.gz", hash = "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"}, +] +colorama = [ + {file = "colorama-0.4.3-py2.py3-none-any.whl", hash = "sha256:7d73d2a99753107a36ac6b455ee49046802e59d9d076ef8e47b61499fa29afff"}, + {file = "colorama-0.4.3.tar.gz", hash = "sha256:e96da0d330793e2cb9485e9ddfd918d456036c7149416295932478192f4436a1"}, +] +cryptography = [ + {file = "cryptography-3.1-cp27-cp27m-macosx_10_10_x86_64.whl", hash = "sha256:969ae512a250f869c1738ca63be843488ff5cc031987d302c1f59c7dbe1b225f"}, + {file = "cryptography-3.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:b45ab1c6ece7c471f01c56f5d19818ca797c34541f0b2351635a5c9fe09ac2e0"}, + {file = "cryptography-3.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:247df238bc05c7d2e934a761243bfdc67db03f339948b1e2e80c75d41fc7cc36"}, + {file = "cryptography-3.1-cp27-cp27m-win32.whl", hash = "sha256:10c9775a3f31610cf6b694d1fe598f2183441de81cedcf1814451ae53d71b13a"}, + {file = "cryptography-3.1-cp27-cp27m-win_amd64.whl", hash = "sha256:9f734423eb9c2ea85000aa2476e0d7a58e021bc34f0a373ac52a5454cd52f791"}, + {file = "cryptography-3.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:e7563eb7bc5c7e75a213281715155248cceba88b11cb4b22957ad45b85903761"}, + {file = "cryptography-3.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:94191501e4b4009642be21dde2a78bd3c2701a81ee57d3d3d02f1d99f8b64a9e"}, + {file = "cryptography-3.1-cp35-abi3-macosx_10_10_x86_64.whl", hash = "sha256:dc3f437ca6353979aace181f1b790f0fc79e446235b14306241633ab7d61b8f8"}, + {file = "cryptography-3.1-cp35-abi3-manylinux1_x86_64.whl", hash = "sha256:725875681afe50b41aee7fdd629cedbc4720bab350142b12c55c0a4d17c7416c"}, + {file = "cryptography-3.1-cp35-abi3-manylinux2010_x86_64.whl", hash = "sha256:321761d55fb7cb256b771ee4ed78e69486a7336be9143b90c52be59d7657f50f"}, + {file = "cryptography-3.1-cp35-abi3-manylinux2014_aarch64.whl", hash = "sha256:2a27615c965173c4c88f2961cf18115c08fedfb8bdc121347f26e8458dc6d237"}, + {file = "cryptography-3.1-cp35-cp35m-win32.whl", hash = "sha256:e7dad66a9e5684a40f270bd4aee1906878193ae50a4831922e454a2a457f1716"}, + {file = "cryptography-3.1-cp35-cp35m-win_amd64.whl", hash = "sha256:4005b38cd86fc51c955db40b0f0e52ff65340874495af72efabb1bb8ca881695"}, + {file = "cryptography-3.1-cp36-abi3-win32.whl", hash = "sha256:cc6096c86ec0de26e2263c228fb25ee01c3ff1346d3cfc219d67d49f303585af"}, + {file = "cryptography-3.1-cp36-abi3-win_amd64.whl", hash = "sha256:2e26223ac636ca216e855748e7d435a1bf846809ed12ed898179587d0cf74618"}, + {file = "cryptography-3.1-cp36-cp36m-win32.whl", hash = "sha256:7a63e97355f3cd77c94bd98c59cb85fe0efd76ea7ef904c9b0316b5bbfde6ed1"}, + {file = "cryptography-3.1-cp36-cp36m-win_amd64.whl", hash = "sha256:4b9e96543d0784acebb70991ebc2dbd99aa287f6217546bb993df22dd361d41c"}, + {file = "cryptography-3.1-cp37-cp37m-win32.whl", hash = "sha256:eb80a288e3cfc08f679f95da72d2ef90cb74f6d8a8ba69d2f215c5e110b2ca32"}, + {file = "cryptography-3.1-cp37-cp37m-win_amd64.whl", hash = "sha256:180c9f855a8ea280e72a5d61cf05681b230c2dce804c48e9b2983f491ecc44ed"}, + {file = "cryptography-3.1-cp38-cp38-win32.whl", hash = "sha256:fa7fbcc40e2210aca26c7ac8a39467eae444d90a2c346cbcffd9133a166bcc67"}, + {file = "cryptography-3.1-cp38-cp38-win_amd64.whl", hash = "sha256:548b0818e88792318dc137d8b1ec82a0ab0af96c7f0603a00bb94f896fbf5e10"}, + {file = "cryptography-3.1.tar.gz", hash = "sha256:26409a473cc6278e4c90f782cd5968ebad04d3911ed1c402fc86908c17633e08"}, +] +decorator = [ + {file = "decorator-4.4.2-py2.py3-none-any.whl", hash = "sha256:41fa54c2a0cc4ba648be4fd43cff00aedf5b9465c9bf18d64325bc225f08f760"}, + {file = "decorator-4.4.2.tar.gz", hash = "sha256:e3a62f0520172440ca0dcc823749319382e377f37f140a0b99ef45fecb84bfe7"}, +] +gitdb = [ + {file = "gitdb-4.0.5-py3-none-any.whl", hash = "sha256:91f36bfb1ab7949b3b40e23736db18231bf7593edada2ba5c3a174a7b23657ac"}, + {file = "gitdb-4.0.5.tar.gz", hash = "sha256:c9e1f2d0db7ddb9a704c2a0217be31214e91a4fe1dea1efad19ae42ba0c285c9"}, +] +gitpython = [ + {file = "GitPython-3.1.8-py3-none-any.whl", hash = "sha256:1858f4fd089abe92ae465f01d5aaaf55e937eca565fb2c1fce35a51b5f85c910"}, + {file = "GitPython-3.1.8.tar.gz", hash = "sha256:080bf8e2cf1a2b907634761c2eaefbe83b69930c94c66ad11b65a8252959f912"}, +] +gssapi = [ + {file = "gssapi-1.6.9-cp36-cp36m-win_amd64.whl", hash = "sha256:7b5055a191bf89e7a3f5241d8f817143d6ca092ef3f2c9166f888382c1fcd442"}, + {file = "gssapi-1.6.9-cp37-cp37m-win_amd64.whl", hash = "sha256:866522a7858a2006b5aae784a01cb01f00ebcff150beb3fc69625e7d36048740"}, + {file = "gssapi-1.6.9-cp38-cp38-win_amd64.whl", hash = "sha256:7ec548f34e1d6520f0ad8bda19ae0708cbeb0b3bbf04c30ac99e0ca1d8401d2a"}, + {file = "gssapi-1.6.9.tar.gz", hash = "sha256:0b0aac7138abd3c6d2d8b8400e83933c04a811734456e387e3cb7d59ec4547b9"}, +] +idna = [ + {file = "idna-2.10-py2.py3-none-any.whl", hash = "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"}, + {file = "idna-2.10.tar.gz", hash = "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6"}, +] +importlib-metadata = [ + {file = "importlib_metadata-1.7.0-py2.py3-none-any.whl", hash = "sha256:dc15b2969b4ce36305c51eebe62d418ac7791e9a157911d58bfb1f9ccd8e2070"}, + {file = "importlib_metadata-1.7.0.tar.gz", hash = "sha256:90bb658cdbbf6d1735b6341ce708fc7024a3e14e99ffdc5783edea9f9b077f83"}, +] +iniconfig = [ + {file = "iniconfig-1.0.1-py3-none-any.whl", hash = "sha256:80cf40c597eb564e86346103f609d74efce0f6b4d4f30ec8ce9e2c26411ba437"}, + {file = "iniconfig-1.0.1.tar.gz", hash = "sha256:e5f92f89355a67de0595932a6c6c02ab4afddc6fcdc0bfc5becd0d60884d3f69"}, +] +koji = [ + {file = "koji-1.22.0-py2-none-any.whl", hash = "sha256:767150fa94b87ed20f311b6c8d14adcf47a455e704a80fa947d846ee3c05d4f9"}, + {file = "koji-1.22.0-py3-none-any.whl", hash = "sha256:c1a2db19eb416d8127aa5b828ecc5a059f7831b51a4043eda1530ed7d3b8c9eb"}, + {file = "koji-1.22.0.tar.gz", hash = "sha256:fd40bfee1e930054a172f0bb2da262300423a636d1091b077a7b61177e16d129"}, +] +more-itertools = [ + {file = "more-itertools-8.5.0.tar.gz", hash = "sha256:6f83822ae94818eae2612063a5101a7311e68ae8002005b5e05f03fd74a86a20"}, + {file = "more_itertools-8.5.0-py3-none-any.whl", hash = "sha256:9b30f12df9393f0d28af9210ff8efe48d10c94f73e5daf886f10c4b0b0b4f03c"}, +] +packaging = [ + {file = "packaging-20.4-py2.py3-none-any.whl", hash = "sha256:998416ba6962ae7fbd6596850b80e17859a5753ba17c32284f67bfff33784181"}, + {file = "packaging-20.4.tar.gz", hash = "sha256:4357f74f47b9c12db93624a82154e9b120fa8293699949152b22065d556079f8"}, +] +pluggy = [ + {file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"}, + {file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"}, +] +py = [ + {file = "py-1.9.0-py2.py3-none-any.whl", hash = "sha256:366389d1db726cd2fcfc79732e75410e5fe4d31db13692115529d34069a043c2"}, + {file = "py-1.9.0.tar.gz", hash = "sha256:9ca6883ce56b4e8da7e79ac18787889fa5206c79dcc67fb065376cd2fe03f342"}, +] +pycparser = [ + {file = "pycparser-2.20-py2.py3-none-any.whl", hash = "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"}, + {file = "pycparser-2.20.tar.gz", hash = "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0"}, +] +pycurl = [ + {file = "pycurl-7.43.0.6.tar.gz", hash = "sha256:8301518689daefa53726b59ded6b48f33751c383cf987b0ccfbbc4ed40281325"}, +] +pyopenssl = [ + {file = "pyOpenSSL-19.1.0-py2.py3-none-any.whl", hash = "sha256:621880965a720b8ece2f1b2f54ea2071966ab00e2970ad2ce11d596102063504"}, + {file = "pyOpenSSL-19.1.0.tar.gz", hash = "sha256:9a24494b2602aaf402be5c9e30a0b82d4a5c67528fe8fb475e3f3bc00dd69507"}, +] +pyparsing = [ + {file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"}, + {file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"}, +] +pytest = [ + {file = "pytest-6.0.1-py3-none-any.whl", hash = "sha256:8b6007800c53fdacd5a5c192203f4e531eb2a1540ad9c752e052ec0f7143dbad"}, + {file = "pytest-6.0.1.tar.gz", hash = "sha256:85228d75db9f45e06e57ef9bf4429267f81ac7c0d742cc9ed63d09886a9fe6f4"}, +] +pytest-sugar = [ + {file = "pytest-sugar-0.9.4.tar.gz", hash = "sha256:b1b2186b0a72aada6859bea2a5764145e3aaa2c1cfbb23c3a19b5f7b697563d3"}, +] +python-dateutil = [ + {file = "python-dateutil-2.8.1.tar.gz", hash = "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c"}, + {file = "python_dateutil-2.8.1-py2.py3-none-any.whl", hash = "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a"}, +] +pyyaml = [ + {file = "PyYAML-5.3.1-cp27-cp27m-win32.whl", hash = "sha256:74809a57b329d6cc0fdccee6318f44b9b8649961fa73144a98735b0aaf029f1f"}, + {file = "PyYAML-5.3.1-cp27-cp27m-win_amd64.whl", hash = "sha256:240097ff019d7c70a4922b6869d8a86407758333f02203e0fc6ff79c5dcede76"}, + {file = "PyYAML-5.3.1-cp35-cp35m-win32.whl", hash = "sha256:4f4b913ca1a7319b33cfb1369e91e50354d6f07a135f3b901aca02aa95940bd2"}, + {file = "PyYAML-5.3.1-cp35-cp35m-win_amd64.whl", hash = "sha256:cc8955cfbfc7a115fa81d85284ee61147059a753344bc51098f3ccd69b0d7e0c"}, + {file = "PyYAML-5.3.1-cp36-cp36m-win32.whl", hash = "sha256:7739fc0fa8205b3ee8808aea45e968bc90082c10aef6ea95e855e10abf4a37b2"}, + {file = "PyYAML-5.3.1-cp36-cp36m-win_amd64.whl", hash = "sha256:69f00dca373f240f842b2931fb2c7e14ddbacd1397d57157a9b005a6a9942648"}, + {file = "PyYAML-5.3.1-cp37-cp37m-win32.whl", hash = "sha256:d13155f591e6fcc1ec3b30685d50bf0711574e2c0dfffd7644babf8b5102ca1a"}, + {file = "PyYAML-5.3.1-cp37-cp37m-win_amd64.whl", hash = "sha256:73f099454b799e05e5ab51423c7bcf361c58d3206fa7b0d555426b1f4d9a3eaf"}, + {file = "PyYAML-5.3.1-cp38-cp38-win32.whl", hash = "sha256:06a0d7ba600ce0b2d2fe2e78453a470b5a6e000a985dd4a4e54e436cc36b0e97"}, + {file = "PyYAML-5.3.1-cp38-cp38-win_amd64.whl", hash = "sha256:95f71d2af0ff4227885f7a6605c37fd53d3a106fcab511b8860ecca9fcf400ee"}, + {file = "PyYAML-5.3.1.tar.gz", hash = "sha256:b8eac752c5e14d3eca0e6dd9199cd627518cb5ec06add0de9d32baeee6fe645d"}, +] +requests = [ + {file = "requests-2.24.0-py2.py3-none-any.whl", hash = "sha256:fe75cc94a9443b9246fc7049224f75604b113c36acb93f87b80ed42c44cbb898"}, + {file = "requests-2.24.0.tar.gz", hash = "sha256:b3559a131db72c33ee969480840fff4bb6dd111de7dd27c8ee1f820f4f00231b"}, +] +requests-gssapi = [ + {file = "requests-gssapi-1.2.2.tar.gz", hash = "sha256:bbc6abbde8744c154a508638e5c7e226611acdbbdce454463af27bd7d0d0bee9"}, +] +rpkg = [] +rpm = [ + {file = "rpm-0.0.2-py2.py3-none-any.whl", hash = "sha256:508ff9f220ccafb497455d874debab585eea0e7ebeff0eb7dc569a44be42c269"}, + {file = "rpm-0.0.2.tar.gz", hash = "sha256:3f48ec380cd048cef08d0af9585be3c3a4422c86d1866492baaf03650d13a8e1"}, +] +six = [ + {file = "six-1.15.0-py2.py3-none-any.whl", hash = "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"}, + {file = "six-1.15.0.tar.gz", hash = "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259"}, +] +smmap = [ + {file = "smmap-3.0.4-py2.py3-none-any.whl", hash = "sha256:54c44c197c819d5ef1991799a7e30b662d1e520f2ac75c9efbeb54a742214cf4"}, + {file = "smmap-3.0.4.tar.gz", hash = "sha256:9c98bbd1f9786d22f14b3d4126894d56befb835ec90cef151af566c7e19b5d24"}, +] +termcolor = [ + {file = "termcolor-1.1.0.tar.gz", hash = "sha256:1d6d69ce66211143803fbc56652b41d73b4a400a2891d7bf7a1cdf4c02de613b"}, +] +toml = [ + {file = "toml-0.10.1-py2.py3-none-any.whl", hash = "sha256:bda89d5935c2eac546d648028b9901107a595863cb36bae0c73ac804a9b4ce88"}, + {file = "toml-0.10.1.tar.gz", hash = "sha256:926b612be1e5ce0634a2ca03470f95169cf16f939018233a670519cb4ac58b0f"}, +] +urllib3 = [ + {file = "urllib3-1.25.10-py2.py3-none-any.whl", hash = "sha256:e7983572181f5e1522d9c98453462384ee92a0be7fac5f1413a1e35c56cc0461"}, + {file = "urllib3-1.25.10.tar.gz", hash = "sha256:91056c15fa70756691db97756772bb1eb9678fa585d9184f24534b100dc60f4a"}, +] +zipp = [ + {file = "zipp-3.1.0-py3-none-any.whl", hash = "sha256:aa36550ff0c0b7ef7fa639055d797116ee891440eac1a56f378e2d3179e0320b"}, + {file = "zipp-3.1.0.tar.gz", hash = "sha256:c599e4d75c98f6798c509911d08a22e6c021d074469042177c8c86fb92eefd96"}, +] diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..3c08a68 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,25 @@ +[tool.poetry] +name = "centpkg" +version = "0.0.1" +description = "centpkg is a centos cli implementation of rpkg" +authors = ["lrossett "] +license = "GPL-2.0-or-later" +packages = [ + { include = "centpkg", from = "src" }, +] + +[tool.poetry.dependencies] +python = "^3.6" +rpkg = { git = "https://pagure.io/rpkg.git" } +rpm = "^0.0.2" + +[tool.poetry.dev-dependencies] +pytest = "^6.0.1" +pytest-sugar = "^0.9.4" + +[tool.poetry.scripts] +clirun = 'centpkg.cli:run' +[build-system] +requires = ["poetry>=0.12"] +build-backend = "poetry.masonry.api" + diff --git a/setup.py b/setup.py deleted file mode 100644 index d71cd96..0000000 --- a/setup.py +++ /dev/null @@ -1,18 +0,0 @@ -from setuptools import setup - -__version__ = None -execfile('src/centpkg/version.py') - -setup( - name="centpkg", - version=__version__, - author="Brian Stinson", - author_email="brian@bstinson.com", - description="CentOS Plugin to rpkg for managing RPM package sources", - url="http://bitbucket.org/bstinsonmhk/centpkg.git", - license="GPLv2+", - package_dir={'': 'src'}, - packages=['centpkg'], - scripts=['src/bin/centpkg'], - data_files=[('/etc/rpkg',['src/centpkg.conf']),] -) diff --git a/src/bin/cenpkg b/src/bin/cenpkg new file mode 100755 index 0000000..6756800 --- /dev/null +++ b/src/bin/cenpkg @@ -0,0 +1,6 @@ +#!/usr/bin/env python +from centpkg import cli + + +if __name__ == '__main__': + cli.run() diff --git a/src/bin/centpkg b/src/bin/centpkg deleted file mode 100755 index adc5811..0000000 --- a/src/bin/centpkg +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env python -''' - centpkg - a script to interact with CentOS Packages -''' -# -# Author(s): -# Brian Stinson -# Pat Riehecky -# -# 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. See http://www.gnu.org/copyleft/gpl.html for -# the full text of the license. - -from centpkg.__main__ import main - -if __name__ == "__main__": - main() - diff --git a/src/centpkg.conf b/src/centpkg.conf deleted file mode 100644 index 8c24671..0000000 --- a/src/centpkg.conf +++ /dev/null @@ -1,13 +0,0 @@ -[centpkg] -lookaside = https://git.stg.centos.org/sources -lookasidehash = sha1 -lookaside_cgi = https://git.stg.centos.org/sources/upload.cgi -lookaside_request_params = branch -distgit_namespaced = True -distgit_namespaces = rpms -gitbaseurl = https://%(user)s@git.stg.centos.org/%(repo)s.git -anongiturl = https://git.stg.centos.org/%(repo)s -branchre = .+\d$|.+\d-.+|master$ -kojiprofile = cbs -build_client = cbs -clone_config = diff --git a/src/centpkg/__init__.py b/src/centpkg/__init__.py index 166ad6b..e69de29 100644 --- a/src/centpkg/__init__.py +++ b/src/centpkg/__init__.py @@ -1,170 +0,0 @@ -#pylint: disable=line-too-long,abstract-class-not-used -''' - Top level function library for centpkg -''' -# -# Author(s): -# Jesse Keating -# Pat Riehecky -# Brian Stinson -# -# 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. See http://www.gnu.org/copyleft/gpl.html for -# the full text of the license. - - - -import os -import re -import sys -import urlparse -import warnings - -from pyrpkg import Commands, rpkgError -from pyrpkg.layout import ExplodedSRPMLayout, DistGitLayout -from centos import centos_cert -from .lookaside import CentOSLookasideCache -from pyrpkg.utils import cached_property -from . import cli - - -class DistGitDirectory(object): - - signame = None - centosversion = None - projectname = None - releasename = None - distrobranch = False - - def __init__(self, branchtext): - sigtobranchre = r'c(?P\d+)-sig-(?P\w+)-?(?P\w+)?-?(?P\w+)?' - distrobranchre = r'c(?P\d+)-?(?P\w+)?' - oldbranchre = r'(?P\w+)(?P\d)' - sigmatch = re.match(sigtobranchre, branchtext) - distromatch = re.match(distrobranchre, branchtext) - oldbranchmatch = re.match(oldbranchre, branchtext) - if sigmatch: - gd = sigmatch.groupdict() - self.signame = gd['signame'] - self.centosversion = gd['centosversion'] - - # Users have the option to specify (or not specify) common in their - # git repos. Ww need to handle these cases because common is not a - # project nor is it a release. - if gd['projectname'] != 'common': - self.projectname = gd['projectname'] - if gd['releasename'] != 'common': - self.releasename = gd['releasename'] - elif distromatch: - gd = distromatch.groupdict() - self.distrobranch = True - self.signame = 'centos' - self.centosversion = gd['centosversion'] - - if gd['projectname'] != 'common': - self.projectname = gd['projectname'] - elif oldbranchmatch: - warnings.warn("This branch is deprecated and will be removed soon", - DeprecationWarning) - else: - raise ValueError("Branchname: {0} is not valid".format(branchtext)) - - @property - def target(self): - projectorcommon = self.projectname - releaseorcommon = self.releasename - - if self.distrobranch: - return '-'.join(filter(None, ['c'+self.centosversion, - projectorcommon])) - - if not releaseorcommon: - if not projectorcommon or projectorcommon == 'common': - projectorcommon = 'common' - else: - releaseorcommon = 'common' - - return '-'.join(filter(None, [self.signame+self.centosversion, - projectorcommon, releaseorcommon])) + '-el{0}'.format(self.centosversion) - - -class Commands(Commands): - ''' - For the pyrpkg commands with centpkg behavior - ''' - def __init__(self, *args, **kwargs): - ''' - Init the object and some configuration details. - ''' - super(Commands, self).__init__(*args, **kwargs) - - self.source_entry_type = 'old' - - @property - def distgitdir(self): - return DistGitDirectory(self.branch_merge) - - @cached_property - def lookasidecache(self): - return CentOSLookasideCache(self.lookasidehash, - self.lookaside, - self.lookaside_cgi, - self.repo_name, - self.branch_merge) - - # redefined loaders - def load_rpmdefines(self): - ''' - Populate rpmdefines based on branch data - ''' - - if not self.distgitdir.centosversion: - raise rpkgError('Could not get the OS version from the branch:{0}'.format(self.branch_merge)) - - self._distvar = self.distgitdir.centosversion - self._distval = self._distvar.replace('.', '_') - - self._disttag = 'el%s' % self._distval - self._rpmdefines = ["--define '_sourcedir %s'" % self.layout.sourcedir, - "--define '_specdir %s'" % self.layout.specdir, - "--define '_builddir %s'" % self.layout.builddir, - "--define '_srcrpmdir %s'" % self.layout.srcrpmdir, - "--define '_rpmdir %s'" % self.layout.rpmdir, - "--define 'dist .%s'" % self._disttag, - # int and float this to remove the decimal - "--define '%s 1'" % self._disttag] - self.log.debug("RPMDefines: %s" % self._rpmdefines) - - def load_target(self): - """ This sets the target attribute (used for mock and koji) """ - - self._target = self.distgitdir.target - - def load_user(self): - try: - self._user = centos_cert.CentOSUserCert().CN - except Exception: - print >>sys.stderr, "Could not load user from cert file" - super(Commands, self).load_user() - - # These are the commands defined in the base pyrpkg.Commands class - # and have been implemented here - - def upload(self, *args, **kwargs): - if not self.distgitdir.distrobranch: - self.source_entry_type = 'bsd' - return super(Commands, self).upload(*args, **kwargs) - - def import_srpm(self, *args, **kwargs): - raise NotImplementedError("import_srpm is not yet implemented in centpkg") - - def patch(self, *args, **kwargs): - raise NotImplementedError("patch is not yet implemented in centpkg") - - def install(self, *args, **kwargs): - raise NotImplementedError("install is not yet implemented in centpkg") - - def lint(self, *args, **kwargs): - raise NotImplementedError("lint is not yet implemented in centpkg") diff --git a/src/centpkg/__main__.py b/src/centpkg/__main__.py deleted file mode 100644 index db1dcf5..0000000 --- a/src/centpkg/__main__.py +++ /dev/null @@ -1,83 +0,0 @@ -''' - The main behavior of centpkg -''' -# -# Author(s): -# Jesse Keating -# Pat Riehecky -# Brian Stinson -# -# 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. See http://www.gnu.org/copyleft/gpl.html for -# the full text of the license. - -import os -import sys -import logging -import ConfigParser -import argparse - -import fedpkg -import pyrpkg -import centpkg -from pyrpkg.layout import Layout, ExplodedSRPMLayout, DistGitLayout - -def main(): - ''' - Where things actually happen - ''' - parser = argparse.ArgumentParser(add_help=False) - parser.add_argument('-C', '--config', help='The rpkg config file to use', - default='/etc/rpkg/centpkg.conf') - - (args, other) = parser.parse_known_args() - - # Make sure we have a sane config file - if not os.path.exists(args.config) and not other[-1] in ['--help', '-h']: - sys.stderr.write('Invalid config file %s\n' % args.config) - sys.exit(1) - - config = ConfigParser.SafeConfigParser() - config.read(args.config) - - layout = Layout.load() - if isinstance(layout, DistGitLayout): - config.read('/etc/rpkg/fedpkg.conf') - client = fedpkg.cli.fedpkgClient(config, name='fedpkg') - else: - client = centpkg.cli.centpkgClient(config) - - client.do_imports(site=client.DEFAULT_CLI_NAME) - client.parse_cmdline() - - if not client.args.path: - try: - client.args.path = os.getcwd() - except OSError as err_msg: - print('Could not get current path') - print(err_msg) - sys.exit(1) - - log = pyrpkg.log - client.setupLogging(log) - - if client.args.v: - log.setLevel(logging.DEBUG) - elif client.args.q: - log.setLevel(logging.WARNING) - else: - log.setLevel(logging.INFO) - - # Run the necessary command - try: - sys.exit(client.args.command()) - except KeyboardInterrupt: - pass - except Exception, e: - log.error('Could not execute %s: %s' % (client.args.command.__name__, e)) - sys.exit(1) - -if __name__ == '__main__': - main() diff --git a/src/centpkg/api/__init__.py b/src/centpkg/api/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/centpkg/api/__init__.py diff --git a/src/centpkg/api/cli.py b/src/centpkg/api/cli.py new file mode 100644 index 0000000..67fb6e9 --- /dev/null +++ b/src/centpkg/api/cli.py @@ -0,0 +1,19 @@ +import pyrpkg.cli + + +class CentPkgCli(pyrpkg.cli.cliClient): + """ + Centos Package CLI client wrapper, inherits most of its + behaviour from `pyrpkg.cli.cliClient`. + """ + def __init__(self, config, name='centpkg'): + """ + The main class constructor, it needs a dict with config data and a name + which are passed to its RPKG patent class constructor. + + Name defaults to 'centpkg' if none is provided. + + :param config: dict + :param name: str + """ + super(CentPkgCli, self).__init__(config, name=name) diff --git a/src/centpkg/centos_cert.py b/src/centpkg/centos_cert.py deleted file mode 100644 index 854f396..0000000 --- a/src/centpkg/centos_cert.py +++ /dev/null @@ -1,74 +0,0 @@ -import os -from OpenSSL import crypto -import urlgrabber -import datetime - -# This file was modified from the fedora_cert section in fedora-packager written -# by Dennis Gilmore (https://fedorahosted.org/fedora-packager/) - - -# Define our own error class -class centos_cert_error(Exception): - pass - -def _open_cert(): - """ - Read in the certificate so we dont duplicate the code - """ - # Make sure we can even read the thing. - cert_file = os.path.join(os.path.expanduser('~'), ".koji", "client.crt") - if not os.access(cert_file, os.R_OK): - raise centos_cert_error("""!!! cannot read your centos cert file !!! -!!! Ensure the file is readable and try again !!!""") - raw_cert = open(cert_file).read() - my_cert = crypto.load_certificate(crypto.FILETYPE_PEM, raw_cert) - return my_cert - -def verify_cert(): - """ - Check that the user cert is valid. - things to check/return - not revoked - Expiry time warn if less than 21 days - """ - my_cert = _open_cert() - serial_no = my_cert.get_serial_number() - valid_until = my_cert.get_notAfter()[:8] - # CRL verification would go here - #crl = urlgrabber.urlread("https:///ca/crl.pem") - dateFmt = '%Y%m%d' - delta = datetime.datetime.now() + datetime.timedelta(days=21) - warn = datetime.datetime.strftime(delta, dateFmt) - - print 'cert expires: %s-%s-%s' % (valid_until[:4], valid_until[4:6], valid_until[6:8]) - - if valid_until < warn: - print 'WARNING: Your cert expires soon.' - - -def certificate_expired(): - """ - Check to see if client cert is expired - Returns True or False - - """ - my_cert = _open_cert() - - if my_cert.has_expired(): - return True - else: - return False - -def read_user_cert(): - """ - Figure out the Fedora user name from client cert - - """ - my_cert = _open_cert() - - subject = str(my_cert.get_subject()) - subject_line = subject.split("CN=") - cn_parts = subject_line[1].split("/") - username = cn_parts[0] - return username - diff --git a/src/centpkg/cli.py b/src/centpkg/cli.py deleted file mode 100755 index b6c573f..0000000 --- a/src/centpkg/cli.py +++ /dev/null @@ -1,23 +0,0 @@ -''' - Command line behavior for centpkg -''' -# -# Author(s): -# Jesse Keating -# Pat Riehecky -# Brian Stinson -# -# 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. See http://www.gnu.org/copyleft/gpl.html for -# the full text of the license. - -from __future__ import print_function -from pyrpkg.cli import cliClient - - -class centpkgClient(cliClient): - def __init__(self, config, name=None): - self.DEFAULT_CLI_NAME = 'centpkg' - super(centpkgClient, self).__init__(config, name) diff --git a/src/centpkg/cli/__init__.py b/src/centpkg/cli/__init__.py new file mode 100644 index 0000000..3963485 --- /dev/null +++ b/src/centpkg/cli/__init__.py @@ -0,0 +1,67 @@ +import os +import sys +import argparse +import logging +import configparser + +import pyrpkg.utils +# import pyrpkg.cli + +import centpkg.api.cli + + +def get_log(client): + """ + Returns a logging level based on client params. + :param client: pyrpkg.cli.cliClient + :return: str + """ + if client.args.v: + return logging.DEBUG + if client.args.q: + return logging.WARNING + return logging.INFO + + +def run(*args, **kwargs): + """ + Runs centpkg command based on args and kwargs. + It will use sys.argv as cli arguments if no args or kwargs are provided. + + :param args: list + :param kwargs: dict + :return: None + """ + cli_name = 'centpkg' + parser = argparse.ArgumentParser(add_help=False) + parser.add_argument( + '-C', '--config', help='Specify a config file to use', + default='/etc/rpkg/rpkg.conf') + (args, other) = parser.parse_known_args() + + if not os.path.exists(args.config) and not other[-1] in ['--help', '-h']: + sys.stderr.write(f'Invalid config file {cli_name} {args.config}\n') + sys.exit(1) + + config = configparser.SafeConfigParser() + config.read(args.config) + + client = centpkg.api.cli.CentPkgCli(config) + client.do_imports() + client.parse_cmdline() + + if not client.args.path: + try: + client.args.path = pyrpkg.utils.getcwd() + except Exception: + print('Could not get current path, have you deleted it?') + sys.exit(1) + + log = pyrpkg.log + client.setupLogging(log) + log.setLevel(get_log(client)) + + try: + sys.exit(client.args.command()) + except KeyboardInterrupt: + pass diff --git a/src/centpkg/lookaside.py b/src/centpkg/lookaside.py deleted file mode 100644 index 10fece1..0000000 --- a/src/centpkg/lookaside.py +++ /dev/null @@ -1,185 +0,0 @@ -# Copyright (c) 2018 - Red Hat Inc. -# -# 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. See http://www.gnu.org/copyleft/gpl.html for -# the full text of the license. - - -"""Interact with the CentOS lookaside cache - -We need to override the pyrpkg.lookasidecache module to handle our custom -download path. -""" - -import hashlib -import io -import logging -import os -import sys - -import pycurl -import six - -from pyrpkg.errors import DownloadError, InvalidHashType, UploadError -from pyrpkg.lookaside import CGILookasideCache -from six.moves import http_client - - -class CentOSLookasideCache(CGILookasideCache): - def __init__(self, hashtype, download_url, upload_url, name, branch): - super(CentOSLookasideCache, self).__init__( - hashtype, download_url, upload_url, client_cert="/home/bstinson/.centos.cert") - self.branch = branch - - self.download_path = ( - '%(name)s/%(branch)s/%(hash)s') - - def remote_file_exists(self, name, filename, hash): - """Verify whether a file exists on the lookaside cache - - :param str name: The name of the module. (usually the name of the - SRPM). This can include the namespace as well (depending on what - the server side expects). - :param str filename: The name of the file to check for. - :param str hash: The known good hash of the file. - """ - - # RHEL 7 ships pycurl that does not accept unicode. When given unicode - # type it would explode with "unsupported second type in tuple". Let's - # convert to str just to be sure. - # https://bugzilla.redhat.com/show_bug.cgi?id=1241059 - if six.PY2 and isinstance(filename, six.text_type): - filename = filename.encode('utf-8') - - if six.PY2 and isinstance(self.branch, six.text_type): - self.branch = self.branch.encode('utf-8') - - post_data = [('name', name), - ('%ssum' % self.hashtype, hash), - ('branch', self.branch), - ('filename', filename)] - - with io.BytesIO() as buf: - c = pycurl.Curl() - c.setopt(pycurl.URL, self.upload_url) - c.setopt(pycurl.WRITEFUNCTION, buf.write) - c.setopt(pycurl.HTTPPOST, post_data) - - if self.client_cert is not None: - if os.path.exists(self.client_cert): - c.setopt(pycurl.SSLCERT, self.client_cert) - else: - self.log.warning("Missing certificate: %s" - % self.client_cert) - - if self.ca_cert is not None: - if os.path.exists(self.ca_cert): - c.setopt(pycurl.CAINFO, self.ca_cert) - else: - self.log.warning("Missing certificate: %s", self.ca_cert) - - c.setopt(pycurl.HTTPAUTH, pycurl.HTTPAUTH_GSSNEGOTIATE) - c.setopt(pycurl.USERPWD, ':') - - try: - c.perform() - status = c.getinfo(pycurl.RESPONSE_CODE) - - except Exception as e: - raise UploadError(e) - - finally: - c.close() - - output = buf.getvalue().strip() - - if status != 200: - self.raise_upload_error(status) - - # Lookaside CGI script returns these strings depending on whether - # or not the file exists: - if output == b'Available': - return True - - if output == b'Missing': - return False - - # Something unexpected happened - self.log.debug(output) - raise UploadError('Error checking for %s at %s' - % (filename, self.upload_url)) - - def upload(self, name, filepath, hash): - """Upload a source file - - :param str name: The name of the module. (usually the name of the SRPM) - This can include the namespace as well (depending on what the - server side expects). - :param str filepath: The full path to the file to upload. - :param str hash: The known good hash of the file. - """ - filename = os.path.basename(filepath) - - # As in remote_file_exists, we need to convert unicode strings to str - if six.PY2: - if isinstance(name, six.text_type): - name = name.encode('utf-8') - if isinstance(filepath, six.text_type): - filepath = filepath.encode('utf-8') - - if self.remote_file_exists(name, filename, hash): - self.log.info("File already uploaded: %s", filepath) - return - - self.log.info("Uploading: %s", filepath) - post_data = [('name', name), - ('%ssum' % self.hashtype, hash), - ('branch', self.branch), - ('file', (pycurl.FORM_FILE, filepath))] - - with io.BytesIO() as buf: - c = pycurl.Curl() - c.setopt(pycurl.URL, self.upload_url) - c.setopt(pycurl.NOPROGRESS, False) - c.setopt(pycurl.PROGRESSFUNCTION, self.print_progress) - c.setopt(pycurl.WRITEFUNCTION, buf.write) - c.setopt(pycurl.HTTPPOST, post_data) - - if self.client_cert is not None: - if os.path.exists(self.client_cert): - c.setopt(pycurl.SSLCERT, self.client_cert) - else: - self.log.warning("Missing certificate: %s", self.client_cert) - - if self.ca_cert is not None: - if os.path.exists(self.ca_cert): - c.setopt(pycurl.CAINFO, self.ca_cert) - else: - self.log.warning("Missing certificate: %s", self.ca_cert) - - c.setopt(pycurl.HTTPAUTH, pycurl.HTTPAUTH_GSSNEGOTIATE) - c.setopt(pycurl.USERPWD, ':') - - try: - c.perform() - status = c.getinfo(pycurl.RESPONSE_CODE) - - except Exception as e: - raise UploadError(e) - - finally: - c.close() - - output = buf.getvalue().strip() - - # Get back a new line, after displaying the download progress - sys.stdout.write('\n') - sys.stdout.flush() - - if status != 200: - self.raise_upload_error(status) - - if output: - self.log.debug(output) diff --git a/src/centpkg/version.py b/src/centpkg/version.py deleted file mode 100644 index ab45471..0000000 --- a/src/centpkg/version.py +++ /dev/null @@ -1 +0,0 @@ -__version__ = '0.4.6' diff --git a/tests/__init__.py b/tests/__init__.py index 6c4d60c..e69de29 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1,6 +0,0 @@ -import os -import sys - -sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), - '../src')) - diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..f39ab84 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,6 @@ +import sys +import os + + +cwd = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(f'{cwd}/../src/') diff --git a/tests/mixins.py b/tests/mixins.py deleted file mode 100644 index 49add16..0000000 --- a/tests/mixins.py +++ /dev/null @@ -1,35 +0,0 @@ -import warnings - -__unittest=True - -class _AssertWarnsContext(object): - def __init__(self, warningtype, testcase, msg=''): - self.warningtype = warningtype - warnings.filterwarnings('error') - self.failureException = testcase.failureException - - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_value, tb): - if exc_type is None: - try: - exc_name = self.warningtype.__name__ - except AttributeError: - exc_name = str(self.warningtype) - raise self.failureException( - "{0} not raised".format(exc_name)) - - if not issubclass(exc_type, self.warningtype): - raise self.failureException('"%s" does not match "%s"' % - (self.warningtype.__name__, str(exc_type.__name__))) - - return True - -class CatchWarningsMixin(object): - def assertWarns(self, wrnClass, callableObj=None, *args, **kwargs): - context = _AssertWarnsContext(wrnClass, self) - if callableObj is None: - return context - with context: - callableObj(*args, **kwargs) diff --git a/tests/test_cli.py b/tests/test_cli.py new file mode 100644 index 0000000..aaf78a1 --- /dev/null +++ b/tests/test_cli.py @@ -0,0 +1,5 @@ +from centpkg import cli + + +def test_cli(): + assert 1 == 1 diff --git a/tests/test_distgit.py b/tests/test_distgit.py deleted file mode 100644 index 4081522..0000000 --- a/tests/test_distgit.py +++ /dev/null @@ -1,182 +0,0 @@ -import unittest - -from mixins import CatchWarningsMixin -from centpkg import DistGitDirectory - -class TestDistGitNothing(unittest.TestCase): - def test_distgit_emptystring(self): - with self.assertRaises(TypeError): - d = DistGitDirectory() - -class TestDistGitInvalid(unittest.TestCase): - def test_invalid_branchstring_raises(self): - self.branchstring = 'nope-not-a-branch' - - with self.assertRaises(ValueError): - self.d = DistGitDirectory(self.branchstring) - -class TestDistgitOnlySig(unittest.TestCase): - def setUp(self): - self.branchstring = 'sig-cloud7' - self.d = DistGitDirectory(self.branchstring) - - def test_signame_gets_set(self): - self.assertEqual(self.d.signame, 'cloud') - - def test_centosversion_gets_set(self): - self.assertEqual(self.d.centosversion, '7') - - def test_projectname_gets_set(self): - self.assertEqual(self.d.projectname, None) - - def test_releasename_gets_set(self): - self.assertEqual(self.d.releasename, None) - - def test_target_gets_set(self): - self.assertEqual(self.d.target, 'cloud7-common-el7') - -class TestDistgitSigAndCommon(unittest.TestCase): - def setUp(self): - self.branchstring = 'sig-cloud7-common' - self.d = DistGitDirectory(self.branchstring) - - def test_signame_gets_set(self): - self.assertEqual(self.d.signame, 'cloud') - - def test_centosversion_gets_set(self): - self.assertEqual(self.d.centosversion, '7') - - def test_projectname_gets_set(self): - self.assertEqual(self.d.projectname, None) - - def test_releasename_gets_set(self): - self.assertEqual(self.d.releasename, None) - - def test_target_gets_set(self): - self.assertEqual(self.d.target, 'cloud7-common-el7') - -class TestDistgitSigAndProject(unittest.TestCase): - def setUp(self): - self.branchstring = 'sig-cloud7-openstack' - self.d = DistGitDirectory(self.branchstring) - - def test_signame_gets_set(self): - self.assertEqual(self.d.signame, 'cloud') - - def test_centosversion_gets_set(self): - self.assertEqual(self.d.centosversion, '7') - - def test_projectname_gets_set(self): - self.assertEqual(self.d.projectname, 'openstack') - - def test_releasename_gets_set(self): - self.assertEqual(self.d.releasename, None) - - def test_target_gets_set(self): - self.assertEqual(self.d.target, 'cloud7-openstack-common-el7') - -class TestDistgitSigProjectAndCommon(unittest.TestCase): - def setUp(self): - self.branchstring = 'sig-cloud7-openstack-common' - self.d = DistGitDirectory(self.branchstring) - - def test_signame_gets_set(self): - self.assertEqual(self.d.signame, 'cloud') - - def test_centosversion_gets_set(self): - self.assertEqual(self.d.centosversion, '7') - - def test_projectname_gets_set(self): - self.assertEqual(self.d.projectname, 'openstack') - - def test_releasename_gets_set(self): - self.assertEqual(self.d.releasename, None) - - def test_target_gets_set(self): - self.assertEqual(self.d.target, 'cloud7-openstack-common-el7') - -class TestDistgitSigProjectAndRelease(unittest.TestCase): - def setUp(self): - self.branchstring = 'sig-cloud7-openstack-kilo' - self.d = DistGitDirectory(self.branchstring) - - def test_signame_gets_set(self): - self.assertEqual(self.d.signame, 'cloud') - - def test_centosversion_gets_set(self): - self.assertEqual(self.d.centosversion, '7') - - def test_projectname_gets_set(self): - self.assertEqual(self.d.projectname, 'openstack') - - def test_releasename_gets_set(self): - self.assertEqual(self.d.releasename, 'kilo') - - def test_target_gets_set(self): - self.assertEqual(self.d.target, 'cloud7-openstack-kilo-el7') - -class TestDistgitC7DistroBranch(unittest.TestCase): - def setUp(self): - self.branchstring = 'c7' - self.d = DistGitDirectory(self.branchstring) - - def test_signame_gets_set(self): - self.assertEqual(self.d.signame, 'centos') - - def test_centosversion_gets_set(self): - self.assertEqual(self.d.centosversion, '7') - - def test_projectname_gets_set(self): - self.assertEqual(self.d.projectname, None) - - def test_releasename_gets_set(self): - self.assertEqual(self.d.releasename, None) - - def test_target_gets_set(self): - self.assertEqual(self.d.target, 'c7') - -class TestDistgitC6DistroBranch(unittest.TestCase): - def setUp(self): - self.branchstring = 'c6' - self.d = DistGitDirectory(self.branchstring) - - def test_signame_gets_set(self): - self.assertEqual(self.d.signame, 'centos') - - def test_centosversion_gets_set(self): - self.assertEqual(self.d.centosversion, '6') - - def test_projectname_gets_set(self): - self.assertEqual(self.d.projectname, None) - - def test_releasename_gets_set(self): - self.assertEqual(self.d.releasename, None) - - def test_target_gets_set(self): - self.assertEqual(self.d.target, 'c6') - -class TestDistgitC6PlusDistroBranch(unittest.TestCase): - def setUp(self): - self.branchstring = 'c6-plus' - self.d = DistGitDirectory(self.branchstring) - - def test_signame_gets_set(self): - self.assertEqual(self.d.signame, 'centos') - - def test_centosversion_gets_set(self): - self.assertEqual(self.d.centosversion, '6') - - def test_projectname_gets_set(self): - self.assertEqual(self.d.projectname, 'plus') - - def test_releasename_gets_set(self): - self.assertEqual(self.d.releasename, None) - - def test_target_gets_set(self): - self.assertEqual(self.d.target, 'c6-plus') - -class TestOldGitBranch(unittest.TestCase, CatchWarningsMixin): - def test_old_branch_warns(self): - with self.assertWarns(DeprecationWarning): - branchstring = 'virt7' - d = DistGitDirectory(branchstring)