Skip to content

Commit

Permalink
feat: add support for python 3.12 (#153)
Browse files Browse the repository at this point in the history
* feat: add support for python 3.12

* remove usage of datetime.datetime.utcnow

* fix tests

* fix tests

* fix tests

* 🦉 Updates from OwlBot post-processor

See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md

* update post processor image

* 🦉 Updates from OwlBot post-processor

See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md

---------

Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com>
  • Loading branch information
parthea and gcf-owl-bot[bot] committed Nov 23, 2023
1 parent 8545fbd commit 474961a
Show file tree
Hide file tree
Showing 19 changed files with 113 additions and 26 deletions.
4 changes: 2 additions & 2 deletions .github/.OwlBot.lock.yaml
Expand Up @@ -13,5 +13,5 @@
# limitations under the License.
docker:
image: gcr.io/cloud-devrel-public-resources/owlbot-python:latest
digest: sha256:caffe0a9277daeccc4d1de5c9b55ebba0901b57c2f713ec9c876b0d4ec064f61
# created: 2023-11-08T19:46:45.022803742Z
digest: sha256:bacc3af03bff793a03add584537b36b5644342931ad989e3ba1171d3bd5399f5
# created: 2023-11-23T18:17:28.105124211Z
2 changes: 2 additions & 0 deletions .github/sync-repo-settings.yaml
Expand Up @@ -14,6 +14,8 @@ branchProtectionRules:
- 'unit (3.8)'
- 'unit (3.9)'
- 'unit (3.10)'
- 'unit (3.11)'
- 'unit (3.12)'
- 'cover'
permissionRules:
- team: actools-python
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/unittest.yml
Expand Up @@ -8,7 +8,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python: ['3.7', '3.8', '3.9', '3.10', '3.11']
python: ['3.7', '3.8', '3.9', '3.10', '3.11', '3.12']
steps:
- name: Checkout
uses: actions/checkout@v3
Expand Down
40 changes: 40 additions & 0 deletions .kokoro/samples/python3.12/common.cfg
@@ -0,0 +1,40 @@
# Format: //devtools/kokoro/config/proto/build.proto

# Build logs will be here
action {
define_artifacts {
regex: "**/*sponge_log.xml"
}
}

# Specify which tests to run
env_vars: {
key: "RUN_TESTS_SESSION"
value: "py-3.12"
}

# Declare build specific Cloud project.
env_vars: {
key: "BUILD_SPECIFIC_GCLOUD_PROJECT"
value: "python-docs-samples-tests-312"
}

env_vars: {
key: "TRAMPOLINE_BUILD_FILE"
value: "github/python-test-utils/.kokoro/test-samples.sh"
}

# Configure the docker image for kokoro-trampoline.
env_vars: {
key: "TRAMPOLINE_IMAGE"
value: "gcr.io/cloud-devrel-kokoro-resources/python-samples-testing-docker"
}

# Download secrets for samples
gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/python-docs-samples"

# Download trampoline resources.
gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline"

# Use the trampoline script to run in docker.
build_file: "python-test-utils/.kokoro/trampoline_v2.sh"
6 changes: 6 additions & 0 deletions .kokoro/samples/python3.12/continuous.cfg
@@ -0,0 +1,6 @@
# Format: //devtools/kokoro/config/proto/build.proto

env_vars: {
key: "INSTALL_LIBRARY_FROM_SOURCE"
value: "True"
}
11 changes: 11 additions & 0 deletions .kokoro/samples/python3.12/periodic-head.cfg
@@ -0,0 +1,11 @@
# Format: //devtools/kokoro/config/proto/build.proto

env_vars: {
key: "INSTALL_LIBRARY_FROM_SOURCE"
value: "True"
}

env_vars: {
key: "TRAMPOLINE_BUILD_FILE"
value: "github/python-test-utils/.kokoro/test-samples-against-head.sh"
}
6 changes: 6 additions & 0 deletions .kokoro/samples/python3.12/periodic.cfg
@@ -0,0 +1,6 @@
# Format: //devtools/kokoro/config/proto/build.proto

env_vars: {
key: "INSTALL_LIBRARY_FROM_SOURCE"
value: "False"
}
6 changes: 6 additions & 0 deletions .kokoro/samples/python3.12/presubmit.cfg
@@ -0,0 +1,6 @@
# Format: //devtools/kokoro/config/proto/build.proto

env_vars: {
key: "INSTALL_LIBRARY_FROM_SOURCE"
value: "True"
}
2 changes: 1 addition & 1 deletion mypy.ini
@@ -1,3 +1,3 @@
[mypy]
python_version = 3.6
python_version = 3.9
exclude = tests/unit/resources/
6 changes: 3 additions & 3 deletions noxfile.py
Expand Up @@ -86,7 +86,7 @@ def mypy(session):
session.run("mypy", "test_utils/", "tests/")


@nox.session(python=["3.7", "3.8", "3.9", "3.10", "3.11"])
@nox.session(python=["3.7", "3.8", "3.9", "3.10", "3.11", "3.12"])
def unit(session):
constraints_path = str(
CURRENT_DIRECTORY / "testing" / f"constraints-{session.python}.txt"
Expand Down Expand Up @@ -123,7 +123,7 @@ def check_lower_bounds(session):
"--package-name",
"google-cloud-testutils",
"--constraints-file",
"testing/constraints-3.6.txt",
"testing/constraints-3.7.txt",
)


Expand All @@ -137,5 +137,5 @@ def update_lower_bounds(session):
"--package-name",
"google-cloud-testutils",
"--constraints-file",
"testing/constraints-3.6.txt",
"testing/constraints-3.7.txt",
)
17 changes: 15 additions & 2 deletions setup.py
Expand Up @@ -28,6 +28,12 @@
["lower-bound-checker=test_utils.lower_bound_checker.lower_bound_checker:main"],
)

packages = [
package
for package in setuptools.find_namespace_packages()
if package.startswith("test_utils")
]

setuptools.setup(
name="google-cloud-testutils",
version=version,
Expand All @@ -36,11 +42,16 @@
author_email="googleapis-packages@google.com",
license="Apache 2.0",
url="https://github.com/googleapis/python-test-utils",
packages=setuptools.PEP420PackageFinder.find(),
packages=packages,
entry_points={"console_scripts": scripts},
platforms="Posix; MacOS X; Windows",
include_package_data=True,
install_requires=("google-auth >= 0.4.0", "click>=7.0.0", "packaging>=19.0"),
install_requires=(
"google-auth >= 0.4.0",
"click>=7.0.0",
"packaging>=19.0",
"importlib_metadata>=1.0.0; python_version<'3.8'",
),
python_requires=">=3.7",
classifiers=[
"Development Status :: 4 - Beta",
Expand All @@ -51,6 +62,8 @@
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Topic :: Internet",
"Topic :: Software Development :: Libraries :: Python Modules",
],
Expand Down
19 changes: 12 additions & 7 deletions test_utils/lower_bound_checker/lower_bound_checker.py
Expand Up @@ -12,13 +12,18 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import click
from pathlib import Path
from typing import List, Tuple, Set
import sys

import click
from packaging.requirements import Requirement
from packaging.version import Version
import pkg_resources

if sys.version_info < (3, 8):
import importlib_metadata as metadata
else:
import importlib.metadata as metadata


def _get_package_requirements(package_name: str) -> List[Requirement]:
Expand All @@ -30,12 +35,12 @@ def _get_package_requirements(package_name: str) -> List[Requirement]:
package_name (str): The name of the package.
Returns:
List[pkg_resources.Requirement]: A list of package requirements and extras.
List[packaging.requirements.Requirement]: A list of package requirements and extras.
"""
dist = pkg_resources.get_distribution(package_name)
extras = tuple(dist.extras)
requirements = [Requirement(str(r)) for r in dist.requires(extras=extras)]

requirements = []
distribution = metadata.distribution(package_name)
if distribution.requires:
requirements = [Requirement(str(r)) for r in distribution.requires]
return requirements


Expand Down
6 changes: 4 additions & 2 deletions test_utils/prefixer.py
Expand Up @@ -58,7 +58,8 @@ def __init__(
self._prefix = _common_prefix(repo, relative_dir, separator=separator)

def create_prefix(self) -> str:
timestamp = datetime.datetime.utcnow().strftime(_RESOURCE_DATE_FORMAT)
now = datetime.datetime.now(datetime.timezone.utc).replace(tzinfo=None)
timestamp = now.strftime(_RESOURCE_DATE_FORMAT)
random_string = hex(random.randrange(0x1000000))[2:]
return f"{self._prefix}{self._separator}{timestamp}{self._separator}{random_string}"

Expand All @@ -72,7 +73,8 @@ def _name_to_date(self, resource_name: str) -> Union[datetime.datetime, None]:
return None

def should_cleanup(self, resource_name: str) -> bool:
yesterday = datetime.datetime.utcnow() - self._cleanup_age
now = datetime.datetime.now(datetime.timezone.utc).replace(tzinfo=None)
yesterday = now - self._cleanup_age
if not resource_name.startswith(self._prefix):
return False

Expand Down
Empty file added testing/constraints-3.12.txt
Empty file.
4 changes: 0 additions & 4 deletions testing/constraints-3.6.txt

This file was deleted.

2 changes: 1 addition & 1 deletion testing/constraints-3.7.txt
@@ -1,4 +1,4 @@
click==7.0.0
google-auth==0.4.0
importlib-metadata==1.0.0
packaging==19.0
colorlog==3.0.0
2 changes: 1 addition & 1 deletion tests/unit/resources/bad_package/setup.py
Expand Up @@ -36,5 +36,5 @@
],
install_requires=requirements,
packages=setuptools.find_packages(),
python_requires=">=3.6",
python_requires=">=3.7",
)
2 changes: 1 addition & 1 deletion tests/unit/resources/good_package/setup.py
Expand Up @@ -42,5 +42,5 @@
install_requires=requirements,
extras_require=extras,
packages=setuptools.find_packages(),
python_requires=">=3.6",
python_requires=">=3.7",
)
2 changes: 1 addition & 1 deletion tests/unit/test_prefixer.py
Expand Up @@ -28,7 +28,7 @@ class FakeDateTime(object):
def __init__(self, fake_now):
self._fake_now = fake_now

def utcnow(self):
def now(self, timezone):
return self._fake_now

strptime = datetime.datetime.strptime
Expand Down

0 comments on commit 474961a

Please sign in to comment.