Skip to content

Commit 01dbac5

Browse files
authored
chore(resumable-media): add prerelease_deps and core_deps_from_source nox sessions (#17341)
This PR adds missing `prerelease_deps` and `core_deps_from_source` nox sessions for the google-resumable-media package. Changes to each nox session are based on the versions found in the **gapic-generator** [`noxfile.py.j2` template](https://github.com/googleapis/google-cloud-python/blob/main/packages/gapic-generator/gapic/templates/noxfile.py.j2). Fixes #17053
1 parent a76861b commit 01dbac5

1 file changed

Lines changed: 141 additions & 10 deletions

File tree

packages/google-resumable-media/noxfile.py

Lines changed: 141 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from __future__ import absolute_import
1616
import os
1717
import pathlib
18+
import re
1819
import shutil
1920

2021
import nox
@@ -303,17 +304,147 @@ def cover(session):
303304

304305
@nox.session(python=DEFAULT_PYTHON_VERSION)
305306
def prerelease_deps(session):
306-
# TODO(https://github.com/googleapis/google-cloud-python/issues/16014):
307-
# Resolve the linked bug once prerelease_deps and core_deps_from_source
308-
# are implemented for this package.
309-
if session.python == DEFAULT_PYTHON_VERSION:
310-
session.skip(f"Skipping prerelease_deps for {DEFAULT_PYTHON_VERSION} until a future release.")
307+
"""
308+
Run all tests with pre-release versions of dependencies installed
309+
rather than the standard non pre-release versions.
310+
Pre-release versions can be installed using
311+
`pip install --pre <package>`.
312+
"""
313+
314+
# Install standard test dependencies, then install local packages in-place.
315+
session.install("mock", "pytest", "pytest-cov", "pytest-asyncio<=0.14.0", "brotli")
316+
session.install("-e", ".[requests,aiohttp]")
317+
318+
# Because we test minimum dependency versions on the minimum Python
319+
# version, the first version we test with in the unit tests sessions has a
320+
# constraints file containing all dependencies and extras.
321+
with open(
322+
CURRENT_DIRECTORY / "testing" / f"constraints-{UNIT_TEST_PYTHON_VERSIONS[0]}.txt",
323+
encoding="utf-8",
324+
) as constraints_file:
325+
constraints_text = constraints_file.read()
326+
327+
# Ignore leading whitespace and comment lines.
328+
constraints_deps = [
329+
match.group(1)
330+
for match in re.finditer(
331+
r"^\s*(\S+)(?===\S+)", constraints_text, flags=re.MULTILINE
332+
)
333+
]
334+
335+
# Install dependencies specified in `testing/constraints-X.txt`.
336+
session.install(*constraints_deps)
337+
338+
# Note: If a dependency is added to the `prerel_deps` list,
339+
# the `core_dependencies_from_source` list in the `core_deps_from_source`
340+
# nox session should also be updated.
341+
prerel_deps = [
342+
"google-crc32c",
343+
"google-auth",
344+
"cryptography",
345+
"cffi",
346+
"cachetools",
347+
"rsa",
348+
"pyasn1",
349+
]
350+
351+
deps_dir = CURRENT_DIRECTORY.parent
352+
while deps_dir.name != "packages" and deps_dir.parent != deps_dir:
353+
deps_dir = deps_dir.parent
354+
355+
# Extract the base package name, safely ignoring version bounds and spaces
356+
# (e.g., "grpcio>=1.75.1" becomes "grpcio")
357+
parsed_deps = {
358+
dep: re.match(r"^([a-zA-Z0-9_-]+)", dep).group(1) for dep in prerel_deps
359+
}
360+
361+
# Dynamically sort local packages vs PyPI dependencies
362+
local_paths = []
363+
pypi_deps = []
364+
365+
for dep, pkg_name in parsed_deps.items():
366+
if (deps_dir / pkg_name).exists():
367+
local_paths.append(str(deps_dir / pkg_name))
368+
else:
369+
pypi_deps.append(dep)
370+
371+
# Batch pip installations to avoid sequential overhead
372+
if local_paths:
373+
session.install(*local_paths, "--no-deps", "--ignore-installed")
374+
if pypi_deps:
375+
session.install(*pypi_deps, "--pre", "--no-deps", "--ignore-installed")
376+
377+
# Reuse the parsed names for logging and version verification
378+
for dep, pkg_name in parsed_deps.items():
379+
print(f"Installed {dep}")
380+
381+
session.run(
382+
"py.test",
383+
os.path.join("tests", "unit"),
384+
os.path.join("tests_async", "unit"),
385+
*session.posargs,
386+
)
311387

312388

313389
@nox.session(python=DEFAULT_PYTHON_VERSION)
314390
def core_deps_from_source(session):
315-
## TODO(https://github.com/googleapis/google-cloud-python/issues/16014):
316-
# Resolve the linked bug once prerelease_deps and core_deps_from_source
317-
# are implemented for this package.
318-
if session.python == DEFAULT_PYTHON_VERSION:
319-
session.skip(f"Skipping core_deps_from_source for {DEFAULT_PYTHON_VERSION} until a future release.")
391+
"""Run all tests with core dependencies installed from source
392+
rather than pulling the dependencies from PyPI.
393+
"""
394+
395+
# Install standard test dependencies, then install local packages in-place.
396+
session.install("mock", "pytest", "pytest-cov", "pytest-asyncio<=0.14.0", "brotli")
397+
session.install("-e", ".[requests,aiohttp]")
398+
399+
# Because we test minimum dependency versions on the minimum Python
400+
# version, the first version we test with in the unit tests sessions has a
401+
# constraints file containing all dependencies and extras.
402+
with open(
403+
CURRENT_DIRECTORY / "testing" / f"constraints-{UNIT_TEST_PYTHON_VERSIONS[0]}.txt",
404+
encoding="utf-8",
405+
) as constraints_file:
406+
constraints_text = constraints_file.read()
407+
408+
# Ignore leading whitespace and comment lines.
409+
constraints_deps = [
410+
match.group(1)
411+
for match in re.finditer(
412+
r"^\s*(\S+)(?===\S+)", constraints_text, flags=re.MULTILINE
413+
)
414+
]
415+
416+
# Install dependencies specified in `testing/constraints-X.txt`.
417+
session.install(*constraints_deps)
418+
419+
# Note: If a dependency is added to the `core_dependencies_from_source` list,
420+
# the `prerel_deps` list in the `prerelease_deps` nox session should also be updated.
421+
core_dependencies_from_source = [
422+
"google-crc32c",
423+
"google-auth",
424+
]
425+
426+
deps_dir = CURRENT_DIRECTORY.parent
427+
while deps_dir.name != "packages" and deps_dir.parent != deps_dir:
428+
deps_dir = deps_dir.parent
429+
430+
# Batch the pip installation to avoid sequential overhead
431+
dep_paths = [str(deps_dir / dep) for dep in core_dependencies_from_source]
432+
433+
session.install(*dep_paths, "--no-deps", "--ignore-installed")
434+
print(f"Installed {', '.join(core_dependencies_from_source)} locally from {deps_dir}")
435+
436+
other_deps = [
437+
"cryptography",
438+
"cffi",
439+
"cachetools",
440+
"rsa",
441+
"pyasn1",
442+
]
443+
session.install(*other_deps)
444+
445+
session.run(
446+
"py.test",
447+
os.path.join("tests", "unit"),
448+
os.path.join("tests_async", "unit"),
449+
*session.posargs,
450+
)

0 commit comments

Comments
 (0)