Skip to content

Commit a585f25

Browse files
committed
Squashed commit
1 parent 6206ce0 commit a585f25

File tree

17 files changed

+131
-116
lines changed

17 files changed

+131
-116
lines changed

.github/.OwlBot.lock.yaml

Lines changed: 0 additions & 17 deletions
This file was deleted.

.github/.OwlBot.yaml

Lines changed: 0 additions & 19 deletions
This file was deleted.

.github/release-please.yml

Lines changed: 0 additions & 11 deletions
This file was deleted.

.github/release-trigger.yml

Lines changed: 0 additions & 2 deletions
This file was deleted.

.librarian/config.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
global_files_allowlist:
2+
# Allow the container to read and write the root `CHANGELOG.md`
3+
# file during the `release` step to update the latest client library
4+
# versions which are hardcoded in the file.
5+
- path: "CHANGELOG.md"
6+
permissions: "read-write"

.librarian/state.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
image: us-central1-docker.pkg.dev/cloud-sdk-librarian-prod/images-prod/python-librarian-generator:latest
2+
libraries:
3+
- id: google-api-core
4+
version: 2.28.1
5+
apis: []
6+
source_roots:
7+
- .
8+
preserve_regex: []
9+
remove_regex: []
10+
tag_format: v{version}

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@
44

55
[1]: https://pypi.org/project/google-api-core/#history
66

7+
## [2.28.1](https://github.com/googleapis/python-api-core/compare/v2.28.0...v2.28.1) (2025-10-28)
8+
9+
10+
### Bug Fixes
11+
12+
* Remove dependency on packaging and pkg_resources ([#852](https://github.com/googleapis/python-api-core/issues/852)) ([ca59a86](https://github.com/googleapis/python-api-core/commit/ca59a863b08a79c2bf0607f9085de1417422820b))
13+
714
## [2.28.0](https://github.com/googleapis/python-api-core/compare/v2.27.0...v2.28.0) (2025-10-24)
815

916

google/api_core/_python_package_support.py

Lines changed: 45 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
import warnings
1818
import sys
19-
from typing import Optional
19+
from typing import Optional, Tuple
2020

2121
from collections import namedtuple
2222

@@ -25,7 +25,14 @@
2525
_get_distribution_and_import_packages,
2626
)
2727

28-
from packaging.version import parse as parse_version
28+
if sys.version_info >= (3, 8):
29+
from importlib import metadata
30+
else:
31+
# TODO(https://github.com/googleapis/python-api-core/issues/835): Remove
32+
# this code path once we drop support for Python 3.7
33+
import importlib_metadata as metadata
34+
35+
ParsedVersion = Tuple[int, ...]
2936

3037
# Here we list all the packages for which we want to issue warnings
3138
# about deprecated and unsupported versions.
@@ -48,42 +55,56 @@
4855
UNKNOWN_VERSION_STRING = "--"
4956

5057

58+
def parse_version_to_tuple(version_string: str) -> ParsedVersion:
59+
"""Safely converts a semantic version string to a comparable tuple of integers.
60+
61+
Example: "4.25.8" -> (4, 25, 8)
62+
Ignores non-numeric parts and handles common version formats.
63+
64+
Args:
65+
version_string: Version string in the format "x.y.z" or "x.y.z<suffix>"
66+
67+
Returns:
68+
Tuple of integers for the parsed version string.
69+
"""
70+
parts = []
71+
for part in version_string.split("."):
72+
try:
73+
parts.append(int(part))
74+
except ValueError:
75+
# If it's a non-numeric part (e.g., '1.0.0b1' -> 'b1'), stop here.
76+
# This is a simplification compared to 'packaging.parse_version', but sufficient
77+
# for comparing strictly numeric semantic versions.
78+
break
79+
return tuple(parts)
80+
81+
5182
def get_dependency_version(
5283
dependency_name: str,
5384
) -> DependencyVersion:
5485
"""Get the parsed version of an installed package dependency.
5586
5687
This function checks for an installed package and returns its version
57-
as a `packaging.version.Version` object for safe comparison. It handles
88+
as a comparable tuple of integers object for safe comparison. It handles
5889
both modern (Python 3.8+) and legacy (Python 3.7) environments.
5990
6091
Args:
6192
dependency_name: The distribution name of the package (e.g., 'requests').
6293
6394
Returns:
64-
A DependencyVersion namedtuple with `version` and
95+
A DependencyVersion namedtuple with `version` (a tuple of integers) and
6596
`version_string` attributes, or `DependencyVersion(None,
6697
UNKNOWN_VERSION_STRING)` if the package is not found or
6798
another error occurs during version discovery.
6899
69100
"""
70101
try:
71-
if sys.version_info >= (3, 8):
72-
from importlib import metadata
73-
74-
version_string = metadata.version(dependency_name)
75-
return DependencyVersion(parse_version(version_string), version_string)
76-
77-
# TODO(https://github.com/googleapis/python-api-core/issues/835): Remove
78-
# this code path once we drop support for Python 3.7
79-
else: # pragma: NO COVER
80-
# Use pkg_resources, which is part of setuptools.
81-
import pkg_resources
82-
83-
version_string = pkg_resources.get_distribution(dependency_name).version
84-
return DependencyVersion(parse_version(version_string), version_string)
85-
102+
version_string: str = metadata.version(dependency_name)
103+
parsed_version = parse_version_to_tuple(version_string)
104+
return DependencyVersion(parsed_version, version_string)
86105
except Exception:
106+
# Catch exceptions from metadata.version() (e.g., PackageNotFoundError)
107+
# or errors during parse_version_to_tuple
87108
return DependencyVersion(None, UNKNOWN_VERSION_STRING)
88109

89110

@@ -132,10 +153,14 @@ def warn_deprecation_for_versions_less_than(
132153
or not minimum_fully_supported_version
133154
): # pragma: NO COVER
134155
return
156+
135157
dependency_version = get_dependency_version(dependency_import_package)
136158
if not dependency_version.version:
137159
return
138-
if dependency_version.version < parse_version(minimum_fully_supported_version):
160+
161+
if dependency_version.version < parse_version_to_tuple(
162+
minimum_fully_supported_version
163+
):
139164
(
140165
dependency_package,
141166
dependency_distribution_package,

google/api_core/bidi.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -281,13 +281,12 @@ def open(self):
281281

282282
def close(self):
283283
"""Closes the stream."""
284-
if self.call is None:
285-
return
284+
if self.call is not None:
285+
self.call.cancel()
286286

287+
# Put None in request queue to signal termination.
287288
self._request_queue.put(None)
288-
self.call.cancel()
289289
self._request_generator = None
290-
self._initial_request = None
291290
self._callbacks = []
292291
# Don't set self.call to None. Keep it around so that send/recv can
293292
# raise the error.

google/api_core/bidi_async.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -197,13 +197,12 @@ async def open(self) -> None:
197197

198198
async def close(self) -> None:
199199
"""Closes the stream."""
200-
if self.call is None:
201-
return
200+
if self.call is not None:
201+
self.call.cancel()
202202

203+
# Put None in request queue to signal termination.
203204
await self._request_queue.put(None)
204-
self.call.cancel()
205205
self._request_generator = None
206-
self._initial_request = None
207206
self._callbacks = []
208207
# Don't set self.call to None. Keep it around so that send/recv can
209208
# raise the error.

0 commit comments

Comments
 (0)