openSUSE Commits
Threads by month
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
May 2019
- 1 participants
- 2232 discussions
Hello community,
here is the log from the commit of package python-virtualenvwrapper for openSUSE:Factory checked in at 2019-05-27 08:38:28
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-virtualenvwrapper (Old)
and /work/SRC/openSUSE:Factory/.python-virtualenvwrapper.new.5148 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-virtualenvwrapper"
Mon May 27 08:38:28 2019 rev:23 rq:705276 version:4.8.4
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-virtualenvwrapper/python-virtualenvwrapper.changes 2018-12-24 11:45:57.653209222 +0100
+++ /work/SRC/openSUSE:Factory/.python-virtualenvwrapper.new.5148/python-virtualenvwrapper.changes 2019-05-27 08:38:29.663068425 +0200
@@ -1,0 +2,10 @@
+Fri May 24 14:04:24 UTC 2019 - Tomáš Chvátal <tchvatal(a)suse.com>
+
+- Update to 4.8.4:
+ * various typo / docu fixes
+ * Support for python 3.7
+- Remove virtualenvwrapper-4.2-fix-bashisms.patch as the script
+ looks posix and if it is still applicable it should be sent
+ upstream
+
+-------------------------------------------------------------------
Old:
----
virtualenvwrapper-4.2-fix-bashisms.patch
virtualenvwrapper-4.8.2.tar.gz
New:
----
virtualenvwrapper-4.8.4.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-virtualenvwrapper.spec ++++++
--- /var/tmp/diff_new_pack.aF3x84/_old 2019-05-27 08:38:30.483068105 +0200
+++ /var/tmp/diff_new_pack.aF3x84/_new 2019-05-27 08:38:30.483068105 +0200
@@ -1,7 +1,7 @@
#
# spec file for package python-virtualenvwrapper
#
-# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -19,14 +19,13 @@
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
%bcond_with test
Name: python-virtualenvwrapper
-Version: 4.8.2
+Version: 4.8.4
Release: 0
Summary: Enhancements to virtualenv
License: MIT
Group: Development/Languages/Python
URL: https://virtualenvwrapper.readthedocs.io/
Source: https://files.pythonhosted.org/packages/source/v/virtualenvwrapper/virtuale…
-Patch0: virtualenvwrapper-4.2-fix-bashisms.patch
BuildRequires: %{python_module pbr}
BuildRequires: %{python_module setuptools}
BuildRequires: fdupes
@@ -60,7 +59,6 @@
%prep
%setup -q -n virtualenvwrapper-%{version}
-%patch0 -p1
sed -i -e '1i#!/bin/sh' virtualenvwrapper.sh
%build
++++++ virtualenvwrapper-4.8.2.tar.gz -> virtualenvwrapper-4.8.4.tar.gz ++++++
++++ 22767 lines of diff (skipped)
1
0
Hello community,
here is the log from the commit of package python-warlock for openSUSE:Factory checked in at 2019-05-27 08:38:26
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-warlock (Old)
and /work/SRC/openSUSE:Factory/.python-warlock.new.5148 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-warlock"
Mon May 27 08:38:26 2019 rev:16 rq:705263 version:1.3.3
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-warlock/python-warlock.changes 2018-12-24 11:46:01.497205846 +0100
+++ /work/SRC/openSUSE:Factory/.python-warlock.new.5148/python-warlock.changes 2019-05-27 08:38:26.203069773 +0200
@@ -1,0 +2,8 @@
+Fri May 24 13:56:28 UTC 2019 - Tomáš Chvátal <tchvatal(a)suse.com>
+
+- Update to 1.3.2:
+ * README failed parsing in non utf-8 environments. Enforce encoding. #37
+ * Move unittests to tests/ directory
+ * Upstream no longer ships tests on pypi
+
+-------------------------------------------------------------------
Old:
----
warlock-1.3.0.tar.gz
New:
----
warlock-1.3.3.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-warlock.spec ++++++
--- /var/tmp/diff_new_pack.wDJXvX/_old 2019-05-27 08:38:26.787069546 +0200
+++ /var/tmp/diff_new_pack.wDJXvX/_new 2019-05-27 08:38:26.787069546 +0200
@@ -1,7 +1,7 @@
#
# spec file for package python-warlock
#
-# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -18,25 +18,24 @@
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
Name: python-warlock
-Version: 1.3.0
+Version: 1.3.3
Release: 0
Summary: Python object model built on top of JSON schema
License: Apache-2.0
Group: Development/Languages/Python
-Url: http://github.com/bcwaldon/warlock
+URL: http://github.com/bcwaldon/warlock
Source: https://files.pythonhosted.org/packages/source/w/warlock/warlock-%{version}…
-BuildRequires: %{python_module jsonpatch}
-BuildRequires: %{python_module jsonschema}
+BuildRequires: %{python_module jsonpatch >= 0.7}
+BuildRequires: %{python_module jsonschema >= 0.10}
BuildRequires: %{python_module pytest}
BuildRequires: %{python_module setuptools}
BuildRequires: %{python_module six}
+BuildRequires: fdupes
BuildRequires: python-rpm-macros
Requires: python-jsonpatch >= 0.7
Requires: python-jsonschema >= 0.10
Requires: python-six
-BuildRoot: %{_tmppath}/%{name}-%{version}-build
BuildArch: noarch
-
%python_subpackages
%description
@@ -44,20 +43,21 @@
%prep
%setup -q -n warlock-%{version}
-sed -i "s|jsonschema>=0.7,<1|jsonschema>=0.7,<=1|" requirements.txt
%build
%python_build
%install
%python_install
+%python_expand %fdupes %{buildroot}%{$python_sitelib}
%check
-%python_exec setup.py test
+# tests are not distributed by upstream and github does not
+# use setuptools anymore
%files %{python_files}
-%defattr(-,root,root,-)
%doc README.md
+%license LICENSE
%{python_sitelib}/*
%changelog
++++++ warlock-1.3.0.tar.gz -> warlock-1.3.3.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/warlock-1.3.0/LICENSE new/warlock-1.3.3/LICENSE
--- old/warlock-1.3.0/LICENSE 1970-01-01 01:00:00.000000000 +0100
+++ new/warlock-1.3.3/LICENSE 2019-05-20 08:26:22.000000000 +0200
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/warlock-1.3.0/LICENSE.txt new/warlock-1.3.3/LICENSE.txt
--- old/warlock-1.3.0/LICENSE.txt 2016-06-25 19:38:50.000000000 +0200
+++ new/warlock-1.3.3/LICENSE.txt 1970-01-01 01:00:00.000000000 +0100
@@ -1,202 +0,0 @@
-
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/warlock-1.3.0/MANIFEST.in new/warlock-1.3.3/MANIFEST.in
--- old/warlock-1.3.0/MANIFEST.in 2016-06-25 19:38:50.000000000 +0200
+++ new/warlock-1.3.3/MANIFEST.in 2019-05-20 11:40:24.000000000 +0200
@@ -1,4 +1,4 @@
-include LICENSE.txt
+include LICENSE
include README.md
include requirements.txt
include setup.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/warlock-1.3.0/PKG-INFO new/warlock-1.3.3/PKG-INFO
--- old/warlock-1.3.0/PKG-INFO 2016-06-25 20:13:37.000000000 +0200
+++ new/warlock-1.3.3/PKG-INFO 2019-05-20 12:10:52.000000000 +0200
@@ -1,10 +1,105 @@
-Metadata-Version: 1.0
+Metadata-Version: 2.1
Name: warlock
-Version: 1.3.0
+Version: 1.3.3
Summary: Python object model built on JSON schema and JSON patch.
Home-page: http://github.com/bcwaldon/warlock
Author: Brian Waldon
Author-email: bcwaldon(a)gmail.com
-License: UNKNOWN
-Description: UNKNOWN
+Maintainer: Jan Willhaus
+Maintainer-email: mail(a)janwillhaus.de
+License: Apache-2.0
+Description: # Warlock — self-validating Python objects using JSON schema
+
+ [![PyPI](https://img.shields.io/pypi/v/warlock.svg)][warlock]
+ [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/warlock.svg)][warlock]
+ [![PyPI - Downloads](https://img.shields.io/pypi/dw/warlock.svg)][pypistats]
+
+ [![Build Status](https://travis-ci.org/bcwaldon/warlock.svg?branch=master)][ci-builds]
+ [![Coverage Status](https://coveralls.io/repos/github/bcwaldon/warlock/badge.svg?branch=master)][coveralls]
+
+ ## Installation
+
+ Warlock is [available on PyPI][warlock]:
+
+ ```shell
+ pip install warlock
+ ```
+
+ ## Usage
+
+ 1) Create your schema
+
+ ```python
+ >>> schema = {
+ 'name': 'Country',
+ 'properties': {
+ 'name': {'type': 'string'},
+ 'abbreviation': {'type': 'string'},
+ 'population': {'type': 'integer'},
+ },
+ 'additionalProperties': False,
+ }
+ ```
+
+ 2) Create a model
+
+ ```python
+ >>> import warlock
+ >>> Country = warlock.model_factory(schema)
+ ```
+
+ 3) Create an object using your model
+
+ ```python
+ >>> sweden = Country(name='Sweden', abbreviation='SE')
+ ```
+
+ 4) Let the object validate itself
+
+ ```python
+ >>> sweden.name = 5
+ Traceback (most recent call last):
+ File "<stdin>", line 1, in <module>
+ File "warlock/core.py", line 53, in __setattr__
+ raise InvalidOperation(msg)
+ warlock.core.InvalidOperation: Unable to set 'name' to '5'
+
+ >>> sweden.overlord = 'Bears'
+ Traceback (most recent call last):
+ File "<stdin>", line 1, in <module>
+ File "warlock/core.py", line 53, in __setattr__
+ raise InvalidOperation(msg)
+ warlock.core.InvalidOperation: Unable to set 'overlord' to 'Bears'
+ ```
+
+ 5) Generate a [JSON Patch document](http://tools.ietf.org/html/draft-ietf-appsawg-json-patch) to track changes
+
+ ```python
+ >>> sweden.population=9453000
+ >>> sweden.patch
+ '[{"path": "/population", "value": 9453000, "op": "add"}]'
+ ```
+
+ [warlock]: https://pypi.org/project/warlock/
+ [pip]: https://pip.pypa.io/en/stable/
+ [ci-builds]: https://travis-ci.org/bcwaldon/warlock
+ [coveralls]: https://coveralls.io/github/bcwaldon/warlock?branch=master
+ [pypistats]: https://pypistats.org/packages/warlock
+
+Keywords: JSON schema,JSON patch,model validation
Platform: UNKNOWN
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Intended Audience :: Developers
+Classifier: Operating System :: MacOS :: MacOS X
+Classifier: Operating System :: Microsoft :: Windows
+Classifier: Operating System :: POSIX
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.4
+Classifier: Programming Language :: Python :: 3.5
+Classifier: Programming Language :: Python :: 3.6
+Classifier: Programming Language :: Python :: 3.7
+Classifier: Topic :: Software Development :: Libraries :: Python Modules
+Description-Content-Type: text/markdown
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/warlock-1.3.0/README.md new/warlock-1.3.3/README.md
--- old/warlock-1.3.0/README.md 2016-06-25 19:42:56.000000000 +0200
+++ new/warlock-1.3.3/README.md 2019-05-20 11:40:24.000000000 +0200
@@ -1,11 +1,25 @@
-# Warlock
+# Warlock — self-validating Python objects using JSON schema
-[![Build Status](https://travis-ci.org/bcwaldon/warlock.svg?branch=master)](https://…
+[![PyPI](https://img.shields.io/pypi/v/warlock.svg)][warlock]
+[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/warlock.svg)][warlock]
+[![PyPI - Downloads](https://img.shields.io/pypi/dw/warlock.svg)][pypistats]
-Build self-validating python objects using JSON schemas.
+[![Build Status](https://travis-ci.org/bcwaldon/warlock.svg?branch=master)][ci-builds]
+[![Coverage Status](https://coveralls.io/repos/github/bcwaldon/warlock/badge.svg?branch=master)][coveralls]
+
+## Installation
+
+Warlock is [available on PyPI][warlock]:
+
+```shell
+pip install warlock
+```
+
+## Usage
1) Create your schema
+ ```python
>>> schema = {
'name': 'Country',
'properties': {
@@ -15,22 +29,28 @@
},
'additionalProperties': False,
}
+ ```
2) Create a model
+ ```python
>>> import warlock
>>> Country = warlock.model_factory(schema)
+ ```
3) Create an object using your model
+ ```python
>>> sweden = Country(name='Sweden', abbreviation='SE')
+ ```
4) Let the object validate itself
+ ```python
>>> sweden.name = 5
Traceback (most recent call last):
- File "<stdin>", line 1, in <module>
- File "warlock/core.py", line 53, in __setattr__
+ File "<stdin>", line 1, in <module>
+ File "warlock/core.py", line 53, in __setattr__
raise InvalidOperation(msg)
warlock.core.InvalidOperation: Unable to set 'name' to '5'
@@ -40,9 +60,18 @@
File "warlock/core.py", line 53, in __setattr__
raise InvalidOperation(msg)
warlock.core.InvalidOperation: Unable to set 'overlord' to 'Bears'
+ ```
5) Generate a [JSON Patch document](http://tools.ietf.org/html/draft-ietf-appsawg-json-patch) to track changes
+ ```python
>>> sweden.population=9453000
>>> sweden.patch
'[{"path": "/population", "value": 9453000, "op": "add"}]'
+ ```
+
+[warlock]: https://pypi.org/project/warlock/
+[pip]: https://pip.pypa.io/en/stable/
+[ci-builds]: https://travis-ci.org/bcwaldon/warlock
+[coveralls]: https://coveralls.io/github/bcwaldon/warlock?branch=master
+[pypistats]: https://pypistats.org/packages/warlock
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/warlock-1.3.0/requirements.txt new/warlock-1.3.3/requirements.txt
--- old/warlock-1.3.0/requirements.txt 2016-06-25 19:38:50.000000000 +0200
+++ new/warlock-1.3.3/requirements.txt 2019-05-20 11:40:24.000000000 +0200
@@ -1,3 +1,3 @@
-jsonschema>=0.7,<3
+jsonschema>=0.7,<4
jsonpatch>=0.10,<2
six
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/warlock-1.3.0/setup.cfg new/warlock-1.3.3/setup.cfg
--- old/warlock-1.3.0/setup.cfg 2016-06-25 20:13:37.000000000 +0200
+++ new/warlock-1.3.3/setup.cfg 2019-05-20 12:10:52.000000000 +0200
@@ -4,5 +4,4 @@
[egg_info]
tag_build =
tag_date = 0
-tag_svn_revision = 0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/warlock-1.3.0/setup.py new/warlock-1.3.3/setup.py
--- old/warlock-1.3.0/setup.py 2016-06-25 20:13:05.000000000 +0200
+++ new/warlock-1.3.3/setup.py 2019-05-20 12:07:12.000000000 +0200
@@ -13,22 +13,53 @@
# limitations under the License.
import setuptools
+import io
+import os
def parse_requirements():
- fap = open('requirements.txt', 'r')
+ fap = io.open("requirements.txt", "r", encoding="utf-8")
raw_req = fap.read()
fap.close()
- return raw_req.split('\n')
+ return raw_req.split("\n")
+
+
+def read(fname):
+ with io.open(
+ os.path.join(os.path.dirname(__file__), fname), "r", encoding="utf-8"
+ ) as fp:
+ return fp.read()
setuptools.setup(
- name='warlock',
- version='1.3.0',
- description='Python object model built on JSON schema and JSON patch.',
- author='Brian Waldon',
- author_email='bcwaldon(a)gmail.com',
- url='http://github.com/bcwaldon/warlock',
- packages=['warlock'],
+ name="warlock",
+ version="1.3.3",
+ description="Python object model built on JSON schema and JSON patch.",
+ long_description=read("README.md"),
+ long_description_content_type="text/markdown",
+ keywords=["JSON schema", "JSON patch", "model validation"],
+ author="Brian Waldon",
+ author_email="bcwaldon(a)gmail.com",
+ maintainer="Jan Willhaus",
+ maintainer_email="mail(a)janwillhaus.de",
+ url="http://github.com/bcwaldon/warlock",
+ packages=["warlock"],
install_requires=parse_requirements(),
+ license="Apache-2.0",
+ classifiers=[
+ "Development Status :: 5 - Production/Stable",
+ "Intended Audience :: Developers",
+ "Operating System :: MacOS :: MacOS X",
+ "Operating System :: Microsoft :: Windows",
+ "Operating System :: POSIX",
+ "Programming Language :: Python",
+ "Programming Language :: Python :: 2",
+ "Programming Language :: Python :: 2.7",
+ "Programming Language :: Python :: 3",
+ "Programming Language :: Python :: 3.4",
+ "Programming Language :: Python :: 3.5",
+ "Programming Language :: Python :: 3.6",
+ "Programming Language :: Python :: 3.7",
+ "Topic :: Software Development :: Libraries :: Python Modules",
+ ],
)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/warlock-1.3.0/test/test_core.py new/warlock-1.3.3/test/test_core.py
--- old/warlock-1.3.0/test/test_core.py 2016-06-25 20:04:07.000000000 +0200
+++ new/warlock-1.3.3/test/test_core.py 1970-01-01 01:00:00.000000000 +0100
@@ -1,307 +0,0 @@
-# Copyright 2012 Brian Waldon
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import copy
-import unittest
-import os
-
-import json
-
-import six
-
-import warlock
-
-
-fixture = {
- 'name': 'Country',
- 'properties': {
- 'name': {'type': 'string'},
- 'population': {'type': 'integer'},
- },
- 'additionalProperties': False,
-}
-
-
-complex_fixture = {
- 'name': 'Mixmaster',
- 'properties': {
- 'sub': {'type': 'object',
- 'properties': {'foo': {'type': 'string'}}}
- },
-}
-
-parent_fixture = {
- 'name': 'Parent',
- 'properties': {
- 'name': {'type': 'string'},
- 'children': {'type': 'array', 'items': [{'type': 'object'}]}
- },
- 'required': ['name', 'children']
-}
-
-child_fixture = {
- 'name': 'Child',
- 'properties': {
- 'age': {'type': 'integer'},
- 'mother': {'type': 'object'}
- },
- 'required': ['age', 'mother']
-}
-
-
-nameless_fixture = {
- 'properties': {
- 'name': {'type': 'string'},
- 'population': {'type': 'integer'},
- },
- 'additionalProperties': False,
-}
-
-
-class TestCore(unittest.TestCase):
- def test_create_invalid_object(self):
- Country = warlock.model_factory(fixture)
- self.assertRaises(ValueError, Country, name=1)
-
- def test_class_name_from_unicode_schema_name(self):
- fixture_copy = copy.deepcopy(fixture)
- fixture_copy['name'] = six.text_type(fixture_copy['name'])
- # Can't set class.__name__ to a unicode object, ensure warlock
- # does some magic to make it possible
- warlock.model_factory(fixture_copy)
-
- def test_invalid_operations(self):
- Country = warlock.model_factory(fixture)
- sweden = Country(name='Sweden', population=9379116)
-
- # Ensure a valid object was created
- self.assertEqual(sweden.name, 'Sweden')
- self.assertEqual(sweden.population, 9379116)
-
- # Specific exceptions should be raised for invalid operations
- self.assertRaises(AttributeError, getattr, sweden, 'overlord')
- exc = warlock.InvalidOperation
- self.assertRaises(exc, setattr, sweden, 'overlord', 'Bears')
- self.assertRaises(exc, setattr, sweden, 'name', 5)
- self.assertRaises(exc, setattr, sweden, 'population', 'N/A')
-
- def test_no_mask_arbitrary_properties(self):
- fixture_copy = copy.deepcopy(fixture)
- fixture_copy['additionalProperties'] = {'type': 'string'}
- Country = warlock.model_factory(fixture_copy)
-
- # We should still depend on the schema for validation
- self.assertRaises(ValueError, Country, GDP=56956)
-
- # But arbitrary properties should be allowed if they check out
- sweden = Country(overlord='Waldon')
- sweden.abbreviation = 'SE'
- exc = warlock.InvalidOperation
- self.assertRaises(exc, setattr, sweden, 'abbreviation', 0)
-
- def test_items(self):
- Country = warlock.model_factory(fixture)
- sweden = Country(name='Sweden', population=9379116)
- self.assertEqual(set(list(six.iteritems(sweden))),
- set([('name', 'Sweden'), ('population', 9379116)]))
- self.assertEqual(set(sweden.items()),
- set([('name', 'Sweden'), ('population', 9379116)]))
-
- def test_update(self):
- Country = warlock.model_factory(fixture)
- sweden = Country(name='Sweden', population=9379116)
- exc = warlock.InvalidOperation
- self.assertRaises(exc, sweden.update, {'population': 'N/A'})
- self.assertRaises(exc, sweden.update, {'overloard': 'Bears'})
-
- def test_naming(self):
- Country = warlock.model_factory(fixture)
- self.assertEqual('Country', Country.__name__)
-
- Country2 = warlock.model_factory(fixture, name='Country2')
- self.assertEqual('Country2', Country2.__name__)
-
- nameless = warlock.model_factory(nameless_fixture)
- self.assertEqual('Model', nameless.__name__)
-
- nameless2 = warlock.model_factory(nameless_fixture, name='Country3')
- self.assertEqual('Country3', nameless2.__name__)
-
- def test_deepcopy(self):
- """Make sure we aren't leaking references."""
- Mixmaster = warlock.model_factory(complex_fixture)
- mike = Mixmaster(sub={'foo': 'mike'})
-
- self.assertEquals('mike', mike.sub['foo'])
-
- mike_1 = mike.copy()
- mike_1['sub']['foo'] = 'james'
- self.assertEquals('mike', mike.sub['foo'])
-
- mike_2 = dict(six.iteritems(mike))
- mike_2['sub']['foo'] = 'james'
- self.assertEquals('mike', mike.sub['foo'])
-
- mike_2 = dict(mike.items())
- mike_2['sub']['foo'] = 'james'
- self.assertEquals('mike', mike.sub['foo'])
-
- mike_3_sub = list(six.itervalues(mike))[0]
- mike_3_sub['foo'] = 'james'
- self.assertEquals('mike', mike.sub['foo'])
-
- mike_3_sub = list(mike.values())[0]
- mike_3_sub['foo'] = 'james'
- self.assertEquals('mike', mike.sub['foo'])
-
- def test_forbidden_methods(self):
- Country = warlock.model_factory(fixture)
- sweden = Country(name='Sweden', population=9379116)
- exc = warlock.InvalidOperation
- self.assertRaises(exc, sweden.clear)
- self.assertRaises(exc, sweden.pop, 0)
- self.assertRaises(exc, sweden.popitem)
-
- def test_dict_syntax(self):
- Country = warlock.model_factory(fixture)
- sweden = Country(name='Sweden', population=9379116)
-
- sweden['name'] = 'Finland'
- self.assertEqual('Finland', sweden['name'])
-
- del sweden['name']
- self.assertRaises(AttributeError, getattr, sweden, 'name')
-
- def test_attr_syntax(self):
- Country = warlock.model_factory(fixture)
- sweden = Country(name='Sweden', population=9379116)
-
- sweden.name = 'Finland'
- self.assertEqual('Finland', sweden.name)
-
- delattr(sweden, 'name')
- self.assertRaises(AttributeError, getattr, sweden, 'name')
-
- def test_changes(self):
- Country = warlock.model_factory(fixture)
- sweden = Country(name='Sweden', population=9379116)
- self.assertEqual(sweden.changes, {})
- sweden['name'] = 'Finland'
- self.assertEqual(sweden.changes, {'name': 'Finland'})
- sweden['name'] = 'Norway'
- self.assertEqual(sweden.changes, {'name': 'Norway'})
-
- def test_patch_no_changes(self):
- Country = warlock.model_factory(fixture)
- sweden = Country(name='Sweden', population=9379116)
- self.assertEqual(sweden.patch, '[]')
-
- def test_patch_alter_value(self):
- Country = warlock.model_factory(fixture)
- sweden = Country(name='Sweden', population=9379116)
- sweden['name'] = 'Finland'
- self.assertEqual(
- json.loads(sweden.patch),
- json.loads(
- '[{"path": "/name", "value": "Finland", "op": "replace"}]'))
-
- def test_patch_drop_attribute(self):
- Country = warlock.model_factory(fixture)
- sweden = Country(name='Sweden', population=9379116)
- del sweden['name']
- self.assertEqual(
- json.loads(sweden.patch),
- json.loads('[{"path": "/name", "op": "remove"}]'))
-
- def test_patch_reduce_operations(self):
- Country = warlock.model_factory(fixture)
- sweden = Country(name='Sweden', population=9379116)
-
- sweden['name'] = 'Finland'
- self.assertEqual(
- json.loads(sweden.patch),
- json.loads(
- '[{"path": "/name", "value": "Finland", "op": "replace"}]'))
-
- sweden['name'] = 'Norway'
- self.assertEqual(
- json.loads(sweden.patch),
- json.loads(
- '[{"path": "/name", "value": "Norway", "op": "replace"}]'))
-
- def test_patch_multiple_operations(self):
- Country = warlock.model_factory(fixture)
- sweden = Country(name='Sweden', population=9379116)
-
- sweden['name'] = 'Finland'
- sweden['population'] = 5387000
-
- self.assertEqual(len(json.loads(sweden.patch)), 2)
-
- patches = json.loads(
- '[{"path": "/name", "value": "Finland", "op": "replace"}, '
- '{"path": "/population", "value": 5387000, "op": "replace"}]')
-
- for patch in json.loads(sweden.patch):
- self.assertTrue(patch in patches)
-
- def test_resolver(self):
- from jsonschema import RefResolver
- dirname = os.path.dirname(__file__)
- schemas_path = 'file://' + os.path.join(dirname, 'schemas/')
- resolver = RefResolver(schemas_path, None)
-
- country_schema_file = \
- open(os.path.join(dirname, 'schemas/') + 'country.json')
- person_schema_file = \
- open(os.path.join(dirname, 'schemas/') + 'person.json')
-
- country_schema = json.load(country_schema_file)
- person_schema = json.load(person_schema_file)
- Country = warlock.model_factory(country_schema, resolver)
- Person = warlock.model_factory(person_schema, resolver)
-
- england = Country(
- name="England",
- population=53865800,
- overlord=Person(
- title="Queen",
- firstname="Elizabeth",
- lastname="Windsor"
- )
- )
- expected = {
- 'name': 'England',
- 'population': 53865800,
- 'overlord': {
- 'title': 'Queen',
- 'lastname': 'Windsor',
- 'firstname': 'Elizabeth'
- }
- }
- self.assertEqual(england, expected)
-
- def test_recursive_models(self):
- Parent = warlock.model_factory(parent_fixture)
- Child = warlock.model_factory(child_fixture)
-
- mom = Parent(name='Abby', children=[])
-
- teenager = Child(age=15, mother=mom)
- toddler = Child(age=3, mother=mom)
-
- mom.children = [teenager, toddler]
-
- self.assertEqual(mom.children[0].age, 15)
- self.assertEqual(mom.children[1].age, 3)
Binary files old/warlock-1.3.0/warlock/__init__.pyc and new/warlock-1.3.3/warlock/__init__.pyc differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/warlock-1.3.0/warlock/core.py new/warlock-1.3.3/warlock/core.py
--- old/warlock-1.3.0/warlock/core.py 2016-06-25 19:48:59.000000000 +0200
+++ new/warlock-1.3.3/warlock/core.py 2019-05-20 08:26:22.000000000 +0200
@@ -30,8 +30,8 @@
class Model(base_class):
def __init__(self, *args, **kwargs):
- self.__dict__['schema'] = schema
- self.__dict__['resolver'] = resolver
+ self.__dict__["schema"] = schema
+ self.__dict__["resolver"] = resolver
base_class.__init__(self, *args, **kwargs)
if resolver is not None:
@@ -39,6 +39,6 @@
if name is not None:
Model.__name__ = name
- elif 'name' in schema:
- Model.__name__ = str(schema['name'])
+ elif "name" in schema:
+ Model.__name__ = str(schema["name"])
return Model
Binary files old/warlock-1.3.0/warlock/core.pyc and new/warlock-1.3.3/warlock/core.pyc differ
Binary files old/warlock-1.3.0/warlock/exceptions.pyc and new/warlock-1.3.3/warlock/exceptions.pyc differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/warlock-1.3.0/warlock/model.py new/warlock-1.3.3/warlock/model.py
--- old/warlock-1.3.0/warlock/model.py 2016-06-25 20:08:28.000000000 +0200
+++ new/warlock-1.3.3/warlock/model.py 2019-05-20 08:26:22.000000000 +0200
@@ -25,7 +25,6 @@
class Model(dict):
-
def __init__(self, *args, **kwargs):
# we overload setattr so set this manually
d = dict(*args, **kwargs)
@@ -37,8 +36,8 @@
else:
dict.__init__(self, d)
- self.__dict__['changes'] = {}
- self.__dict__['__original__'] = copy.deepcopy(d)
+ self.__dict__["changes"] = {}
+ self.__dict__["__original__"] = copy.deepcopy(d)
def __setitem__(self, key, value):
mutation = dict(self.items())
@@ -46,13 +45,12 @@
try:
self.validate(mutation)
except exceptions.ValidationError as exc:
- msg = ("Unable to set '%s' to %r. Reason: %s"
- % (key, value, str(exc)))
+ msg = "Unable to set '%s' to %r. Reason: %s" % (key, value, str(exc))
raise exceptions.InvalidOperation(msg)
dict.__setitem__(self, key, value)
- self.__dict__['changes'][key] = value
+ self.__dict__["changes"][key] = value
def __delitem__(self, key):
mutation = dict(self.items())
@@ -60,8 +58,7 @@
try:
self.validate(mutation)
except exceptions.ValidationError as exc:
- msg = ("Unable to delete attribute '%s'. Reason: %s"
- % (key, str(exc)))
+ msg = "Unable to delete attribute '%s'. Reason: %s" % (key, str(exc))
raise exceptions.InvalidOperation(msg)
dict.__delitem__(self, key)
@@ -124,15 +121,15 @@
@property
def patch(self):
"""Return a jsonpatch object representing the delta"""
- original = self.__dict__['__original__']
+ original = self.__dict__["__original__"]
return jsonpatch.make_patch(original, dict(self)).to_string()
@property
def changes(self):
"""Dumber version of 'patch' method"""
- deprecation_msg = 'Model.changes will be removed in warlock v2'
+ deprecation_msg = "Model.changes will be removed in warlock v2"
warnings.warn(deprecation_msg, DeprecationWarning, stacklevel=2)
- return copy.deepcopy(self.__dict__['changes'])
+ return copy.deepcopy(self.__dict__["changes"])
def validate(self, obj):
"""Apply a JSON schema to an object"""
Binary files old/warlock-1.3.0/warlock/model.pyc and new/warlock-1.3.3/warlock/model.pyc differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/warlock-1.3.0/warlock.egg-info/PKG-INFO new/warlock-1.3.3/warlock.egg-info/PKG-INFO
--- old/warlock-1.3.0/warlock.egg-info/PKG-INFO 2016-06-25 20:13:37.000000000 +0200
+++ new/warlock-1.3.3/warlock.egg-info/PKG-INFO 2019-05-20 12:10:52.000000000 +0200
@@ -1,10 +1,105 @@
-Metadata-Version: 1.0
+Metadata-Version: 2.1
Name: warlock
-Version: 1.3.0
+Version: 1.3.3
Summary: Python object model built on JSON schema and JSON patch.
Home-page: http://github.com/bcwaldon/warlock
Author: Brian Waldon
Author-email: bcwaldon(a)gmail.com
-License: UNKNOWN
-Description: UNKNOWN
+Maintainer: Jan Willhaus
+Maintainer-email: mail(a)janwillhaus.de
+License: Apache-2.0
+Description: # Warlock — self-validating Python objects using JSON schema
+
+ [![PyPI](https://img.shields.io/pypi/v/warlock.svg)][warlock]
+ [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/warlock.svg)][warlock]
+ [![PyPI - Downloads](https://img.shields.io/pypi/dw/warlock.svg)][pypistats]
+
+ [![Build Status](https://travis-ci.org/bcwaldon/warlock.svg?branch=master)][ci-builds]
+ [![Coverage Status](https://coveralls.io/repos/github/bcwaldon/warlock/badge.svg?branch=master)][coveralls]
+
+ ## Installation
+
+ Warlock is [available on PyPI][warlock]:
+
+ ```shell
+ pip install warlock
+ ```
+
+ ## Usage
+
+ 1) Create your schema
+
+ ```python
+ >>> schema = {
+ 'name': 'Country',
+ 'properties': {
+ 'name': {'type': 'string'},
+ 'abbreviation': {'type': 'string'},
+ 'population': {'type': 'integer'},
+ },
+ 'additionalProperties': False,
+ }
+ ```
+
+ 2) Create a model
+
+ ```python
+ >>> import warlock
+ >>> Country = warlock.model_factory(schema)
+ ```
+
+ 3) Create an object using your model
+
+ ```python
+ >>> sweden = Country(name='Sweden', abbreviation='SE')
+ ```
+
+ 4) Let the object validate itself
+
+ ```python
+ >>> sweden.name = 5
+ Traceback (most recent call last):
+ File "<stdin>", line 1, in <module>
+ File "warlock/core.py", line 53, in __setattr__
+ raise InvalidOperation(msg)
+ warlock.core.InvalidOperation: Unable to set 'name' to '5'
+
+ >>> sweden.overlord = 'Bears'
+ Traceback (most recent call last):
+ File "<stdin>", line 1, in <module>
+ File "warlock/core.py", line 53, in __setattr__
+ raise InvalidOperation(msg)
+ warlock.core.InvalidOperation: Unable to set 'overlord' to 'Bears'
+ ```
+
+ 5) Generate a [JSON Patch document](http://tools.ietf.org/html/draft-ietf-appsawg-json-patch) to track changes
+
+ ```python
+ >>> sweden.population=9453000
+ >>> sweden.patch
+ '[{"path": "/population", "value": 9453000, "op": "add"}]'
+ ```
+
+ [warlock]: https://pypi.org/project/warlock/
+ [pip]: https://pip.pypa.io/en/stable/
+ [ci-builds]: https://travis-ci.org/bcwaldon/warlock
+ [coveralls]: https://coveralls.io/github/bcwaldon/warlock?branch=master
+ [pypistats]: https://pypistats.org/packages/warlock
+
+Keywords: JSON schema,JSON patch,model validation
Platform: UNKNOWN
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Intended Audience :: Developers
+Classifier: Operating System :: MacOS :: MacOS X
+Classifier: Operating System :: Microsoft :: Windows
+Classifier: Operating System :: POSIX
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.4
+Classifier: Programming Language :: Python :: 3.5
+Classifier: Programming Language :: Python :: 3.6
+Classifier: Programming Language :: Python :: 3.7
+Classifier: Topic :: Software Development :: Libraries :: Python Modules
+Description-Content-Type: text/markdown
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/warlock-1.3.0/warlock.egg-info/SOURCES.txt new/warlock-1.3.3/warlock.egg-info/SOURCES.txt
--- old/warlock-1.3.0/warlock.egg-info/SOURCES.txt 2016-06-25 20:13:37.000000000 +0200
+++ new/warlock-1.3.3/warlock.egg-info/SOURCES.txt 2019-05-20 12:10:52.000000000 +0200
@@ -1,14 +1,17 @@
-LICENSE.txt
+LICENSE
MANIFEST.in
README.md
requirements.txt
setup.cfg
setup.py
-test/test_core.py
warlock/__init__.py
+warlock/__init__.pyc
warlock/core.py
+warlock/core.pyc
warlock/exceptions.py
+warlock/exceptions.pyc
warlock/model.py
+warlock/model.pyc
warlock.egg-info/PKG-INFO
warlock.egg-info/SOURCES.txt
warlock.egg-info/dependency_links.txt
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/warlock-1.3.0/warlock.egg-info/requires.txt new/warlock-1.3.3/warlock.egg-info/requires.txt
--- old/warlock-1.3.0/warlock.egg-info/requires.txt 2016-06-25 20:13:37.000000000 +0200
+++ new/warlock-1.3.3/warlock.egg-info/requires.txt 2019-05-20 12:10:52.000000000 +0200
@@ -1,3 +1,3 @@
-jsonschema>=0.7,<3
-jsonpatch>=0.10,<2
+jsonschema<4,>=0.7
+jsonpatch<2,>=0.10
six
1
0
Hello community,
here is the log from the commit of package python-knack for openSUSE:Factory checked in at 2019-05-27 08:38:23
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-knack (Old)
and /work/SRC/openSUSE:Factory/.python-knack.new.5148 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-knack"
Mon May 27 08:38:23 2019 rev:8 rq:705262 version:0.6.2
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-knack/python-knack.changes 2019-05-22 11:16:43.162502081 +0200
+++ /work/SRC/openSUSE:Factory/.python-knack.new.5148/python-knack.changes 2019-05-27 08:38:24.555070416 +0200
@@ -1,0 +2,12 @@
+Fri May 24 12:36:58 UTC 2019 - pgajdos(a)suse.com
+
+- version update to 0.6.2
+ * Adds ability to declare that command groups, commands, and arguments
+ are in a preview status and therefore might change or be removed.
+ This is done by passing the kwarg `is_preview=True`.
+ * Adds a generic `StatusTag` class to `knack.util` that allows you
+ to create your own colorized tags like `[Preview]` and `[Deprecated]`.
+ * When an incorrect command name is entered, Knack will now attempt
+ to suggest the closest alternative.
+
+-------------------------------------------------------------------
Old:
----
v0.6.1.tar.gz
New:
----
v0.6.2.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-knack.spec ++++++
--- /var/tmp/diff_new_pack.6iAYgT/_old 2019-05-27 08:38:25.147070185 +0200
+++ /var/tmp/diff_new_pack.6iAYgT/_new 2019-05-27 08:38:25.151070184 +0200
@@ -18,7 +18,7 @@
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
Name: python-knack
-Version: 0.6.1
+Version: 0.6.2
Release: 0
Summary: A Command-Line Interface framework
License: MIT
++++++ v0.6.1.tar.gz -> v0.6.2.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/knack-0.6.1/HISTORY.rst new/knack-0.6.2/HISTORY.rst
--- old/knack-0.6.1/HISTORY.rst 1970-01-01 01:00:00.000000000 +0100
+++ new/knack-0.6.2/HISTORY.rst 2019-05-23 00:19:57.000000000 +0200
@@ -0,0 +1,106 @@
+.. :changelog:
+
+Release History
+===============
+
+0.6.2
++++++
+* Adds ability to declare that command groups, commands, and arguments are in a preview status and therefore might change or be removed. This is done by passing the kwarg `is_preview=True`.
+* Adds a generic `StatusTag` class to `knack.util` that allows you to create your own colorized tags like `[Preview]` and `[Deprecated]`.
+* When an incorrect command name is entered, Knack will now attempt to suggest the closest alternative.
+
+0.6.1
++++++
+* Always read from local for configured_default
+
+0.6.0
++++++
+* Support local context chained config file
+
+0.5.4
++++++
+* Allows the loading of text files using @filename syntax.
+* Adds the argument kwarg configured_default to support setting argument defaults via the config file's [defaults] section or an environment variable.
+
+0.5.3
++++++
+* Removes an incorrect check when adding arguments.
+
+0.5.2
++++++
+* Updates usages of yaml.load to use yaml.safe_load.
+
+0.5.1
++++++
+* Fix issue with some scenarios (no args and --version)
+
+0.5.0
++++++
+* Adds support for positional arguments with the .positional helper method on ArgumentsContext.
+* Removes the necessity for the type field in help.py. This information can be inferred from the class, so specifying it causes unnecessary crashes.
+* Adds support for examining the result of a command after a call to invoke. The raw object, error (if any) an exit code are accessible.
+* Adds support for accessing the command instance from inside custom commands by putting the special argument cmd in the signature.
+* Fixes an issue with the default config directory. It use to be .cli and is now based on the CLI name.
+* Fixes regression in knack 0.4.5 in behavior when cli_name --verbose/debug is used. Displays the welcome message as intended.
+* Adds ability to specify line width for help text display.
+
+0.4.5
++++++
+* Preserves logging verbosity and output format on the namespace for use by validators.
+
+0.4.4
++++++
+* Adds ability to set config file name.
+* Fixes bug with argument deprecations.
+
+0.4.3
++++++
+* Fixes issue where values were sometimes ignored when using deprecated options regardless of which option was given.
+
+0.4.2
++++++
+* Bug fix: disable number parse on table mode PR #88
+
+0.4.1
++++++
+* Fixes bug with deprecation mechanism.
+* Fixes an issue where the command group table would only be filled by calls to create CommandGroup classes. This resulted in some gaps in the command group table.
+
+0.4.0
++++++
+* Add mechanism to deprecate commands, command groups, arguments and argument options.
+* Improve help display support for Unicode.
+
+0.3.3
++++++
+* expose a callback to let client side perform extra logics (#80)
+* output: don't skip false value on auto-tabulating (#83)
+
+0.3.2
++++++
+* ArgumentsContext.ignore() should use hidden options_list (#76)
+* Consolidate exception handling (#66)
+
+0.3.1
++++++
+* Performance optimization - Delay import of platform and colorama (#47)
+* CLIError: Inherit from Exception directly (#65)
+* Explicitly state which packages to include (so exclude 'tests') (#68)
+
+0.2.0
++++++
+* Support command level and argument level validators.
+* knack.commands.CLICommandsLoader now accepts a command_cls argument so you can provide your own CLICommand class.
+* logging: make determine_verbose_level private method.
+* Allow overriding of NAMED_ARGUMENTS
+* Only pass valid argparse kwargs to argparse.ArgumentParser.add_argument and ignore the rest
+* logging: make determine_verbose_level private method
+* Remove cli_command, register_cli_argument, register_extra_cli_argument as ways to register commands and arguments.
+
+0.1.1
++++++
+* Add more types of command and argument loaders.
+
+0.1.0
++++++
+* Initial release
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/knack-0.6.1/MANIFEST.in new/knack-0.6.2/MANIFEST.in
--- old/knack-0.6.1/MANIFEST.in 2019-04-26 02:11:43.000000000 +0200
+++ new/knack-0.6.2/MANIFEST.in 2019-05-23 00:19:57.000000000 +0200
@@ -1 +1,3 @@
include *.rst
+include LICENSE
+recursive-include tests *
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/knack-0.6.1/docs/cli.md new/knack-0.6.2/docs/cli.md
--- old/knack-0.6.1/docs/cli.md 2019-04-26 02:11:43.000000000 +0200
+++ new/knack-0.6.2/docs/cli.md 2019-05-23 00:19:57.000000000 +0200
@@ -9,7 +9,7 @@
For example:
`cli_name` - Name of CLI. Typically the executable name.
-`config_dir` - Path to config dir. e.g. `os.path.join('~', '.myconfig')`
+`config_dir` - Path to config dir. e.g. `os.path.expanduser(os.path.join('~', '.myconfig'))`
`config_env_var_prefix` - A prefix for environment variables used in config e.g. `CLI_`.
Use the `invoke()` method to invoke commands.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/knack-0.6.1/examples/exapp new/knack-0.6.2/examples/exapp
--- old/knack-0.6.1/examples/exapp 2019-04-26 02:11:43.000000000 +0200
+++ new/knack-0.6.2/examples/exapp 2019-05-23 00:19:57.000000000 +0200
@@ -79,7 +79,7 @@
mycli = CLI(cli_name=cli_name,
- config_dir=os.path.join('~', '.{}'.format(cli_name)),
+ config_dir=os.path.expanduser(os.path.join('~', '.{}'.format(cli_name))),
config_env_var_prefix=cli_name,
commands_loader_cls=MyCommandsLoader,
help_cls=MyCLIHelp)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/knack-0.6.1/examples/exapp2 new/knack-0.6.2/examples/exapp2
--- old/knack-0.6.1/examples/exapp2 2019-04-26 02:11:43.000000000 +0200
+++ new/knack-0.6.2/examples/exapp2 2019-05-23 00:19:57.000000000 +0200
@@ -86,7 +86,7 @@
mycli = MyCLI(cli_name=cli_name,
- config_dir=os.path.join('~', '.{}'.format(cli_name)),
+ config_dir=os.path.expanduser(os.path.join('~', '.{}'.format(cli_name))),
config_env_var_prefix=cli_name,
commands_loader_cls=MyCommandsLoader,
help_cls=MyCLIHelp)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/knack-0.6.1/examples/test_exapp new/knack-0.6.2/examples/test_exapp
--- old/knack-0.6.1/examples/test_exapp 2019-04-26 02:11:43.000000000 +0200
+++ new/knack-0.6.2/examples/test_exapp 2019-05-23 00:19:57.000000000 +0200
@@ -47,7 +47,7 @@
name = 'exapp4'
mycli = CLI(cli_name=name,
- config_dir=os.path.join('~', '.{}'.format(name)),
+ config_dir=os.path.expanduser(os.path.join('~', '.{}'.format(name))),
config_env_var_prefix=name,
commands_loader_cls=MyCommandsLoader)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/knack-0.6.1/knack/arguments.py new/knack-0.6.2/knack/arguments.py
--- old/knack-0.6.1/knack/arguments.py 2019-04-26 02:11:43.000000000 +0200
+++ new/knack-0.6.2/knack/arguments.py 2019-05-23 00:19:57.000000000 +0200
@@ -7,6 +7,7 @@
from collections import defaultdict
from .deprecation import Deprecated
+from .preview import PreviewItem
from .log import get_logger
from .util import CLIError
@@ -42,7 +43,7 @@
class CLICommandArgument(object):
- NAMED_ARGUMENTS = ['options_list', 'validator', 'completer', 'arg_group', 'deprecate_info']
+ NAMED_ARGUMENTS = ['options_list', 'validator', 'completer', 'arg_group', 'deprecate_info', 'preview_info']
def __init__(self, dest=None, argtype=None, **kwargs):
"""An argument that has a specific destination parameter.
@@ -221,6 +222,55 @@
action = _handle_option_deprecation(deprecated_opts)
return action
+ def _handle_previews(self, argument_dest, **kwargs):
+
+ if not kwargs.get('is_preview', False):
+ return kwargs
+
+ def _handle_argument_preview(preview_info):
+
+ parent_class = self._get_parent_class(**kwargs)
+
+ class PreviewArgumentAction(parent_class):
+
+ def __call__(self, parser, namespace, values, option_string=None):
+ if not hasattr(namespace, '_argument_previews'):
+ setattr(namespace, '_argument_previews', [preview_info])
+ else:
+ namespace._argument_previews.append(preview_info) # pylint: disable=protected-access
+ try:
+ super(PreviewArgumentAction, self).__call__(parser, namespace, values, option_string)
+ except NotImplementedError:
+ setattr(namespace, self.dest, values)
+
+ return PreviewArgumentAction
+
+ def _get_preview_arg_message(self):
+ return "{} '{}' is in preview. It may be changed/removed in a future release.".format(
+ self.object_type.capitalize(), self.target)
+
+ options_list = kwargs.get('options_list', None)
+ object_type = 'argument'
+
+ if options_list is None:
+ # convert argument dest
+ target = '--{}'.format(argument_dest.replace('_', '-'))
+ elif options_list:
+ target = sorted(options_list, key=len)[-1]
+ else:
+ # positional argument
+ target = kwargs.get('metavar', '<{}>'.format(argument_dest.upper()))
+ object_type = 'positional argument'
+
+ preview_info = PreviewItem(
+ target=target,
+ object_type=object_type,
+ message_func=_get_preview_arg_message
+ )
+ kwargs['preview_info'] = preview_info
+ kwargs['action'] = _handle_argument_preview(preview_info)
+ return kwargs
+
# pylint: disable=inconsistent-return-statements
def deprecate(self, **kwargs):
@@ -252,7 +302,8 @@
:param arg_type: Predefined CLIArgumentType definition to register, as modified by any provided kwargs.
:type arg_type: knack.arguments.CLIArgumentType
:param kwargs: Possible values: `options_list`, `validator`, `completer`, `nargs`, `action`, `const`, `default`,
- `type`, `choices`, `required`, `help`, `metavar`. See /docs/arguments.md.
+ `type`, `choices`, `required`, `help`, `metavar`, `is_preview`, `deprecate_info`.
+ See /docs/arguments.md.
"""
self._check_stale()
if not self._applicable():
@@ -261,6 +312,8 @@
deprecate_action = self._handle_deprecations(argument_dest, **kwargs)
if deprecate_action:
kwargs['action'] = deprecate_action
+
+ kwargs = self._handle_previews(argument_dest, **kwargs)
self.command_loader.argument_registry.register_cli_argument(self.command_scope,
argument_dest,
arg_type,
@@ -274,7 +327,8 @@
:param arg_type: Predefined CLIArgumentType definition to register, as modified by any provided kwargs.
:type arg_type: knack.arguments.CLIArgumentType
:param kwargs: Possible values: `validator`, `completer`, `nargs`, `action`, `const`, `default`,
- `type`, `choices`, `required`, `help`, `metavar`. See /docs/arguments.md.
+ `type`, `choices`, `required`, `help`, `metavar`, `is_preview`, `deprecate_info`.
+ See /docs/arguments.md.
"""
self._check_stale()
if not self._applicable():
@@ -293,11 +347,14 @@
raise CLIError("command authoring error: commands may have, at most, one positional argument. '{}' already "
"has positional argument: {}.".format(self.command_scope, ' '.join(positional_args.keys())))
+ kwargs['options_list'] = []
+
deprecate_action = self._handle_deprecations(argument_dest, **kwargs)
if deprecate_action:
kwargs['action'] = deprecate_action
- kwargs['options_list'] = []
+ kwargs = self._handle_previews(argument_dest, **kwargs)
+
self.command_loader.argument_registry.register_cli_argument(self.command_scope,
argument_dest,
arg_type,
@@ -323,7 +380,8 @@
:param argument_dest: The destination argument to add this argument type to
:type argument_dest: str
:param kwargs: Possible values: `options_list`, `validator`, `completer`, `nargs`, `action`, `const`, `default`,
- `type`, `choices`, `required`, `help`, `metavar`. See /docs/arguments.md.
+ `type`, `choices`, `required`, `help`, `metavar`, `is_preview`, `deprecate_info`.
+ See /docs/arguments.md.
"""
self._check_stale()
if not self._applicable():
@@ -337,6 +395,9 @@
deprecate_action = self._handle_deprecations(argument_dest, **kwargs)
if deprecate_action:
kwargs['action'] = deprecate_action
+
+ kwargs = self._handle_previews(argument_dest, **kwargs)
+
self.command_loader.extra_argument_registry[self.command_scope][argument_dest] = CLICommandArgument(
argument_dest, **kwargs)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/knack-0.6.1/knack/commands.py new/knack-0.6.2/knack/commands.py
--- old/knack-0.6.1/knack/commands.py 2019-04-26 02:11:43.000000000 +0200
+++ new/knack-0.6.2/knack/commands.py 2019-05-23 00:19:57.000000000 +0200
@@ -10,6 +10,7 @@
import six
from .deprecation import Deprecated
+from .preview import PreviewItem
from .prompting import prompt_y_n, NoTTYException
from .util import CLIError, CtxTypeError
from .arguments import ArgumentRegistry, CLICommandArgument
@@ -27,7 +28,8 @@
# pylint: disable=unused-argument
def __init__(self, cli_ctx, name, handler, description=None, table_transformer=None,
arguments_loader=None, description_loader=None,
- formatter_class=None, deprecate_info=None, validator=None, confirmation=None, **kwargs):
+ formatter_class=None, deprecate_info=None, validator=None, confirmation=None, preview_info=None,
+ **kwargs):
""" The command object that goes into the command table.
:param cli_ctx: CLI Context
@@ -48,6 +50,8 @@
:type formatter_class: class
:param deprecate_info: Deprecation message to display when this command is invoked
:type deprecate_info: str
+ :param preview_info: Indicates a command is in preview
+ :type preview_info: bool
:param validator: The command validator
:param confirmation: User confirmation required for command
:type confirmation: bool, str, callable
@@ -66,6 +70,7 @@
self.table_transformer = table_transformer
self.formatter_class = formatter_class
self.deprecate_info = deprecate_info
+ self.preview_info = preview_info
self.confirmation = confirmation
self.validator = validator
@@ -295,6 +300,11 @@
Deprecated.ensure_new_style_deprecation(self.command_loader.cli_ctx, self.group_kwargs, 'command group')
if kwargs['deprecate_info']:
kwargs['deprecate_info'].target = group_name
+ if kwargs.get('is_preview', False):
+ kwargs['preview_info'] = PreviewItem(
+ target=group_name,
+ object_type='command group'
+ )
command_loader._populate_command_group_table_with_subgroups(group_name) # pylint: disable=protected-access
self.command_loader.command_group_table[group_name] = self
@@ -313,7 +323,8 @@
:type handler_name: str
:param kwargs: Kwargs to apply to the command.
Possible values: `client_factory`, `arguments_loader`, `description_loader`, `description`,
- `formatter_class`, `table_transformer`, `deprecate_info`, `validator`, `confirmation`.
+ `formatter_class`, `table_transformer`, `deprecate_info`, `validator`, `confirmation`,
+ `is_preview`.
"""
import copy
@@ -322,6 +333,11 @@
command_kwargs.update(kwargs)
# don't inherit deprecation info from command group
command_kwargs['deprecate_info'] = kwargs.get('deprecate_info', None)
+ if kwargs.get('is_preview', False):
+ command_kwargs['preview_info'] = PreviewItem(
+ self.command_loader.cli_ctx,
+ object_type='command'
+ )
self.command_loader._populate_command_group_table_with_subgroups(' '.join(command_name.split()[:-1])) # pylint: disable=protected-access
self.command_loader.command_table[command_name] = self.command_loader.create_command(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/knack-0.6.1/knack/config.py new/knack-0.6.2/knack/config.py
--- old/knack-0.6.1/knack/config.py 2019-04-26 02:11:43.000000000 +0200
+++ new/knack-0.6.2/knack/config.py 2019-05-23 00:19:57.000000000 +0200
@@ -21,7 +21,7 @@
'0': False, 'no': False, 'false': False, 'off': False}
_DEFAULT_CONFIG_ENV_VAR_PREFIX = 'CLI'
- _DEFAULT_CONFIG_DIR = os.path.join('~', '.{}'.format('cli'))
+ _DEFAULT_CONFIG_DIR = os.path.expanduser(os.path.join('~', '.{}'.format('cli')))
_DEFAULT_CONFIG_FILE_NAME = 'config'
_CONFIG_DEFAULTS_SECTION = 'defaults'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/knack-0.6.1/knack/deprecation.py new/knack-0.6.2/knack/deprecation.py
--- old/knack-0.6.1/knack/deprecation.py 2019-04-26 02:11:43.000000000 +0200
+++ new/knack-0.6.2/knack/deprecation.py 2019-05-23 00:19:57.000000000 +0200
@@ -5,6 +5,7 @@
from six import string_types as STRING_TYPES
+from .util import StatusTag
DEFAULT_DEPRECATED_TAG = '[Deprecated]'
@@ -29,25 +30,8 @@
return deprecate_info
-class ColorizedString(object):
-
- def __init__(self, message, color):
- import colorama
- self._message = message
- self._color = getattr(colorama.Fore, color.upper(), None)
-
- def __len__(self):
- return len(self._message)
-
- def __str__(self):
- import colorama
- if not self._color:
- return self._message
- return self._color + self._message + colorama.Fore.RESET
-
-
# pylint: disable=too-many-instance-attributes
-class Deprecated(object):
+class Deprecated(StatusTag):
@staticmethod
def ensure_new_style_deprecation(cli_ctx, kwargs, object_type):
@@ -62,7 +46,7 @@
return deprecate_info
def __init__(self, cli_ctx=None, object_type='', target=None, redirect=None, hide=False, expiration=None,
- tag_func=None, message_func=None):
+ tag_func=None, message_func=None, **kwargs):
""" Create a collection of deprecation metadata.
:param cli_ctx: The CLI context associated with the deprecated item.
@@ -87,13 +71,6 @@
Omit to use the default.
:type message_func: callable
"""
- self.cli_ctx = cli_ctx
- self.object_type = object_type
- self.target = target
- self.redirect = redirect
- self.hide = hide
- self.expiration = expiration
-
def _default_get_message(self):
msg = "This {} has been deprecated and will be removed ".format(self.object_type)
if self.expiration:
@@ -104,24 +81,18 @@
msg += " Use '{}' instead.".format(self.redirect)
return msg
- self._get_tag = tag_func or (lambda _: DEFAULT_DEPRECATED_TAG)
- self._get_message = message_func or _default_get_message
-
- def __deepcopy__(self, memo):
- import copy
+ self.redirect = redirect
+ self.hide = hide
+ self.expiration = expiration
- cls = self.__class__
- result = cls.__new__(cls)
- memo[id(self)] = result
- for k, v in self.__dict__.items():
- try:
- setattr(result, k, copy.deepcopy(v, memo))
- except TypeError:
- if k == 'cli_ctx':
- setattr(result, k, self.cli_ctx)
- else:
- raise
- return result
+ super(Deprecated, self).__init__(
+ cli_ctx=cli_ctx,
+ object_type=object_type,
+ target=target,
+ color='yellow',
+ tag_func=tag_func or (lambda _: DEFAULT_DEPRECATED_TAG),
+ message_func=message_func or _default_get_message
+ )
# pylint: disable=no-self-use
def _version_less_than_or_equal_to(self, v1, v2):
@@ -148,16 +119,6 @@
def show_in_help(self):
return not self.hidden() and not self.expired()
- @property
- def tag(self):
- """ Returns a tag object. """
- return ColorizedString(self._get_tag(self), 'yellow')
-
- @property
- def message(self):
- """ Returns a tuple with the formatted message string and the message length. """
- return ColorizedString(self._get_message(self), 'yellow')
-
class ImplicitDeprecated(Deprecated):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/knack-0.6.1/knack/help.py new/knack-0.6.2/knack/help.py
--- old/knack-0.6.1/knack/help.py 2019-04-26 02:11:43.000000000 +0200
+++ new/knack-0.6.2/knack/help.py 2019-05-23 00:19:57.000000000 +0200
@@ -10,6 +10,7 @@
from .deprecation import ImplicitDeprecated, resolve_deprecate_info
from .log import get_logger
+from .preview import ImplicitPreviewItem, resolve_preview_info
from .util import CtxTypeError
from .help_files import _load_help_file
@@ -21,13 +22,6 @@
REQUIRED_TAG = '[Required]'
-def _get_preview_tag():
- import colorama
- PREVIEW_TAG = '{}[Preview]{}'.format(colorama.Fore.CYAN, colorama.Fore.RESET)
- PREVIEW_TAG_LEN = len(PREVIEW_TAG) - 2 * len(colorama.Fore.RESET)
- return (PREVIEW_TAG, PREVIEW_TAG_LEN)
-
-
def _get_hanging_indent(max_length, indent):
return max_length + (indent * 4) + len(FIRST_LINE_PREFIX) - 1
@@ -159,6 +153,26 @@
del deprecate_kwargs['_get_message']
self.deprecate_info = ImplicitDeprecated(**deprecate_kwargs)
+ # resolve preview info
+ direct_preview_info = resolve_preview_info(help_ctx.cli_ctx, delimiters)
+ if direct_preview_info:
+ self.preview_info = direct_preview_info
+
+ # search for implicit preview
+ path_comps = delimiters.split()[:-1]
+ implicit_preview_info = None
+ while path_comps and not implicit_preview_info:
+ implicit_preview_info = resolve_preview_info(help_ctx.cli_ctx, ' '.join(path_comps))
+ del path_comps[-1]
+
+ if implicit_preview_info:
+ preview_kwargs = implicit_preview_info.__dict__.copy()
+ if delimiters in help_ctx.cli_ctx.invocation.commands_loader.command_table:
+ preview_kwargs['object_type'] = 'command'
+ else:
+ preview_kwargs['object_type'] = 'command group'
+ self.preview_info = ImplicitPreviewItem(**preview_kwargs)
+
def load(self, options):
description = getattr(options, 'description', None)
try:
@@ -208,7 +222,6 @@
super(GroupHelpFile, self).__init__(help_ctx, delimiters)
self.type = 'group'
- self.preview_info = getattr(parser, 'preview_info', None)
self.children = []
if getattr(parser, 'choices', None):
@@ -244,6 +257,7 @@
param_kwargs = {
'name_source': [action.metavar or action.dest],
'deprecate_info': getattr(action, 'deprecate_info', None),
+ 'preview_info': getattr(action, 'preview_info', None),
'description': action.help,
'choices': action.choices,
'required': False,
@@ -280,7 +294,8 @@
self.parameters.append(HelpParameter(**param_kwargs))
param_kwargs.update({
'name_source': normal_options,
- 'deprecate_info': getattr(param, 'deprecate_info', None)
+ 'deprecate_info': getattr(param, 'deprecate_info', None),
+ 'preview_info': getattr(param, 'preview_info', None)
})
self.parameters.append(HelpParameter(**param_kwargs))
@@ -304,7 +319,7 @@
class HelpParameter(HelpObject): # pylint: disable=too-many-instance-attributes
def __init__(self, name_source, description, required, choices=None,
- default=None, group_name=None, deprecate_info=None):
+ default=None, group_name=None, deprecate_info=None, preview_info=None):
super(HelpParameter, self).__init__()
self.name_source = name_source
self.name = ' '.join(sorted(name_source))
@@ -317,6 +332,7 @@
self.default = default
self.group_name = group_name
self.deprecate_info = deprecate_info
+ self.preview_info = preview_info
def update_from_data(self, data):
if self.name != data.get('name'):
@@ -367,6 +383,8 @@
lines.append(item.long_summary)
if item.deprecate_info:
lines.append(str(item.deprecate_info.message))
+ if item.preview_info:
+ lines.append(str(item.preview_info.message))
return ' '.join(lines)
indent += 1
@@ -381,15 +399,18 @@
self.max_line_len = 0
def _build_tags_string(item):
- PREVIEW_TAG, PREVIEW_TAG_LEN = _get_preview_tag()
+
+ preview_info = getattr(item, 'preview_info', None)
+ preview = preview_info.tag if preview_info else ''
+
deprecate_info = getattr(item, 'deprecate_info', None)
deprecated = deprecate_info.tag if deprecate_info else ''
- preview = PREVIEW_TAG if getattr(item, 'preview_info', None) else ''
+
required = REQUIRED_TAG if getattr(item, 'required', None) else ''
- tags = ' '.join([x for x in [str(deprecated), preview, required] if x])
+ tags = ' '.join([x for x in [str(deprecated), str(preview), required] if x])
tags_len = sum([
len(deprecated),
- PREVIEW_TAG_LEN if preview else 0,
+ len(preview),
len(required),
tags.count(' ')
])
@@ -488,15 +509,18 @@
return None
def _build_tags_string(item):
- PREVIEW_TAG, PREVIEW_TAG_LEN = _get_preview_tag()
+
+ preview_info = getattr(item, 'preview_info', None)
+ preview = preview_info.tag if preview_info else ''
+
deprecate_info = getattr(item, 'deprecate_info', None)
deprecated = deprecate_info.tag if deprecate_info else ''
- preview = PREVIEW_TAG if getattr(item, 'preview_info', None) else ''
+
required = REQUIRED_TAG if getattr(item, 'required', None) else ''
- tags = ' '.join([x for x in [str(deprecated), preview, required] if x])
+ tags = ' '.join([x for x in [str(deprecated), str(preview), required] if x])
tags_len = sum([
len(deprecated),
- PREVIEW_TAG_LEN if preview else 0,
+ len(preview),
len(required),
tags.count(' ')
])
@@ -573,6 +597,9 @@
deprecate_info = getattr(item, 'deprecate_info', None)
if deprecate_info:
lines.append(str(item.deprecate_info.message))
+ preview_info = getattr(item, 'preview_info', None)
+ if preview_info:
+ lines.append(str(item.preview_info.message))
return ' '.join(lines)
group_registry = ArgumentGroupRegistry([p.group_name for p in help_file.parameters if p.group_name])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/knack-0.6.1/knack/invocation.py new/knack-0.6.2/knack/invocation.py
--- old/knack-0.6.1/knack/invocation.py 2019-04-26 02:11:43.000000000 +0200
+++ new/knack-0.6.2/knack/invocation.py 2019-05-23 00:19:57.000000000 +0200
@@ -10,6 +10,7 @@
from collections import defaultdict
from .deprecation import ImplicitDeprecated, resolve_deprecate_info
+from .preview import ImplicitPreviewItem, resolve_preview_info
from .util import CLIError, CtxTypeError, CommandResultItem, todict
from .parser import CLICommandParser
from .commands import CLICommandsLoader
@@ -117,6 +118,7 @@
err = sys.exc_info()[1]
getattr(parsed_ns, '_parser', self.parser).validation_error(str(err))
+ # pylint: disable=too-many-statements
def execute(self, args):
""" Executes the command invocation
@@ -164,6 +166,10 @@
if cmd.deprecate_info:
deprecations.append(cmd.deprecate_info)
+ previews = getattr(parsed_args, '_argument_previews', [])
+ if cmd.preview_info:
+ previews.append(cmd.preview_info)
+
params = self._filter_params(parsed_args)
# search for implicit deprecation
@@ -180,9 +186,23 @@
del deprecate_kwargs['_get_message']
deprecations.append(ImplicitDeprecated(**deprecate_kwargs))
+ # search for implicit preview
+ path_comps = cmd.name.split()[:-1]
+ implicit_preview_info = None
+ while path_comps and not implicit_preview_info:
+ implicit_preview_info = resolve_preview_info(self.cli_ctx, ' '.join(path_comps))
+ del path_comps[-1]
+
+ if implicit_preview_info:
+ preview_kwargs = implicit_preview_info.__dict__.copy()
+ preview_kwargs['object_type'] = 'command'
+ previews.append(ImplicitPreviewItem(**preview_kwargs))
+
colorama.init()
for d in deprecations:
print(d.message, file=sys.stderr)
+ for p in previews:
+ print(p.message, file=sys.stderr)
colorama.deinit()
cmd_result = parsed_args.func(params)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/knack-0.6.1/knack/parser.py new/knack-0.6.2/knack/parser.py
--- old/knack-0.6.1/knack/parser.py 2019-04-26 02:11:43.000000000 +0200
+++ new/knack-0.6.2/knack/parser.py 2019-05-23 00:19:57.000000000 +0200
@@ -3,6 +3,8 @@
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------
+from __future__ import print_function
+
import argparse
from .deprecation import Deprecated
@@ -170,6 +172,7 @@
param = CLICommandParser._add_argument(command_parser, arg)
param.completer = arg.completer
param.deprecate_info = arg.deprecate_info
+ param.preview_info = arg.preview_info
command_parser.set_defaults(
func=metadata,
command=command_name,
@@ -254,3 +257,27 @@
"""
self._expand_prefixed_files(args)
return super(CLICommandParser, self).parse_args(args)
+
+ def _check_value(self, action, value):
+ # Override to customize the error message when a argument is not among the available choices
+ # converted value must be one of the choices (if specified)
+ import difflib
+ import sys
+
+ if action.choices is not None and value not in action.choices:
+ # parser has no `command_source`, value is part of command itself
+ error_msg = "{prog}: '{value}' is not in the '{prog}' command group. See '{prog} --help'.".format(
+ prog=self.prog, value=value)
+ logger.error(error_msg)
+ candidates = difflib.get_close_matches(value, action.choices, cutoff=0.7)
+ if candidates:
+ print_args = {
+ 's': 's' if len(candidates) > 1 else '',
+ 'verb': 'are' if len(candidates) > 1 else 'is',
+ 'value': value
+ }
+ suggestion_msg = "\nThe most similar choice{s} to '{value}' {verb}:\n".format(**print_args)
+ suggestion_msg += '\n'.join(['\t' + candidate for candidate in candidates])
+ print(suggestion_msg, file=sys.stderr)
+
+ self.exit(2)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/knack-0.6.1/knack/preview.py new/knack-0.6.2/knack/preview.py
--- old/knack-0.6.1/knack/preview.py 1970-01-01 01:00:00.000000000 +0100
+++ new/knack-0.6.2/knack/preview.py 2019-05-23 00:19:57.000000000 +0200
@@ -0,0 +1,77 @@
+# --------------------------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for license information.
+# --------------------------------------------------------------------------------------------
+
+from .util import StatusTag
+
+_PREVIEW_TAG = '[Preview]'
+_preview_kwarg = 'preview_info'
+
+
+def resolve_preview_info(cli_ctx, name):
+
+ def _get_command(name):
+ return cli_ctx.invocation.commands_loader.command_table[name]
+
+ def _get_command_group(name):
+ return cli_ctx.invocation.commands_loader.command_group_table.get(name, None)
+
+ preview_info = None
+ try:
+ command = _get_command(name)
+ preview_info = getattr(command, _preview_kwarg, None)
+ except KeyError:
+ command_group = _get_command_group(name)
+ group_kwargs = getattr(command_group, 'group_kwargs', None)
+ if group_kwargs:
+ preview_info = group_kwargs.get(_preview_kwarg, None)
+ return preview_info
+
+
+# pylint: disable=too-many-instance-attributes
+class PreviewItem(StatusTag):
+
+ def __init__(self, cli_ctx=None, object_type='', target=None, tag_func=None, message_func=None, **kwargs):
+ """ Create a collection of preview metadata.
+
+ :param cli_ctx: The CLI context associated with the preview item.
+ :type cli_ctx: knack.cli.CLI
+ :param object_type: A label describing the type of object in preview.
+ :type: object_type: str
+ :param target: The name of the object in preview.
+ :type target: str
+ :param tag_func: Callable which returns the desired unformatted tag string for the preview item.
+ Omit to use the default.
+ :type tag_func: callable
+ :param message_func: Callable which returns the desired unformatted message string for the preview item.
+ Omit to use the default.
+ :type message_func: callable
+ """
+
+ def _default_get_message(self):
+ return "This {} is in preview. It may be changed/removed in a future release.".format(self.object_type)
+
+ super(PreviewItem, self).__init__(
+ cli_ctx=cli_ctx,
+ object_type=object_type,
+ target=target,
+ color='cyan',
+ tag_func=tag_func or (lambda _: _PREVIEW_TAG),
+ message_func=message_func or _default_get_message
+ )
+
+
+class ImplicitPreviewItem(PreviewItem):
+
+ def __init__(self, **kwargs):
+
+ def get_implicit_preview_message(self):
+ return "Command group '{}' is in preview. It may be changed/removed " \
+ "in a future release.".format(self.target)
+
+ kwargs.update({
+ 'tag_func': lambda _: '',
+ 'message_func': get_implicit_preview_message
+ })
+ super(ImplicitPreviewItem, self).__init__(**kwargs)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/knack-0.6.1/knack/util.py new/knack-0.6.2/knack/util.py
--- old/knack-0.6.1/knack/util.py 2019-04-26 02:11:43.000000000 +0200
+++ new/knack-0.6.2/knack/util.py 2019-05-23 00:19:57.000000000 +0200
@@ -35,6 +35,68 @@
obj.__class__.__name__))
+class ColorizedString(object):
+
+ def __init__(self, message, color):
+ import colorama
+ self._message = message
+ self._color = getattr(colorama.Fore, color.upper(), None)
+
+ def __len__(self):
+ return len(self._message)
+
+ def __str__(self):
+ import colorama
+ if not self._color:
+ return self._message
+ return self._color + self._message + colorama.Fore.RESET
+
+
+class StatusTag(object):
+
+ # pylint: disable=unused-argument
+ def __init__(self, cli_ctx, object_type, target, tag_func, message_func, color, **kwargs):
+ self.cli_ctx = cli_ctx
+ self.object_type = object_type
+ self.target = target
+ self._color = color
+ self._get_tag = tag_func
+ self._get_message = message_func
+
+ def __deepcopy__(self, memo):
+ import copy
+
+ cls = self.__class__
+ result = cls.__new__(cls)
+ memo[id(self)] = result
+ for k, v in self.__dict__.items():
+ try:
+ setattr(result, k, copy.deepcopy(v, memo))
+ except TypeError:
+ if k == 'cli_ctx':
+ setattr(result, k, self.cli_ctx)
+ else:
+ raise
+ return result
+
+ # pylint: disable=no-self-use
+ def hidden(self):
+ return False
+
+ def show_in_help(self):
+ return not self.hidden()
+
+ @property
+ def tag(self):
+ """ Returns a tag object. """
+ return ColorizedString(self._get_tag(self), self._color)
+
+ @property
+ def message(self):
+ """ Returns a tuple with the formatted message string and the message length. """
+ return ColorizedString(self._get_message(self), self._color)
+
+
def ensure_dir(d):
""" Create a directory if it doesn't exist """
if not os.path.isdir(d):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/knack-0.6.1/setup.py new/knack-0.6.2/setup.py
--- old/knack-0.6.1/setup.py 2019-04-26 02:11:43.000000000 +0200
+++ new/knack-0.6.2/setup.py 2019-05-23 00:19:57.000000000 +0200
@@ -9,7 +9,7 @@
from codecs import open
from setuptools import setup, find_packages
-VERSION = '0.6.1'
+VERSION = '0.6.2'
DEPENDENCIES = [
'argcomplete',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/knack-0.6.1/tests/test_cli_scenarios.py new/knack-0.6.2/tests/test_cli_scenarios.py
--- old/knack-0.6.1/tests/test_cli_scenarios.py 2019-04-26 02:11:43.000000000 +0200
+++ new/knack-0.6.2/tests/test_cli_scenarios.py 2019-05-23 00:19:57.000000000 +0200
@@ -4,6 +4,7 @@
# --------------------------------------------------------------------------------------------
import os
+from collections import OrderedDict
import unittest
try:
import mock
@@ -11,7 +12,6 @@
from unittest import mock
import mock
-from collections import OrderedDict
from six import StringIO
from knack import CLI
@@ -87,7 +87,7 @@
self.command_table['abc list'] = CLICommand(self.cli_ctx, 'abc list', a_test_command_handler)
return OrderedDict(self.command_table)
- mycli = CLI(cli_name='exapp1', config_dir=os.path.join('~', '.exapp1'), commands_loader_cls=MyCommandsLoader)
+ mycli = CLI(cli_name='exapp1', config_dir=os.path.expanduser(os.path.join('~', '.exapp1')), commands_loader_cls=MyCommandsLoader)
expected_output = """[
{
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/knack-0.6.1/tests/test_command_with_configured_defaults.py new/knack-0.6.2/tests/test_command_with_configured_defaults.py
--- old/knack-0.6.1/tests/test_command_with_configured_defaults.py 2019-04-26 02:11:43.000000000 +0200
+++ new/knack-0.6.2/tests/test_command_with_configured_defaults.py 2019-05-23 00:19:57.000000000 +0200
@@ -5,17 +5,15 @@
from __future__ import print_function
import os
import logging
+import sys
import unittest
try:
import mock
except ImportError:
from unittest import mock
-from six import StringIO
-import sys
from knack.arguments import ArgumentsContext
-from knack.commands import CLICommandsLoader, CLICommand, CommandGroup
-from knack.config import CLIConfig
+from knack.commands import CLICommandsLoader, CommandGroup
from tests.util import DummyCLI, redirect_io
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/knack-0.6.1/tests/test_deprecation.py new/knack-0.6.2/tests/test_deprecation.py
--- old/knack-0.6.1/tests/test_deprecation.py 2019-04-26 02:11:43.000000000 +0200
+++ new/knack-0.6.2/tests/test_deprecation.py 2019-05-23 00:19:57.000000000 +0200
@@ -28,6 +28,7 @@
pass
+# pylint: disable=line-too-long
class TestCommandDeprecation(unittest.TestCase):
def setUp(self):
@@ -132,7 +133,8 @@
with self.assertRaises(SystemExit):
self.cli_ctx.invoke('cmd5 -h'.split())
actual = self.io.getvalue()
- self.assertTrue(u'invalid choice' in actual and u'cmd5' in actual)
+ expected = """The most similar choices to 'cmd5'"""
+ self.assertIn(expected, actual)
class TestCommandGroupDeprecation(unittest.TestCase):
@@ -231,7 +233,8 @@
with self.assertRaises(SystemExit):
self.cli_ctx.invoke('group5 -h'.split())
actual = self.io.getvalue()
- self.assertTrue(u'invalid choice' in actual and u'group5' in actual)
+ expected = """The most similar choices to 'group5'"""
+ self.assertIn(expected, actual)
@redirect_io
def test_deprecate_command_implicitly(self):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/knack-0.6.1/tests/test_introspection.py new/knack-0.6.2/tests/test_introspection.py
--- old/knack-0.6.1/tests/test_introspection.py 2019-04-26 02:11:43.000000000 +0200
+++ new/knack-0.6.2/tests/test_introspection.py 2019-05-23 00:19:57.000000000 +0200
@@ -3,12 +3,7 @@
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------
-import os
-import stat
import unittest
-import tempfile
-import mock
-from six.moves import configparser
from knack.introspection import extract_full_summary_from_signature, option_descriptions, extract_args_from_signature
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/knack-0.6.1/tests/test_preview.py new/knack-0.6.2/tests/test_preview.py
--- old/knack-0.6.1/tests/test_preview.py 1970-01-01 01:00:00.000000000 +0100
+++ new/knack-0.6.2/tests/test_preview.py 2019-05-23 00:19:57.000000000 +0200
@@ -0,0 +1,196 @@
+# --------------------------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for license information.
+# --------------------------------------------------------------------------------------------
+
+from __future__ import unicode_literals
+
+import unittest
+try:
+ import mock
+except ImportError:
+ from unittest import mock
+from threading import Lock
+
+from knack.arguments import ArgumentsContext
+from knack.commands import CLICommand, CLICommandsLoader, CommandGroup
+
+from tests.util import DummyCLI, redirect_io
+
+
+def example_handler(arg1, arg2=None, arg3=None):
+ """ Short summary here. Long summary here. Still long summary. """
+ pass
+
+
+def example_arg_handler(arg1, opt1, arg2=None, opt2=None, arg3=None,
+ opt3=None, arg4=None, opt4=None, arg5=None, opt5=None):
+ pass
+
+
+class TestCommandPreview(unittest.TestCase):
+
+ def setUp(self):
+
+ from knack.help_files import helps
+
+ class PreviewTestCommandLoader(CLICommandsLoader):
+ def load_command_table(self, args):
+ super(PreviewTestCommandLoader, self).load_command_table(args)
+ with CommandGroup(self, '', '{}#{{}}'.format(__name__)) as g:
+ g.command('cmd1', 'example_handler', is_preview=True)
+
+ with CommandGroup(self, 'grp1', '{}#{{}}'.format(__name__), is_preview=True) as g:
+ g.command('cmd1', 'example_handler')
+
+ return self.command_table
+
+ def load_arguments(self, command):
+ with ArgumentsContext(self, '') as c:
+ c.argument('arg1', options_list=['--arg', '-a'], required=False, type=int, choices=[1, 2, 3])
+ c.argument('arg2', options_list=['-b'], required=True, choices=['a', 'b', 'c'])
+
+ super(PreviewTestCommandLoader, self).load_arguments(command)
+
+ helps['grp1'] = """
+ type: group
+ short-summary: A group.
+"""
+ self.cli_ctx = DummyCLI(commands_loader_cls=PreviewTestCommandLoader)
+
+ @redirect_io
+ def test_preview_command_group_help(self):
+ """ Ensure preview commands appear correctly in group help view. """
+ with self.assertRaises(SystemExit):
+ self.cli_ctx.invoke('-h'.split())
+ actual = self.io.getvalue()
+ expected = u"""
+Group
+ {}
+
+Subgroups:
+ grp1 [Preview] : A group.
+
+Commands:
+ cmd1 [Preview] : Short summary here.
+
+""".format(self.cli_ctx.name)
+ self.assertEqual(expected, actual)
+
+ @redirect_io
+ def test_preview_command_plain_execute(self):
+ """ Ensure general warning displayed when running preview command. """
+ self.cli_ctx.invoke('cmd1 -b b'.split())
+ actual = self.io.getvalue()
+ expected = "This command is in preview. It may be changed/removed in a future release."
+ self.assertIn(expected, actual)
+
+
+class TestCommandGroupPreview(unittest.TestCase):
+
+ def setUp(self):
+
+ from knack.help_files import helps
+
+ class PreviewTestCommandLoader(CLICommandsLoader):
+ def load_command_table(self, args):
+ super(PreviewTestCommandLoader, self).load_command_table(args)
+
+ with CommandGroup(self, 'group1', '{}#{{}}'.format(__name__), is_preview=True) as g:
+ g.command('cmd1', 'example_handler')
+
+ return self.command_table
+
+ def load_arguments(self, command):
+ with ArgumentsContext(self, '') as c:
+ c.argument('arg1', options_list=['--arg', '-a'], required=False, type=int, choices=[1, 2, 3])
+ c.argument('arg2', options_list=['-b'], required=True, choices=['a', 'b', 'c'])
+
+ super(PreviewTestCommandLoader, self).load_arguments(command)
+
+ helps['group1'] = """
+ type: group
+ short-summary: A group.
+"""
+ self.cli_ctx = DummyCLI(commands_loader_cls=PreviewTestCommandLoader)
+
+ @redirect_io
+ def test_preview_command_group_help_plain(self):
+ """ Ensure help warnings appear for preview command group help. """
+ with self.assertRaises(SystemExit):
+ self.cli_ctx.invoke('group1 -h'.split())
+ actual = self.io.getvalue()
+ expected = """
+Group
+ cli group1 : A group.
+ This command group is in preview. It may be changed/removed in a future release.
+Commands:
+ cmd1 : Short summary here.
+
+""".format(self.cli_ctx.name)
+ self.assertEqual(expected, actual)
+
+ @redirect_io
+ def test_preview_command_implicitly(self):
+ """ Ensure help warning displayed for command in preview because of a preview parent group. """
+ with self.assertRaises(SystemExit):
+ self.cli_ctx.invoke('group1 cmd1 -h'.split())
+ actual = self.io.getvalue()
+ expected = """
+Command
+ {} group1 cmd1 : Short summary here.
+ Long summary here. Still long summary. Command group 'group1' is in preview. It may be
+ changed/removed in a future release.
+""".format(self.cli_ctx.name)
+ self.assertIn(expected, actual)
+
+
+class TestArgumentPreview(unittest.TestCase):
+
+ def setUp(self):
+
+ from knack.help_files import helps
+
+ class PreviewTestCommandLoader(CLICommandsLoader):
+ def load_command_table(self, args):
+ super(PreviewTestCommandLoader, self).load_command_table(args)
+ with CommandGroup(self, '', '{}#{{}}'.format(__name__)) as g:
+ g.command('arg-test', 'example_arg_handler')
+ return self.command_table
+
+ def load_arguments(self, command):
+ with ArgumentsContext(self, 'arg-test') as c:
+ c.argument('arg1', help='Arg1', is_preview=True)
+
+ super(PreviewTestCommandLoader, self).load_arguments(command)
+
+ helps['grp1'] = """
+ type: group
+ short-summary: A group.
+"""
+ self.cli_ctx = DummyCLI(commands_loader_cls=PreviewTestCommandLoader)
+
+ @redirect_io
+ def test_preview_arguments_command_help(self):
+ """ Ensure preview arguments appear correctly in command help view. """
+ with self.assertRaises(SystemExit):
+ self.cli_ctx.invoke('arg-test -h'.split())
+ actual = self.io.getvalue()
+ expected = """
+Arguments
+ --arg1 [Preview] [Required] : Arg1.
+ Argument '--arg1' is in preview. It may be changed/removed in a future release.
+""".format(self.cli_ctx.name)
+ self.assertIn(expected, actual)
+
+ @redirect_io
+ def test_preview_arguments_execute(self):
+ """ Ensure deprecated arguments can be used. """
+ self.cli_ctx.invoke('arg-test --arg1 foo --opt1 bar'.split())
+ actual = self.io.getvalue()
+ expected = "Argument '--arg1' is in preview. It may be changed/removed in a future release."
+ self.assertIn(expected, actual)
+
+
+if __name__ == '__main__':
+ unittest.main()
1
0
Hello community,
here is the log from the commit of package python-wsgi_intercept for openSUSE:Factory checked in at 2019-05-27 08:38:20
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-wsgi_intercept (Old)
and /work/SRC/openSUSE:Factory/.python-wsgi_intercept.new.5148 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-wsgi_intercept"
Mon May 27 08:38:20 2019 rev:20 rq:705258 version:1.8.1
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-wsgi_intercept/python-wsgi_intercept.changes 2019-03-21 09:53:39.182783136 +0100
+++ /work/SRC/openSUSE:Factory/.python-wsgi_intercept.new.5148/python-wsgi_intercept.changes 2019-05-27 08:38:21.767071503 +0200
@@ -1,0 +2,6 @@
+Fri May 24 13:45:03 UTC 2019 - Tomáš Chvátal <tchvatal(a)suse.com>
+
+- Update to 1.8.1:
+ * Fixes issues with latest urllib
+
+-------------------------------------------------------------------
Old:
----
wsgi_intercept-1.8.0.tar.gz
New:
----
wsgi_intercept-1.8.1.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-wsgi_intercept.spec ++++++
--- /var/tmp/diff_new_pack.P68o97/_old 2019-05-27 08:38:22.443071239 +0200
+++ /var/tmp/diff_new_pack.P68o97/_new 2019-05-27 08:38:22.443071239 +0200
@@ -18,31 +18,29 @@
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
Name: python-wsgi_intercept
-Version: 1.8.0
+Version: 1.8.1
Release: 0
Summary: Installs a WSGI application in place of a real URI for testing
License: MIT
Group: Development/Languages/Python
-Url: https://github.com/cdent/python3-wsgi-intercept
-Source: https://pypi.io/packages/source/w/wsgi_intercept/wsgi_intercept-%{version}.…
-BuildRequires: %{python_module setuptools}
-BuildRequires: python-rpm-macros
-# Test requirements:
+URL: https://github.com/cdent/python3-wsgi-intercept
+Source: https://files.pythonhosted.org/packages/source/w/wsgi_intercept/wsgi_interc…
BuildRequires: %{python_module devel}
BuildRequires: %{python_module httplib2}
BuildRequires: %{python_module pytest >= 2.4}
BuildRequires: %{python_module requests >= 2.0.1}
+BuildRequires: %{python_module setuptools}
BuildRequires: %{python_module six}
BuildRequires: %{python_module urllib3 >= 1.11.0}
BuildRequires: fdupes
+BuildRequires: python-rpm-macros
Requires: python-six
+BuildArch: noarch
%if 0%{?_no_weakdeps}
Requires: python-requests >= 2.0.1
%else
Recommends: python-requests >= 2.0.1
%endif
-BuildArch: noarch
-
%python_subpackages
%description
@@ -54,9 +52,6 @@
%prep
%setup -q -n wsgi_intercept-%{version}
-%if 0%{?suse_version} == 1230
-%patch0 -p1
-%endif
%build
%python_build
@@ -68,7 +63,7 @@
%check
export WSGI_INTERCEPT_SKIP_NETWORK=true
-%python_exec -m pytest --ignore _build.python2 --ignore _build.python3
+%pytest
%files %{python_files}
%{python_sitelib}/wsgi_intercept-%{version}-py%{py_ver}.egg-info
++++++ wsgi_intercept-1.8.0.tar.gz -> wsgi_intercept-1.8.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/wsgi_intercept-1.8.0/PKG-INFO new/wsgi_intercept-1.8.1/PKG-INFO
--- old/wsgi_intercept-1.8.0/PKG-INFO 2018-07-06 13:24:09.000000000 +0200
+++ new/wsgi_intercept-1.8.1/PKG-INFO 2019-05-23 12:57:28.000000000 +0200
@@ -1,12 +1,11 @@
-Metadata-Version: 1.1
+Metadata-Version: 2.1
Name: wsgi_intercept
-Version: 1.8.0
+Version: 1.8.1
Summary: wsgi_intercept installs a WSGI application in place of a real URI for testing.
Home-page: http://pypi.python.org/pypi/wsgi_intercept
Author: Titus Brown, Kumar McMillan, Chris Dent, Sasha Hart
Author-email: cdent(a)peermore.com
License: MIT License
-Description-Content-Type: UNKNOWN
Description: Installs a WSGI application in place of a real host for testing.
Introduction
@@ -158,5 +157,8 @@
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
+Classifier: Programming Language :: Python :: 3.7
Classifier: Topic :: Internet :: WWW/HTTP :: WSGI
Classifier: Topic :: Software Development :: Testing
+Provides-Extra: testing
+Provides-Extra: docs
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/wsgi_intercept-1.8.0/setup.py new/wsgi_intercept-1.8.1/setup.py
--- old/wsgi_intercept-1.8.0/setup.py 2018-07-06 13:21:51.000000000 +0200
+++ new/wsgi_intercept-1.8.1/setup.py 2019-05-23 12:33:23.000000000 +0200
@@ -1,7 +1,7 @@
from setuptools import setup, find_packages
-VERSION = '1.8.0'
+VERSION = '1.8.1'
CLASSIFIERS = """
Environment :: Web Environment
@@ -14,6 +14,7 @@
Programming Language :: Python :: 3.4
Programming Language :: Python :: 3.5
Programming Language :: Python :: 3.6
+Programming Language :: Python :: 3.7
Topic :: Internet :: WWW/HTTP :: WSGI
Topic :: Software Development :: Testing
""".strip().splitlines()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/wsgi_intercept-1.8.0/wsgi_intercept/_urllib3.py new/wsgi_intercept-1.8.1/wsgi_intercept/_urllib3.py
--- old/wsgi_intercept-1.8.0/wsgi_intercept/_urllib3.py 2017-09-26 00:14:59.000000000 +0200
+++ new/wsgi_intercept-1.8.1/wsgi_intercept/_urllib3.py 2019-05-23 12:28:17.000000000 +0200
@@ -27,6 +27,7 @@
if 'strict' in kwargs and sys.version_info > (3, 0):
kwargs.pop('strict')
kwargs.pop('socket_options', None)
+ kwargs.pop('key_password', None)
WSGI_HTTPSConnection.__init__(self, *args, **kwargs)
HTTPSConnection.__init__(self, *args, **kwargs)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/wsgi_intercept-1.8.0/wsgi_intercept/tests/test_response_headers.py new/wsgi_intercept-1.8.1/wsgi_intercept/tests/test_response_headers.py
--- old/wsgi_intercept-1.8.0/wsgi_intercept/tests/test_response_headers.py 2017-09-26 00:14:59.000000000 +0200
+++ new/wsgi_intercept-1.8.1/wsgi_intercept/tests/test_response_headers.py 2019-05-23 12:14:50.000000000 +0200
@@ -77,8 +77,8 @@
with py.test.raises(TypeError) as error:
response = requests.get(url)
- assert (str(error.value) ==
- "Header has a key '%s' or value '%s' "
+ assert (
+ str(error.value) == "Header has a key '%s' or value '%s' "
"which is not a native str." % (header_key, header_value))
# When False, other types of strings are okay.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/wsgi_intercept-1.8.0/wsgi_intercept.egg-info/PKG-INFO new/wsgi_intercept-1.8.1/wsgi_intercept.egg-info/PKG-INFO
--- old/wsgi_intercept-1.8.0/wsgi_intercept.egg-info/PKG-INFO 2018-07-06 13:24:09.000000000 +0200
+++ new/wsgi_intercept-1.8.1/wsgi_intercept.egg-info/PKG-INFO 2019-05-23 12:57:27.000000000 +0200
@@ -1,12 +1,11 @@
-Metadata-Version: 1.1
+Metadata-Version: 2.1
Name: wsgi-intercept
-Version: 1.8.0
+Version: 1.8.1
Summary: wsgi_intercept installs a WSGI application in place of a real URI for testing.
Home-page: http://pypi.python.org/pypi/wsgi_intercept
Author: Titus Brown, Kumar McMillan, Chris Dent, Sasha Hart
Author-email: cdent(a)peermore.com
License: MIT License
-Description-Content-Type: UNKNOWN
Description: Installs a WSGI application in place of a real host for testing.
Introduction
@@ -158,5 +157,8 @@
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
+Classifier: Programming Language :: Python :: 3.7
Classifier: Topic :: Internet :: WWW/HTTP :: WSGI
Classifier: Topic :: Software Development :: Testing
+Provides-Extra: testing
+Provides-Extra: docs
1
0
Hello community,
here is the log from the commit of package python-zstandard for openSUSE:Factory checked in at 2019-05-27 08:38:17
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-zstandard (Old)
and /work/SRC/openSUSE:Factory/.python-zstandard.new.5148 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-zstandard"
Mon May 27 08:38:17 2019 rev:2 rq:705256 version:0.11.1
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-zstandard/python-zstandard.changes 2019-05-07 23:20:39.293148249 +0200
+++ /work/SRC/openSUSE:Factory/.python-zstandard.new.5148/python-zstandard.changes 2019-05-27 08:38:18.495072778 +0200
@@ -1,0 +2,6 @@
+Fri May 24 13:39:30 UTC 2019 - Tomáš Chvátal <tchvatal(a)suse.com>
+
+- Update to 0.11.1:
+ * Fix memory leak in ``ZstdDecompressionReader.seek()`` (#82).
+
+-------------------------------------------------------------------
Old:
----
zstandard-0.11.0.tar.gz
New:
----
zstandard-0.11.1.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-zstandard.spec ++++++
--- /var/tmp/diff_new_pack.vGls2Q/_old 2019-05-27 08:38:19.139072527 +0200
+++ /var/tmp/diff_new_pack.vGls2Q/_new 2019-05-27 08:38:19.143072526 +0200
@@ -12,32 +12,32 @@
# license that conforms to the Open Source Definition (Version 1.9)
# published by the Open Source Initiative.
-# Please submit bugfixes or comments via http://bugs.opensuse.org/
+# Please submit bugfixes or comments via https://bugs.opensuse.org/
+#
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
Name: python-zstandard
-Version: 0.11.0
+Version: 0.11.1
Release: 0
-License: BSD-3-Clause
Summary: Zstandard bindings for Python
-Url: https://github.com/indygreg/python-zstandard
+License: BSD-3-Clause
Group: Development/Languages/Python
+URL: https://github.com/indygreg/python-zstandard
Source: https://files.pythonhosted.org/packages/source/z/zstandard/zstandard-%{vers…
BuildRequires: %{python_module devel}
BuildRequires: %{python_module setuptools}
BuildRequires: fdupes
+BuildRequires: libzstd-devel
BuildRequires: python-rpm-macros
BuildRequires: zstd
-BuildRequires: libzstd-devel
+Requires: python-cffi >= 1.11
+Requires: zstd
+Conflicts: python-zstd
# SECTION test requirements
BuildRequires: %{python_module cffi >= 1.11}
BuildRequires: %{python_module nose}
# /SECTION
-Requires: python-cffi >= 1.11
-Requires: zstd
-Conflicts: python-zstd
-
%python_subpackages
%description
++++++ zstandard-0.11.0.tar.gz -> zstandard-0.11.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/zstandard-0.11.0/NEWS.rst new/zstandard-0.11.1/NEWS.rst
--- old/zstandard-0.11.0/NEWS.rst 2019-02-26 01:17:23.000000000 +0100
+++ new/zstandard-0.11.1/NEWS.rst 2019-05-15 05:00:47.000000000 +0200
@@ -66,6 +66,11 @@
* API for ensuring max memory ceiling isn't exceeded.
* Move off nose for testing.
+0.11.1 (released 2019-05-14)
+============================
+
+* Fix memory leak in ``ZstdDecompressionReader.seek()`` (#82).
+
0.11.0 (released 2019-02-24)
============================
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/zstandard-0.11.0/PKG-INFO new/zstandard-0.11.1/PKG-INFO
--- old/zstandard-0.11.0/PKG-INFO 2019-02-26 01:17:31.000000000 +0100
+++ new/zstandard-0.11.1/PKG-INFO 2019-05-15 05:00:56.000000000 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: zstandard
-Version: 0.11.0
+Version: 0.11.1
Summary: Zstandard bindings for Python
Home-page: https://github.com/indygreg/python-zstandard
Author: Gregory Szorc
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/zstandard-0.11.0/c-ext/decompressionreader.c new/zstandard-0.11.1/c-ext/decompressionreader.c
--- old/zstandard-0.11.0/c-ext/decompressionreader.c 2019-02-26 01:17:23.000000000 +0100
+++ new/zstandard-0.11.1/c-ext/decompressionreader.c 2019-05-15 05:00:47.000000000 +0200
@@ -653,6 +653,8 @@
readSize = PyBytes_GET_SIZE(readResult);
+ Py_CLEAR(readResult);
+
/* Empty read means EOF. */
if (!readSize) {
break;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/zstandard-0.11.0/c-ext/python-zstandard.h new/zstandard-0.11.1/c-ext/python-zstandard.h
--- old/zstandard-0.11.0/c-ext/python-zstandard.h 2019-02-26 01:17:23.000000000 +0100
+++ new/zstandard-0.11.1/c-ext/python-zstandard.h 2019-05-15 05:00:47.000000000 +0200
@@ -16,7 +16,7 @@
#include <zdict.h>
/* Remember to change the string in zstandard/__init__ as well */
-#define PYTHON_ZSTANDARD_VERSION "0.11.0"
+#define PYTHON_ZSTANDARD_VERSION "0.11.1"
typedef enum {
compressorobj_flush_finish,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/zstandard-0.11.0/tests/test_module_attributes.py new/zstandard-0.11.1/tests/test_module_attributes.py
--- old/zstandard-0.11.0/tests/test_module_attributes.py 2019-02-26 01:17:23.000000000 +0100
+++ new/zstandard-0.11.1/tests/test_module_attributes.py 2019-05-15 05:00:47.000000000 +0200
@@ -14,7 +14,7 @@
def test_version(self):
self.assertEqual(zstd.ZSTD_VERSION, (1, 3, 8))
- self.assertEqual(zstd.__version__, '0.11.0')
+ self.assertEqual(zstd.__version__, '0.11.1')
def test_constants(self):
self.assertEqual(zstd.MAX_COMPRESSION_LEVEL, 22)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/zstandard-0.11.0/zstandard/__init__.py new/zstandard-0.11.1/zstandard/__init__.py
--- old/zstandard-0.11.0/zstandard/__init__.py 2019-02-26 01:17:23.000000000 +0100
+++ new/zstandard-0.11.1/zstandard/__init__.py 2019-05-15 05:00:47.000000000 +0200
@@ -62,4 +62,4 @@
'cext, or cffi' % _module_policy)
# Keep this in sync with python-zstandard.h.
-__version__ = '0.11.0'
+__version__ = '0.11.1'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/zstandard-0.11.0/zstandard.egg-info/PKG-INFO new/zstandard-0.11.1/zstandard.egg-info/PKG-INFO
--- old/zstandard-0.11.0/zstandard.egg-info/PKG-INFO 2019-02-26 01:17:31.000000000 +0100
+++ new/zstandard-0.11.1/zstandard.egg-info/PKG-INFO 2019-05-15 05:00:56.000000000 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: zstandard
-Version: 0.11.0
+Version: 0.11.1
Summary: Zstandard bindings for Python
Home-page: https://github.com/indygreg/python-zstandard
Author: Gregory Szorc
1
0
Hello community,
here is the log from the commit of package python-jupyter-server for openSUSE:Factory checked in at 2019-05-27 08:38:14
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-jupyter-server (Old)
and /work/SRC/openSUSE:Factory/.python-jupyter-server.new.5148 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-jupyter-server"
Mon May 27 08:38:14 2019 rev:2 rq:705255 version:0.0.4
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-jupyter-server/python-jupyter-server.changes 2019-05-22 11:10:14.318595105 +0200
+++ /work/SRC/openSUSE:Factory/.python-jupyter-server.new.5148/python-jupyter-server.changes 2019-05-27 08:38:15.527073936 +0200
@@ -1,0 +2,6 @@
+Wed May 22 21:53:32 UTC 2019 - Todd R <toddrme2178(a)gmail.com>
+
+- Remove selenium test dependency, it isn't really needed for the
+ tests and doesn't work on ARM.
+
+-------------------------------------------------------------------
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-jupyter-server.spec ++++++
--- /var/tmp/diff_new_pack.HuONKX/_old 2019-05-27 08:38:16.215073667 +0200
+++ /var/tmp/diff_new_pack.HuONKX/_new 2019-05-27 08:38:16.219073666 +0200
@@ -44,7 +44,7 @@
BuildRequires: %{python_module prometheus_client}
BuildRequires: %{python_module pyzmq >= 17}
BuildRequires: %{python_module requests}
-BuildRequires: %{python_module selenium}
+# BuildRequires: %%{python_module selenium}
BuildRequires: %{python_module terminado >= 0.8.1}
BuildRequires: %{python_module tornado >= 4}
BuildRequires: %{python_module traitlets >= 4.2.1}
1
0
Hello community,
here is the log from the commit of package proftpd for openSUSE:Factory checked in at 2019-05-27 08:38:07
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/proftpd (Old)
and /work/SRC/openSUSE:Factory/.proftpd.new.5148 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "proftpd"
Mon May 27 08:38:07 2019 rev:32 rq:705245 version:1.3.6
Changes:
--------
--- /work/SRC/openSUSE:Factory/proftpd/proftpd.changes 2018-07-18 22:53:41.715009585 +0200
+++ /work/SRC/openSUSE:Factory/.proftpd.new.5148/proftpd.changes 2019-05-27 08:38:12.287075198 +0200
@@ -1,0 +2,66 @@
+Tue Mar 26 11:35:53 UTC 2019 - Jan Engelhardt <jengelh(a)inai.de>
+
+- Fix the Factory build: select the appropriate OpenSSL version
+ to build with.
+
+-------------------------------------------------------------------
+Wed Mar 20 18:46:47 UTC 2019 - Jan Engelhardt <jengelh(a)inai.de>
+
+- Reduce hard dependency on systemd to only that which is
+ necessary for building and installation.
+- Modernize RPM macro use (%make_install, %tmpfiles_create).
+- Strip emphasis from description and trim other platform mentions.
+
+-------------------------------------------------------------------
+Wed Jul 11 08:05:29 UTC 2018 - chris(a)computersalat.de
+
+- update to 1.3.6
+ * Support for using Redis for caching, logging; see the doc/howto/Redis.html
+ documentation.
+ * Fixed mod_sql_postgres SSL support (Issue #415).
+ * Support building against LibreSSL instead of OpenSSL (Issue #361).
+ * Better support on AIX for login restraictions (Bug #4285).
+ * TimeoutLogin (and other timeouts) were not working properly for SFTP
+ connections (Bug#4299).
+ * Handling of the SIGILL and SIGINT signals, by the daemon process, now causes
+ the child processes to be terminated as well (Issue #461).
+ * RPM .spec file naming changed to conform to Fedora guidelines.
+ * Fix for "AllowChrootSymlinks off" checking each component for symlinks
+ (CVE-2017-7418).
+ -New Modules:
+ * mod_redis, mod_tls_redis, mod_wrap2_redis
+ With Redis now supported as a caching mechanism, similar to Memcache,
+ there are now Redis-using modules: mod_redis (for configuring the Redis
+ connection information), mod_tls_redis (for caching SSL sessions and
+ OCSP information using Redis), and mod_wrap2_redis (for using ACLs stored
+ in Redis).
+ -Changed Modules:
+ * mod_ban
+ The mod_ban module's BanCache directive can now use Redis-based caching;
+ see doc/contrib/mod_ban.html#BanCache.
+ -New Configuration Directives
+ * SQLPasswordArgon2, SQLPasswordScrypt
+ The key lengths for Argon2 and Scrypt-based passwords are now configurable
+ via these new directives; previously, the key length had been hardcoded
+ to be 32 bytes, which is not interoperable with all other implementations
+ (Issue #454).
+ -Changed Configuration Directives
+ * AllowChrootSymlinks
+ When "AllowChrootSymlinks off" was used, only the last portion of the
+ DefaultRoot path would be checked to see if it was a symlink. Now,
+ each component of the DefaultRoot path will be checked to see if it is
+ a symlink when "AllowChrootSymlinks off" is used.
+ * Include
+ The Include directive can now be used within a <Limit> section, e.g.:
+ <Limit LOGIN>
+ Include /path/to/allowed.txt
+ DenyAll
+ </Limit>
+ -API Changes
+ * A new JSON API has been added, for use by third-party modules.
+- remove obsolete proftpd_include-in-limit-section.patch
+- rebase patches
+ * proftpd-ftpasswd.patch
+ * proftpd-no_BuildDate.patch
+
+-------------------------------------------------------------------
Old:
----
proftpd-1.3.5e.tar.gz
proftpd-1.3.5e.tar.gz.asc
proftpd_include-in-limit-section.patch
New:
----
proftpd-1.3.6.tar.gz
proftpd-1.3.6.tar.gz.asc
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ proftpd.spec ++++++
--- /var/tmp/diff_new_pack.DYVWrX/_old 2019-05-27 08:38:13.839074594 +0200
+++ /var/tmp/diff_new_pack.DYVWrX/_new 2019-05-27 08:38:13.839074594 +0200
@@ -1,7 +1,7 @@
#
# spec file for package proftpd
#
-# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -12,17 +12,17 @@
# license that conforms to the Open Source Definition (Version 1.9)
# published by the Open Source Initiative.
-# Please submit bugfixes or comments via http://bugs.opensuse.org/
+# Please submit bugfixes or comments via https://bugs.opensuse.org/
#
Name: proftpd
-Summary: Highly configurable GPL-licensed FTP server software
+Summary: Configurable GPL-licensed FTP server software
# Please save your time and do not update to "rc" versions.
# We only accept updates for "STABLE" Versions
License: GPL-2.0-or-later
Group: Productivity/Networking/Ftp/Servers
-Version: 1.3.5e
+Version: 1.3.6
Release: 0
Url: http://www.proftpd.org/
Source0: ftp://ftp.proftpd.org/distrib/source/%{name}-%{version}.tar.gz
@@ -45,8 +45,6 @@
Patch103: %{name}-strip.patch
#PATCH-FIX-openSUSE: file-contains-date-and-time
Patch104: %{name}-no_BuildDate.patch
-#PATCH-Feature-back-port: include-in-limit-section
-Patch105: %{name}_include-in-limit-section.patch
BuildRoot: %{_tmppath}/%{name}-%{version}-build
#BuildRequires: gpg-offline
BuildRequires: fdupes
@@ -58,12 +56,12 @@
BuildRequires: mysql-devel
BuildRequires: ncurses-devel
BuildRequires: openldap2-devel
-BuildRequires: openssl-devel
BuildRequires: pam-devel
BuildRequires: pkg-config
BuildRequires: postgresql-devel
BuildRequires: sqlite3-devel
BuildRequires: unixODBC-devel
+BuildRequires: pkgconfig(libssl) < 1.1
Requires: logrotate
%if 0%{?lang_package:1} > 0
@@ -71,17 +69,16 @@
%endif
%if 0%{?suse_version} >= 1210
-BuildRequires: systemd
-%{?systemd_requires}
+BuildRequires: systemd-rpm-macros
+%{?systemd_ordering}
%define has_systemd 1
%else
Requires(pre): %insserv_prereq
%endif
%description
-ProFTPD is a highly configurable FTP daemon for Unix and Unix-like
-operating systems. See the README.ports file for more details about
-the platforms on which ProFTPD in known or thought to build and run.
+ProFTPD is a configurable FTP daemon for Unix and Unix-like
+operating systems.
%{?lang_package}
@@ -151,7 +148,6 @@
%patch102
%patch103
%patch104
-%patch105
%build
rm contrib/mod_wrap.c
@@ -184,7 +180,7 @@
make %{?_smp_mflags}
%install
-%makeinstall INSTALL_USER=`id -un` INSTALL_GROUP=`id -gn`
+%make_install INSTALL_USER=`id -un` INSTALL_GROUP=`id -gn`
install -D -m 0644 contrib/dist/rpm/ftp.pamd %{buildroot}/%{_sysconfdir}/pam.d/%{name}
install -D -m 0644 contrib/dist/rpm/%{name}.logrotate %{buildroot}/%{_sysconfdir}/logrotate.d/%{name}
#
@@ -231,7 +227,7 @@
%post
%if 0%{?has_systemd}
%service_add_post %{name}.service
-%tmpfiles_create %{_tmpfilesdir}/%{name}.conf || :
+%tmpfiles_create %{_tmpfilesdir}/%{name}.conf
%else
%{fillup_and_insserv -f proftpd}
install -d %{_localstatedir}/run/%{name}
++++++ proftpd-1.3.5e.tar.gz -> proftpd-1.3.6.tar.gz ++++++
/work/SRC/openSUSE:Factory/proftpd/proftpd-1.3.5e.tar.gz /work/SRC/openSUSE:Factory/.proftpd.new.5148/proftpd-1.3.6.tar.gz differ: char 12, line 1
++++++ proftpd-ftpasswd.patch ++++++
--- /var/tmp/diff_new_pack.DYVWrX/_old 2019-05-27 08:38:13.899074570 +0200
+++ /var/tmp/diff_new_pack.DYVWrX/_new 2019-05-27 08:38:13.899074570 +0200
@@ -2,7 +2,7 @@
===================================================================
--- contrib/ftpasswd.orig
+++ contrib/ftpasswd
-@@ -34,8 +34,8 @@ use Getopt::Long;
+@@ -32,8 +32,8 @@ use Getopt::Long;
$Getopt::Long::auto_abbrev = 0;
my $program = basename($0);
@@ -13,7 +13,7 @@
my $shell_file = "/etc/shells";
my $default_cracklib_dict = "/usr/lib/cracklib_dict";
my $cracklib_dict;
-@@ -1074,6 +1074,46 @@ usage: $program [--help] [--hash|--group
+@@ -1109,6 +1109,46 @@ usage: $program [--help] [--hash|--group
--version
Displays the version of $program.
++++++ proftpd-no_BuildDate.patch ++++++
--- /var/tmp/diff_new_pack.DYVWrX/_old 2019-05-27 08:38:13.919074562 +0200
+++ /var/tmp/diff_new_pack.DYVWrX/_new 2019-05-27 08:38:13.919074562 +0200
@@ -65,13 +65,13 @@
-#include "buildstamp.h"
-
/* Application version (in various forms) */
- #define PROFTPD_VERSION_NUMBER 0x0001030511
- #define PROFTPD_VERSION_TEXT "1.3.5e"
+ #define PROFTPD_VERSION_NUMBER 0x0001030605
+ #define PROFTPD_VERSION_TEXT "1.3.6"
Index: src/main.c
===================================================================
--- src/main.c.orig
+++ src/main.c
-@@ -2435,8 +2435,8 @@ static void standalone_main(void) {
+@@ -1883,8 +1883,8 @@ static void standalone_main(void) {
init_bindings();
@@ -80,9 +80,9 @@
+ pr_log_pri(PR_LOG_NOTICE, "ProFTPD %s standalone mode STARTUP",
+ PROFTPD_VERSION_TEXT " " PR_STATUS);
- pr_pidfile_write();
- daemon_loop();
-@@ -2491,7 +2491,6 @@ static void show_settings(void) {
+ if (pr_pidfile_write() < 0) {
+ fprintf(stderr, "error opening PidFile '%s': %s\n", pr_pidfile_get(),
+@@ -1944,7 +1944,6 @@ static void show_settings(void) {
printf("%s", " Platform: " PR_PLATFORM " [unknown]\n");
#endif /* !HAVE_UNAME */
@@ -90,11 +90,11 @@
printf("%s", " Built With:\n configure " PR_BUILD_OPTS "\n\n");
printf("%s", " CFLAGS: " PR_BUILD_CFLAGS "\n");
-@@ -3009,7 +3008,6 @@ int main(int argc, char *argv[], char **
+@@ -2523,7 +2522,6 @@ int main(int argc, char *argv[], char **
printf("ProFTPD Version: %s", PROFTPD_VERSION_TEXT " " PR_STATUS "\n");
printf(" Scoreboard Version: %08x\n", PR_SCOREBOARD_VERSION);
- printf(" Built: %s\n\n", BUILD_STAMP);
- modules_list(PR_MODULES_LIST_FL_SHOW_VERSION);
+ modules_list2(NULL, PR_MODULES_LIST_FL_SHOW_VERSION);
exit(0);
1
0
Hello community,
here is the log from the commit of package opus for openSUSE:Factory checked in at 2019-05-27 08:37:44
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/opus (Old)
and /work/SRC/openSUSE:Factory/.opus.new.5148 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "opus"
Mon May 27 08:37:44 2019 rev:20 rq:705399 version:1.3.1
Changes:
--------
--- /work/SRC/openSUSE:Factory/opus/opus.changes 2018-10-25 08:10:18.260268112 +0200
+++ /work/SRC/openSUSE:Factory/.opus.new.5148/opus.changes 2019-05-27 08:37:45.679085571 +0200
@@ -1,0 +2,15 @@
+Sat May 25 08:29:45 UTC 2019 - Luigi Baldoni <aloisio(a)gmx.com>
+
+- Update to version 1.3.1
+ * This release fixes an issue with the analysis on files with
+ digital silence (all zeros), especially on x87 builds
+ (mostly affects 32-bit builds).
+ * Two new features:
+ + A new OPUS_GET_IN_DTX query to know if the encoder is in
+ DTX mode (last frame was either a comfort noise frame or
+ not encoded at all)
+ + A new (and still experimental) CMake-based build system
+ that is eventually meant to replace the VS2015 build
+ system (the autotools one will stay).
+
+-------------------------------------------------------------------
Old:
----
opus-1.3.tar.gz
New:
----
opus-1.3.1.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ opus.spec ++++++
--- /var/tmp/diff_new_pack.ICNwr5/_old 2019-05-27 08:37:46.791085137 +0200
+++ /var/tmp/diff_new_pack.ICNwr5/_new 2019-05-27 08:37:46.795085136 +0200
@@ -1,7 +1,7 @@
#
# spec file for package opus
#
-# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
# Copyright (c) 2012 Pascal Bleser <pascal.bleser(a)opensuse.org>
#
# All modifications and additions to the file contributed by third parties
@@ -19,7 +19,7 @@
%define sover 0
Name: opus
-Version: 1.3
+Version: 1.3.1
Release: 0
Summary: Audio Codec Library
License: BSD-3-Clause
++++++ opus-1.3.tar.gz -> opus-1.3.1.tar.gz ++++++
++++ 1779 lines of diff (skipped)
1
0
Hello community,
here is the log from the commit of package python-pyasn1-modules for openSUSE:Factory checked in at 2019-05-27 08:37:33
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-pyasn1-modules (Old)
and /work/SRC/openSUSE:Factory/.python-pyasn1-modules.new.5148 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-pyasn1-modules"
Mon May 27 08:37:33 2019 rev:23 rq:705395 version:0.2.5
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-pyasn1-modules/python-pyasn1-modules.changes 2019-02-02 21:45:26.836178420 +0100
+++ /work/SRC/openSUSE:Factory/.python-pyasn1-modules.new.5148/python-pyasn1-modules.changes 2019-05-27 08:37:34.751089831 +0200
@@ -1,0 +2,20 @@
+Sat May 25 09:39:16 UTC 2019 - Tomáš Chvátal <tchvatal(a)suse.com>
+
+- Update to 0.2.5:
+ - Added RFC3560 providing RSAES-OAEP Key Transport Algorithm
+ in CMS
+ - Added RFC6019 providing BinaryTime - an alternate format
+ for representing Date and Time
+ - RFC3565 superseded by RFC5649
+ - Added RFC5480 providng Elliptic Curve Cryptography Subject
+ Public Key Information
+ - Added RFC8520 providing X.509 Extensions for MUD URL and
+ MUD Signer
+ - Added RFC3161 providing Time-Stamp Protocol support
+ - Added RFC3709 providing Logotypes in X.509 Certificates
+ - Added RFC3274 providing CMS Compressed Data Content Type
+ - Added RFC4073 providing Multiple Contents protection
+ with CMS
+- Execute testsuite
+
+-------------------------------------------------------------------
Old:
----
pyasn1-modules-0.2.4.tar.gz
New:
----
pyasn1-modules-0.2.5.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-pyasn1-modules.spec ++++++
--- /var/tmp/diff_new_pack.33dpmN/_old 2019-05-27 08:37:35.275089627 +0200
+++ /var/tmp/diff_new_pack.33dpmN/_new 2019-05-27 08:37:35.287089622 +0200
@@ -1,7 +1,7 @@
#
# spec file for package python-pyasn1-modules
#
-# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -12,25 +12,26 @@
# license that conforms to the Open Source Definition (Version 1.9)
# published by the Open Source Initiative.
-# Please submit bugfixes or comments via http://bugs.opensuse.org/
+# Please submit bugfixes or comments via https://bugs.opensuse.org/
#
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
Name: python-pyasn1-modules
-Version: 0.2.4
+Version: 0.2.5
Release: 0
-Url: https://github.com/etingof/pyasn1-modules
Summary: Collection of protocols modules written in ASN.1 language
License: BSD-3-Clause
Group: Development/Languages/Python
-Source: https://pypi.io/packages/source/p/pyasn1-modules/pyasn1-modules-%{version}.…
-BuildRoot: %{_tmppath}/%{name}-%{version}-build
+URL: https://github.com/etingof/pyasn1-modules
+Source: https://files.pythonhosted.org/packages/source/p/pyasn1-modules/pyasn1-modu…
+BuildRequires: %{python_module pyasn1 >= 0.3.4}
+BuildRequires: %{python_module pytest}
BuildRequires: %{python_module setuptools}
+BuildRequires: fdupes
BuildRequires: python-rpm-macros
Requires: python-pyasn1 >= 0.3.4
BuildArch: noarch
-
%python_subpackages
%description
@@ -47,10 +48,14 @@
%install
%python_install
+%python_expand %fdupes %{buildroot}%{$python_sitelib}
+
+%check
+%pytest
-%files %python_files
-%defattr(-,root,root,-)
-%doc CHANGES.txt LICENSE.txt README.md
+%files %{python_files}
+%license LICENSE.txt
+%doc CHANGES.txt README.md
%{python_sitelib}/*
%changelog
++++++ pyasn1-modules-0.2.4.tar.gz -> pyasn1-modules-0.2.5.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyasn1-modules-0.2.4/CHANGES.txt new/pyasn1-modules-0.2.5/CHANGES.txt
--- old/pyasn1-modules-0.2.4/CHANGES.txt 2019-01-26 18:53:16.000000000 +0100
+++ new/pyasn1-modules-0.2.5/CHANGES.txt 2019-04-24 06:40:45.000000000 +0200
@@ -1,4 +1,24 @@
+Revision 0.2.5, released 24-04-2019
+-----------------------------------
+
+- Added module RFC5958 providing Asymmetric Key Packages,
+ which is essentially version 2 of the PrivateKeyInfo
+ structure in PKCS#8 in RFC 5208
+- Added module RFC8410 providing algorithm Identifiers for
+ Ed25519, Ed448, X25519, and X448
+- Added module RFC8418 providing Elliptic Curve Diffie-Hellman
+ (ECDH) Key Agreement Algorithm with X25519 and X448
+- Added module RFC3565 providing Elliptic Curve Diffie-Hellman
+ Key Agreement Algorithm use with X25519 and X448 in the
+ Cryptographic Message Syntax (CMS)
+- Added module RFC4108 providing CMS Firmware Wrapper
+- Added module RFC3779 providing X.509 Extensions for IP
+ Addresses and AS Identifiers
+- Added module RFC4055 providing additional Algorithms and
+ Identifiers for RSA Cryptography for use in Certificates
+ and CRLs
+
Revision 0.2.4, released 26-01-2018
-----------------------------------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyasn1-modules-0.2.4/PKG-INFO new/pyasn1-modules-0.2.5/PKG-INFO
--- old/pyasn1-modules-0.2.4/PKG-INFO 2019-01-26 18:54:25.000000000 +0100
+++ new/pyasn1-modules-0.2.5/PKG-INFO 2019-04-24 06:42:13.000000000 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: pyasn1-modules
-Version: 0.2.4
+Version: 0.2.5
Summary: A collection of ASN.1-based protocols modules.
Home-page: https://github.com/etingof/pyasn1-modules
Author: Ilya Etingof <etingof(a)gmail.com>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyasn1-modules-0.2.4/pyasn1_modules/__init__.py new/pyasn1-modules-0.2.5/pyasn1_modules/__init__.py
--- old/pyasn1-modules-0.2.4/pyasn1_modules/__init__.py 2019-01-26 18:53:16.000000000 +0100
+++ new/pyasn1-modules-0.2.5/pyasn1_modules/__init__.py 2019-04-24 06:40:45.000000000 +0200
@@ -1,2 +1,2 @@
# http://www.python.org/dev/peps/pep-0396/
-__version__ = '0.2.4'
+__version__ = '0.2.5'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyasn1-modules-0.2.4/pyasn1_modules/rfc3565.py new/pyasn1-modules-0.2.5/pyasn1_modules/rfc3565.py
--- old/pyasn1-modules-0.2.4/pyasn1_modules/rfc3565.py 1970-01-01 01:00:00.000000000 +0100
+++ new/pyasn1-modules-0.2.5/pyasn1_modules/rfc3565.py 2019-04-24 06:40:45.000000000 +0200
@@ -0,0 +1,41 @@
+# This file is being contributed to pyasn1-modules software.
+#
+# Created by Russ Housley.
+#
+# Copyright (c) 2019, Vigil Security, LLC
+# License: http://snmplabs.com/pyasn1/license.html
+#
+# Use of the Elliptic Curve Diffie-Hellman Key Agreement Algorithm
+# with X25519 and X448 in the Cryptographic Message Syntax (CMS)
+#
+# ASN.1 source from:
+# https://www.rfc-editor.org/rfc/rfc3565.txt
+
+
+from pyasn1.type import univ, constraint
+
+from pyasn1_modules import rfc5280
+
+
+class AlgorithmIdentifier(rfc5280.AlgorithmIdentifier):
+ pass
+
+
+class AES_IV(univ.OctetString):
+ pass
+
+AES_IV.subtypeSpec = constraint.ValueSizeConstraint(16, 16)
+
+
+id_aes128_CBC = univ.ObjectIdentifier('2.16.840.1.101.3.4.1.2')
+
+id_aes192_CBC = univ.ObjectIdentifier('2.16.840.1.101.3.4.1.22')
+
+id_aes256_CBC = univ.ObjectIdentifier('2.16.840.1.101.3.4.1.42')
+
+
+id_aes128_wrap = univ.ObjectIdentifier('2.16.840.1.101.3.4.1.5')
+
+id_aes192_wrap = univ.ObjectIdentifier('2.16.840.1.101.3.4.1.25')
+
+id_aes256_wrap = univ.ObjectIdentifier('2.16.840.1.101.3.4.1.45')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyasn1-modules-0.2.4/pyasn1_modules/rfc3779.py new/pyasn1-modules-0.2.5/pyasn1_modules/rfc3779.py
--- old/pyasn1-modules-0.2.4/pyasn1_modules/rfc3779.py 1970-01-01 01:00:00.000000000 +0100
+++ new/pyasn1-modules-0.2.5/pyasn1_modules/rfc3779.py 2019-04-24 06:40:45.000000000 +0200
@@ -0,0 +1,112 @@
+#
+# This file is part of pyasn1-modules software.
+#
+# Created by Russ Housley with assistance from asn1ate v.0.6.0.
+#
+# Copyright (c) 2019, Vigil Security, LLC
+# License: http://snmplabs.com/pyasn1/license.html
+#
+# X.509 Extensions for IP Addresses and AS Identifiers
+#
+# ASN.1 source from:
+# https://www.rfc-editor.org/rfc/rfc3779.txt
+#
+
+
+from pyasn1.type import univ, char, namedtype, namedval, tag, constraint, useful
+
+
+# IP Address Delegation Extension
+
+id_pe_ipAddrBlocks = univ.ObjectIdentifier('1.3.6.1.5.5.7.1.7')
+
+
+class IPAddress(univ.BitString):
+ pass
+
+
+class IPAddressRange(univ.Sequence):
+ pass
+
+IPAddressRange.componentType = namedtype.NamedTypes(
+ namedtype.NamedType('min', IPAddress()),
+ namedtype.NamedType('max', IPAddress())
+)
+
+
+class IPAddressOrRange(univ.Choice):
+ pass
+
+IPAddressOrRange.componentType = namedtype.NamedTypes(
+ namedtype.NamedType('addressPrefix', IPAddress()),
+ namedtype.NamedType('addressRange', IPAddressRange())
+)
+
+
+class IPAddressChoice(univ.Choice):
+ pass
+
+IPAddressChoice.componentType = namedtype.NamedTypes(
+ namedtype.NamedType('inherit', univ.Null()),
+ namedtype.NamedType('addressesOrRanges', univ.SequenceOf(componentType=IPAddressOrRange()))
+)
+
+
+class IPAddressFamily(univ.Sequence):
+ pass
+
+IPAddressFamily.componentType = namedtype.NamedTypes(
+ namedtype.NamedType('addressFamily', univ.OctetString().subtype(subtypeSpec=constraint.ValueSizeConstraint(2, 3))),
+ namedtype.NamedType('ipAddressChoice', IPAddressChoice())
+)
+
+
+class IPAddrBlocks(univ.SequenceOf):
+ pass
+
+IPAddrBlocks.componentType = IPAddressFamily()
+
+
+# Autonomous System Identifier Delegation Extension
+
+id_pe_autonomousSysIds = univ.ObjectIdentifier('1.3.6.1.5.5.7.1.8')
+
+
+class ASId(univ.Integer):
+ pass
+
+
+class ASRange(univ.Sequence):
+ pass
+
+ASRange.componentType = namedtype.NamedTypes(
+ namedtype.NamedType('min', ASId()),
+ namedtype.NamedType('max', ASId())
+)
+
+
+class ASIdOrRange(univ.Choice):
+ pass
+
+ASIdOrRange.componentType = namedtype.NamedTypes(
+ namedtype.NamedType('id', ASId()),
+ namedtype.NamedType('range', ASRange())
+)
+
+
+class ASIdentifierChoice(univ.Choice):
+ pass
+
+ASIdentifierChoice.componentType = namedtype.NamedTypes(
+ namedtype.NamedType('inherit', univ.Null()),
+ namedtype.NamedType('asIdsOrRanges', univ.SequenceOf(componentType=ASIdOrRange()))
+)
+
+
+class ASIdentifiers(univ.Sequence):
+ pass
+
+ASIdentifiers.componentType = namedtype.NamedTypes(
+ namedtype.OptionalNamedType('asnum', ASIdentifierChoice().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0))),
+ namedtype.OptionalNamedType('rdi', ASIdentifierChoice().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1)))
+)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyasn1-modules-0.2.4/pyasn1_modules/rfc4055.py new/pyasn1-modules-0.2.5/pyasn1_modules/rfc4055.py
--- old/pyasn1-modules-0.2.4/pyasn1_modules/rfc4055.py 1970-01-01 01:00:00.000000000 +0100
+++ new/pyasn1-modules-0.2.5/pyasn1_modules/rfc4055.py 2019-04-24 06:40:45.000000000 +0200
@@ -0,0 +1,249 @@
+#
+# This file is part of pyasn1-modules software.
+#
+# Created by Russ Housley with a very small amount of assistance from
+# asn1ate v.0.6.0.
+#
+# Copyright (c) 2019, Vigil Security, LLC
+# License: http://snmplabs.com/pyasn1/license.html
+#
+# Additional Algorithms and Identifiers for RSA Cryptography
+# for use in Certificates and CRLs
+#
+# ASN.1 source from:
+# https://www.rfc-editor.org/rfc/rfc4055.txt
+#
+
+from pyasn1.type import univ, char, namedtype, namedval, tag, constraint, useful
+from pyasn1_modules import rfc5280
+
+
+def _OID(*components):
+ output = []
+ for x in tuple(components):
+ if isinstance(x, univ.ObjectIdentifier):
+ output.extend(list(x))
+ else:
+ output.append(int(x))
+ return univ.ObjectIdentifier(output)
+
+
+id_sha1 = _OID(1, 3, 14, 3, 2, 26)
+
+
+id_sha256 = _OID(2, 16, 840, 1, 101, 3, 4, 2, 1)
+
+
+id_sha384 = _OID(2, 16, 840, 1, 101, 3, 4, 2, 2)
+
+
+id_sha512 = _OID(2, 16, 840, 1, 101, 3, 4, 2, 3)
+
+
+id_sha224 = _OID(2, 16, 840, 1, 101, 3, 4, 2, 4)
+
+
+rsaEncryption = _OID(1, 2, 840, 113549, 1, 1, 1)
+
+
+id_mgf1 = _OID(1, 2, 840, 113549, 1, 1, 8)
+
+
+id_RSAES_OAEP = _OID(1, 2, 840, 113549, 1, 1, 7)
+
+
+id_pSpecified = _OID(1, 2, 840, 113549, 1, 1, 9)
+
+
+id_RSASSA_PSS = _OID(1, 2, 840, 113549, 1, 1, 10)
+
+
+sha256WithRSAEncryption = _OID(1, 2, 840, 113549, 1, 1, 11)
+
+
+sha384WithRSAEncryption = _OID(1, 2, 840, 113549, 1, 1, 12)
+
+
+sha512WithRSAEncryption = _OID(1, 2, 840, 113549, 1, 1, 13)
+
+
+sha224WithRSAEncryption = _OID(1, 2, 840, 113549, 1, 1, 14)
+
+
+sha1Identifier = rfc5280.AlgorithmIdentifier()
+sha1Identifier['algorithm'] = id_sha1
+sha1Identifier['parameters'] = univ.Null("")
+
+
+sha224Identifier = rfc5280.AlgorithmIdentifier()
+sha224Identifier['algorithm'] = id_sha224
+sha224Identifier['parameters'] = univ.Null("")
+
+
+sha256Identifier = rfc5280.AlgorithmIdentifier()
+sha256Identifier['algorithm'] = id_sha256
+sha256Identifier['parameters'] = univ.Null("")
+
+
+sha384Identifier = rfc5280.AlgorithmIdentifier()
+sha384Identifier['algorithm'] = id_sha384
+sha384Identifier['parameters'] = univ.Null("")
+
+
+sha512Identifier = rfc5280.AlgorithmIdentifier()
+sha512Identifier['algorithm'] = id_sha512
+sha512Identifier['parameters'] = univ.Null("")
+
+
+mgf1SHA1Identifier = rfc5280.AlgorithmIdentifier()
+mgf1SHA1Identifier['algorithm'] = id_mgf1
+mgf1SHA1Identifier['parameters'] = sha1Identifier
+
+
+mgf1SHA224Identifier = rfc5280.AlgorithmIdentifier()
+mgf1SHA224Identifier['algorithm'] = id_mgf1
+mgf1SHA224Identifier['parameters'] = sha224Identifier
+
+
+mgf1SHA256Identifier = rfc5280.AlgorithmIdentifier()
+mgf1SHA256Identifier['algorithm'] = id_mgf1
+mgf1SHA256Identifier['parameters'] = sha256Identifier
+
+
+mgf1SHA384Identifier = rfc5280.AlgorithmIdentifier()
+mgf1SHA384Identifier['algorithm'] = id_mgf1
+mgf1SHA384Identifier['parameters'] = sha384Identifier
+
+
+mgf1SHA512Identifier = rfc5280.AlgorithmIdentifier()
+mgf1SHA512Identifier['algorithm'] = id_mgf1
+mgf1SHA512Identifier['parameters'] = sha512Identifier
+
+
+pSpecifiedEmptyIdentifier = rfc5280.AlgorithmIdentifier()
+pSpecifiedEmptyIdentifier['algorithm'] = id_pSpecified
+pSpecifiedEmptyIdentifier['parameters'] = univ.OctetString(value='')
+
+
+class RSAPublicKey(univ.Sequence):
+ pass
+
+RSAPublicKey.componentType = namedtype.NamedTypes(
+ namedtype.NamedType('modulus', univ.Integer()),
+ namedtype.NamedType('publicExponent', univ.Integer())
+)
+
+
+class HashAlgorithm(rfc5280.AlgorithmIdentifier):
+ pass
+
+
+class MaskGenAlgorithm(rfc5280.AlgorithmIdentifier):
+ pass
+
+
+class RSAES_OAEP_params(univ.Sequence):
+ pass
+
+RSAES_OAEP_params.componentType = namedtype.NamedTypes(
+ namedtype.OptionalNamedType('hashFunc', rfc5280.AlgorithmIdentifier().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0))),
+ namedtype.OptionalNamedType('maskGenFunc', rfc5280.AlgorithmIdentifier().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1))),
+ namedtype.OptionalNamedType('pSourceFunc', rfc5280.AlgorithmIdentifier().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 2)))
+)
+
+
+rSAES_OAEP_Default_Params = RSAES_OAEP_params()
+
+rSAES_OAEP_Default_Identifier = rfc5280.AlgorithmIdentifier()
+rSAES_OAEP_Default_Identifier['algorithm'] = id_RSAES_OAEP
+rSAES_OAEP_Default_Identifier['parameters'] = rSAES_OAEP_Default_Params
+
+
+rSAES_OAEP_SHA224_Params = RSAES_OAEP_params()
+rSAES_OAEP_SHA224_Params['hashFunc'] = sha224Identifier.subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0), cloneValueFlag=True)
+rSAES_OAEP_SHA224_Params['maskGenFunc'] = mgf1SHA224Identifier.subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1), cloneValueFlag=True)
+
+rSAES_OAEP_SHA224_Identifier = rfc5280.AlgorithmIdentifier()
+rSAES_OAEP_SHA224_Identifier['algorithm'] = id_RSAES_OAEP
+rSAES_OAEP_SHA224_Identifier['parameters'] = rSAES_OAEP_SHA224_Params
+
+
+rSAES_OAEP_SHA256_Params = RSAES_OAEP_params()
+rSAES_OAEP_SHA256_Params['hashFunc'] = sha256Identifier.subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0), cloneValueFlag=True)
+rSAES_OAEP_SHA256_Params['maskGenFunc'] = mgf1SHA256Identifier.subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1), cloneValueFlag=True)
+
+rSAES_OAEP_SHA256_Identifier = rfc5280.AlgorithmIdentifier()
+rSAES_OAEP_SHA256_Identifier['algorithm'] = id_RSAES_OAEP
+rSAES_OAEP_SHA256_Identifier['parameters'] = rSAES_OAEP_SHA256_Params
+
+
+rSAES_OAEP_SHA384_Params = RSAES_OAEP_params()
+rSAES_OAEP_SHA384_Params['hashFunc'] = sha384Identifier.subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0), cloneValueFlag=True)
+rSAES_OAEP_SHA384_Params['maskGenFunc'] = mgf1SHA384Identifier.subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1), cloneValueFlag=True)
+
+rSAES_OAEP_SHA384_Identifier = rfc5280.AlgorithmIdentifier()
+rSAES_OAEP_SHA384_Identifier['algorithm'] = id_RSAES_OAEP
+rSAES_OAEP_SHA384_Identifier['parameters'] = rSAES_OAEP_SHA384_Params
+
+
+rSAES_OAEP_SHA512_Params = RSAES_OAEP_params()
+rSAES_OAEP_SHA512_Params['hashFunc'] = sha512Identifier.subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0), cloneValueFlag=True)
+rSAES_OAEP_SHA512_Params['maskGenFunc'] = mgf1SHA512Identifier.subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1), cloneValueFlag=True)
+
+rSAES_OAEP_SHA512_Identifier = rfc5280.AlgorithmIdentifier()
+rSAES_OAEP_SHA512_Identifier['algorithm'] = id_RSAES_OAEP
+rSAES_OAEP_SHA512_Identifier['parameters'] = rSAES_OAEP_SHA512_Params
+
+
+class RSASSA_PSS_params(univ.Sequence):
+ pass
+
+RSASSA_PSS_params.componentType = namedtype.NamedTypes(
+ namedtype.OptionalNamedType('hashAlgorithm', rfc5280.AlgorithmIdentifier().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0))),
+ namedtype.OptionalNamedType('maskGenAlgorithm', rfc5280.AlgorithmIdentifier().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1))),
+ namedtype.DefaultedNamedType('saltLength', univ.Integer(value=20).subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))),
+ namedtype.DefaultedNamedType('trailerField', univ.Integer(value=1).subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3)))
+)
+
+
+rSASSA_PSS_Default_Params = RSASSA_PSS_params()
+
+rSASSA_PSS_Default_Identifier = rfc5280.AlgorithmIdentifier()
+rSASSA_PSS_Default_Identifier['algorithm'] = id_RSASSA_PSS
+rSASSA_PSS_Default_Identifier['parameters'] = rSASSA_PSS_Default_Params
+
+
+rSASSA_PSS_SHA224_Params = RSASSA_PSS_params()
+rSASSA_PSS_SHA224_Params['hashAlgorithm'] = sha224Identifier.subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0), cloneValueFlag=True)
+rSASSA_PSS_SHA224_Params['maskGenAlgorithm'] = mgf1SHA224Identifier.subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1), cloneValueFlag=True)
+
+rSASSA_PSS_SHA224_Identifier = rfc5280.AlgorithmIdentifier()
+rSASSA_PSS_SHA224_Identifier['algorithm'] = id_RSASSA_PSS
+rSASSA_PSS_SHA224_Identifier['parameters'] = rSASSA_PSS_SHA224_Params
+
+
+rSASSA_PSS_SHA256_Params = RSASSA_PSS_params()
+rSASSA_PSS_SHA256_Params['hashAlgorithm'] = sha256Identifier.subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0), cloneValueFlag=True)
+rSASSA_PSS_SHA256_Params['maskGenAlgorithm'] = mgf1SHA256Identifier.subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1), cloneValueFlag=True)
+
+rSASSA_PSS_SHA256_Identifier = rfc5280.AlgorithmIdentifier()
+rSASSA_PSS_SHA256_Identifier['algorithm'] = id_RSASSA_PSS
+rSASSA_PSS_SHA256_Identifier['parameters'] = rSASSA_PSS_SHA256_Params
+
+
+rSASSA_PSS_SHA384_Params = RSASSA_PSS_params()
+rSASSA_PSS_SHA384_Params['hashAlgorithm'] = sha384Identifier.subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0), cloneValueFlag=True)
+rSASSA_PSS_SHA384_Params['maskGenAlgorithm'] = mgf1SHA384Identifier.subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1), cloneValueFlag=True)
+
+rSASSA_PSS_SHA384_Identifier = rfc5280.AlgorithmIdentifier()
+rSASSA_PSS_SHA384_Identifier['algorithm'] = id_RSASSA_PSS
+rSASSA_PSS_SHA384_Identifier['parameters'] = rSASSA_PSS_SHA384_Params
+
+
+rSASSA_PSS_SHA512_Params = RSASSA_PSS_params()
+rSASSA_PSS_SHA512_Params['hashAlgorithm'] = sha512Identifier.subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0), cloneValueFlag=True)
+rSASSA_PSS_SHA512_Params['maskGenAlgorithm'] = mgf1SHA512Identifier.subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1), cloneValueFlag=True)
+
+rSASSA_PSS_SHA512_Identifier = rfc5280.AlgorithmIdentifier()
+rSASSA_PSS_SHA512_Identifier['algorithm'] = id_RSASSA_PSS
+rSASSA_PSS_SHA512_Identifier['parameters'] = rSASSA_PSS_SHA512_Params
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyasn1-modules-0.2.4/pyasn1_modules/rfc4108.py new/pyasn1-modules-0.2.5/pyasn1_modules/rfc4108.py
--- old/pyasn1-modules-0.2.4/pyasn1_modules/rfc4108.py 1970-01-01 01:00:00.000000000 +0100
+++ new/pyasn1-modules-0.2.5/pyasn1_modules/rfc4108.py 2019-04-24 06:40:45.000000000 +0200
@@ -0,0 +1,294 @@
+#
+# This file is part of pyasn1-modules software.
+#
+# Created by Russ Housley with assistance from asn1ate v.0.6.0.
+#
+# Copyright (c) 2019, Vigil Security, LLC
+# License: http://snmplabs.com/pyasn1/license.html
+#
+# CMS Firmware Wrapper
+#
+# ASN.1 source from:
+# https://www.rfc-editor.org/rfc/rfc4108.txt
+#
+
+
+from pyasn1.type import univ, char, namedtype, namedval, tag, constraint, useful
+
+from pyasn1_modules import rfc5652
+
+MAX = float('inf')
+
+
+class HardwareSerialEntry(univ.Choice):
+ pass
+
+HardwareSerialEntry.componentType = namedtype.NamedTypes(
+ namedtype.NamedType('all', univ.Null()),
+ namedtype.NamedType('single', univ.OctetString()),
+ namedtype.NamedType('block', univ.Sequence(componentType=namedtype.NamedTypes(
+ namedtype.NamedType('low', univ.OctetString()),
+ namedtype.NamedType('high', univ.OctetString())
+ ))
+ )
+)
+
+
+class HardwareModules(univ.Sequence):
+ pass
+
+HardwareModules.componentType = namedtype.NamedTypes(
+ namedtype.NamedType('hwType', univ.ObjectIdentifier()),
+ namedtype.NamedType('hwSerialEntries', univ.SequenceOf(componentType=HardwareSerialEntry()))
+)
+
+
+class CommunityIdentifier(univ.Choice):
+ pass
+
+CommunityIdentifier.componentType = namedtype.NamedTypes(
+ namedtype.NamedType('communityOID', univ.ObjectIdentifier()),
+ namedtype.NamedType('hwModuleList', HardwareModules())
+)
+
+
+
+class PreferredPackageIdentifier(univ.Sequence):
+ pass
+
+PreferredPackageIdentifier.componentType = namedtype.NamedTypes(
+ namedtype.NamedType('fwPkgID', univ.ObjectIdentifier()),
+ namedtype.NamedType('verNum', univ.Integer().subtype(subtypeSpec=constraint.ValueRangeConstraint(0, MAX)))
+)
+
+
+class PreferredOrLegacyPackageIdentifier(univ.Choice):
+ pass
+
+PreferredOrLegacyPackageIdentifier.componentType = namedtype.NamedTypes(
+ namedtype.NamedType('preferred', PreferredPackageIdentifier()),
+ namedtype.NamedType('legacy', univ.OctetString())
+)
+
+
+class CurrentFWConfig(univ.Sequence):
+ pass
+
+CurrentFWConfig.componentType = namedtype.NamedTypes(
+ namedtype.OptionalNamedType('fwPkgType', univ.Integer()),
+ namedtype.NamedType('fwPkgName', PreferredOrLegacyPackageIdentifier())
+)
+
+
+class PreferredOrLegacyStalePackageIdentifier(univ.Choice):
+ pass
+
+PreferredOrLegacyStalePackageIdentifier.componentType = namedtype.NamedTypes(
+ namedtype.NamedType('preferredStaleVerNum', univ.Integer().subtype(subtypeSpec=constraint.ValueRangeConstraint(0, MAX))),
+ namedtype.NamedType('legacyStaleVersion', univ.OctetString())
+)
+
+
+class FirmwarePackageLoadErrorCode(univ.Enumerated):
+ pass
+
+FirmwarePackageLoadErrorCode.namedValues = namedval.NamedValues(
+ ('decodeFailure', 1),
+ ('badContentInfo', 2),
+ ('badSignedData', 3),
+ ('badEncapContent', 4),
+ ('badCertificate', 5),
+ ('badSignerInfo', 6),
+ ('badSignedAttrs', 7),
+ ('badUnsignedAttrs', 8),
+ ('missingContent', 9),
+ ('noTrustAnchor', 10),
+ ('notAuthorized', 11),
+ ('badDigestAlgorithm', 12),
+ ('badSignatureAlgorithm', 13),
+ ('unsupportedKeySize', 14),
+ ('signatureFailure', 15),
+ ('contentTypeMismatch', 16),
+ ('badEncryptedData', 17),
+ ('unprotectedAttrsPresent', 18),
+ ('badEncryptContent', 19),
+ ('badEncryptAlgorithm', 20),
+ ('missingCiphertext', 21),
+ ('noDecryptKey', 22),
+ ('decryptFailure', 23),
+ ('badCompressAlgorithm', 24),
+ ('missingCompressedContent', 25),
+ ('decompressFailure', 26),
+ ('wrongHardware', 27),
+ ('stalePackage', 28),
+ ('notInCommunity', 29),
+ ('unsupportedPackageType', 30),
+ ('missingDependency', 31),
+ ('wrongDependencyVersion', 32),
+ ('insufficientMemory', 33),
+ ('badFirmware', 34),
+ ('unsupportedParameters', 35),
+ ('breaksDependency', 36),
+ ('otherError', 99)
+)
+
+
+class VendorLoadErrorCode(univ.Integer):
+ pass
+
+
+
+# Wrapped Firmware Key Unsigned Attribute and Object Identifiers
+
+id_aa_wrappedFirmwareKey = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.39')
+
+class WrappedFirmwareKey(rfc5652.EnvelopedData):
+ pass
+
+
+# Firmware Package Information Signed Attribute and Object Identifier
+
+id_aa_firmwarePackageInfo = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.42')
+
+class FirmwarePackageInfo(univ.Sequence):
+ pass
+
+FirmwarePackageInfo.componentType = namedtype.NamedTypes(
+ namedtype.OptionalNamedType('fwPkgType', univ.Integer()),
+ namedtype.OptionalNamedType('dependencies', univ.SequenceOf(componentType=PreferredOrLegacyPackageIdentifier()))
+)
+
+FirmwarePackageInfo.sizeSpec = univ.Sequence.sizeSpec + constraint.ValueSizeConstraint(1, 2)
+
+
+# Community Identifiers Signed Attribute and Object Identifier
+
+id_aa_communityIdentifiers = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.40')
+
+class CommunityIdentifiers(univ.SequenceOf):
+ pass
+
+CommunityIdentifiers.componentType = CommunityIdentifier()
+
+
+# Implemented Compression Algorithms Signed Attribute and Object Identifier
+
+id_aa_implCompressAlgs = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.43')
+
+class ImplementedCompressAlgorithms(univ.SequenceOf):
+ pass
+
+ImplementedCompressAlgorithms.componentType = univ.ObjectIdentifier()
+
+
+# Implemented Cryptographic Algorithms Signed Attribute and Object Identifier
+
+id_aa_implCryptoAlgs = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.38')
+
+class ImplementedCryptoAlgorithms(univ.SequenceOf):
+ pass
+
+ImplementedCryptoAlgorithms.componentType = univ.ObjectIdentifier()
+
+
+# Decrypt Key Identifier Signed Attribute and Object Identifier
+
+id_aa_decryptKeyID = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.37')
+
+class DecryptKeyIdentifier(univ.OctetString):
+ pass
+
+
+# Target Hardware Identifier Signed Attribute and Object Identifier
+
+id_aa_targetHardwareIDs = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.36')
+
+class TargetHardwareIdentifiers(univ.SequenceOf):
+ pass
+
+TargetHardwareIdentifiers.componentType = univ.ObjectIdentifier()
+
+
+# Firmware Package Identifier Signed Attribute and Object Identifier
+
+id_aa_firmwarePackageID = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.35')
+
+class FirmwarePackageIdentifier(univ.Sequence):
+ pass
+
+FirmwarePackageIdentifier.componentType = namedtype.NamedTypes(
+ namedtype.NamedType('name', PreferredOrLegacyPackageIdentifier()),
+ namedtype.OptionalNamedType('stale', PreferredOrLegacyStalePackageIdentifier())
+)
+
+
+# Firmware Package Load Error Report Content Type and Object Identifier
+
+class FWErrorVersion(univ.Integer):
+ pass
+
+FWErrorVersion.namedValues = namedval.NamedValues(
+ ('v1', 1)
+)
+
+
+id_ct_firmwareLoadError = univ.ObjectIdentifier('1.2.840.113549.1.9.16.1.18')
+
+class FirmwarePackageLoadError(univ.Sequence):
+ pass
+
+FirmwarePackageLoadError.componentType = namedtype.NamedTypes(
+ namedtype.DefaultedNamedType('version', FWErrorVersion().subtype(value='v1')),
+ namedtype.NamedType('hwType', univ.ObjectIdentifier()),
+ namedtype.NamedType('hwSerialNum', univ.OctetString()),
+ namedtype.NamedType('errorCode', FirmwarePackageLoadErrorCode()),
+ namedtype.OptionalNamedType('vendorErrorCode', VendorLoadErrorCode()),
+ namedtype.OptionalNamedType('fwPkgName', PreferredOrLegacyPackageIdentifier()),
+ namedtype.OptionalNamedType('config', univ.SequenceOf(componentType=CurrentFWConfig()).subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1)))
+)
+
+
+# Firmware Package Load Receipt Content Type and Object Identifier
+
+class FWReceiptVersion(univ.Integer):
+ pass
+
+FWReceiptVersion.namedValues = namedval.NamedValues(
+ ('v1', 1)
+)
+
+
+id_ct_firmwareLoadReceipt = univ.ObjectIdentifier('1.2.840.113549.1.9.16.1.17')
+
+class FirmwarePackageLoadReceipt(univ.Sequence):
+ pass
+
+FirmwarePackageLoadReceipt.componentType = namedtype.NamedTypes(
+ namedtype.DefaultedNamedType('version', FWReceiptVersion().subtype(value='v1')),
+ namedtype.NamedType('hwType', univ.ObjectIdentifier()),
+ namedtype.NamedType('hwSerialNum', univ.OctetString()),
+ namedtype.NamedType('fwPkgName', PreferredOrLegacyPackageIdentifier()),
+ namedtype.OptionalNamedType('trustAnchorKeyID', univ.OctetString()),
+ namedtype.OptionalNamedType('decryptKeyID', univ.OctetString().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1)))
+)
+
+
+# Firmware Package Content Type and Object Identifier
+
+id_ct_firmwarePackage = univ.ObjectIdentifier('1.2.840.113549.1.9.16.1.16')
+
+class FirmwarePkgData(univ.OctetString):
+ pass
+
+
+# Other Name syntax for Hardware Module Name
+
+id_on_hardwareModuleName = univ.ObjectIdentifier('1.3.6.1.5.5.7.8.4')
+
+class HardwareModuleName(univ.Sequence):
+ pass
+
+HardwareModuleName.componentType = namedtype.NamedTypes(
+ namedtype.NamedType('hwType', univ.ObjectIdentifier()),
+ namedtype.NamedType('hwSerialNum', univ.OctetString())
+)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyasn1-modules-0.2.4/pyasn1_modules/rfc5958.py new/pyasn1-modules-0.2.5/pyasn1_modules/rfc5958.py
--- old/pyasn1-modules-0.2.4/pyasn1_modules/rfc5958.py 1970-01-01 01:00:00.000000000 +0100
+++ new/pyasn1-modules-0.2.5/pyasn1_modules/rfc5958.py 2019-04-24 06:40:45.000000000 +0200
@@ -0,0 +1,87 @@
+#
+# This file is being contributed to pyasn1-modules software.
+#
+# Created by Russ Housley.
+#
+# Copyright (c) 2019, Vigil Security, LLC
+# License: http://snmplabs.com/pyasn1/license.html
+#
+# Asymmetric Key Packages, which is essentially version 2 of
+# the PrivateKeyInfo structure in PKCS#8 in RFC 5208
+#
+# ASN.1 source from:
+# https://www.rfc-editor.org/rfc/rfc8418.txt
+
+from pyasn1.type import univ, constraint, namedtype, namedval, tag
+
+from pyasn1_modules import rfc5280
+
+
+MAX = float('inf')
+
+
+class KeyEncryptionAlgorithmIdentifier(rfc5280.AlgorithmIdentifier):
+ pass
+
+
+class PrivateKeyAlgorithmIdentifier(rfc5280.AlgorithmIdentifier):
+ pass
+
+
+class EncryptedData(univ.OctetString):
+ pass
+
+
+class EncryptedPrivateKeyInfo(univ.Sequence):
+ componentType = namedtype.NamedTypes(
+ namedtype.NamedType('encryptionAlgorithm', KeyEncryptionAlgorithmIdentifier()),
+ namedtype.NamedType('encryptedData', EncryptedData())
+ )
+
+
+class Version(univ.Integer):
+ namedValues = namedval.NamedValues(('v1', 0), ('v2', 1))
+
+
+class PrivateKey(univ.OctetString):
+ pass
+
+
+class Attributes(univ.SetOf):
+ componentType = rfc5280.Attribute()
+
+
+class PublicKey(univ.BitString):
+ pass
+
+
+# OneAsymmetricKey is essentially version 2 of PrivateKeyInfo.
+# If publicKey is present, then the version must be v2;
+# otherwise, the version should be v1.
+
+class OneAsymmetricKey(univ.Sequence):
+ componentType = namedtype.NamedTypes(
+ namedtype.NamedType('version', Version()),
+ namedtype.NamedType('privateKeyAlgorithm', PrivateKeyAlgorithmIdentifier()),
+ namedtype.NamedType('privateKey', PrivateKey()),
+ namedtype.OptionalNamedType('attributes', Attributes().subtype(
+ implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0))),
+ namedtype.OptionalNamedType('publicKey', PublicKey().subtype(
+ implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1)))
+ )
+
+
+class PrivateKeyInfo(OneAsymmetricKey):
+ pass
+
+
+# The CMS AsymmetricKeyPackage Content Type
+
+id_ct_KP_aKeyPackage = univ.ObjectIdentifier('2.16.840.1.101.2.1.2.78.5')
+
+class AsymmetricKeyPackage(univ.SequenceOf):
+ pass
+
+AsymmetricKeyPackage.componentType = OneAsymmetricKey()
+AsymmetricKeyPackage.subtypeSpec=constraint.ValueSizeConstraint(1, MAX)
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyasn1-modules-0.2.4/pyasn1_modules/rfc8410.py new/pyasn1-modules-0.2.5/pyasn1_modules/rfc8410.py
--- old/pyasn1-modules-0.2.4/pyasn1_modules/rfc8410.py 1970-01-01 01:00:00.000000000 +0100
+++ new/pyasn1-modules-0.2.5/pyasn1_modules/rfc8410.py 2019-04-24 06:40:45.000000000 +0200
@@ -0,0 +1,47 @@
+# This file is being contributed to pyasn1-modules software.
+#
+# Created by Russ Housley.
+#
+# Copyright (c) 2019, Vigil Security, LLC
+# License: http://snmplabs.com/pyasn1/license.html
+#
+# Algorithm Identifiers for Ed25519, Ed448, X25519, and X448
+#
+# ASN.1 source from:
+# https://www.rfc-editor.org/rfc/rfc8410.txt
+
+
+from pyasn1.type import univ
+from pyasn1_modules import rfc3565
+from pyasn1_modules import rfc4055
+from pyasn1_modules import rfc5280
+
+
+class SignatureAlgorithmIdentifier(rfc5280.AlgorithmIdentifier):
+ pass
+
+
+class KeyEncryptionAlgorithmIdentifier(rfc5280.AlgorithmIdentifier):
+ pass
+
+
+class CurvePrivateKey(univ.OctetString):
+ pass
+
+
+id_X25519 = univ.ObjectIdentifier('1.3.101.110')
+
+id_X448 = univ.ObjectIdentifier('1.3.101.111')
+
+
+id_Ed25519 = univ.ObjectIdentifier('1.3.101.112')
+
+id_Ed448 = univ.ObjectIdentifier('1.3.101.113')
+
+
+id_sha512 = rfc4055.id_sha512
+
+
+id_aes128_wrap = rfc3565.id_aes128_wrap
+
+id_aes256_wrap = rfc3565.id_aes256_wrap
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyasn1-modules-0.2.4/pyasn1_modules/rfc8418.py new/pyasn1-modules-0.2.5/pyasn1_modules/rfc8418.py
--- old/pyasn1-modules-0.2.4/pyasn1_modules/rfc8418.py 1970-01-01 01:00:00.000000000 +0100
+++ new/pyasn1-modules-0.2.5/pyasn1_modules/rfc8418.py 2019-04-24 06:40:45.000000000 +0200
@@ -0,0 +1,37 @@
+# This file is being contributed to pyasn1-modules software.
+#
+# Created by Russ Housley.
+#
+# Copyright (c) 2019, Vigil Security, LLC
+# License: http://snmplabs.com/pyasn1/license.html
+#
+# Elliptic Curve Diffie-Hellman (ECDH) Key Agreement Algorithm
+# with X25519 and X448
+#
+# ASN.1 source from:
+# https://www.rfc-editor.org/rfc/rfc8418.txt
+
+from pyasn1.type import univ
+from pyasn1_modules import rfc5280
+
+
+class KeyEncryptionAlgorithmIdentifier(rfc5280.AlgorithmIdentifier):
+ pass
+
+
+class KeyWrapAlgorithmIdentifier(rfc5280.AlgorithmIdentifier):
+ pass
+
+
+dhSinglePass_stdDH_sha256kdf_scheme = univ.ObjectIdentifier('1.3.133.16.840.63.0.11.1')
+
+dhSinglePass_stdDH_sha384kdf_scheme = univ.ObjectIdentifier('1.3.133.16.840.63.0.11.2')
+
+dhSinglePass_stdDH_sha512kdf_scheme = univ.ObjectIdentifier('1.3.133.16.840.63.0.11.3')
+
+
+dhSinglePass_stdDH_hkdf_sha256_scheme = univ.ObjectIdentifier('1.2.840.113549.1.9.16.3.19')
+
+dhSinglePass_stdDH_hkdf_sha384_scheme = univ.ObjectIdentifier('1.2.840.113549.1.9.16.3.20')
+
+dhSinglePass_stdDH_hkdf_sha512_scheme = univ.ObjectIdentifier('1.2.840.113549.1.9.16.3.21')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyasn1-modules-0.2.4/pyasn1_modules.egg-info/PKG-INFO new/pyasn1-modules-0.2.5/pyasn1_modules.egg-info/PKG-INFO
--- old/pyasn1-modules-0.2.4/pyasn1_modules.egg-info/PKG-INFO 2019-01-26 18:54:25.000000000 +0100
+++ new/pyasn1-modules-0.2.5/pyasn1_modules.egg-info/PKG-INFO 2019-04-24 06:42:12.000000000 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: pyasn1-modules
-Version: 0.2.4
+Version: 0.2.5
Summary: A collection of ASN.1-based protocols modules.
Home-page: https://github.com/etingof/pyasn1-modules
Author: Ilya Etingof <etingof(a)gmail.com>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyasn1-modules-0.2.4/pyasn1_modules.egg-info/SOURCES.txt new/pyasn1-modules-0.2.5/pyasn1_modules.egg-info/SOURCES.txt
--- old/pyasn1-modules-0.2.4/pyasn1_modules.egg-info/SOURCES.txt 2019-01-26 18:54:25.000000000 +0100
+++ new/pyasn1-modules-0.2.5/pyasn1_modules.egg-info/SOURCES.txt 2019-04-24 06:42:13.000000000 +0200
@@ -26,7 +26,11 @@
pyasn1_modules/rfc3412.py
pyasn1_modules/rfc3414.py
pyasn1_modules/rfc3447.py
+pyasn1_modules/rfc3565.py
+pyasn1_modules/rfc3779.py
pyasn1_modules/rfc3852.py
+pyasn1_modules/rfc4055.py
+pyasn1_modules/rfc4108.py
pyasn1_modules/rfc4210.py
pyasn1_modules/rfc4211.py
pyasn1_modules/rfc5083.py
@@ -34,9 +38,12 @@
pyasn1_modules/rfc5208.py
pyasn1_modules/rfc5280.py
pyasn1_modules/rfc5652.py
+pyasn1_modules/rfc5958.py
pyasn1_modules/rfc6402.py
pyasn1_modules/rfc8103.py
pyasn1_modules/rfc8226.py
+pyasn1_modules/rfc8410.py
+pyasn1_modules/rfc8418.py
pyasn1_modules.egg-info/PKG-INFO
pyasn1_modules.egg-info/SOURCES.txt
pyasn1_modules.egg-info/dependency_links.txt
@@ -52,14 +59,21 @@
tests/test_rfc2511.py
tests/test_rfc2560.py
tests/test_rfc2986.py
+tests/test_rfc3565.py
+tests/test_rfc3779.py
+tests/test_rfc4055.py
+tests/test_rfc4108.py
tests/test_rfc4210.py
tests/test_rfc5083.py
tests/test_rfc5084.py
tests/test_rfc5208.py
tests/test_rfc5280.py
tests/test_rfc5652.py
+tests/test_rfc5958.py
tests/test_rfc8103.py
tests/test_rfc8226.py
+tests/test_rfc8410.py
+tests/test_rfc8418.py
tools/cmcdump.py
tools/cmpdump.py
tools/crldump.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyasn1-modules-0.2.4/tests/__main__.py new/pyasn1-modules-0.2.5/tests/__main__.py
--- old/pyasn1-modules-0.2.4/tests/__main__.py 2019-01-26 18:53:16.000000000 +0100
+++ new/pyasn1-modules-0.2.5/tests/__main__.py 2019-04-24 06:40:45.000000000 +0200
@@ -18,11 +18,21 @@
'tests.test_rfc2511.suite',
'tests.test_rfc2560.suite',
'tests.test_rfc2986.suite',
+ 'tests.test_rfc3565.suite',
+ 'tests.test_rfc3779.suite',
+ 'tests.test_rfc4055.suite'
+ 'tests.test_rfc4108.suite'
'tests.test_rfc4210.suite',
+ 'tests.test_rfc5083.suite'
+ 'tests.test_rfc5084.suite'
'tests.test_rfc5208.suite',
'tests.test_rfc5280.suite',
'tests.test_rfc5652.suite',
- 'tests.test_rfc8226.suite']
+ 'tests.test_rfc5958.suite'
+ 'tests.test_rfc8103.suite'
+ 'tests.test_rfc8226.suite',
+ 'tests.test_rfc8410.suite'
+ 'tests.test_rfc8418.suite']
)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyasn1-modules-0.2.4/tests/test_rfc3565.py new/pyasn1-modules-0.2.5/tests/test_rfc3565.py
--- old/pyasn1-modules-0.2.4/tests/test_rfc3565.py 1970-01-01 01:00:00.000000000 +0100
+++ new/pyasn1-modules-0.2.5/tests/test_rfc3565.py 2019-04-24 06:40:45.000000000 +0200
@@ -0,0 +1,57 @@
+#
+# This file is part of pyasn1-modules software.
+#
+# Created by Russ Housley
+# Copyright (c) 2019, Vigil Security, LLC
+# License: http://snmplabs.com/pyasn1/license.html
+#
+
+import sys
+
+from pyasn1.codec.der import decoder as der_decoder
+from pyasn1.codec.der import encoder as der_encoder
+
+from pyasn1_modules import pem
+from pyasn1_modules import rfc3565
+
+try:
+ import unittest2 as unittest
+except ImportError:
+ import unittest
+
+
+class AESKeyWrapTestCase(unittest.TestCase):
+ kw_alg_id_pem_text = "MAsGCWCGSAFlAwQBLQ=="
+
+ def setUp(self):
+ self.asn1Spec = rfc3565.AlgorithmIdentifier()
+
+ def testDerCodec(self):
+ substrate = pem.readBase64fromText(self.kw_alg_id_pem_text)
+ asn1Object, rest = der_decoder.decode(substrate, asn1Spec=self.asn1Spec)
+ assert not rest
+ assert asn1Object.prettyPrint()
+ assert asn1Object[0] == rfc3565.id_aes256_wrap
+ assert der_encoder.encode(asn1Object) == substrate
+
+
+class AESCBCTestCase(unittest.TestCase):
+ aes_alg_id_pem_text = "MB0GCWCGSAFlAwQBKgQQEImWuoUOPwM5mTu1h4oONw=="
+
+ def setUp(self):
+ self.asn1Spec = rfc3565.AlgorithmIdentifier()
+
+ def testDerCodec(self):
+ substrate = pem.readBase64fromText(self.aes_alg_id_pem_text)
+ asn1Object, rest = der_decoder.decode(substrate, asn1Spec=self.asn1Spec)
+ assert not rest
+ assert asn1Object.prettyPrint()
+ assert asn1Object[0] == rfc3565.id_aes256_CBC
+ assert asn1Object[1].isValue
+ assert der_encoder.encode(asn1Object) == substrate
+
+
+suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__])
+
+if __name__ == '__main__':
+ unittest.TextTestRunner(verbosity=2).run(suite)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyasn1-modules-0.2.4/tests/test_rfc3779.py new/pyasn1-modules-0.2.5/tests/test_rfc3779.py
--- old/pyasn1-modules-0.2.4/tests/test_rfc3779.py 1970-01-01 01:00:00.000000000 +0100
+++ new/pyasn1-modules-0.2.5/tests/test_rfc3779.py 2019-04-24 06:40:45.000000000 +0200
@@ -0,0 +1,81 @@
+#
+# This file is part of pyasn1-modules software.
+#
+# Copyright (c) 2019, Vigil Security, LLC
+# License: http://snmplabs.com/pyasn1/license.html
+#
+import sys
+
+from pyasn1.codec.der import decoder as der_decoder
+from pyasn1.codec.der import encoder as der_encoder
+
+from pyasn1_modules import pem
+from pyasn1_modules import rfc5280
+from pyasn1_modules import rfc3779
+
+try:
+ import unittest2 as unittest
+except ImportError:
+ import unittest
+
+
+class CertificateExtnTestCase(unittest.TestCase):
+ pem_text = """\
+MIIECjCCAvKgAwIBAgICAMkwDQYJKoZIhvcNAQELBQAwFjEUMBIGA1UEAxMLcmlw
+ZS1uY2MtdGEwIBcNMTcxMTI4MTQzOTU1WhgPMjExNzExMjgxNDM5NTVaMBYxFDAS
+BgNVBAMTC3JpcGUtbmNjLXRhMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEA0URYSGqUz2myBsOzeW1jQ6NsxNvlLMyhWknvnl8NiBCs/T/S2XuNKQNZ+wBZ
+xIgPPV2pFBFeQAvoH/WK83HwA26V2siwm/MY2nKZ+Olw+wlpzlZ1p3Ipj2eNcKrm
+it8BwBC8xImzuCGaV0jkRB0GZ0hoH6Ml03umLprRsn6v0xOP0+l6Qc1ZHMFVFb38
+5IQ7FQQTcVIxrdeMsoyJq9eMkE6DoclHhF/NlSllXubASQ9KUWqJ0+Ot3QCXr4LX
+ECMfkpkVR2TZT+v5v658bHVs6ZxRD1b6Uk1uQKAyHUbn/tXvP8lrjAibGzVsXDT2
+L0x4Edx+QdixPgOji3gBMyL2VwIDAQABo4IBXjCCAVowHQYDVR0OBBYEFOhVKx/W
+0aT35ATG2OVoDR68Fj/DMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEG
+MIGxBggrBgEFBQcBCwSBpDCBoTA8BggrBgEFBQcwCoYwcnN5bmM6Ly9ycGtpLnJp
+cGUubmV0L3JlcG9zaXRvcnkvcmlwZS1uY2MtdGEubWZ0MDIGCCsGAQUFBzANhiZo
+dHRwczovL3JyZHAucmlwZS5uZXQvbm90aWZpY2F0aW9uLnhtbDAtBggrBgEFBQcw
+BYYhcnN5bmM6Ly9ycGtpLnJpcGUubmV0L3JlcG9zaXRvcnkvMBgGA1UdIAEB/wQO
+MAwwCgYIKwYBBQUHDgIwJwYIKwYBBQUHAQcBAf8EGDAWMAkEAgABMAMDAQAwCQQC
+AAIwAwMBADAhBggrBgEFBQcBCAEB/wQSMBCgDjAMMAoCAQACBQD/////MA0GCSqG
+SIb3DQEBCwUAA4IBAQAVgJjrZ3wFppC8Yk8D2xgzwSeWVT2vtYq96CQQsjaKb8nb
+eVz3DwcS3a7RIsevrNVGo43k3AGymg1ki+AWJjvHvJ+tSzCbn5+X6Z7AfYTf2g37
+xINVDHru0PTQUargSMBAz/MBNpFG8KThtT7WbJrK4+f/lvx0m8QOlYm2a17iXS3A
+GQJ6RHcq9ADscqGdumxmMMDjwED26bGaYdmru1hNIpwF//jVM/eRjBFoPHKFlx0k
+Ld/yoCQNmx1kW+xANx4uyWxi/DYgSV7Oynq+C60OucW+d8tIhkblh8+YfrmukJds
+V+vo2L72yerdbsP9xjqvhZrLKfsLZjYK4SdYYthi
+"""
+
+ def setUp(self):
+ self.asn1Spec = rfc5280.Certificate()
+
+ def testDerCodec(self):
+
+ substrate = pem.readBase64fromText(self.pem_text)
+
+ asn1Object, rest = der_decoder.decode(substrate, asn1Spec=self.asn1Spec)
+
+ assert not rest
+ assert asn1Object.prettyPrint()
+ assert der_encoder.encode(asn1Object) == substrate
+
+ for extn in asn1Object['tbsCertificate']['extensions']:
+
+ if extn['extnID'] == rfc3779.id_pe_ipAddrBlocks:
+ s = extn['extnValue']
+ addr_blocks, rest = der_decoder.decode(s, rfc3779.IPAddrBlocks())
+ assert not rest
+ assert addr_blocks.prettyPrint()
+ assert der_encoder.encode(addr_blocks) == s
+
+ if extn['extnID'] == rfc3779.id_pe_autonomousSysIds:
+ s = extn['extnValue']
+ as_ids, rest = der_decoder.decode(s, rfc3779.ASIdentifiers())
+ assert not rest
+ assert as_ids.prettyPrint()
+ assert der_encoder.encode(as_ids) == s
+
+
+suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__])
+
+if __name__ == '__main__':
+ unittest.TextTestRunner(verbosity=2).run(suite)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyasn1-modules-0.2.4/tests/test_rfc4055.py new/pyasn1-modules-0.2.5/tests/test_rfc4055.py
--- old/pyasn1-modules-0.2.4/tests/test_rfc4055.py 1970-01-01 01:00:00.000000000 +0100
+++ new/pyasn1-modules-0.2.5/tests/test_rfc4055.py 2019-04-24 06:40:45.000000000 +0200
@@ -0,0 +1,107 @@
+#
+# This file is part of pyasn1-modules software.
+#
+# Created by Russ Housley
+# Copyright (c) 2019, Vigil Security, LLC
+# License: http://snmplabs.com/pyasn1/license.html
+#
+
+import sys
+
+from pyasn1.codec.der import decoder as der_decoder
+from pyasn1.codec.der import encoder as der_encoder
+
+from pyasn1_modules import pem
+from pyasn1_modules import rfc5280
+from pyasn1_modules import rfc4055
+
+try:
+ import unittest2 as unittest
+except ImportError:
+ import unittest
+
+
+class PSSDefautTestCase(unittest.TestCase):
+ pss_default_pem_text = "MAsGCSqGSIb3DQEBCg=="
+
+ def setUp(self):
+ self.asn1Spec = rfc5280.AlgorithmIdentifier()
+
+ def testDerCodec(self):
+ substrate = pem.readBase64fromText(self.pss_default_pem_text)
+ asn1Object, rest = der_decoder.decode(substrate, asn1Spec=self.asn1Spec)
+ assert not rest
+ assert asn1Object.prettyPrint()
+ assert asn1Object[0] == rfc4055.id_RSASSA_PSS
+ assert der_encoder.encode(asn1Object) == substrate
+ assert substrate == der_encoder.encode(asn1Object)
+
+
+class PSSSHA512TestCase(unittest.TestCase):
+ pss_sha512_pem_text = "MDwGCSqGSIb3DQEBCjAvoA8wDQYJYIZIAWUDBAIDBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZIAWUDBAIDBQA="
+
+ def setUp(self):
+ self.asn1Spec = rfc5280.AlgorithmIdentifier()
+
+ def testDerCodec(self):
+ substrate = pem.readBase64fromText(self.pss_sha512_pem_text)
+ asn1Object, rest = der_decoder.decode(substrate, asn1Spec=self.asn1Spec)
+ assert not rest
+ assert asn1Object.prettyPrint()
+ assert asn1Object[0] == rfc4055.id_RSASSA_PSS
+ assert der_encoder.encode(asn1Object) == substrate
+ assert substrate == der_encoder.encode(asn1Object)
+
+
+class OAEPDefautTestCase(unittest.TestCase):
+ oaep_default_pem_text = "MAsGCSqGSIb3DQEBBw=="
+
+ def setUp(self):
+ self.asn1Spec = rfc5280.AlgorithmIdentifier()
+
+ def testDerCodec(self):
+ substrate = pem.readBase64fromText(self.oaep_default_pem_text)
+ asn1Object, rest = der_decoder.decode(substrate, asn1Spec=self.asn1Spec)
+ assert not rest
+ assert asn1Object.prettyPrint()
+ assert asn1Object[0] == rfc4055.id_RSAES_OAEP
+ assert der_encoder.encode(asn1Object) == substrate
+ assert substrate == der_encoder.encode(asn1Object)
+
+
+class OAEPSHA256TestCase(unittest.TestCase):
+ oaep_sha256_pem_text = "MDwGCSqGSIb3DQEBBzAvoA8wDQYJYIZIAWUDBAIBBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZIAWUDBAIBBQA="
+
+ def setUp(self):
+ self.asn1Spec = rfc5280.AlgorithmIdentifier()
+
+ def testDerCodec(self):
+ substrate = pem.readBase64fromText(self.oaep_sha256_pem_text)
+ asn1Object, rest = der_decoder.decode(substrate, asn1Spec=self.asn1Spec)
+ assert not rest
+ assert asn1Object.prettyPrint()
+ assert asn1Object[0] == rfc4055.id_RSAES_OAEP
+ assert der_encoder.encode(asn1Object) == substrate
+ assert substrate == der_encoder.encode(asn1Object)
+
+
+class OAEPFullTestCase(unittest.TestCase):
+ oaep_full_pem_text = "MFMGCSqGSIb3DQEBBzBGoA8wDQYJYIZIAWUDBAICBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZIAWUDBAICBQCiFTATBgkqhkiG9w0BAQkEBmZvb2Jhcg=="
+
+ def setUp(self):
+ self.asn1Spec = rfc5280.AlgorithmIdentifier()
+
+ def testDerCodec(self):
+ substrate = pem.readBase64fromText(self.oaep_full_pem_text)
+ asn1Object, rest = der_decoder.decode(substrate, asn1Spec=self.asn1Spec)
+ assert not rest
+ assert asn1Object.prettyPrint()
+ assert asn1Object[0] == rfc4055.id_RSAES_OAEP
+ assert der_encoder.encode(asn1Object) == substrate
+ assert substrate == der_encoder.encode(asn1Object)
+
+
+suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__])
+
+if __name__ == '__main__':
+ unittest.TextTestRunner(verbosity=2).run(suite)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyasn1-modules-0.2.4/tests/test_rfc4108.py new/pyasn1-modules-0.2.5/tests/test_rfc4108.py
--- old/pyasn1-modules-0.2.4/tests/test_rfc4108.py 1970-01-01 01:00:00.000000000 +0100
+++ new/pyasn1-modules-0.2.5/tests/test_rfc4108.py 2019-04-24 06:40:45.000000000 +0200
@@ -0,0 +1,80 @@
+#
+# This file is part of pyasn1-modules software.
+#
+# Copyright (c) 2019, Vigil Security, LLC
+# License: http://snmplabs.com/pyasn1/license.html
+#
+import sys
+
+from pyasn1.codec.der.decoder import decode as der_decode
+from pyasn1.codec.der.encoder import encode as der_encode
+
+from pyasn1.type import univ
+
+from pyasn1_modules import pem
+from pyasn1_modules import rfc5652
+from pyasn1_modules import rfc4108
+
+try:
+ import unittest2 as unittest
+except ImportError:
+ import unittest
+
+
+class CMSFirmwareWrapperTestCase(unittest.TestCase):
+ pem_text = """\
+MIIEdwYJKoZIhvcNAQcCoIIEaDCCBGQCAQExDTALBglghkgBZQMEAgEwggIVBgsq
+hkiG9w0BCRABEKCCAgQEggIA3ntqPr5kDpx+//pgWGfHCH/Ht4pbenGwXv80txyE
+Y0I2mT9BUGz8ILkbhD7Xz89pBS5KhEJpthxH8WREJtvS+wL4BqYLt23wjWoZy5Gt
+5dPzWgaNlV/aQ5AdfAY9ljmnNYnK8D8r8ur7bQM4cKUdxry+QA0nqXHMAOSpx4Um
+8impCc0BICXaFfL3zBrNxyPubbFO9ofbYOAWaNmmIAhzthXf12vDrLostIqmYrP4
+LMRCjTr4LeYaVrAWfKtbUbByN6IuBef3Qt5cJaChr74udz3JvbYFsUvCpl64kpRq
+g2CT6R+xE4trO/pViJlI15dvJVz04BBYQ2jQsutJwChi97/DDcjIv03VBmrwRE0k
+RJNFP9vpDM8CxJIqcobC5Kuv8b0GqGfGl6ouuQKEVMfBcrupgjk3oc3KL1iVdSr1
++74amb1vDtTMWNm6vWRqh+Kk17NGEi2mNvYkkZUTIHNGH7OgiDclFU8dSMZd1fun
+/D9dmiFiErDB3Fzr4+8Qz0aKedNE/1uvM+dhu9qjuRdkDzZ4S7txTfk6y9pG9iyk
+aEeTV2kElKXblgi+Cf0Ut4f5he8rt6jveHdMo9X36YiUQVvevj2cgN7lFivEnFYV
+QY0xugpP7lvEFDfsi2+0ozgP8EKOLYaCUKpuvttlYJ+vdtUFEijizEZ4cx02RsXm
+EesxggI1MIICMQIBA4AUnutnybladNRNLxY5ZoDoAbXLpJwwCwYJYIZIAWUDBAIB
+oHgwGgYJKoZIhvcNAQkDMQ0GCyqGSIb3DQEJEAEQMCkGCyqGSIb3DQEJEAIkMRoG
+CysGAQQBjb9BAQEqBgsrBgEEAY2/QQEBMDAvBgkqhkiG9w0BCQQxIgQgAJfvuasB
+4P6WDLOkOyvj33YPgZW4olHbidzyh1EKP9YwCwYJKoZIhvcNAQELBIIBgDn0y+4B
+cCX7ICovWcyWf0IxNXx7+1VlYneAZ8pMBaKu+6q7jRFZ+QsQFFbQ1yPO/3Pr2wVb
+UJSJAL4QCJDurJ42LdPQIOGIV2aWq70vl6B9yt6svEdjxJ3XkopwcCBXLcB1Hp9b
+6wYZzSFCujOlsABJiz2gMD6wUT4lq7RJO31LEPxx/Va4Ftp1F4okmgL8VpMemihU
+atRXpIhedfli+TWEtMmoxcX3paLcU7MmJFUAwkHmb8rSRF5VBy5QWcNgzzskof0W
+mCR/8bZjqR/g3VlFPyz7zOCxG/wIdZVAb4O/QP8fC0GhyHNE+NX6d+GI8RPpRyMf
+5RfCCsHwbApCv8+tpFslYzwvUTIFx0y9zVrnkz/UrDjZtrKxLC0oRJlnlnKR1unm
+lbolB9c2p60/mZHwQhLM5CjeYcMX3mMVJo4jqag+8o48CibW50h8y21usKaeA9b0
+9EMxfG3KaaP5mMEOZMpeGdUKQSJYweDstxlrY5ajPbeOycdMv7tRNoLpyw==
+"""
+
+ def setUp(self):
+ self.asn1Spec = rfc5652.ContentInfo()
+
+ def testDerCodec(self):
+ substrate = pem.readBase64fromText(self.pem_text)
+
+ asn1Object, rest = der_decode(substrate, asn1Spec=self.asn1Spec)
+
+ assert not rest
+ assert asn1Object.prettyPrint()
+ assert der_encode(asn1Object) == substrate
+
+ assert asn1Object['contentType'] == rfc5652.id_signedData
+ inner, rest = der_decode(asn1Object['content'], asn1Spec=rfc5652.SignedData())
+
+ assert inner['encapContentInfo']['eContentType'] == rfc4108.id_ct_firmwarePackage
+ assert inner['encapContentInfo']['eContent']
+
+ found_target_hardware_identifier_attribute = False
+ for attr in inner['signerInfos'][0]['signedAttrs']:
+ if attr['attrType'] == rfc4108.id_aa_targetHardwareIDs:
+ found_target_hardware_identifier_attribute = True
+ assert found_target_hardware_identifier_attribute
+
+
+suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__])
+
+if __name__ == '__main__':
+ unittest.TextTestRunner(verbosity=2).run(suite)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyasn1-modules-0.2.4/tests/test_rfc5958.py new/pyasn1-modules-0.2.5/tests/test_rfc5958.py
--- old/pyasn1-modules-0.2.4/tests/test_rfc5958.py 1970-01-01 01:00:00.000000000 +0100
+++ new/pyasn1-modules-0.2.5/tests/test_rfc5958.py 2019-04-24 06:40:45.000000000 +0200
@@ -0,0 +1,50 @@
+#
+# This file is part of pyasn1-modules software.
+#
+# Created by Russ Housley
+# Copyright (c) 2019, Vigil Security, LLC
+# License: http://snmplabs.com/pyasn1/license.html
+#
+
+import sys
+
+from pyasn1.codec.der import decoder as der_decoder
+from pyasn1.codec.der import encoder as der_encoder
+
+from pyasn1_modules import pem
+from pyasn1_modules import rfc5958
+from pyasn1_modules import rfc8410
+
+try:
+ import unittest2 as unittest
+except ImportError:
+ import unittest
+
+
+class PrivateKeyTestCase(unittest.TestCase):
+ priv_key_pem_text = """\
+MHICAQEwBQYDK2VwBCIEINTuctv5E1hK1bbY8fdp+K06/nwoy/HU++CXqI9EdVhC
+oB8wHQYKKoZIhvcNAQkJFDEPDA1DdXJkbGUgQ2hhaXJzgSEAGb9ECWmEzf6FQbrB
+Z9w7lshQhqowtrbLDFw4rXAxZuE=
+"""
+
+ def setUp(self):
+ self.asn1Spec = rfc5958.PrivateKeyInfo()
+
+ def testDerCodec(self):
+ substrate = pem.readBase64fromText(self.priv_key_pem_text)
+ asn1Object, rest = der_decoder.decode(substrate, asn1Spec=self.asn1Spec)
+ assert not rest
+ assert asn1Object.prettyPrint()
+ assert asn1Object['privateKeyAlgorithm']['algorithm'] == rfc8410.id_Ed25519
+ assert asn1Object['privateKey'].isValue
+ assert asn1Object['privateKey'].prettyPrint()[0:10] == "0x0420d4ee"
+ assert asn1Object['publicKey'].isValue
+ assert asn1Object['publicKey'].prettyPrint()[0:10] == "1164575857"
+ assert der_encoder.encode(asn1Object) == substrate
+
+
+suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__])
+
+if __name__ == '__main__':
+ unittest.TextTestRunner(verbosity=2).run(suite)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyasn1-modules-0.2.4/tests/test_rfc8410.py new/pyasn1-modules-0.2.5/tests/test_rfc8410.py
--- old/pyasn1-modules-0.2.4/tests/test_rfc8410.py 1970-01-01 01:00:00.000000000 +0100
+++ new/pyasn1-modules-0.2.5/tests/test_rfc8410.py 2019-04-24 06:40:45.000000000 +0200
@@ -0,0 +1,44 @@
+#
+# This file is part of pyasn1-modules software.
+#
+# Created by Russ Housley
+# Copyright (c) 2019, Vigil Security, LLC
+# License: http://snmplabs.com/pyasn1/license.html
+#
+
+import sys
+
+from pyasn1.codec.der import decoder as der_decoder
+from pyasn1.codec.der import encoder as der_encoder
+
+from pyasn1_modules import pem
+from pyasn1_modules import rfc5208
+from pyasn1_modules import rfc8410
+
+try:
+ import unittest2 as unittest
+except ImportError:
+ import unittest
+
+
+class PrivateKeyTestCase(unittest.TestCase):
+ no_pub_key_pem_text = "MC4CAQAwBQYDK2VwBCIEINTuctv5E1hK1bbY8fdp+K06/nwoy/HU++CXqI9EdVhC"
+
+ def setUp(self):
+ self.asn1Spec = rfc5208.PrivateKeyInfo()
+
+ def testDerCodec(self):
+ substrate = pem.readBase64fromText(self.no_pub_key_pem_text)
+ asn1Object, rest = der_decoder.decode(substrate, asn1Spec=self.asn1Spec)
+ assert not rest
+ assert asn1Object.prettyPrint()
+ assert asn1Object['privateKeyAlgorithm']['algorithm'] == rfc8410.id_Ed25519
+ assert asn1Object['privateKey'].isValue
+ assert asn1Object['privateKey'].prettyPrint()[0:10] == "0x0420d4ee"
+ assert der_encoder.encode(asn1Object) == substrate
+
+
+suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__])
+
+if __name__ == '__main__':
+ unittest.TextTestRunner(verbosity=2).run(suite)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyasn1-modules-0.2.4/tests/test_rfc8418.py new/pyasn1-modules-0.2.5/tests/test_rfc8418.py
--- old/pyasn1-modules-0.2.4/tests/test_rfc8418.py 1970-01-01 01:00:00.000000000 +0100
+++ new/pyasn1-modules-0.2.5/tests/test_rfc8418.py 2019-04-24 06:40:45.000000000 +0200
@@ -0,0 +1,43 @@
+#
+# This file is part of pyasn1-modules software.
+#
+# Created by Russ Housley
+# Copyright (c) 2019, Vigil Security, LLC
+# License: http://snmplabs.com/pyasn1/license.html
+#
+
+import sys
+
+from pyasn1.codec.der import decoder as der_decoder
+from pyasn1.codec.der import encoder as der_encoder
+
+from pyasn1_modules import pem
+from pyasn1_modules import rfc5280
+from pyasn1_modules import rfc8418
+
+try:
+ import unittest2 as unittest
+except ImportError:
+ import unittest
+
+
+class KeyAgreeAlgTestCase(unittest.TestCase):
+ key_agree_alg_id_pem_text = "MBoGCyqGSIb3DQEJEAMUMAsGCWCGSAFlAwQBLQ=="
+
+ def setUp(self):
+ self.asn1Spec = rfc5280.AlgorithmIdentifier()
+
+ def testDerCodec(self):
+ substrate = pem.readBase64fromText(self.key_agree_alg_id_pem_text)
+ asn1Object, rest = der_decoder.decode(substrate, asn1Spec=self.asn1Spec)
+ assert not rest
+ assert asn1Object.prettyPrint()
+ assert asn1Object['algorithm'] == rfc8418.dhSinglePass_stdDH_hkdf_sha384_scheme
+ assert asn1Object['parameters'].isValue
+ assert der_encoder.encode(asn1Object) == substrate
+
+
+suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__])
+
+if __name__ == '__main__':
+ unittest.TextTestRunner(verbosity=2).run(suite)
1
0
Hello community,
here is the log from the commit of package python-pexpect for openSUSE:Factory checked in at 2019-05-27 08:37:25
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-pexpect (Old)
and /work/SRC/openSUSE:Factory/.python-pexpect.new.5148 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-pexpect"
Mon May 27 08:37:25 2019 rev:28 rq:705391 version:4.7.0
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-pexpect/python-pexpect.changes 2018-12-27 00:27:30.387755644 +0100
+++ /work/SRC/openSUSE:Factory/.python-pexpect.new.5148/python-pexpect.changes 2019-05-27 08:37:26.583093016 +0200
@@ -1,0 +2,12 @@
+Sat May 25 09:06:04 UTC 2019 - Tomáš Chvátal <tchvatal(a)suse.com>
+
+- Update to 4.7.0:
+ * The :meth:`.pxssh.login` method now no longer requires a username if an ssh config is provided and will raise an error if neither are provided. (:ghpull:`562`).
+ * The :meth:`.pxssh.login` method now supports providing your own ssh command via the cmd parameter. (:ghpull:`528`) (:ghpull:`563`).
+ * :class:`.pxssh` now supports the use_poll parameter which is passed into :meth:`.pexpect.spawn` (:ghpull:`542`).
+ * Minor bug fix with ssh_config. (:ghpull:`498`).
+ * :meth:`.replwrap.run_command` now has async support via an async_ parameter. (:ghpull:`501`).
+ * :meth:`.pexpect.spawn` will now read additional bytes if able up to a buffer limit. (:ghpull:`304`).
+- Drop merged patch fix-test.patch
+
+-------------------------------------------------------------------
Old:
----
fix-test.patch
pexpect-4.6.0.tar.gz
New:
----
pexpect-4.7.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-pexpect.spec ++++++
--- /var/tmp/diff_new_pack.6jP1es/_old 2019-05-27 08:37:27.227092764 +0200
+++ /var/tmp/diff_new_pack.6jP1es/_new 2019-05-27 08:37:27.231092763 +0200
@@ -1,7 +1,7 @@
#
# spec file for package python-pexpect
#
-# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -18,20 +18,21 @@
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
Name: python-pexpect
-Version: 4.6.0
+Version: 4.7.0
Release: 0
Summary: Pure Python Expect-like module
License: ISC
Group: Development/Libraries/Python
URL: http://pexpect.readthedocs.org/en/latest/
Source: https://files.pythonhosted.org/packages/source/p/pexpect/pexpect-%{version}…
-Patch0: fix-test.patch
BuildRequires: %{python_module ptyprocess}
BuildRequires: %{python_module pytest}
BuildRequires: fdupes
# For man validation
BuildRequires: man
# For test command calls
+# For bash validation
+BuildRequires: bash
BuildRequires: openssl
BuildRequires: python-rpm-macros
Requires: python-ptyprocess
@@ -44,7 +45,6 @@
%prep
%setup -q -n pexpect-%{version}
-%patch0 -p1
# Fix wrong-script-interpreter
find examples -type f -name "*.py" -exec sed -i "s|#!%{_bindir}/env python||" {} \;
@@ -59,7 +59,8 @@
%check
export LANG=en_US.UTF-8
-%python_expand py.test-%{$python_bin_suffix}
+# test_bash https://github.com/pexpect/pexpect/issues/568
+%pytest -k 'not test_bash'
%files %{python_files}
%license LICENSE
++++++ pexpect-4.6.0.tar.gz -> pexpect-4.7.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pexpect-4.6.0/.coveragerc new/pexpect-4.7.0/.coveragerc
--- old/pexpect-4.6.0/.coveragerc 2015-12-08 19:43:59.000000000 +0100
+++ new/pexpect-4.7.0/.coveragerc 1970-01-01 01:00:00.000000000 +0100
@@ -1,3 +0,0 @@
-[run]
-source = pexpect
-parallel = True
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pexpect-4.6.0/MANIFEST.in new/pexpect-4.7.0/MANIFEST.in
--- old/pexpect-4.6.0/MANIFEST.in 1970-01-01 01:00:00.000000000 +0100
+++ new/pexpect-4.7.0/MANIFEST.in 2019-04-07 03:54:51.000000000 +0200
@@ -0,0 +1,6 @@
+recursive-include doc *
+prune doc/_build
+recursive-include examples *
+include .coveragerc README.rst LICENSE pexpect/bashrc.sh
+recursive-include tests *
+global-exclude __pycache__ *.pyc *~
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pexpect-4.6.0/PKG-INFO new/pexpect-4.7.0/PKG-INFO
--- old/pexpect-4.6.0/PKG-INFO 2018-05-29 14:32:50.000000000 +0200
+++ new/pexpect-4.7.0/PKG-INFO 2019-04-07 03:54:58.000000000 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: pexpect
-Version: 4.6.0
+Version: 4.7.0
Summary: Pexpect allows easy control of interactive console applications.
Home-page: https://pexpect.readthedocs.io/
Author: Noah Spurrier; Thomas Kluyver; Jeff Quast
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pexpect-4.6.0/doc/api/pxssh.rst new/pexpect-4.7.0/doc/api/pxssh.rst
--- old/pexpect-4.6.0/doc/api/pxssh.rst 2015-12-08 19:43:59.000000000 +0100
+++ new/pexpect-4.7.0/doc/api/pxssh.rst 2019-04-07 03:54:51.000000000 +0200
@@ -1,6 +1,14 @@
pxssh - control an SSH session
==============================
+.. note::
+
+ *pxssh* is a screen-scraping wrapper around the SSH command on your system.
+ In many cases, you should consider using
+ `Paramiko <https://github.com/paramiko/paramiko>`_ instead.
+ Paramiko is a Python module which speaks the SSH protocol directly, so it
+ doesn't have the extra complexity of running a local subprocess.
+
.. automodule:: pexpect.pxssh
.. autoclass:: ExceptionPxssh
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pexpect-4.6.0/doc/conf.py new/pexpect-4.7.0/doc/conf.py
--- old/pexpect-4.6.0/doc/conf.py 2018-05-29 14:15:18.000000000 +0200
+++ new/pexpect-4.7.0/doc/conf.py 2019-04-07 03:54:51.000000000 +0200
@@ -52,7 +52,7 @@
# built documents.
#
# The short X.Y version.
-version = '4.6'
+version = '4.7'
# The full version, including alpha/beta/rc tags.
release = version
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pexpect-4.6.0/doc/history.rst new/pexpect-4.7.0/doc/history.rst
--- old/pexpect-4.6.0/doc/history.rst 2018-05-29 14:12:45.000000000 +0200
+++ new/pexpect-4.7.0/doc/history.rst 2019-04-07 03:54:51.000000000 +0200
@@ -4,6 +4,24 @@
Releases
--------
+Version 4.7
+```````````
+
+* The :meth:`.pxssh.login` method now no longer requires a username if an ssh
+ config is provided and will raise an error if neither are provided.
+ (:ghpull:`562`).
+* The :meth:`.pxssh.login` method now supports providing your own ``ssh``
+ command via the ``cmd`` parameter.
+ (:ghpull:`528`) (:ghpull:`563`).
+* :class:`.pxssh` now supports the ``use_poll`` parameter which is passed into :meth:`.pexpect.spawn`
+ (:ghpull:`542`).
+* Minor bug fix with ``ssh_config``.
+ (:ghpull:`498`).
+* :meth:`.replwrap.run_command` now has async support via an ``async_`` parameter.
+ (:ghpull:`501`).
+* :meth:`.pexpect.spawn` will now read additional bytes if able up to a buffer limit.
+ (:ghpull:`304`).
+
Version 4.6
```````````
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pexpect-4.6.0/doc/overview.rst new/pexpect-4.7.0/doc/overview.rst
--- old/pexpect-4.6.0/doc/overview.rst 2018-04-13 19:51:22.000000000 +0200
+++ new/pexpect-4.7.0/doc/overview.rst 2019-04-07 03:54:51.000000000 +0200
@@ -207,7 +207,10 @@
following will turn on logging and send output to stdout (the screen)::
child = pexpect.spawn(foo)
- child.logfile = sys.stdout
+ child.logfile = sys.stdout.buffer
+
+The `sys.stdout.buffer` object is available since Python 3. With Python 2, one
+has to assign just `sys.stdout` instead.
Exceptions
----------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pexpect-4.6.0/pexpect/__init__.py new/pexpect-4.7.0/pexpect/__init__.py
--- old/pexpect-4.6.0/pexpect/__init__.py 2018-05-29 14:15:18.000000000 +0200
+++ new/pexpect-4.7.0/pexpect/__init__.py 2019-04-07 03:54:51.000000000 +0200
@@ -75,7 +75,7 @@
from .pty_spawn import spawn, spawnu
from .run import run, runu
-__version__ = '4.6.0'
+__version__ = '4.7.0'
__revision__ = ''
__all__ = ['ExceptionPexpect', 'EOF', 'TIMEOUT', 'spawn', 'spawnu', 'run', 'runu',
'which', 'split_command_line', '__version__', '__revision__']
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pexpect-4.6.0/pexpect/_async.py new/pexpect-4.7.0/pexpect/_async.py
--- old/pexpect-4.6.0/pexpect/_async.py 2018-04-11 21:03:57.000000000 +0200
+++ new/pexpect-4.7.0/pexpect/_async.py 2019-04-07 03:54:51.000000000 +0200
@@ -1,5 +1,6 @@
import asyncio
import errno
+import signal
from pexpect import EOF
@@ -29,6 +30,23 @@
transport.pause_reading()
return expecter.timeout(e)
+(a)asyncio.coroutine
+def repl_run_command_async(repl, cmdlines, timeout=-1):
+ res = []
+ repl.child.sendline(cmdlines[0])
+ for line in cmdlines[1:]:
+ yield from repl._expect_prompt(timeout=timeout, async_=True)
+ res.append(repl.child.before)
+ repl.child.sendline(line)
+
+ # Command was fully submitted, now wait for the next prompt
+ prompt_idx = yield from repl._expect_prompt(timeout=timeout, async_=True)
+ if prompt_idx == 1:
+ # We got the continuation prompt - command was incomplete
+ repl.child.kill(signal.SIGINT)
+ yield from repl._expect_prompt(timeout=1, async_=True)
+ raise ValueError("Continuation prompt found - input was incomplete:")
+ return u''.join(res + [repl.child.before])
class PatternWaiter(asyncio.Protocol):
transport = None
@@ -41,7 +59,7 @@
if not self.fut.done():
self.fut.set_result(result)
self.transport.pause_reading()
-
+
def error(self, exc):
if not self.fut.done():
self.fut.set_exception(exc)
@@ -49,7 +67,7 @@
def connection_made(self, transport):
self.transport = transport
-
+
def data_received(self, data):
spawn = self.expecter.spawn
s = spawn._decoder.decode(data)
@@ -67,7 +85,7 @@
except Exception as e:
self.expecter.errored()
self.error(e)
-
+
def eof_received(self):
# N.B. If this gets called, async will close the pipe (the spawn object)
# for us
@@ -78,7 +96,7 @@
self.error(e)
else:
self.found(index)
-
+
def connection_lost(self, exc):
if isinstance(exc, OSError) and exc.errno == errno.EIO:
# We may get here without eof_received being called, e.g on Linux
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pexpect-4.6.0/pexpect/expect.py new/pexpect-4.7.0/pexpect/expect.py
--- old/pexpect-4.6.0/pexpect/expect.py 2018-04-11 21:03:57.000000000 +0200
+++ new/pexpect-4.7.0/pexpect/expect.py 2019-04-07 03:54:51.000000000 +0200
@@ -244,7 +244,7 @@
self.eof_index = -1
self.timeout_index = -1
self._searches = []
- for n, s in zip(list(range(len(patterns))), patterns):
+ for n, s in enumerate(patterns):
if s is EOF:
self.eof_index = n
continue
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pexpect-4.6.0/pexpect/pty_spawn.py new/pexpect-4.7.0/pexpect/pty_spawn.py
--- old/pexpect-4.6.0/pexpect/pty_spawn.py 2018-04-13 19:35:52.000000000 +0200
+++ new/pexpect-4.7.0/pexpect/pty_spawn.py 2019-04-07 03:54:51.000000000 +0200
@@ -430,61 +430,83 @@
available right away then one character will be returned immediately.
It will not wait for 30 seconds for another 99 characters to come in.
- This is a wrapper around os.read(). It uses select.select() to
- implement the timeout. '''
+ On the other hand, if there are bytes available to read immediately,
+ all those bytes will be read (up to the buffer size). So, if the
+ buffer size is 1 megabyte and there is 1 megabyte of data available
+ to read, the buffer will be filled, regardless of timeout.
+
+ This is a wrapper around os.read(). It uses select.select() or
+ select.poll() to implement the timeout. '''
if self.closed:
raise ValueError('I/O operation on closed file.')
+ if self.use_poll:
+ def select(timeout):
+ return poll_ignore_interrupts([self.child_fd], timeout)
+ else:
+ def select(timeout):
+ return select_ignore_interrupts([self.child_fd], [], [], timeout)[0]
+
+ # If there is data available to read right now, read as much as
+ # we can. We do this to increase performance if there are a lot
+ # of bytes to be read. This also avoids calling isalive() too
+ # often. See also:
+ # * https://github.com/pexpect/pexpect/pull/304
+ # * http://trac.sagemath.org/ticket/10295
+ if select(0):
+ try:
+ incoming = super(spawn, self).read_nonblocking(size)
+ except EOF:
+ # Maybe the child is dead: update some attributes in that case
+ self.isalive()
+ raise
+ while len(incoming) < size and select(0):
+ try:
+ incoming += super(spawn, self).read_nonblocking(size - len(incoming))
+ except EOF:
+ # Maybe the child is dead: update some attributes in that case
+ self.isalive()
+ # Don't raise EOF, just return what we read so far.
+ return incoming
+ return incoming
+
if timeout == -1:
timeout = self.timeout
- # Note that some systems such as Solaris do not give an EOF when
- # the child dies. In fact, you can still try to read
- # from the child_fd -- it will block forever or until TIMEOUT.
- # For this case, I test isalive() before doing any reading.
- # If isalive() is false, then I pretend that this is the same as EOF.
if not self.isalive():
- # timeout of 0 means "poll"
- if self.use_poll:
- r = poll_ignore_interrupts([self.child_fd], timeout)
- else:
- r, w, e = select_ignore_interrupts([self.child_fd], [], [], 0)
- if not r:
- self.flag_eof = True
- raise EOF('End Of File (EOF). Braindead platform.')
+ # The process is dead, but there may or may not be data
+ # available to read. Note that some systems such as Solaris
+ # do not give an EOF when the child dies. In fact, you can
+ # still try to read from the child_fd -- it will block
+ # forever or until TIMEOUT. For that reason, it's important
+ # to do this check before calling select() with timeout.
+ if select(0):
+ return super(spawn, self).read_nonblocking(size)
+ self.flag_eof = True
+ raise EOF('End Of File (EOF). Braindead platform.')
elif self.__irix_hack:
# Irix takes a long time before it realizes a child was terminated.
+ # Make sure that the timeout is at least 2 seconds.
# FIXME So does this mean Irix systems are forced to always have
# FIXME a 2 second delay when calling read_nonblocking? That sucks.
- if self.use_poll:
- r = poll_ignore_interrupts([self.child_fd], timeout)
- else:
- r, w, e = select_ignore_interrupts([self.child_fd], [], [], 2)
- if not r and not self.isalive():
- self.flag_eof = True
- raise EOF('End Of File (EOF). Slow platform.')
- if self.use_poll:
- r = poll_ignore_interrupts([self.child_fd], timeout)
- else:
- r, w, e = select_ignore_interrupts(
- [self.child_fd], [], [], timeout
- )
-
- if not r:
- if not self.isalive():
- # Some platforms, such as Irix, will claim that their
- # processes are alive; timeout on the select; and
- # then finally admit that they are not alive.
- self.flag_eof = True
- raise EOF('End of File (EOF). Very slow platform.')
- else:
- raise TIMEOUT('Timeout exceeded.')
+ if timeout is not None and timeout < 2:
+ timeout = 2
- if self.child_fd in r:
+ # Because of the select(0) check above, we know that no data
+ # is available right now. But if a non-zero timeout is given
+ # (possibly timeout=None), we call select() with a timeout.
+ if (timeout != 0) and select(timeout):
return super(spawn, self).read_nonblocking(size)
- raise ExceptionPexpect('Reached an unexpected state.') # pragma: no cover
+ if not self.isalive():
+ # Some platforms, such as Irix, will claim that their
+ # processes are alive; timeout on the select; and
+ # then finally admit that they are not alive.
+ self.flag_eof = True
+ raise EOF('End of File (EOF). Very slow platform.')
+ else:
+ raise TIMEOUT('Timeout exceeded.')
def write(self, s):
'''This is similar to send() except that there is no return value.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pexpect-4.6.0/pexpect/pxssh.py new/pexpect-4.7.0/pexpect/pxssh.py
--- old/pexpect-4.6.0/pexpect/pxssh.py 2018-05-29 14:12:45.000000000 +0200
+++ new/pexpect-4.7.0/pexpect/pxssh.py 2019-04-07 03:54:51.000000000 +0200
@@ -109,7 +109,7 @@
username = raw_input('username: ')
password = getpass.getpass('password: ')
s.login (hostname, username, password)
-
+
`debug_command_string` is only for the test suite to confirm that the string
generated for SSH is correct, using this will not allow you to do
anything other than get a string back from `pxssh.pxssh.login()`.
@@ -118,12 +118,12 @@
def __init__ (self, timeout=30, maxread=2000, searchwindowsize=None,
logfile=None, cwd=None, env=None, ignore_sighup=True, echo=True,
options={}, encoding=None, codec_errors='strict',
- debug_command_string=False):
+ debug_command_string=False, use_poll=False):
spawn.__init__(self, None, timeout=timeout, maxread=maxread,
searchwindowsize=searchwindowsize, logfile=logfile,
cwd=cwd, env=env, ignore_sighup=ignore_sighup, echo=echo,
- encoding=encoding, codec_errors=codec_errors)
+ encoding=encoding, codec_errors=codec_errors, use_poll=use_poll)
self.name = '<pxssh>'
@@ -154,7 +154,7 @@
# Unsetting SSH_ASKPASS on the remote side doesn't disable it! Annoying!
#self.SSH_OPTS = "-x -o'RSAAuthentication=no' -o 'PubkeyAuthentication=no'"
self.force_password = False
-
+
self.debug_command_string = debug_command_string
# User defined SSH options, eg,
@@ -220,7 +220,7 @@
can take 12 seconds. Low latency connections are more likely to fail
with a low sync_multiplier. Best case sync time gets worse with a
high sync multiplier (500 ms with default). '''
-
+
# All of these timing pace values are magic.
# I came up with these based on what seemed reliable for
# connecting to a heavily loaded machine I have.
@@ -253,20 +253,19 @@
### TODO: This is getting messy and I'm pretty sure this isn't perfect.
### TODO: I need to draw a flow chart for this.
### TODO: Unit tests for SSH tunnels, remote SSH command exec, disabling original prompt sync
- def login (self, server, username, password='', terminal_type='ansi',
+ def login (self, server, username=None, password='', terminal_type='ansi',
original_prompt=r"[#$]", login_timeout=10, port=None,
auto_prompt_reset=True, ssh_key=None, quiet=True,
sync_multiplier=1, check_local_ip=True,
password_regex=r'(?i)(?:password:)|(?:passphrase for key)',
ssh_tunnels={}, spawn_local_ssh=True,
- sync_original_prompt=True, ssh_config=None):
+ sync_original_prompt=True, ssh_config=None, cmd='ssh'):
'''This logs the user into the given server.
- It uses
- 'original_prompt' to try to find the prompt right after login. When it
- finds the prompt it immediately tries to reset the prompt to something
- more easily matched. The default 'original_prompt' is very optimistic
- and is easily fooled. It's more reliable to try to match the original
+ It uses 'original_prompt' to try to find the prompt right after login.
+ When it finds the prompt it immediately tries to reset the prompt to
+ something more easily matched. The default 'original_prompt' is very
+ optimistic and is easily fooled. It's more reliable to try to match the original
prompt as exactly as possible to prevent false matches by server
strings such as the "Message Of The Day". On many systems you can
disable the MOTD on the remote server by creating a zero-length file
@@ -284,27 +283,31 @@
uses a unique prompt in the :meth:`prompt` method. If the original prompt is
not reset then this will disable the :meth:`prompt` method unless you
manually set the :attr:`PROMPT` attribute.
-
+
Set ``password_regex`` if there is a MOTD message with `password` in it.
Changing this is like playing in traffic, don't (p)expect it to match straight
away.
-
+
If you require to connect to another SSH server from the your original SSH
connection set ``spawn_local_ssh`` to `False` and this will use your current
session to do so. Setting this option to `False` and not having an active session
will trigger an error.
-
+
Set ``ssh_key`` to a file path to an SSH private key to use that SSH key
for the session authentication.
Set ``ssh_key`` to `True` to force passing the current SSH authentication socket
to the desired ``hostname``.
-
+
Set ``ssh_config`` to a file path string of an SSH client config file to pass that
file to the client to handle itself. You may set any options you wish in here, however
doing so will require you to post extra information that you may not want to if you
run into issues.
+
+ Alter the ``cmd`` to change the ssh client used, or to prepend it with network
+ namespaces. For example ```cmd="ip netns exec vlan2 ssh"``` to execute the ssh in
+ network namespace named ```vlan```.
'''
-
+
session_regex_array = ["(?i)are you sure you want to continue connecting", original_prompt, password_regex, "(?i)permission denied", "(?i)terminal type", TIMEOUT]
session_init_regex_array = []
session_init_regex_array.extend(session_regex_array)
@@ -320,7 +323,7 @@
if ssh_config is not None:
if spawn_local_ssh and not os.path.isfile(ssh_config):
raise ExceptionPxssh('SSH config does not exist or is not a file.')
- ssh_options = ssh_options + '-F ' + ssh_config
+ ssh_options = ssh_options + ' -F ' + ssh_config
if port is not None:
ssh_options = ssh_options + ' -p %s'%(str(port))
if ssh_key is not None:
@@ -331,7 +334,7 @@
if spawn_local_ssh and not os.path.isfile(ssh_key):
raise ExceptionPxssh('private ssh key does not exist or is not a file.')
ssh_options = ssh_options + ' -i %s' % (ssh_key)
-
+
# SSH tunnels, make sure you know what you're putting into the lists
# under each heading. Do not expect these to open 100% of the time,
# The port you're requesting might be bound.
@@ -354,7 +357,42 @@
if spawn_local_ssh==False:
tunnel = quote(str(tunnel))
ssh_options = ssh_options + ' -' + cmd_type + ' ' + str(tunnel)
- cmd = "ssh %s -l %s %s" % (ssh_options, username, server)
+
+ if username is not None:
+ ssh_options = ssh_options + ' -l ' + username
+ elif ssh_config is None:
+ raise TypeError('login() needs either a username or an ssh_config')
+ else: # make sure ssh_config has an entry for the server with a username
+ with open(ssh_config, 'rt') as f:
+ lines = [l.strip() for l in f.readlines()]
+
+ server_regex = r'^Host\s+%s\s*$' % server
+ user_regex = r'^User\s+\w+\s*$'
+ config_has_server = False
+ server_has_username = False
+ for line in lines:
+ if not config_has_server and re.match(server_regex, line, re.IGNORECASE):
+ config_has_server = True
+ elif config_has_server and 'hostname' in line.lower():
+ pass
+ elif config_has_server and 'host' in line.lower():
+ server_has_username = False # insurance
+ break # we have left the relevant section
+ elif config_has_server and re.match(user_regex, line, re.IGNORECASE):
+ server_has_username = True
+ break
+
+ if lines:
+ del line
+
+ del lines
+
+ if not config_has_server:
+ raise TypeError('login() ssh_config has no Host entry for %s' % server)
+ elif not server_has_username:
+ raise TypeError('login() ssh_config has no user entry for %s' % server)
+
+ cmd += " %s %s" % (ssh_options, server)
if self.debug_command_string:
return(cmd)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pexpect-4.6.0/pexpect/replwrap.py new/pexpect-4.7.0/pexpect/replwrap.py
--- old/pexpect-4.6.0/pexpect/replwrap.py 2018-02-10 13:16:58.000000000 +0100
+++ new/pexpect-4.7.0/pexpect/replwrap.py 2019-04-07 03:54:51.000000000 +0200
@@ -61,11 +61,11 @@
self.child.expect(orig_prompt)
self.child.sendline(prompt_change)
- def _expect_prompt(self, timeout=-1):
+ def _expect_prompt(self, timeout=-1, async_=False):
return self.child.expect_exact([self.prompt, self.continuation_prompt],
- timeout=timeout)
+ timeout=timeout, async_=async_)
- def run_command(self, command, timeout=-1):
+ def run_command(self, command, timeout=-1, async_=False):
"""Send a command to the REPL, wait for and return output.
:param str command: The command to send. Trailing newlines are not needed.
@@ -75,6 +75,10 @@
:param int timeout: How long to wait for the next prompt. -1 means the
default from the :class:`pexpect.spawn` object (default 30 seconds).
None means to wait indefinitely.
+ :param bool async_: On Python 3.4, or Python 3.3 with asyncio
+ installed, passing ``async_=True`` will make this return an
+ :mod:`asyncio` Future, which you can yield from to get the same
+ result that this method would normally give directly.
"""
# Split up multiline commands and feed them in bit-by-bit
cmdlines = command.splitlines()
@@ -84,6 +88,10 @@
if not cmdlines:
raise ValueError("No command was given")
+ if async_:
+ from ._async import repl_run_command_async
+ return repl_run_command_async(self, cmdlines, timeout)
+
res = []
self.child.sendline(cmdlines[0])
for line in cmdlines[1:]:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pexpect-4.6.0/pexpect.egg-info/PKG-INFO new/pexpect-4.7.0/pexpect.egg-info/PKG-INFO
--- old/pexpect-4.6.0/pexpect.egg-info/PKG-INFO 1970-01-01 01:00:00.000000000 +0100
+++ new/pexpect-4.7.0/pexpect.egg-info/PKG-INFO 2019-04-07 03:54:58.000000000 +0200
@@ -0,0 +1,46 @@
+Metadata-Version: 1.1
+Name: pexpect
+Version: 4.7.0
+Summary: Pexpect allows easy control of interactive console applications.
+Home-page: https://pexpect.readthedocs.io/
+Author: Noah Spurrier; Thomas Kluyver; Jeff Quast
+Author-email: noah(a)noah.org, thomas(a)kluyver.me.uk, contact(a)jeffquast.com
+License: ISC license
+Description:
+ Pexpect is a pure Python module for spawning child applications; controlling
+ them; and responding to expected patterns in their output. Pexpect works like
+ Don Libes' Expect. Pexpect allows your script to spawn a child application and
+ control it as if a human were typing commands.
+
+ Pexpect can be used for automating interactive applications such as ssh, ftp,
+ passwd, telnet, etc. It can be used to a automate setup scripts for duplicating
+ software package installations on different servers. It can be used for
+ automated software testing. Pexpect is in the spirit of Don Libes' Expect, but
+ Pexpect is pure Python.
+
+ The main features of Pexpect require the pty module in the Python standard
+ library, which is only available on Unix-like systems. Some features—waiting
+ for patterns from file descriptors or subprocesses—are also available on
+ Windows.
+
+Platform: UNIX
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Environment :: Console
+Classifier: Intended Audience :: Developers
+Classifier: Intended Audience :: System Administrators
+Classifier: License :: OSI Approved :: ISC License (ISCL)
+Classifier: Operating System :: POSIX
+Classifier: Operating System :: MacOS :: MacOS X
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
+Classifier: Topic :: Software Development
+Classifier: Topic :: Software Development :: Libraries :: Python Modules
+Classifier: Topic :: Software Development :: Quality Assurance
+Classifier: Topic :: Software Development :: Testing
+Classifier: Topic :: System
+Classifier: Topic :: System :: Archiving :: Packaging
+Classifier: Topic :: System :: Installation/Setup
+Classifier: Topic :: System :: Shells
+Classifier: Topic :: System :: Software Distribution
+Classifier: Topic :: Terminals
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pexpect-4.6.0/pexpect.egg-info/SOURCES.txt new/pexpect-4.7.0/pexpect.egg-info/SOURCES.txt
--- old/pexpect-4.6.0/pexpect.egg-info/SOURCES.txt 1970-01-01 01:00:00.000000000 +0100
+++ new/pexpect-4.7.0/pexpect.egg-info/SOURCES.txt 2019-04-07 03:54:58.000000000 +0200
@@ -0,0 +1,128 @@
+LICENSE
+MANIFEST.in
+README.rst
+setup.cfg
+setup.py
+doc/FAQ.rst
+doc/Makefile
+doc/clean.css
+doc/commonissues.rst
+doc/conf.py
+doc/examples.rst
+doc/history.rst
+doc/index.rst
+doc/install.rst
+doc/make.bat
+doc/overview.rst
+doc/requirements.txt
+doc/api/fdpexpect.rst
+doc/api/index.rst
+doc/api/pexpect.rst
+doc/api/popen_spawn.rst
+doc/api/pxssh.rst
+doc/api/replwrap.rst
+doc/sphinxext/github.py
+examples/README
+examples/astat.py
+examples/cgishell.cgi
+examples/chess.py
+examples/chess2.py
+examples/chess3.py
+examples/df.py
+examples/ftp.py
+examples/hive.py
+examples/monitor.py
+examples/passmass.py
+examples/python.py
+examples/script.py
+examples/ssh_tunnel.py
+examples/table_test.html
+examples/topip.py
+examples/uptime.py
+pexpect/ANSI.py
+pexpect/FSM.py
+pexpect/__init__.py
+pexpect/_async.py
+pexpect/bashrc.sh
+pexpect/exceptions.py
+pexpect/expect.py
+pexpect/fdpexpect.py
+pexpect/popen_spawn.py
+pexpect/pty_spawn.py
+pexpect/pxssh.py
+pexpect/replwrap.py
+pexpect/run.py
+pexpect/screen.py
+pexpect/spawnbase.py
+pexpect/utils.py
+pexpect.egg-info/PKG-INFO
+pexpect.egg-info/SOURCES.txt
+pexpect.egg-info/dependency_links.txt
+pexpect.egg-info/requires.txt
+pexpect.egg-info/top_level.txt
+tests/PexpectTestCase.py
+tests/README
+tests/TESTDATA.txt
+tests/__init__.py
+tests/adhoc.py
+tests/alarm_die.py
+tests/bambi.vt
+tests/depricated_test_filedescriptor.py
+tests/echo_w_prompt.py
+tests/echo_wait.py
+tests/exit1.py
+tests/exit667.c
+tests/getch.py
+tests/globe.vt
+tests/interact.py
+tests/list100.py
+tests/needs_kill.py
+tests/pexpectTest.py
+tests/qa.py
+tests/sigwinch_report.py
+tests/sleep_for.py
+tests/swapcase_echo.py
+tests/test_FSM.py
+tests/test_ansi.py
+tests/test_async.py
+tests/test_command_list_split.py
+tests/test_constructor.py
+tests/test_ctrl_chars.py
+tests/test_delay.py
+tests/test_destructor.py
+tests/test_dotall.py
+tests/test_env.py
+tests/test_expect.py
+tests/test_filedescriptor.py
+tests/test_interact.py
+tests/test_isalive.py
+tests/test_log.py
+tests/test_misc.py
+tests/test_missing_command.py
+tests/test_performance.py
+tests/test_pickling.py
+tests/test_popen_spawn.py
+tests/test_pxssh.py
+tests/test_replwrap.py
+tests/test_repr.py
+tests/test_run.py
+tests/test_run_out_of_pty.py
+tests/test_screen.py
+tests/test_socket.py
+tests/test_timeout_pattern.py
+tests/test_unicode.py
+tests/test_which.py
+tests/test_winsize.py
+tests/tetris.data
+tests/ticker.py
+tests/torturet.vt
+tests/utils.py
+tests/fakessh/ssh
+tests/platform_checks/README
+tests/platform_checks/check.py
+tests/platform_checks/check2.py
+tests/platform_checks/check_control_terminal.py
+tests/platform_checks/check_handler.py
+tests/platform_checks/check_read.py
+tests/platform_checks/check_signals.py
+tests/platform_checks/CSIGNALTEST/test.c
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pexpect-4.6.0/pexpect.egg-info/dependency_links.txt new/pexpect-4.7.0/pexpect.egg-info/dependency_links.txt
--- old/pexpect-4.6.0/pexpect.egg-info/dependency_links.txt 1970-01-01 01:00:00.000000000 +0100
+++ new/pexpect-4.7.0/pexpect.egg-info/dependency_links.txt 2019-04-07 03:54:58.000000000 +0200
@@ -0,0 +1 @@
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pexpect-4.6.0/pexpect.egg-info/requires.txt new/pexpect-4.7.0/pexpect.egg-info/requires.txt
--- old/pexpect-4.6.0/pexpect.egg-info/requires.txt 1970-01-01 01:00:00.000000000 +0100
+++ new/pexpect-4.7.0/pexpect.egg-info/requires.txt 2019-04-07 03:54:58.000000000 +0200
@@ -0,0 +1 @@
+ptyprocess>=0.5
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pexpect-4.6.0/pexpect.egg-info/top_level.txt new/pexpect-4.7.0/pexpect.egg-info/top_level.txt
--- old/pexpect-4.6.0/pexpect.egg-info/top_level.txt 1970-01-01 01:00:00.000000000 +0100
+++ new/pexpect-4.7.0/pexpect.egg-info/top_level.txt 2019-04-07 03:54:58.000000000 +0200
@@ -0,0 +1 @@
+pexpect
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pexpect-4.6.0/setup.cfg new/pexpect-4.7.0/setup.cfg
--- old/pexpect-4.6.0/setup.cfg 2018-04-11 21:03:57.000000000 +0200
+++ new/pexpect-4.7.0/setup.cfg 2019-04-07 03:54:58.000000000 +0200
@@ -2,4 +2,9 @@
norecursedirs = .git
[bdist_wheel]
-universal=1
+universal = 1
+
+[egg_info]
+tag_build =
+tag_date = 0
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pexpect-4.6.0/tests/fakessh/ssh new/pexpect-4.7.0/tests/fakessh/ssh
--- old/pexpect-4.6.0/tests/fakessh/ssh 2016-08-21 21:57:33.000000000 +0200
+++ new/pexpect-4.7.0/tests/fakessh/ssh 2019-04-07 03:54:52.000000000 +0200
@@ -3,13 +3,52 @@
import getpass
import sys
+import getopt
PY3 = (sys.version_info[0] >= 3)
if not PY3:
input = raw_input
-server = sys.argv[-1]
-if server == 'noserver':
- print('No route to host')
+ssh_usage = "usage: ssh [-2qV] [-c cipher_spec] [-l login_name]\r\n" \
+ + " hostname"
+
+cipher_valid_list = ['aes128-ctr', 'aes192-ctr', 'aes256-ctr', 'arcfour256', 'arcfour128', \
+ 'aes128-cbc','3des-cbc','blowfish-cbc','cast128-cbc','aes192-cbc', \
+ 'aes256-cbc','arcfour']
+
+try:
+ server = sys.argv[-1]
+ if server == 'noserver':
+ print('No route to host')
+ sys.exit(1)
+
+ elif len(sys.argv) < 2:
+ print(ssh_usage)
+ sys.exit(1)
+
+ cipher = ''
+ cipher_list = []
+ fullCmdArguments = sys.argv
+ argumentList = fullCmdArguments[1:]
+ unixOptions = "2qVc:l"
+ arguments, values = getopt.getopt(argumentList, unixOptions)
+ for currentArgument, currentValue in arguments:
+ if currentArgument in ("-2"):
+ pass
+ elif currentArgument in ("-V"):
+ print("Mock SSH client version 0.2")
+ sys.exit(1)
+ elif currentArgument in ("-c"):
+ cipher = currentValue
+ cipher_list = cipher.split(",")
+ for cipher_item in cipher_list:
+ if cipher_item not in cipher_valid_list:
+ print("Unknown cipher type '" + str(cipher_item) + "'")
+ sys.exit(1)
+
+
+except Exception as e:
+ print(ssh_usage)
+ print('error = ' + str(e))
sys.exit(1)
print("Mock SSH client for tests. Do not enter real security info.")
@@ -31,4 +70,5 @@
elif cmd == 'echo $?':
print(0)
elif cmd in ('exit', 'logout'):
+ print('Closed connection')
break
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pexpect-4.6.0/tests/test_async.py new/pexpect-4.7.0/tests/test_async.py
--- old/pexpect-4.6.0/tests/test_async.py 2018-02-10 13:16:58.000000000 +0100
+++ new/pexpect-4.7.0/tests/test_async.py 2019-04-07 03:54:51.000000000 +0200
@@ -8,6 +8,7 @@
import unittest
import pexpect
+from pexpect import replwrap
from .PexpectTestCase import PexpectTestCase
def run(coro):
@@ -27,7 +28,7 @@
coro = p.expect('foo', timeout=1, async_=True)
with self.assertRaises(pexpect.TIMEOUT):
run(coro)
-
+
p = pexpect.spawn('cat')
coro = p.expect(['foo', pexpect.TIMEOUT], timeout=1, async_=True)
assert run(coro) == 1
@@ -68,3 +69,29 @@
assert run(p.expect_exact(u'1', async_=True)) == 0
assert p.expect_exact(u'2') == 0
assert run(p.expect_exact(u'3', async_=True)) == 0
+
+ def test_async_replwrap(self):
+ bash = replwrap.bash()
+ coro = bash.run_command("time", async_=True)
+ res = run(coro)
+ assert 'real' in res, res
+
+ def test_async_replwrap_multiline(self):
+ bash = replwrap.bash()
+ coro = bash.run_command("echo '1 2\n3 4'", async_=True)
+ res = run(coro)
+ self.assertEqual(res.strip().splitlines(), ['1 2', '3 4'])
+
+ # Should raise ValueError if input is incomplete
+ coro = bash.run_command("echo '5 6", async_=True)
+ try:
+ run(coro)
+ except ValueError:
+ pass
+ else:
+ assert False, "Didn't raise ValueError for incomplete input"
+
+ # Check that the REPL was reset (SIGINT) after the incomplete input
+ coro = bash.run_command("echo '1 2\n3 4'", async_=True)
+ res = run(coro)
+ self.assertEqual(res.strip().splitlines(), ['1 2', '3 4'])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pexpect-4.6.0/tests/test_expect.py new/pexpect-4.7.0/tests/test_expect.py
--- old/pexpect-4.6.0/tests/test_expect.py 2018-04-11 21:03:57.000000000 +0200
+++ new/pexpect-4.7.0/tests/test_expect.py 2019-04-07 03:54:51.000000000 +0200
@@ -411,7 +411,7 @@
def test_before_across_chunks(self):
# https://github.com/pexpect/pexpect/issues/478
child = pexpect.spawn(
- '''/bin/bash -c "openssl rand -base64 {} | head -500 | nl --number-format=rz --number-width=5 2>&1 ; echo 'PATTERN!!!'"'''.format(1024 * 1024 * 2),
+ '''/bin/bash -c "openssl rand -base64 {} 2>/dev/null | head -500 | nl --number-format=rz --number-width=5 2>&1 ; echo 'PATTERN!!!'"'''.format(1024 * 1024 * 2),
searchwindowsize=128
)
child.expect(['PATTERN'])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pexpect-4.6.0/tests/test_pxssh.py new/pexpect-4.7.0/tests/test_pxssh.py
--- old/pexpect-4.6.0/tests/test_pxssh.py 2018-05-29 14:12:45.000000000 +0200
+++ new/pexpect-4.7.0/tests/test_pxssh.py 2019-04-07 03:54:51.000000000 +0200
@@ -87,11 +87,82 @@
def test_ssh_config_passing_string(self):
ssh = pxssh.pxssh(debug_command_string=True)
- (temp_file,config_path) = tempfile.mkstemp()
+ temp_file = tempfile.NamedTemporaryFile()
+ config_path = temp_file.name
string = ssh.login('server', 'me', password='s3cret', spawn_local_ssh=False, ssh_config=config_path)
if not '-F '+config_path in string:
assert False, 'String generated from SSH config passing is incorrect.'
+ def test_username_or_ssh_config(self):
+ try:
+ ssh = pxssh.pxssh(debug_command_string=True)
+ temp_file = tempfile.NamedTemporaryFile()
+ config_path = temp_file.name
+ string = ssh.login('server')
+ raise AssertionError('Should have failed due to missing username and missing ssh_config.')
+ except TypeError:
+ pass
+
+ def test_ssh_config_user(self):
+ ssh = pxssh.pxssh(debug_command_string=True)
+ temp_file = tempfile.NamedTemporaryFile()
+ config_path = temp_file.name
+ temp_file.write(b'HosT server\n'
+ b'UsEr me\n'
+ b'hOSt not-server\n')
+ temp_file.seek(0)
+ string = ssh.login('server', ssh_config=config_path)
+
+ def test_ssh_config_no_username_empty_config(self):
+ ssh = pxssh.pxssh(debug_command_string=True)
+ temp_file = tempfile.NamedTemporaryFile()
+ config_path = temp_file.name
+ try:
+ string = ssh.login('server', ssh_config=config_path)
+ raise AssertionError('Should have failed due to no Host.')
+ except TypeError:
+ pass
+
+ def test_ssh_config_wrong_Host(self):
+ ssh = pxssh.pxssh(debug_command_string=True)
+ temp_file = tempfile.NamedTemporaryFile()
+ config_path = temp_file.name
+ temp_file.write(b'Host not-server\n'
+ b'Host also-not-server\n')
+ temp_file.seek(0)
+ try:
+ string = ssh.login('server', ssh_config=config_path)
+ raise AssertionError('Should have failed due to no matching Host.')
+ except TypeError:
+ pass
+
+ def test_ssh_config_no_user(self):
+ ssh = pxssh.pxssh(debug_command_string=True)
+ temp_file = tempfile.NamedTemporaryFile()
+ config_path = temp_file.name
+ temp_file.write(b'Host server\n'
+ b'Host not-server\n')
+ temp_file.seek(0)
+ try:
+ string = ssh.login('server', ssh_config=config_path)
+ raise AssertionError('Should have failed due to no user.')
+ except TypeError:
+ pass
+
+ def test_ssh_config_empty_user(self):
+ ssh = pxssh.pxssh(debug_command_string=True)
+ temp_file = tempfile.NamedTemporaryFile()
+ config_path = temp_file.name
+ temp_file.write(b'Host server\n'
+ b'user \n'
+ b'Host not-server\n')
+ temp_file.seek(0)
+ try:
+ string = ssh.login('server', ssh_config=config_path)
+ raise AssertionError('Should have failed due to empty user.')
+ except TypeError:
+ pass
+
def test_ssh_key_string(self):
ssh = pxssh.pxssh(debug_command_string=True)
confirmation_strings = 0
@@ -105,7 +176,8 @@
assert False, 'String generated from forcing the SSH agent sock is incorrect.'
confirmation_strings = 0
- (temp_file,ssh_key) = tempfile.mkstemp()
+ temp_file = tempfile.NamedTemporaryFile()
+ ssh_key = temp_file.name
confirmation_array = [' -i '+ssh_key]
string = ssh.login('server', 'me', password='s3cret', ssh_key=ssh_key)
for confirmation in confirmation_array:
@@ -115,6 +187,86 @@
if confirmation_strings!=len(confirmation_array):
assert False, 'String generated from adding an SSH key is incorrect.'
+ def test_custom_ssh_cmd_debug(self):
+ ssh = pxssh.pxssh(debug_command_string=True)
+ cipher_string = '-c aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,' \
+ + 'aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,' \
+ + 'aes256-cbc,arcfour'
+ confirmation_strings = 0
+ confirmation_array = [cipher_string, '-2']
+ string = ssh.login('server', 'me', password='s3cret', cmd='ssh ' + cipher_string + ' -2')
+ for confirmation in confirmation_array:
+ if confirmation in string:
+ confirmation_strings+=1
+
+ if confirmation_strings!=len(confirmation_array):
+ assert False, 'String generated for custom ssh client command is incorrect.'
+
+ def test_custom_ssh_cmd_debug(self):
+ ssh = pxssh.pxssh(debug_command_string=True)
+ cipher_string = '-c aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,' \
+ + 'aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,' \
+ + 'aes256-cbc,arcfour'
+ confirmation_strings = 0
+ confirmation_array = [cipher_string, '-2']
+ string = ssh.login('server', 'me', password='s3cret', cmd='ssh ' + cipher_string + ' -2')
+ for confirmation in confirmation_array:
+ if confirmation in string:
+ confirmation_strings+=1
+
+ if confirmation_strings!=len(confirmation_array):
+ assert False, 'String generated for custom ssh client command is incorrect.'
+
+ def test_failed_custom_ssh_cmd_debug(self):
+ ssh = pxssh.pxssh(debug_command_string=True)
+ cipher_string = '-c invalid_cipher'
+ confirmation_strings = 0
+ confirmation_array = [cipher_string, '-2']
+ string = ssh.login('server', 'me', password='s3cret', cmd='ssh ' + cipher_string + ' -2')
+ for confirmation in confirmation_array:
+ if confirmation in string:
+ confirmation_strings+=1
+
+ if confirmation_strings!=len(confirmation_array):
+ assert False, 'String generated for custom ssh client command is incorrect.'
+
+ def test_custom_ssh_cmd(self):
+ try:
+ ssh = pxssh.pxssh()
+ cipher_string = '-c aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,' \
+ + 'aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,' \
+ + 'aes256-cbc,arcfour'
+ result = ssh.login('server', 'me', password='s3cret', cmd='ssh ' + cipher_string + ' -2')
+
+ ssh.PROMPT = r'Closed connection'
+ ssh.sendline('exit')
+ ssh.prompt(timeout=5)
+ string = str(ssh.before) + str(ssh.after)
+
+ if 'Closed connection' not in string:
+ assert False, 'should have logged into Mock SSH client and exited'
+ except pxssh.ExceptionPxssh as e:
+ assert False, 'should not have raised exception, pxssh.ExceptionPxssh'
+ else:
+ pass
+
+ def test_failed_custom_ssh_cmd(self):
+ try:
+ ssh = pxssh.pxssh()
+ cipher_string = '-c invalid_cipher'
+ result = ssh.login('server', 'me', password='s3cret', cmd='ssh ' + cipher_string + ' -2')
+
+ ssh.PROMPT = r'Closed connection'
+ ssh.sendline('exit')
+ ssh.prompt(timeout=5)
+ string = str(ssh.before) + str(ssh.after)
+
+ if 'Closed connection' not in string:
+ assert False, 'should not have completed logging into Mock SSH client and exited'
+ except pxssh.ExceptionPxssh as e:
+ pass
+ else:
+ assert False, 'should have raised exception, pxssh.ExceptionPxssh'
if __name__ == '__main__':
unittest.main()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pexpect-4.6.0/tests/test_replwrap.py new/pexpect-4.7.0/tests/test_replwrap.py
--- old/pexpect-4.6.0/tests/test_replwrap.py 2016-08-21 21:57:33.000000000 +0200
+++ new/pexpect-4.7.0/tests/test_replwrap.py 2019-04-07 03:54:51.000000000 +0200
@@ -24,8 +24,15 @@
def test_bash(self):
bash = replwrap.bash()
- res = bash.run_command("time")
- assert 'real' in res, res
+ res = bash.run_command("alias")
+ assert 'alias' in res, res
+
+ try:
+ bash.run_command('')
+ except ValueError:
+ pass
+ else:
+ assert False, "Didn't raise ValueError for empty input"
def test_pager_as_cat(self):
" PAGER is set to cat, to prevent timeout in ``man sleep``. "
@@ -78,7 +85,7 @@
self.assertEqual(res.strip().splitlines(), ['1 2', '3 4'])
def test_existing_spawn(self):
- child = pexpect.spawn("bash", timeout=5, echo=False, encoding='utf-8')
+ child = pexpect.spawn("bash", timeout=5, encoding='utf-8')
repl = replwrap.REPLWrapper(child, re.compile('[$#]'),
"PS1='{0}' PS2='{1}' "
"PROMPT_COMMAND=''")
1
0