1# -*- coding: utf-8 -*-
2# Copyright 2025 Google LLC
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15#
16import sys
17
18import google.api_core as api_core
19
20from google.cloud.appengine_logging_v1 import gapic_version as package_version
21
22__version__ = package_version.__version__
23
24if sys.version_info >= (3, 8): # pragma: NO COVER
25 from importlib import metadata
26else: # pragma: NO COVER
27 # TODO(https://github.com/googleapis/python-api-core/issues/835): Remove
28 # this code path once we drop support for Python 3.7
29 import importlib_metadata as metadata
30
31from .types.request_log import LogLine, RequestLog, SourceLocation, SourceReference
32
33if hasattr(api_core, "check_python_version") and hasattr(
34 api_core, "check_dependency_versions"
35): # pragma: NO COVER
36 api_core.check_python_version("google.cloud.appengine_logging_v1") # type: ignore
37 api_core.check_dependency_versions("google.cloud.appengine_logging_v1") # type: ignore
38else: # pragma: NO COVER
39 # An older version of api_core is installed which does not define the
40 # functions above. We do equivalent checks manually.
41 try:
42 import sys
43 import warnings
44
45 _py_version_str = sys.version.split()[0]
46 _package_label = "google.cloud.appengine_logging_v1"
47 if sys.version_info < (3, 9):
48 warnings.warn(
49 "You are using a non-supported Python version "
50 + f"({_py_version_str}). Google will not post any further "
51 + f"updates to {_package_label} supporting this Python version. "
52 + "Please upgrade to the latest Python version, or at "
53 + f"least to Python 3.9, and then update {_package_label}.",
54 FutureWarning,
55 )
56 if sys.version_info[:2] == (3, 9):
57 warnings.warn(
58 f"You are using a Python version ({_py_version_str}) "
59 + f"which Google will stop supporting in {_package_label} in "
60 + "January 2026. Please "
61 + "upgrade to the latest Python version, or at "
62 + "least to Python 3.10, before then, and "
63 + f"then update {_package_label}.",
64 FutureWarning,
65 )
66
67 def parse_version_to_tuple(version_string: str):
68 """Safely converts a semantic version string to a comparable tuple of integers.
69 Example: "4.25.8" -> (4, 25, 8)
70 Ignores non-numeric parts and handles common version formats.
71 Args:
72 version_string: Version string in the format "x.y.z" or "x.y.z<suffix>"
73 Returns:
74 Tuple of integers for the parsed version string.
75 """
76 parts = []
77 for part in version_string.split("."):
78 try:
79 parts.append(int(part))
80 except ValueError:
81 # If it's a non-numeric part (e.g., '1.0.0b1' -> 'b1'), stop here.
82 # This is a simplification compared to 'packaging.parse_version', but sufficient
83 # for comparing strictly numeric semantic versions.
84 break
85 return tuple(parts)
86
87 def _get_version(dependency_name):
88 try:
89 version_string: str = metadata.version(dependency_name)
90 parsed_version = parse_version_to_tuple(version_string)
91 return (parsed_version, version_string)
92 except Exception:
93 # Catch exceptions from metadata.version() (e.g., PackageNotFoundError)
94 # or errors during parse_version_to_tuple
95 return (None, "--")
96
97 _dependency_package = "google.protobuf"
98 _next_supported_version = "4.25.8"
99 _next_supported_version_tuple = (4, 25, 8)
100 _recommendation = " (we recommend 6.x)"
101 (_version_used, _version_used_string) = _get_version(_dependency_package)
102 if _version_used and _version_used < _next_supported_version_tuple:
103 warnings.warn(
104 f"Package {_package_label} depends on "
105 + f"{_dependency_package}, currently installed at version "
106 + f"{_version_used_string}. Future updates to "
107 + f"{_package_label} will require {_dependency_package} at "
108 + f"version {_next_supported_version} or higher{_recommendation}."
109 + " Please ensure "
110 + "that either (a) your Python environment doesn't pin the "
111 + f"version of {_dependency_package}, so that updates to "
112 + f"{_package_label} can require the higher version, or "
113 + "(b) you manually update your Python environment to use at "
114 + f"least version {_next_supported_version} of "
115 + f"{_dependency_package}.",
116 FutureWarning,
117 )
118 except Exception:
119 warnings.warn(
120 "Could not determine the version of Python "
121 + "currently being used. To continue receiving "
122 + "updates for {_package_label}, ensure you are "
123 + "using a supported version of Python; see "
124 + "https://devguide.python.org/versions/"
125 )
126
127__all__ = (
128 "LogLine",
129 "RequestLog",
130 "SourceLocation",
131 "SourceReference",
132)