Ver Fonte

Sweep stale Py2.7 / setup.py references from docs and source

Update README badge URLs and table header from py3.8 to py3.13 so they
match the filenames the integration-cloud workflow writes to the gist.

Refresh docs to reflect the modern environment:
- install.rst: prerequisite is Python 3.13.
- testing.rst: tox envs are py3.13-*; replace the gone `setup.py test`
  section with pytest equivalents.
- release_process.rst: dependencies live in pyproject.toml; build with
  `python -m build`; CI is GitHub Actions, not Travis; drop six.
- provider_development.rst: tox env is py3.13; new provider deps go in
  pyproject.toml under [project.optional-dependencies].
- troubleshooting.rst: generalize the macOS Python 3.6 cert path.

Source cleanups:
- openstack/resources.py: drop the urllib.parse/urlparse try/except shim.
- gcp/helpers.py: drop "required for Python 2.7" comments (the str()
  wrappers remain — e.content is bytes, casts are still useful).
- tests/__init__.py and tests/test_compute_service.py: drop py27-only
  invocation guidance and the u"" string-format workaround.
Nuwan Goonasekera há 1 dia atrás
pai
commit
0d604fc044

+ 23 - 23
README.rst

@@ -29,34 +29,34 @@ Build Status Tests
    :target: https://pypistats.org/packages/cloudbridge
    :alt: Download stats
 
-.. |aws-py38| image:: https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/nuwang/d354f151eb8c9752da13e6dec012fb07/raw/cloudbridge_py3.8_aws.json
-              :target: https://github.com/CloudVE/cloudbridge/actions/
+.. |aws-py313| image:: https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/nuwang/d354f151eb8c9752da13e6dec012fb07/raw/cloudbridge_py3.13_aws.json
+               :target: https://github.com/CloudVE/cloudbridge/actions/
 
-.. |azure-py38| image:: https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/nuwang/d354f151eb8c9752da13e6dec012fb07/raw/cloudbridge_py3.8_azure.json
-                :target: https://github.com/CloudVE/cloudbridge/actions/
+.. |azure-py313| image:: https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/nuwang/d354f151eb8c9752da13e6dec012fb07/raw/cloudbridge_py3.13_azure.json
+                 :target: https://github.com/CloudVE/cloudbridge/actions/
 
-.. |gcp-py38| image:: https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/nuwang/d354f151eb8c9752da13e6dec012fb07/raw/cloudbridge_py3.8_gcp.json
-              :target: https://github.com/CloudVE/cloudbridge/actions/
+.. |gcp-py313| image:: https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/nuwang/d354f151eb8c9752da13e6dec012fb07/raw/cloudbridge_py3.13_gcp.json
+               :target: https://github.com/CloudVE/cloudbridge/actions/
+
+.. |mock-py313| image:: https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/nuwang/d354f151eb8c9752da13e6dec012fb07/raw/cloudbridge_py3.13_mock.json
+               :target: https://github.com/CloudVE/cloudbridge/actions/
 
-.. |mock-py38| image:: https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/nuwang/d354f151eb8c9752da13e6dec012fb07/raw/cloudbridge_py3.8_mock.json
+.. |os-py313| image:: https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/nuwang/d354f151eb8c9752da13e6dec012fb07/raw/cloudbridge_py3.13_openstack.json
               :target: https://github.com/CloudVE/cloudbridge/actions/
 
-.. |os-py38| image:: https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/nuwang/d354f151eb8c9752da13e6dec012fb07/raw/cloudbridge_py3.8_openstack.json
-             :target: https://github.com/CloudVE/cloudbridge/actions/
-
-+---------------------------+----------------+
-| **Provider/Environment**  | **Python 3.8** |
-+---------------------------+----------------+
-| **Amazon Web Services**   | |aws-py38|     |
-+---------------------------+----------------+
-| **Google Cloud Platform** | |gcp-py38|     |
-+---------------------------+----------------+
-| **Microsoft Azure**       | |azure-py38|   |
-+---------------------------+----------------+
-| **OpenStack**             | |os-py38|      |
-+---------------------------+----------------+
-| **Mock Provider**         | |mock-py38|    |
-+---------------------------+----------------+
++---------------------------+-----------------+
+| **Provider/Environment**  | **Python 3.13** |
++---------------------------+-----------------+
+| **Amazon Web Services**   | |aws-py313|     |
++---------------------------+-----------------+
+| **Google Cloud Platform** | |gcp-py313|     |
++---------------------------+-----------------+
+| **Microsoft Azure**       | |azure-py313|   |
++---------------------------+-----------------+
+| **OpenStack**             | |os-py313|      |
++---------------------------+-----------------+
+| **Mock Provider**         | |mock-py313|    |
++---------------------------+-----------------+
 
 Installation
 ~~~~~~~~~~~~

+ 0 - 6
cloudbridge/providers/gcp/helpers.py

@@ -41,7 +41,6 @@ def __if_fingerprint_differs(e):
     if isinstance(e, HttpError):
         expected_message = 'Supplied fingerprint does not match current ' \
                            'metadata fingerprint.'
-        # str wrapper required for Python 2.7
         if expected_message in str(e.content):
             return True
     return False
@@ -155,7 +154,6 @@ def __if_label_fingerprint_differs(e):
     if isinstance(e, HttpError):
         expected_message = 'Labels fingerprint either invalid or ' \
                            'resource labels have changed'
-        # str wrapper required for Python 2.7
         if expected_message in str(e.content):
             return True
     return False
@@ -169,10 +167,6 @@ def __if_label_fingerprint_differs(e):
 def change_label(resource, key, value, res_att, request):
     resource.assert_valid_resource_label(value)
     labels = getattr(resource, res_att).get("labels", {})
-    # The returned value from above command yields a unicode dict key, which
-    # cannot be simply cast into a str for py2 so pop the key and re-add it
-    # The casting needs to be done for all labels, as to support both
-    # description and label setting
     labels[key] = str(value)
     for k in list(labels):
         labels[str(k)] = str(labels.pop(k))

+ 2 - 7
cloudbridge/providers/openstack/resources.py

@@ -7,14 +7,9 @@ import logging
 import os
 import re
 
-try:
-    from urllib.parse import urlparse
-    from urllib.parse import urljoin
-except ImportError:  # python 2
-    from urlparse import urlparse
-    from urlparse import urljoin
-
 from datetime import datetime
+from urllib.parse import urljoin
+from urllib.parse import urlparse
 
 from keystoneclient.v3.regions import Region
 

+ 1 - 2
docs/topics/install.rst

@@ -1,8 +1,7 @@
 Installation
 ============
 
-**Prerequisites**: CloudBridge runs on Python 2.7 and higher. Python 3 is
-recommended.
+**Prerequisites**: CloudBridge requires Python 3.13 or higher.
 
 We highly recommend installing CloudBridge in a
 `virtualenv <http://virtualenv.readthedocs.org/>`_. Creating a new virtualenv

+ 9 - 7
docs/topics/provider_development.rst

@@ -45,12 +45,12 @@ This only requires that you register the provider's ID in the ``ProviderList``.
 Add GCP to the ``ProviderList`` class in ``cloudbridge/cloud/factory.py``.
 
 
-5. Run the test suite. We will get the tests passing on py27 first.
+5. Run the test suite.
 
 .. code-block:: bash
 
     export CB_TEST_PROVIDER=gcp
-    tox -e py27
+    tox -e py3.13
 
 You should see the tests fail with the following message:
 
@@ -195,13 +195,15 @@ tests pass.
     is up to the implementor, a general design we have followed is to have the
     cloud connection globally available within the provider.
 
-To add the sdk, we edit CloudBridge's main ``setup.py`` and list the
-dependencies.
+To add the sdk, we edit CloudBridge's main ``pyproject.toml`` and add the
+provider's dependencies under ``[project.optional-dependencies]``.
 
-.. code-block:: python
+.. code-block:: toml
 
-    gcp_reqs = ['google-api-python-client==1.4.2']
-    full_reqs = base_reqs + aws_reqs + openstack_reqs + gcp_reqs
+    [project.optional-dependencies]
+    gcp = [
+        "google-api-python-client>=2.0,<3.0.0",
+    ]
 
 We will also register the provider in ``cloudbridge/cloud/factory.py``'s
 provider list.

+ 7 - 7
docs/topics/release_process.rst

@@ -1,28 +1,28 @@
 Release Process
 ~~~~~~~~~~~~~~~
 
-1. Make sure `all tests pass <https://travis-ci.org/CloudVE/cloudbridge>`_.
+1. Make sure all tests pass on the `GitHub Actions workflows
+   <https://github.com/CloudVE/cloudbridge/actions>`_.
 
 2. Increment version number in ``cloudbridge/__init__.py`` as per
    `semver rules <https://semver.org/>`_.
 
-3. Freeze all library dependencies in ``setup.py`` and commit.
+3. Freeze all library dependencies in ``pyproject.toml`` and commit.
    The version numbers can be a range with the upper limit being the latest
    known working version, and the lowest being the last known working version.
 
    In general, our strategy is to make provider sdk libraries fixed within
    relatively known compatibility ranges, so that we reduce the chances of
    breakage. If someone uses CloudBridge, presumably, they do not use the SDKs
-   directly. For all other libraries, especially, general purpose libraries
-   (e.g. ``six``), our strategy is to make compatibility as broad and
-   unrestricted as possible.
+   directly. For all other general purpose libraries, our strategy is to make
+   compatibility as broad and unrestricted as possible.
 
 4. Add release notes to ``CHANGELOG.rst``. Also add last commit hash to
    changelog. List of commits can be obtained using
    ``git shortlog <last release hash>..HEAD``
 
 5. Release to PyPi.
-   (make sure you have run `pip install wheel twine`)
+   (make sure you have run ``pip install build twine``)
    First, test release with PyPI staging server as described in:
    https://hynek.me/articles/sharing-your-labor-of-love-pypi-quick-and-dirty/
 
@@ -32,7 +32,7 @@ Release Process
 
    # remove stale files or wheel might package them
    rm -r build dist
-   python setup.py sdist bdist_wheel
+   python -m build
    twine upload -r pypi dist/cloudbridge-3.0.0*
 
 6. Tag release and make a GitHub release.

+ 9 - 12
docs/topics/testing.rst

@@ -40,10 +40,9 @@ This will run all the tests for all the environments defined in file
 
 Specific environment and infrastructure
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-If you’d like to run the tests on a specific environment only, say Python 2.7,
-against a specific infrastructure, say aws, use a command like this:
-``tox -e py27-aws``. The available provider names are listed in the
-`ProviderList`_ class (e.g., ``aws`` or ``openstack``).
+To run the tests against a specific infrastructure, say aws, use a command
+like this: ``tox -e py3.13-aws``. The available provider names are listed in
+the `ProviderList`_ class (e.g., ``aws`` or ``openstack``).
 
 Specific test cases
 ~~~~~~~~~~~~~~~~~~~~
@@ -51,19 +50,17 @@ You can run a specific test case, as follows:
 ``tox -- tests/test_image_service.py:CloudImageServiceTestCase.test_create_and_list_imag``
 
 It can also be restricted to a particular environment as follows:
-``tox -e "py27-aws" -- tests/test_cloud_factory.py:CloudFactoryTestCase``
+``tox -e "py3.13-aws" -- tests/test_cloud_factory.py:CloudFactoryTestCase``
 
-See nosetest documentation for other parameters that can be passed in.
-
-Using unittest directly
+Running pytest directly
 ~~~~~~~~~~~~~~~~~~~~~~~
 You can also run the tests against your active virtual environment directly
-with ``python setup.py test``. You will need to set the ``CB_TEST_PROVIDER``
+with ``pytest tests/``. You will need to set the ``CB_TEST_PROVIDER``
 environment variable prior to running the tests, or they will default to
 ``CB_TEST_PROVIDER=aws``.
 
-You can also run a specific test case, as follows:
-``python setup.py test -s tests.test_cloud_factory.CloudFactoryTestCase``
+To run a specific test case:
+``pytest tests/test_cloud_factory.py::CloudFactoryTestCase``
 
 Using a mock provider
 ~~~~~~~~~~~~~~~~~~~~~
@@ -74,7 +71,7 @@ will simulate AWS resources. You can use ``CB_TEST_PROVIDER=mock`` to run tests
 against the mock provider only, which will provide faster feedback times.
 
 Alternatively you can run the mock tests through tox.
-``tox -e "py27-mock"``
+``tox -e "py3.13-mock"``
 
 .. _design goals: https://github.com/CloudVE/cloudbridge/
    blob/main/README.rst

+ 8 - 9
docs/topics/troubleshooting.rst

@@ -5,18 +5,17 @@ macOS Issues
 ------------
 
 * If you are getting an error message like so: ``Authentication with cloud provider failed: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:749)``
-  then this indicates that you are probably using a newer version of Python on
-  macOS. Starting with Python 3.6, the Python installer includes its own version
-  of OpenSSL and it no longer uses the system trusted certificate keychains.
+  then this indicates that you are probably using a Python distribution on
+  macOS whose installer ships its own OpenSSL and does not use the system
+  trusted certificate keychain.
 
-  Python 3.6 includes a script that can install a bundle of root certificates
-  from ``certifi``.  To install this bundle execute the following:
+  The python.org installer includes a script that installs a bundle of root
+  certificates from ``certifi``.  Run the ``Install Certificates.command``
+  script bundled with your Python install, for example:
 
   .. code-block:: bash
 
-    cd /Applications/Python\ 3.6/
-    sudo ./Install\ Certificates.command
+    /Applications/Python\ 3.13/Install\ Certificates.command
 
   For more information see `this StackOverflow
-  answer <https://stackoverflow.com/a/42583411/1419499>`_ and the `Python 3.6
-  Release Notes <https://www.python.org/downloads/release/python-360/>`_.
+  answer <https://stackoverflow.com/a/42583411/1419499>`_.

+ 1 - 4
tests/__init__.py

@@ -1,4 +1 @@
-"""
-Use ``python setup.py test`` to run these unit tests (alternatively, use
-``python -m unittest test``).
-"""
+"""Run these unit tests with ``pytest tests/`` or via ``tox``."""

+ 1 - 2
tests/test_compute_service.py

@@ -147,8 +147,7 @@ class CloudComputeServiceTestCase(ProviderTestBase):
             ip_address = test_instance.public_ips[0] \
                 if test_instance.public_ips and test_instance.public_ips[0] \
                 else ip_private
-            # Convert to unicode for py27 compatibility with ipaddress()
-            ip_address = u"{}".format(ip_address)
+            ip_address = str(ip_address)
             self.assertIsNotNone(
                 ip_address,
                 "Instance must have either a public IP or a private IP")