Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-s3fs for openSUSE:Factory 
checked in at 2022-04-28 23:07:46
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-s3fs (Old)
 and      /work/SRC/openSUSE:Factory/.python-s3fs.new.1538 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-s3fs"

Thu Apr 28 23:07:46 2022 rev:13 rq:973235 version:2022.3.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-s3fs/python-s3fs.changes  2022-02-24 
18:24:05.870648407 +0100
+++ /work/SRC/openSUSE:Factory/.python-s3fs.new.1538/python-s3fs.changes        
2022-04-28 23:07:48.936677529 +0200
@@ -1,0 +2,10 @@
+Mon Apr  4 09:01:45 UTC 2022 - John Paul Adrian Glaubitz 
<adrian.glaub...@suse.com>
+
+- Update to 2022.3.0
+  * pre-commit (#612)
+  * aiobotocore 2.2 (#609)
+  * empty ETag (#605)
+  * HTTPClientError retry (#597)
+  * new callbacks support (#590)
+
+-------------------------------------------------------------------

Old:
----
  s3fs-2022.2.0.tar.gz

New:
----
  s3fs-2022.3.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-s3fs.spec ++++++
--- /var/tmp/diff_new_pack.wYen9T/_old  2022-04-28 23:07:49.432678069 +0200
+++ /var/tmp/diff_new_pack.wYen9T/_new  2022-04-28 23:07:49.432678069 +0200
@@ -19,7 +19,7 @@
 %{?!python_module:%define python_module() python3-%{**}}
 %define skip_python2 1
 Name:           python-s3fs
-Version:        2022.2.0
+Version:        2022.3.0
 Release:        0
 Summary:        Python filesystem interface for S3
 License:        BSD-3-Clause

++++++ s3fs-2022.2.0.tar.gz -> s3fs-2022.3.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/s3fs-2022.2.0/.coveragerc 
new/s3fs-2022.3.0/.coveragerc
--- old/s3fs-2022.2.0/.coveragerc       2020-05-01 18:06:15.000000000 +0200
+++ new/s3fs-2022.3.0/.coveragerc       2022-03-29 19:28:02.000000000 +0200
@@ -1,5 +1,5 @@
 [run]
-include = 
+include =
     s3fs/*
 
 omit =
@@ -10,4 +10,3 @@
 
 [html]
 directory = coverage_html_report
-
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/s3fs-2022.2.0/PKG-INFO new/s3fs-2022.3.0/PKG-INFO
--- old/s3fs-2022.2.0/PKG-INFO  2022-02-22 18:52:20.695571000 +0100
+++ new/s3fs-2022.3.0/PKG-INFO  2022-03-31 20:01:37.321205100 +0200
@@ -1,30 +1,11 @@
 Metadata-Version: 2.1
 Name: s3fs
-Version: 2022.2.0
+Version: 2022.3.0
 Summary: Convenient Filesystem interface over S3
 Home-page: http://github.com/fsspec/s3fs/
 Maintainer: Martin Durant
 Maintainer-email: mdur...@continuum.io
 License: BSD
-Description: s3fs
-        ====
-        
-        |Build Status| |Doc Status|
-        
-        S3FS builds on aiobotocore_ to provide a convenient Python filesystem 
interface for S3.
-        
-        View the documentation_ for s3fs.
-        
-        .. _documentation: http://s3fs.readthedocs.io/en/latest/
-        .. _aiobotocore: https://aiobotocore.readthedocs.io/en/latest/
-        
-        .. |Build Status| image:: 
https://github.com/fsspec/s3fs/workflows/CI/badge.svg
-            :target: https://github.com/fsspec/s3fs/actions
-            :alt: Build Status
-        .. |Doc Status| image:: 
https://readthedocs.org/projects/s3fs/badge/?version=latest
-            :target: https://s3fs.readthedocs.io/en/latest/?badge=latest
-            :alt: Documentation Status
-        
 Keywords: s3,boto
 Platform: UNKNOWN
 Classifier: Development Status :: 4 - Beta
@@ -37,3 +18,25 @@
 Requires-Python: >= 3.7
 Provides-Extra: awscli
 Provides-Extra: boto3
+License-File: LICENSE.txt
+
+s3fs
+====
+
+|Build Status| |Doc Status|
+
+S3FS builds on aiobotocore_ to provide a convenient Python filesystem 
interface for S3.
+
+View the documentation_ for s3fs.
+
+.. _documentation: http://s3fs.readthedocs.io/en/latest/
+.. _aiobotocore: https://aiobotocore.readthedocs.io/en/latest/
+
+.. |Build Status| image:: https://github.com/fsspec/s3fs/workflows/CI/badge.svg
+    :target: https://github.com/fsspec/s3fs/actions
+    :alt: Build Status
+.. |Doc Status| image:: 
https://readthedocs.org/projects/s3fs/badge/?version=latest
+    :target: https://s3fs.readthedocs.io/en/latest/?badge=latest
+    :alt: Documentation Status
+
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/s3fs-2022.2.0/docs/source/changelog.rst 
new/s3fs-2022.3.0/docs/source/changelog.rst
--- old/s3fs-2022.2.0/docs/source/changelog.rst 2022-02-22 18:50:58.000000000 
+0100
+++ new/s3fs-2022.3.0/docs/source/changelog.rst 2022-03-31 20:00:49.000000000 
+0200
@@ -1,6 +1,15 @@
 Changelog
 =========
 
+2022.3.0
+--------
+
+- pre-commit (#612)
+- aiobotocore 2.2 (#609)
+- empty ETag (#605)
+- HTTPClientError retry (#597)
+- new callbacks support (#590)
+
 2022.02.0
 ---------
 
@@ -119,7 +128,7 @@
 - Always use multipart uploads when not autocommitting (:pr:`243`) by `Marius 
van Niekerk`_
 - Create ``CONTRIBUTING.md`` (:pr:`248`) by `Jacob Tomlinson`_
 - Use autofunction for ``S3Map`` sphinx autosummary (:pr:`251`) by `James 
Bourbeau`_
-- Miscellaneous doc updates (:pr:`252`) by `James Bourbeau`_ 
+- Miscellaneous doc updates (:pr:`252`) by `James Bourbeau`_
 - Support for Python 3.8 (:pr:`264`) by `Tom Augspurger`_
 - Improved performance for ``isdir`` (:pr:`259`) by `Nate Yoder`_
 * Increased the minimum required version of fsspec to 0.6.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/s3fs-2022.2.0/docs/source/development.rst 
new/s3fs-2022.3.0/docs/source/development.rst
--- old/s3fs-2022.2.0/docs/source/development.rst       2022-02-08 
22:42:09.000000000 +0100
+++ new/s3fs-2022.3.0/docs/source/development.rst       2022-03-29 
19:28:02.000000000 +0200
@@ -7,4 +7,4 @@
 
 Run tests::
 
-    $ pytest
\ No newline at end of file
+    $ pytest
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/s3fs-2022.2.0/docs/source/index.rst 
new/s3fs-2022.3.0/docs/source/index.rst
--- old/s3fs-2022.2.0/docs/source/index.rst     2021-12-28 21:02:35.000000000 
+0100
+++ new/s3fs-2022.3.0/docs/source/index.rst     2022-03-29 19:28:02.000000000 
+0200
@@ -114,6 +114,18 @@
 works, but you might find the implementation interesting.
 
 
+Multiprocessing
+---------------
+
+When using Python's `multiprocessing`, the start method must be set to either
+``spawn`` or ``forkserver``. ``fork`` is not safe to use because of the open 
sockets
+and async thread used by s3fs, and may lead to
+hard-to-find bugs and occasional deadlocks. Read more about the available
+`start methods`.
+
+.. _multiprocessing: https://docs.python.org/3/library/multiprocessing.html
+.. _start methods: 
https://docs.python.org/3/library/multiprocessing.html#contexts-and-start-methods
+
 Limitations
 -----------
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/s3fs-2022.2.0/requirements.txt 
new/s3fs-2022.3.0/requirements.txt
--- old/s3fs-2022.2.0/requirements.txt  2022-02-22 18:51:22.000000000 +0100
+++ new/s3fs-2022.3.0/requirements.txt  2022-03-31 20:00:49.000000000 +0200
@@ -1,3 +1,3 @@
-aiobotocore~=2.1.0
-fsspec==2022.02.0
+aiobotocore~=2.2.0
+fsspec==2022.3.0
 aiohttp<=4
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/s3fs-2022.2.0/s3fs/_version.py 
new/s3fs-2022.3.0/s3fs/_version.py
--- old/s3fs-2022.2.0/s3fs/_version.py  2022-02-22 18:52:20.696371300 +0100
+++ new/s3fs-2022.3.0/s3fs/_version.py  2022-03-31 20:01:37.322401800 +0200
@@ -8,11 +8,11 @@
 
 version_json = '''
 {
- "date": "2022-02-22T12:51:44-0500",
+ "date": "2022-03-31T14:00:38-0400",
  "dirty": false,
  "error": null,
- "full-revisionid": "50bafe4d8766c3b2a4e1fc09669cf02fb2d71454",
- "version": "2022.02.0"
+ "full-revisionid": "c4fb41f7cc2f2aede6bbb7755096c38b9e4cc553",
+ "version": "2022.3.0"
 }
 '''  # END VERSION_JSON
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/s3fs-2022.2.0/s3fs/core.py 
new/s3fs-2022.3.0/s3fs/core.py
--- old/s3fs-2022.2.0/s3fs/core.py      2022-02-08 22:42:09.000000000 +0100
+++ new/s3fs-2022.3.0/s3fs/core.py      2022-03-29 19:28:02.000000000 +0200
@@ -19,7 +19,7 @@
 import botocore
 import aiobotocore.session
 from aiobotocore.config import AioConfig
-from botocore.exceptions import ClientError, ParamValidationError
+from botocore.exceptions import ClientError, HTTPClientError, 
ParamValidationError
 
 from s3fs.errors import translate_boto_error
 from s3fs.utils import S3BucketRegionCache, ParamKwargsHelper, _get_brange, 
FileExpired
@@ -46,7 +46,7 @@
 
 
 MANAGED_COPY_THRESHOLD = 5 * 2**30
-S3_RETRYABLE_ERRORS = (socket.timeout, IncompleteRead)
+S3_RETRYABLE_ERRORS = (socket.timeout, HTTPClientError, IncompleteRead)
 
 if ClientPayloadError is not None:
     S3_RETRYABLE_ERRORS += (ClientPayloadError,)
@@ -1071,7 +1071,7 @@
                     **self.req_kw,
                 )
                 return {
-                    "ETag": out["ETag"],
+                    "ETag": out.get("ETag", ""),
                     "LastModified": out["LastModified"],
                     "size": out["ContentLength"],
                     "name": "/".join([bucket, key]),
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/s3fs-2022.2.0/s3fs/errors.py 
new/s3fs-2022.3.0/s3fs/errors.py
--- old/s3fs-2022.2.0/s3fs/errors.py    2021-03-17 15:40:53.000000000 +0100
+++ new/s3fs-2022.3.0/s3fs/errors.py    2022-03-29 19:28:02.000000000 +0200
@@ -136,14 +136,15 @@
     An instantiated exception ready to be thrown. If the error code isn't
     recognized, an IOError with the original error message is returned.
     """
-    if not hasattr(error, "response"):
-        # non-http error:
+    error_response = getattr(error, "response", None)
+    if error_response is None:
+        # non-http error, or response is None:
         return error
-    code = error.response["Error"].get("Code")
+    code = error_response["Error"].get("Code")
     constructor = ERROR_CODE_TO_EXCEPTION.get(code)
     if constructor:
         if not message:
-            message = error.response["Error"].get("Message", str(error))
+            message = error_response["Error"].get("Message", str(error))
         custom_exc = constructor(message, *args, **kwargs)
     else:
         # No match found, wrap this in an IOError with the appropriate message.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/s3fs-2022.2.0/s3fs/tests/test_s3fs.py 
new/s3fs-2022.3.0/s3fs/tests/test_s3fs.py
--- old/s3fs-2022.2.0/s3fs/tests/test_s3fs.py   2022-02-22 18:51:29.000000000 
+0100
+++ new/s3fs-2022.3.0/s3fs/tests/test_s3fs.py   2022-03-29 20:00:43.000000000 
+0200
@@ -2274,6 +2274,25 @@
     assert d in s3.ls(test_bucket_name)
 
 
+def test_rm_recursive_folder(s3):
+    s3.touch(test_bucket_name + "/sub/file")
+    s3.rm(test_bucket_name + "/sub", recursive=True)
+    assert not s3.exists(test_bucket_name + "/sub/file")
+    assert not s3.exists(test_bucket_name + "/sub")
+
+    s3.touch(test_bucket_name + "/sub/file")
+    s3.touch(test_bucket_name + "/sub/")  # placeholder
+    s3.rm(test_bucket_name + "/sub", recursive=True)
+    assert not s3.exists(test_bucket_name + "/sub/file")
+    assert not s3.exists(test_bucket_name + "/sub")
+
+    s3.touch(test_bucket_name + "/sub/file")
+    s3.rm(test_bucket_name, recursive=True)
+    assert not s3.exists(test_bucket_name + "/sub/file")
+    assert not s3.exists(test_bucket_name + "/sub")
+    assert not s3.exists(test_bucket_name)
+
+
 def test_copy_file_without_etag(s3, monkeypatch):
 
     s3.touch(test_bucket_name + "/copy_tests/file")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/s3fs-2022.2.0/s3fs.egg-info/PKG-INFO 
new/s3fs-2022.3.0/s3fs.egg-info/PKG-INFO
--- old/s3fs-2022.2.0/s3fs.egg-info/PKG-INFO    2022-02-22 18:52:20.000000000 
+0100
+++ new/s3fs-2022.3.0/s3fs.egg-info/PKG-INFO    2022-03-31 20:01:36.000000000 
+0200
@@ -1,30 +1,11 @@
 Metadata-Version: 2.1
 Name: s3fs
-Version: 2022.2.0
+Version: 2022.3.0
 Summary: Convenient Filesystem interface over S3
 Home-page: http://github.com/fsspec/s3fs/
 Maintainer: Martin Durant
 Maintainer-email: mdur...@continuum.io
 License: BSD
-Description: s3fs
-        ====
-        
-        |Build Status| |Doc Status|
-        
-        S3FS builds on aiobotocore_ to provide a convenient Python filesystem 
interface for S3.
-        
-        View the documentation_ for s3fs.
-        
-        .. _documentation: http://s3fs.readthedocs.io/en/latest/
-        .. _aiobotocore: https://aiobotocore.readthedocs.io/en/latest/
-        
-        .. |Build Status| image:: 
https://github.com/fsspec/s3fs/workflows/CI/badge.svg
-            :target: https://github.com/fsspec/s3fs/actions
-            :alt: Build Status
-        .. |Doc Status| image:: 
https://readthedocs.org/projects/s3fs/badge/?version=latest
-            :target: https://s3fs.readthedocs.io/en/latest/?badge=latest
-            :alt: Documentation Status
-        
 Keywords: s3,boto
 Platform: UNKNOWN
 Classifier: Development Status :: 4 - Beta
@@ -37,3 +18,25 @@
 Requires-Python: >= 3.7
 Provides-Extra: awscli
 Provides-Extra: boto3
+License-File: LICENSE.txt
+
+s3fs
+====
+
+|Build Status| |Doc Status|
+
+S3FS builds on aiobotocore_ to provide a convenient Python filesystem 
interface for S3.
+
+View the documentation_ for s3fs.
+
+.. _documentation: http://s3fs.readthedocs.io/en/latest/
+.. _aiobotocore: https://aiobotocore.readthedocs.io/en/latest/
+
+.. |Build Status| image:: https://github.com/fsspec/s3fs/workflows/CI/badge.svg
+    :target: https://github.com/fsspec/s3fs/actions
+    :alt: Build Status
+.. |Doc Status| image:: 
https://readthedocs.org/projects/s3fs/badge/?version=latest
+    :target: https://s3fs.readthedocs.io/en/latest/?badge=latest
+    :alt: Documentation Status
+
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/s3fs-2022.2.0/s3fs.egg-info/requires.txt 
new/s3fs-2022.3.0/s3fs.egg-info/requires.txt
--- old/s3fs-2022.2.0/s3fs.egg-info/requires.txt        2022-02-22 
18:52:20.000000000 +0100
+++ new/s3fs-2022.3.0/s3fs.egg-info/requires.txt        2022-03-31 
20:01:36.000000000 +0200
@@ -1,9 +1,9 @@
-aiobotocore~=2.1.0
-fsspec==2022.02.0
+aiobotocore~=2.2.0
+fsspec==2022.3.0
 aiohttp<=4
 
 [awscli]
-aiobotocore[awscli]~=2.1.0
+aiobotocore[awscli]~=2.2.0
 
 [boto3]
-aiobotocore[boto3]~=2.1.0
+aiobotocore[boto3]~=2.2.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/s3fs-2022.2.0/setup.cfg new/s3fs-2022.3.0/setup.cfg
--- old/s3fs-2022.2.0/setup.cfg 2022-02-22 18:52:20.696058800 +0100
+++ new/s3fs-2022.3.0/setup.cfg 2022-03-31 20:01:37.321910900 +0200
@@ -2,7 +2,7 @@
 long_description = file: README.rst
 
 [versioneer]
-vcs = git
+VCS = git
 style = pep440
 versionfile_source = s3fs/_version.py
 versionfile_build = s3fs/_version.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/s3fs-2022.2.0/setup.py new/s3fs-2022.3.0/setup.py
--- old/s3fs-2022.2.0/setup.py  2022-02-08 22:42:09.000000000 +0100
+++ new/s3fs-2022.3.0/setup.py  2022-03-29 19:28:02.000000000 +0200
@@ -3,37 +3,39 @@
 from setuptools import setup
 import versioneer
 
-with open('requirements.txt') as file:
-    aiobotocore_version_suffix = ''
+with open("requirements.txt") as file:
+    aiobotocore_version_suffix = ""
     for line in file:
-        parts = line.rstrip().split('aiobotocore')
+        parts = line.rstrip().split("aiobotocore")
         if len(parts) == 2:
             aiobotocore_version_suffix = parts[1]
             break
 
-setup(name='s3fs',
-      version=versioneer.get_version(),
-      cmdclass=versioneer.get_cmdclass(),
-      classifiers=[
-          'Development Status :: 4 - Beta',
-          'Intended Audience :: Developers',
-          'License :: OSI Approved :: BSD License',
-          'Operating System :: OS Independent',
-          'Programming Language :: Python :: 3.7',
-          'Programming Language :: Python :: 3.8',
-          'Programming Language :: Python :: 3.9',
-      ],
-      description='Convenient Filesystem interface over S3',
-      url='http://github.com/fsspec/s3fs/',
-      maintainer='Martin Durant',
-      maintainer_email='mdur...@continuum.io',
-      license='BSD',
-      keywords='s3, boto',
-      packages=['s3fs'],
-      python_requires='>= 3.7',
-      install_requires=[open('requirements.txt').read().strip().split('\n')],
-      extras_require={
-          'awscli': [f"aiobotocore[awscli]{aiobotocore_version_suffix}"],
-          'boto3': [f"aiobotocore[boto3]{aiobotocore_version_suffix}"],
-      },
-      zip_safe=False)
+setup(
+    name="s3fs",
+    version=versioneer.get_version(),
+    cmdclass=versioneer.get_cmdclass(),
+    classifiers=[
+        "Development Status :: 4 - Beta",
+        "Intended Audience :: Developers",
+        "License :: OSI Approved :: BSD License",
+        "Operating System :: OS Independent",
+        "Programming Language :: Python :: 3.7",
+        "Programming Language :: Python :: 3.8",
+        "Programming Language :: Python :: 3.9",
+    ],
+    description="Convenient Filesystem interface over S3",
+    url="http://github.com/fsspec/s3fs/";,
+    maintainer="Martin Durant",
+    maintainer_email="mdur...@continuum.io",
+    license="BSD",
+    keywords="s3, boto",
+    packages=["s3fs"],
+    python_requires=">= 3.7",
+    install_requires=[open("requirements.txt").read().strip().split("\n")],
+    extras_require={
+        "awscli": [f"aiobotocore[awscli]{aiobotocore_version_suffix}"],
+        "boto3": [f"aiobotocore[boto3]{aiobotocore_version_suffix}"],
+    },
+    zip_safe=False,
+)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/s3fs-2022.2.0/versioneer.py 
new/s3fs-2022.3.0/versioneer.py
--- old/s3fs-2022.2.0/versioneer.py     2021-12-13 21:26:38.000000000 +0100
+++ new/s3fs-2022.3.0/versioneer.py     2022-03-29 19:28:02.000000000 +0200
@@ -1,4 +1,3 @@
-
 # Version: 0.20
 
 """The Versioneer - like a rocketeer, but for versions.
@@ -303,11 +302,13 @@
         setup_py = os.path.join(root, "setup.py")
         versioneer_py = os.path.join(root, "versioneer.py")
     if not (os.path.exists(setup_py) or os.path.exists(versioneer_py)):
-        err = ("Versioneer was unable to run the project root directory. "
-               "Versioneer requires setup.py to be executed from "
-               "its immediate directory (like 'python setup.py COMMAND'), "
-               "or in a way that lets it use sys.argv[0] to find the root "
-               "(like 'python path/to/setup.py COMMAND').")
+        err = (
+            "Versioneer was unable to run the project root directory. "
+            "Versioneer requires setup.py to be executed from "
+            "its immediate directory (like 'python setup.py COMMAND'), "
+            "or in a way that lets it use sys.argv[0] to find the root "
+            "(like 'python path/to/setup.py COMMAND')."
+        )
         raise VersioneerBadRootError(err)
     try:
         # Certain runtime workflows (setup.py install/develop in a setuptools
@@ -320,8 +321,10 @@
         me_dir = os.path.normcase(os.path.splitext(my_path)[0])
         vsr_dir = os.path.normcase(os.path.splitext(versioneer_py)[0])
         if me_dir != vsr_dir:
-            print("Warning: build in %s is using versioneer.py from %s"
-                  % (os.path.dirname(my_path), versioneer_py))
+            print(
+                "Warning: build in %s is using versioneer.py from %s"
+                % (os.path.dirname(my_path), versioneer_py)
+            )
     except NameError:
         pass
     return root
@@ -367,16 +370,17 @@
 
 def register_vcs_handler(vcs, method):  # decorator
     """Create decorator to mark a method as the handler of a VCS."""
+
     def decorate(f):
         """Store f in HANDLERS[vcs][method]."""
         HANDLERS.setdefault(vcs, {})[method] = f
         return f
+
     return decorate
 
 
 # pylint:disable=too-many-arguments,consider-using-with # noqa
-def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False,
-                env=None):
+def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False, 
env=None):
     """Call the given command(s)."""
     assert isinstance(commands, list)
     process = None
@@ -384,10 +388,13 @@
         try:
             dispcmd = str([command] + args)
             # remember shell=False, so use git.cmd on windows, not just git
-            process = subprocess.Popen([command] + args, cwd=cwd, env=env,
-                                       stdout=subprocess.PIPE,
-                                       stderr=(subprocess.PIPE if hide_stderr
-                                               else None))
+            process = subprocess.Popen(
+                [command] + args,
+                cwd=cwd,
+                env=env,
+                stdout=subprocess.PIPE,
+                stderr=(subprocess.PIPE if hide_stderr else None),
+            )
             break
         except EnvironmentError:
             e = sys.exc_info()[1]
@@ -410,7 +417,9 @@
     return stdout, process.returncode
 
 
-LONG_VERSION_PY['git'] = r'''
+LONG_VERSION_PY[
+    "git"
+] = r'''
 # This file helps to compute a version number in source trees obtained from
 # git-archive tarball (such as those provided by githubs download-from-tag
 # feature). Distribution tarballs (built by setup.py sdist) and build
@@ -1091,7 +1100,7 @@
     # starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of
     # just "foo-1.0". If we see a "tag: " prefix, prefer those.
     TAG = "tag: "
-    tags = {r[len(TAG):] for r in refs if r.startswith(TAG)}
+    tags = {r[len(TAG) :] for r in refs if r.startswith(TAG)}
     if not tags:
         # Either we're using git < 1.8.3, or there really are no tags. We use
         # a heuristic: assume all version tags have a digit. The old git %d
@@ -1100,7 +1109,7 @@
         # between branches and tags. By ignoring refnames without digits, we
         # filter out many common branch names like "release" and
         # "stabilization", as well as "HEAD" and "main".
-        tags = {r for r in refs if re.search(r'\d', r)}
+        tags = {r for r in refs if re.search(r"\d", r)}
         if verbose:
             print("discarding '%s', no digits" % ",".join(refs - tags))
     if verbose:
@@ -1108,24 +1117,31 @@
     for ref in sorted(tags):
         # sorting will prefer e.g. "2.0" over "2.0rc1"
         if ref.startswith(tag_prefix):
-            r = ref[len(tag_prefix):]
+            r = ref[len(tag_prefix) :]
             # Filter out refs that exactly match prefix or that don't start
             # with a number once the prefix is stripped (mostly a concern
             # when prefix is '')
-            if not re.match(r'\d', r):
+            if not re.match(r"\d", r):
                 continue
             if verbose:
                 print("picking %s" % r)
-            return {"version": r,
-                    "full-revisionid": keywords["full"].strip(),
-                    "dirty": False, "error": None,
-                    "date": date}
+            return {
+                "version": r,
+                "full-revisionid": keywords["full"].strip(),
+                "dirty": False,
+                "error": None,
+                "date": date,
+            }
     # no suitable tags, so version is "0+unknown", but full hex is still there
     if verbose:
         print("no suitable tags, using unknown + full revision id")
-    return {"version": "0+unknown",
-            "full-revisionid": keywords["full"].strip(),
-            "dirty": False, "error": "no suitable tags", "date": None}
+    return {
+        "version": "0+unknown",
+        "full-revisionid": keywords["full"].strip(),
+        "dirty": False,
+        "error": "no suitable tags",
+        "date": None,
+    }
 
 
 @register_vcs_handler("git", "pieces_from_vcs")
@@ -1140,8 +1156,7 @@
     if sys.platform == "win32":
         GITS = ["git.cmd", "git.exe"]
 
-    _, rc = runner(GITS, ["rev-parse", "--git-dir"], cwd=root,
-                   hide_stderr=True)
+    _, rc = runner(GITS, ["rev-parse", "--git-dir"], cwd=root, 
hide_stderr=True)
     if rc != 0:
         if verbose:
             print("Directory %s not under git control" % root)
@@ -1149,10 +1164,19 @@
 
     # if there is a tag matching tag_prefix, this yields TAG-NUM-gHEX[-dirty]
     # if there isn't one, this yields HEX[-dirty] (no NUM)
-    describe_out, rc = runner(GITS, ["describe", "--tags", "--dirty",
-                                     "--always", "--long",
-                                     "--match", "%s*" % tag_prefix],
-                              cwd=root)
+    describe_out, rc = runner(
+        GITS,
+        [
+            "describe",
+            "--tags",
+            "--dirty",
+            "--always",
+            "--long",
+            "--match",
+            "%s*" % tag_prefix,
+        ],
+        cwd=root,
+    )
     # --long was added in git-1.5.5
     if describe_out is None:
         raise NotThisMethod("'git describe' failed")
@@ -1167,8 +1191,7 @@
     pieces["short"] = full_out[:7]  # maybe improved later
     pieces["error"] = None
 
-    branch_name, rc = runner(GITS, ["rev-parse", "--abbrev-ref", "HEAD"],
-                             cwd=root)
+    branch_name, rc = runner(GITS, ["rev-parse", "--abbrev-ref", "HEAD"], 
cwd=root)
     # --abbrev-ref was added in git-1.6.3
     if rc != 0 or branch_name is None:
         raise NotThisMethod("'git rev-parse --abbrev-ref' returned error")
@@ -1208,17 +1231,16 @@
     dirty = git_describe.endswith("-dirty")
     pieces["dirty"] = dirty
     if dirty:
-        git_describe = git_describe[:git_describe.rindex("-dirty")]
+        git_describe = git_describe[: git_describe.rindex("-dirty")]
 
     # now we have TAG-NUM-gHEX or HEX
 
     if "-" in git_describe:
         # TAG-NUM-gHEX
-        mo = re.search(r'^(.+)-(\d+)-g([0-9a-f]+)$', git_describe)
+        mo = re.search(r"^(.+)-(\d+)-g([0-9a-f]+)$", git_describe)
         if not mo:
             # unparsable. Maybe git-describe is misbehaving?
-            pieces["error"] = ("unable to parse git-describe output: '%s'"
-                               % describe_out)
+            pieces["error"] = "unable to parse git-describe output: '%s'" % 
describe_out
             return pieces
 
         # tag
@@ -1227,10 +1249,12 @@
             if verbose:
                 fmt = "tag '%s' doesn't start with prefix '%s'"
                 print(fmt % (full_tag, tag_prefix))
-            pieces["error"] = ("tag '%s' doesn't start with prefix '%s'"
-                               % (full_tag, tag_prefix))
+            pieces["error"] = "tag '%s' doesn't start with prefix '%s'" % (
+                full_tag,
+                tag_prefix,
+            )
             return pieces
-        pieces["closest-tag"] = full_tag[len(tag_prefix):]
+        pieces["closest-tag"] = full_tag[len(tag_prefix) :]
 
         # distance: number of commits since tag
         pieces["distance"] = int(mo.group(2))
@@ -1303,15 +1327,21 @@
     for _ in range(3):
         dirname = os.path.basename(root)
         if dirname.startswith(parentdir_prefix):
-            return {"version": dirname[len(parentdir_prefix):],
-                    "full-revisionid": None,
-                    "dirty": False, "error": None, "date": None}
+            return {
+                "version": dirname[len(parentdir_prefix) :],
+                "full-revisionid": None,
+                "dirty": False,
+                "error": None,
+                "date": None,
+            }
         rootdirs.append(root)
         root = os.path.dirname(root)  # up a level
 
     if verbose:
-        print("Tried directories %s but none started with prefix %s" %
-              (str(rootdirs), parentdir_prefix))
+        print(
+            "Tried directories %s but none started with prefix %s"
+            % (str(rootdirs), parentdir_prefix)
+        )
     raise NotThisMethod("rootdir doesn't start with parentdir_prefix")
 
 
@@ -1340,11 +1370,13 @@
             contents = f.read()
     except EnvironmentError:
         raise NotThisMethod("unable to read _version.py")
-    mo = re.search(r"version_json = '''\n(.*)'''  # END VERSION_JSON",
-                   contents, re.M | re.S)
+    mo = re.search(
+        r"version_json = '''\n(.*)'''  # END VERSION_JSON", contents, re.M | 
re.S
+    )
     if not mo:
-        mo = re.search(r"version_json = '''\r\n(.*)'''  # END VERSION_JSON",
-                       contents, re.M | re.S)
+        mo = re.search(
+            r"version_json = '''\r\n(.*)'''  # END VERSION_JSON", contents, 
re.M | re.S
+        )
     if not mo:
         raise NotThisMethod("no version_json in _version.py")
     return json.loads(mo.group(1))
@@ -1353,8 +1385,7 @@
 def write_to_version_file(filename, versions):
     """Write the given version number to the given _version.py file."""
     os.unlink(filename)
-    contents = json.dumps(versions, sort_keys=True,
-                          indent=1, separators=(",", ": "))
+    contents = json.dumps(versions, sort_keys=True, indent=1, separators=(",", 
": "))
     with open(filename, "w") as f:
         f.write(SHORT_VERSION_PY % contents)
 
@@ -1386,8 +1417,7 @@
                 rendered += ".dirty"
     else:
         # exception #1
-        rendered = "0+untagged.%d.g%s" % (pieces["distance"],
-                                          pieces["short"])
+        rendered = "0+untagged.%d.g%s" % (pieces["distance"], pieces["short"])
         if pieces["dirty"]:
             rendered += ".dirty"
     return rendered
@@ -1416,8 +1446,7 @@
         rendered = "0"
         if pieces["branch"] != "main":
             rendered += ".dev0"
-        rendered += "+untagged.%d.g%s" % (pieces["distance"],
-                                          pieces["short"])
+        rendered += "+untagged.%d.g%s" % (pieces["distance"], pieces["short"])
         if pieces["dirty"]:
             rendered += ".dirty"
     return rendered
@@ -1560,11 +1589,13 @@
 def render(pieces, style):
     """Render the given version pieces into the requested style."""
     if pieces["error"]:
-        return {"version": "unknown",
-                "full-revisionid": pieces.get("long"),
-                "dirty": None,
-                "error": pieces["error"],
-                "date": None}
+        return {
+            "version": "unknown",
+            "full-revisionid": pieces.get("long"),
+            "dirty": None,
+            "error": pieces["error"],
+            "date": None,
+        }
 
     if not style or style == "default":
         style = "pep440"  # the default
@@ -1588,9 +1619,13 @@
     else:
         raise ValueError("unknown style '%s'" % style)
 
-    return {"version": rendered, "full-revisionid": pieces["long"],
-            "dirty": pieces["dirty"], "error": None,
-            "date": pieces.get("date")}
+    return {
+        "version": rendered,
+        "full-revisionid": pieces["long"],
+        "dirty": pieces["dirty"],
+        "error": None,
+        "date": pieces.get("date"),
+    }
 
 
 class VersioneerBadRootError(Exception):
@@ -1613,8 +1648,9 @@
     handlers = HANDLERS.get(cfg.VCS)
     assert handlers, "unrecognized VCS '%s'" % cfg.VCS
     verbose = verbose or cfg.verbose
-    assert cfg.versionfile_source is not None, \
-        "please set versioneer.versionfile_source"
+    assert (
+        cfg.versionfile_source is not None
+    ), "please set versioneer.versionfile_source"
     assert cfg.tag_prefix is not None, "please set versioneer.tag_prefix"
 
     versionfile_abs = os.path.join(root, cfg.versionfile_source)
@@ -1668,9 +1704,13 @@
     if verbose:
         print("unable to compute version")
 
-    return {"version": "0+unknown", "full-revisionid": None,
-            "dirty": None, "error": "unable to compute version",
-            "date": None}
+    return {
+        "version": "0+unknown",
+        "full-revisionid": None,
+        "dirty": None,
+        "error": "unable to compute version",
+        "date": None,
+    }
 
 
 def get_version():
@@ -1723,6 +1763,7 @@
             print(" date: %s" % vers.get("date"))
             if vers["error"]:
                 print(" error: %s" % vers["error"])
+
     cmds["version"] = cmd_version
 
     # we override "build_py" in both distutils and setuptools
@@ -1741,8 +1782,8 @@
     #  setup.py egg_info -> ?
 
     # we override different "build_py" commands for both environments
-    if 'build_py' in cmds:
-        _build_py = cmds['build_py']
+    if "build_py" in cmds:
+        _build_py = cmds["build_py"]
     elif "setuptools" in sys.modules:
         from setuptools.command.build_py import build_py as _build_py
     else:
@@ -1757,14 +1798,14 @@
             # now locate _version.py in the new build/ directory and replace
             # it with an updated value
             if cfg.versionfile_build:
-                target_versionfile = os.path.join(self.build_lib,
-                                                  cfg.versionfile_build)
+                target_versionfile = os.path.join(self.build_lib, 
cfg.versionfile_build)
                 print("UPDATING %s" % target_versionfile)
                 write_to_version_file(target_versionfile, versions)
+
     cmds["build_py"] = cmd_build_py
 
-    if 'build_ext' in cmds:
-        _build_ext = cmds['build_ext']
+    if "build_ext" in cmds:
+        _build_ext = cmds["build_ext"]
     elif "setuptools" in sys.modules:
         from setuptools.command.build_ext import build_ext as _build_ext
     else:
@@ -1784,14 +1825,15 @@
                 return
             # now locate _version.py in the new build/ directory and replace
             # it with an updated value
-            target_versionfile = os.path.join(self.build_lib,
-                                              cfg.versionfile_build)
+            target_versionfile = os.path.join(self.build_lib, 
cfg.versionfile_build)
             print("UPDATING %s" % target_versionfile)
             write_to_version_file(target_versionfile, versions)
+
     cmds["build_ext"] = cmd_build_ext
 
     if "cx_Freeze" in sys.modules:  # cx_freeze enabled?
         from cx_Freeze.dist import build_exe as _build_exe
+
         # nczeczulin reports that py2exe won't like the pep440-style string
         # as FILEVERSION, but it can be used for PRODUCTVERSION, e.g.
         # setup(console=[{
@@ -1812,17 +1854,21 @@
                 os.unlink(target_versionfile)
                 with open(cfg.versionfile_source, "w") as f:
                     LONG = LONG_VERSION_PY[cfg.VCS]
-                    f.write(LONG %
-                            {"DOLLAR": "$",
-                             "STYLE": cfg.style,
-                             "TAG_PREFIX": cfg.tag_prefix,
-                             "PARENTDIR_PREFIX": cfg.parentdir_prefix,
-                             "VERSIONFILE_SOURCE": cfg.versionfile_source,
-                             })
+                    f.write(
+                        LONG
+                        % {
+                            "DOLLAR": "$",
+                            "STYLE": cfg.style,
+                            "TAG_PREFIX": cfg.tag_prefix,
+                            "PARENTDIR_PREFIX": cfg.parentdir_prefix,
+                            "VERSIONFILE_SOURCE": cfg.versionfile_source,
+                        }
+                    )
+
         cmds["build_exe"] = cmd_build_exe
         del cmds["build_py"]
 
-    if 'py2exe' in sys.modules:  # py2exe enabled?
+    if "py2exe" in sys.modules:  # py2exe enabled?
         from py2exe.distutils_buildexe import py2exe as _py2exe
 
         class cmd_py2exe(_py2exe):
@@ -1838,18 +1884,22 @@
                 os.unlink(target_versionfile)
                 with open(cfg.versionfile_source, "w") as f:
                     LONG = LONG_VERSION_PY[cfg.VCS]
-                    f.write(LONG %
-                            {"DOLLAR": "$",
-                             "STYLE": cfg.style,
-                             "TAG_PREFIX": cfg.tag_prefix,
-                             "PARENTDIR_PREFIX": cfg.parentdir_prefix,
-                             "VERSIONFILE_SOURCE": cfg.versionfile_source,
-                             })
+                    f.write(
+                        LONG
+                        % {
+                            "DOLLAR": "$",
+                            "STYLE": cfg.style,
+                            "TAG_PREFIX": cfg.tag_prefix,
+                            "PARENTDIR_PREFIX": cfg.parentdir_prefix,
+                            "VERSIONFILE_SOURCE": cfg.versionfile_source,
+                        }
+                    )
+
         cmds["py2exe"] = cmd_py2exe
 
     # we override different "sdist" commands for both environments
-    if 'sdist' in cmds:
-        _sdist = cmds['sdist']
+    if "sdist" in cmds:
+        _sdist = cmds["sdist"]
     elif "setuptools" in sys.modules:
         from setuptools.command.sdist import sdist as _sdist
     else:
@@ -1874,8 +1924,10 @@
             # updated value
             target_versionfile = os.path.join(base_dir, cfg.versionfile_source)
             print("UPDATING %s" % target_versionfile)
-            write_to_version_file(target_versionfile,
-                                  self._versioneer_generated_versions)
+            write_to_version_file(
+                target_versionfile, self._versioneer_generated_versions
+            )
+
     cmds["sdist"] = cmd_sdist
 
     return cmds
@@ -1935,11 +1987,13 @@
     root = get_root()
     try:
         cfg = get_config_from_root(root)
-    except (EnvironmentError, configparser.NoSectionError,
-            configparser.NoOptionError) as e:
+    except (
+        EnvironmentError,
+        configparser.NoSectionError,
+        configparser.NoOptionError,
+    ) as e:
         if isinstance(e, (EnvironmentError, configparser.NoSectionError)):
-            print("Adding sample versioneer config to setup.cfg",
-                  file=sys.stderr)
+            print("Adding sample versioneer config to setup.cfg", 
file=sys.stderr)
             with open(os.path.join(root, "setup.cfg"), "a") as f:
                 f.write(SAMPLE_CONFIG)
         print(CONFIG_ERROR, file=sys.stderr)
@@ -1948,15 +2002,18 @@
     print(" creating %s" % cfg.versionfile_source)
     with open(cfg.versionfile_source, "w") as f:
         LONG = LONG_VERSION_PY[cfg.VCS]
-        f.write(LONG % {"DOLLAR": "$",
-                        "STYLE": cfg.style,
-                        "TAG_PREFIX": cfg.tag_prefix,
-                        "PARENTDIR_PREFIX": cfg.parentdir_prefix,
-                        "VERSIONFILE_SOURCE": cfg.versionfile_source,
-                        })
+        f.write(
+            LONG
+            % {
+                "DOLLAR": "$",
+                "STYLE": cfg.style,
+                "TAG_PREFIX": cfg.tag_prefix,
+                "PARENTDIR_PREFIX": cfg.parentdir_prefix,
+                "VERSIONFILE_SOURCE": cfg.versionfile_source,
+            }
+        )
 
-    ipy = os.path.join(os.path.dirname(cfg.versionfile_source),
-                       "__init__.py")
+    ipy = os.path.join(os.path.dirname(cfg.versionfile_source), "__init__.py")
     if os.path.exists(ipy):
         try:
             with open(ipy, "r") as f:
@@ -2004,8 +2061,10 @@
     else:
         print(" 'versioneer.py' already in MANIFEST.in")
     if cfg.versionfile_source not in simple_includes:
-        print(" appending versionfile_source ('%s') to MANIFEST.in" %
-              cfg.versionfile_source)
+        print(
+            " appending versionfile_source ('%s') to MANIFEST.in"
+            % cfg.versionfile_source
+        )
         with open(manifest_in, "a") as f:
             f.write("include %s\n" % cfg.versionfile_source)
     else:

Reply via email to