Просмотр исходного кода

Merge pull request #347 from CloudVE/fix-cryptography-dependency

Declare cryptography as a dependency, and guard bare installs
Nuwan Goonasekera 2 дней назад
Родитель
Сommit
093ef66959
3 измененных файлов с 77 добавлено и 0 удалено
  1. 48 0
      .github/workflows/integration.yaml
  2. 24 0
      CHANGELOG.rst
  3. 5 0
      pyproject.toml

+ 48 - 0
.github/workflows/integration.yaml

@@ -63,6 +63,54 @@ jobs:
       - name: Run mypy
         run: tox -e mypy
 
+  bare-install:
+    name: Bare install imports
+    runs-on: ubuntu-latest
+    # Every test environment installs the [dev] extra, which drags in the
+    # provider SDKs and their transitive dependencies, so the suite passes
+    # happily against a package whose declared dependencies are incomplete.
+    # cloudbridge 4.3.1 and 4.4.0 both shipped unable to import
+    # cloudbridge.base.resources from a plain `pip install cloudbridge`,
+    # because base.helpers imports cryptography at module scope and nothing
+    # declared it. Install the built wheel on its own and import the modules
+    # a user reaches for first.
+    steps:
+      - name: Checkout code
+        uses: actions/checkout@v6
+        with:
+          persist-credentials: false
+
+      - name: Setup Python
+        uses: actions/setup-python@v6
+        with:
+          # The floor, since a missing dependency is likelier to be satisfied
+          # by chance on a newer interpreter's richer wheel set.
+          python-version: '3.10'
+
+      - name: Build the distributions
+        run: |
+          pip install build
+          python -m build
+
+      - name: Install the wheel with no extras
+        run: pip install dist/*.whl
+
+      - name: Import without the repo on sys.path
+        # Run from elsewhere: the working directory is the repo root, and
+        # Python would import the source tree in preference to the wheel,
+        # which hides exactly the failure this job exists to catch.
+        working-directory: /tmp
+        run: |
+          python -c "
+          import cloudbridge
+          from cloudbridge.base.resources import BaseBucketObject
+          from cloudbridge.base.helpers import generate_key_pair
+          from cloudbridge.factory import CloudProviderFactory
+          public, _ = generate_key_pair()
+          assert public.startswith('ssh-rsa'), public[:32]
+          print('cloudbridge', cloudbridge.get_version(), 'imports from a bare install')
+          "
+
   mock:
     name: Mock-provider tests
     runs-on: ubuntu-latest

+ 24 - 0
CHANGELOG.rst

@@ -1,3 +1,27 @@
+4.4.1 - unreleased
+------------------
+
+## Fixes
+* **``cryptography`` is now declared as a dependency.**
+  ``cloudbridge.base.helpers`` imports it at module scope, and almost
+  everything imports that module, so it was required for the library to
+  import at all - but it appeared nowhere in ``pyproject.toml``. A plain
+  ``pip install cloudbridge`` therefore produced an installation that raised
+  ``ModuleNotFoundError: No module named 'cryptography'`` on
+  ``import cloudbridge.base.resources``, as did ``cloudbridge[aws]``, since
+  boto3 does not depend on it either. Installations that worked did so
+  because something else in the environment happened to provide it. This
+  affected 4.4.0 and earlier; the import has been there since 2019.
+
+## Build and CI
+* **A new ``Bare install imports`` job builds the wheel, installs it with no
+  extras, and imports the modules a user reaches for first.** Every test
+  environment installs the ``[dev]`` extra, which pulls in the provider SDKs
+  and their transitive dependencies, so the suite passed against a package
+  whose declared dependencies were incomplete. The job runs from outside the
+  repository, so the source tree cannot satisfy the import in place of the
+  installed wheel.
+
 4.4.0 - August 21, 2026 (sha 55d925d56eaad247b960ad00e636253637192549)
 ----------------------------------------------------------------------
 

+ 5 - 0
pyproject.toml

@@ -31,6 +31,11 @@ classifiers = [
 dependencies = [
     "tenacity>=6.0",
     "pyeventsystem<2",
+    # Imported at module scope by cloudbridge.base.helpers, which almost
+    # everything else imports, so it is required for the library to import at
+    # all - not just for generate_key_pair, which is what actually uses it.
+    # Kept unpinned above the floor, per the general-purpose library policy.
+    "cryptography>=3.4",
 ]
 dynamic = ["version"]