Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-google-api-core for
openSUSE:Factory checked in at 2025-01-07 20:53:02
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-google-api-core (Old)
and /work/SRC/openSUSE:Factory/.python-google-api-core.new.1881 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-google-api-core"
Tue Jan 7 20:53:02 2025 rev:39 rq:1235263 version:2.24.0
Changes:
--------
---
/work/SRC/openSUSE:Factory/python-google-api-core/python-google-api-core.changes
2024-12-05 17:11:11.536004136 +0100
+++
/work/SRC/openSUSE:Factory/.python-google-api-core.new.1881/python-google-api-core.changes
2025-01-07 20:53:31.789186583 +0100
@@ -1,0 +2,7 @@
+Mon Jan 6 15:21:38 UTC 2025 - John Paul Adrian Glaubitz
<[email protected]>
+
+- Update to 2.24.0
+ * Add automatic logging config to support debug logging (#754)
+ * Update recognized logging fields (#766)
+
+-------------------------------------------------------------------
Old:
----
google_api_core-2.23.0.tar.gz
New:
----
google_api_core-2.24.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-google-api-core.spec ++++++
--- /var/tmp/diff_new_pack.mdSDx0/_old 2025-01-07 20:53:32.213204120 +0100
+++ /var/tmp/diff_new_pack.mdSDx0/_new 2025-01-07 20:53:32.217204285 +0100
@@ -1,7 +1,7 @@
#
# spec file for package python-google-api-core
#
-# Copyright (c) 2024 SUSE LLC
+# Copyright (c) 2025 SUSE LLC
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -26,7 +26,7 @@
%endif
%{?sle15_python_module_pythons}
Name: python-google-api-core
-Version: 2.23.0
+Version: 2.24.0
Release: 0
Summary: Google API client core library
License: Apache-2.0
++++++ google_api_core-2.23.0.tar.gz -> google_api_core-2.24.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/google_api_core-2.23.0/PKG-INFO
new/google_api_core-2.24.0/PKG-INFO
--- old/google_api_core-2.23.0/PKG-INFO 2024-11-11 18:55:08.073598000 +0100
+++ new/google_api_core-2.24.0/PKG-INFO 2024-12-09 21:19:34.765935400 +0100
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: google-api-core
-Version: 2.23.0
+Version: 2.24.0
Summary: Google API client core library
Author-email: Google LLC <[email protected]>
License: Apache 2.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/google_api_core-2.23.0/google/api_core/client_logging.py
new/google_api_core-2.24.0/google/api_core/client_logging.py
--- old/google_api_core-2.23.0/google/api_core/client_logging.py
1970-01-01 01:00:00.000000000 +0100
+++ new/google_api_core-2.24.0/google/api_core/client_logging.py
2024-12-09 21:15:48.000000000 +0100
@@ -0,0 +1,144 @@
+import logging
+import json
+import os
+
+from typing import List, Optional
+
+_LOGGING_INITIALIZED = False
+_BASE_LOGGER_NAME = "google"
+
+# Fields to be included in the StructuredLogFormatter.
+#
+# TODO(https://github.com/googleapis/python-api-core/issues/761): Update this
list to support additional logging fields.
+_recognized_logging_fields = [
+ "httpRequest",
+ "rpcName",
+ "serviceName",
+ "credentialsType",
+ "credentialsInfo",
+ "universeDomain",
+ "request",
+ "response",
+ "metadata",
+ "retryAttempt",
+ "httpResponse",
+] # Additional fields to be Logged.
+
+
+def logger_configured(logger) -> bool:
+ """Determines whether `logger` has non-default configuration
+
+ Args:
+ logger: The logger to check.
+
+ Returns:
+ bool: Whether the logger has any non-default configuration.
+ """
+ return (
+ logger.handlers != [] or logger.level != logging.NOTSET or not
logger.propagate
+ )
+
+
+def initialize_logging():
+ """Initializes "google" loggers, partly based on the environment variable
+
+ Initializes the "google" logger and any loggers (at the "google"
+ level or lower) specified by the environment variable
+ GOOGLE_SDK_PYTHON_LOGGING_SCOPE, as long as none of these loggers
+ were previously configured. If any such loggers (including the
+ "google" logger) are initialized, they are set to NOT propagate
+ log events up to their parent loggers.
+
+ This initialization is executed only once, and hence the
+ environment variable is only processed the first time this
+ function is called.
+ """
+ global _LOGGING_INITIALIZED
+ if _LOGGING_INITIALIZED:
+ return
+ scopes = os.getenv("GOOGLE_SDK_PYTHON_LOGGING_SCOPE", "")
+ setup_logging(scopes)
+ _LOGGING_INITIALIZED = True
+
+
+def parse_logging_scopes(scopes: Optional[str] = None) -> List[str]:
+ """Returns a list of logger names.
+
+ Splits the single string of comma-separated logger names into a list of
individual logger name strings.
+
+ Args:
+ scopes: The name of a single logger. (In the future, this will be a
comma-separated list of multiple loggers.)
+
+ Returns:
+ A list of all the logger names in scopes.
+ """
+ if not scopes:
+ return []
+ # TODO(https://github.com/googleapis/python-api-core/issues/759): check if
the namespace is a valid namespace.
+ # TODO(b/380481951): Support logging multiple scopes.
+ # TODO(b/380483756): Raise or log a warning for an invalid scope.
+ namespaces = [scopes]
+ return namespaces
+
+
+def configure_defaults(logger):
+ """Configures `logger` to emit structured info to stdout."""
+ if not logger_configured(logger):
+ console_handler = logging.StreamHandler()
+ logger.setLevel("DEBUG")
+ logger.propagate = False
+ formatter = StructuredLogFormatter()
+ console_handler.setFormatter(formatter)
+ logger.addHandler(console_handler)
+
+
+def setup_logging(scopes: str = ""):
+ """Sets up logging for the specified `scopes`.
+
+ If the loggers specified in `scopes` have not been previously
+ configured, this will configure them to emit structured log
+ entries to stdout, and to not propagate their log events to their
+ parent loggers. Additionally, if the "google" logger (whether it
+ was specified in `scopes` or not) was not previously configured,
+ it will also configure it to not propagate log events to the root
+ logger.
+
+ Args:
+ scopes: The name of a single logger. (In the future, this will be a
comma-separated list of multiple loggers.)
+
+ """
+
+ # only returns valid logger scopes (namespaces)
+ # this list has at most one element.
+ logger_names = parse_logging_scopes(scopes)
+
+ for namespace in logger_names:
+ # This will either create a module level logger or get the reference
of the base logger instantiated above.
+ logger = logging.getLogger(namespace)
+
+ # Configure default settings.
+ configure_defaults(logger)
+
+ # disable log propagation at base logger level to the root logger only if
a base logger is not already configured via code changes.
+ base_logger = logging.getLogger(_BASE_LOGGER_NAME)
+ if not logger_configured(base_logger):
+ base_logger.propagate = False
+
+
+# TODO(https://github.com/googleapis/python-api-core/issues/763): Expand
documentation.
+class StructuredLogFormatter(logging.Formatter):
+ # TODO(https://github.com/googleapis/python-api-core/issues/761): ensure
that additional fields such as
+ # function name, file name, and line no. appear in a log output.
+ def format(self, record: logging.LogRecord):
+ log_obj = {
+ "timestamp": self.formatTime(record),
+ "severity": record.levelname,
+ "name": record.name,
+ "message": record.getMessage(),
+ }
+
+ for field_name in _recognized_logging_fields:
+ value = getattr(record, field_name, None)
+ if value is not None:
+ log_obj[field_name] = value
+ return json.dumps(log_obj)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/google_api_core-2.23.0/google/api_core/version.py
new/google_api_core-2.24.0/google/api_core/version.py
--- old/google_api_core-2.23.0/google/api_core/version.py 2024-11-11
18:50:47.000000000 +0100
+++ new/google_api_core-2.24.0/google/api_core/version.py 2024-12-09
21:15:48.000000000 +0100
@@ -12,4 +12,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-__version__ = "2.23.0"
+__version__ = "2.24.0"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/google_api_core-2.23.0/google_api_core.egg-info/PKG-INFO
new/google_api_core-2.24.0/google_api_core.egg-info/PKG-INFO
--- old/google_api_core-2.23.0/google_api_core.egg-info/PKG-INFO
2024-11-11 18:55:07.000000000 +0100
+++ new/google_api_core-2.24.0/google_api_core.egg-info/PKG-INFO
2024-12-09 21:19:34.000000000 +0100
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: google-api-core
-Version: 2.23.0
+Version: 2.24.0
Summary: Google API client core library
Author-email: Google LLC <[email protected]>
License: Apache 2.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/google_api_core-2.23.0/google_api_core.egg-info/SOURCES.txt
new/google_api_core-2.24.0/google_api_core.egg-info/SOURCES.txt
--- old/google_api_core-2.23.0/google_api_core.egg-info/SOURCES.txt
2024-11-11 18:55:07.000000000 +0100
+++ new/google_api_core-2.24.0/google_api_core.egg-info/SOURCES.txt
2024-12-09 21:19:34.000000000 +0100
@@ -8,6 +8,7 @@
google/api_core/_rest_streaming_base.py
google/api_core/bidi.py
google/api_core/client_info.py
+google/api_core/client_logging.py
google/api_core/client_options.py
google/api_core/datetime_helpers.py
google/api_core/exceptions.py
@@ -87,6 +88,7 @@
tests/unit/__init__.py
tests/unit/test_bidi.py
tests/unit/test_client_info.py
+tests/unit/test_client_logging.py
tests/unit/test_client_options.py
tests/unit/test_datetime_helpers.py
tests/unit/test_exceptions.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/google_api_core-2.23.0/tests/unit/test_client_logging.py
new/google_api_core-2.24.0/tests/unit/test_client_logging.py
--- old/google_api_core-2.23.0/tests/unit/test_client_logging.py
1970-01-01 01:00:00.000000000 +0100
+++ new/google_api_core-2.24.0/tests/unit/test_client_logging.py
2024-12-09 21:15:48.000000000 +0100
@@ -0,0 +1,140 @@
+import json
+import logging
+from unittest import mock
+
+from google.api_core.client_logging import (
+ setup_logging,
+ initialize_logging,
+ StructuredLogFormatter,
+)
+
+
+def reset_logger(scope):
+ logger = logging.getLogger(scope)
+ logger.handlers = []
+ logger.setLevel(logging.NOTSET)
+ logger.propagate = True
+
+
+def test_setup_logging_w_no_scopes():
+ with mock.patch("google.api_core.client_logging._BASE_LOGGER_NAME",
"foogle"):
+ setup_logging()
+ base_logger = logging.getLogger("foogle")
+ assert base_logger.handlers == []
+ assert not base_logger.propagate
+ assert base_logger.level == logging.NOTSET
+
+ reset_logger("foogle")
+
+
+def test_setup_logging_w_base_scope():
+ with mock.patch("google.api_core.client_logging._BASE_LOGGER_NAME",
"foogle"):
+ setup_logging("foogle")
+ base_logger = logging.getLogger("foogle")
+ assert isinstance(base_logger.handlers[0], logging.StreamHandler)
+ assert not base_logger.propagate
+ assert base_logger.level == logging.DEBUG
+
+ reset_logger("foogle")
+
+
+def test_setup_logging_w_configured_scope():
+ with mock.patch("google.api_core.client_logging._BASE_LOGGER_NAME",
"foogle"):
+ base_logger = logging.getLogger("foogle")
+ base_logger.propagate = False
+ setup_logging("foogle")
+ assert base_logger.handlers == []
+ assert not base_logger.propagate
+ assert base_logger.level == logging.NOTSET
+
+ reset_logger("foogle")
+
+
+def test_setup_logging_w_module_scope():
+ with mock.patch("google.api_core.client_logging._BASE_LOGGER_NAME",
"foogle"):
+ setup_logging("foogle.bar")
+
+ base_logger = logging.getLogger("foogle")
+ assert base_logger.handlers == []
+ assert not base_logger.propagate
+ assert base_logger.level == logging.NOTSET
+
+ module_logger = logging.getLogger("foogle.bar")
+ assert isinstance(module_logger.handlers[0], logging.StreamHandler)
+ assert not module_logger.propagate
+ assert module_logger.level == logging.DEBUG
+
+ reset_logger("foogle")
+ reset_logger("foogle.bar")
+
+
+def test_setup_logging_w_incorrect_scope():
+ with mock.patch("google.api_core.client_logging._BASE_LOGGER_NAME",
"foogle"):
+ setup_logging("abc")
+
+ base_logger = logging.getLogger("foogle")
+ assert base_logger.handlers == []
+ assert not base_logger.propagate
+ assert base_logger.level == logging.NOTSET
+
+ # TODO(https://github.com/googleapis/python-api-core/issues/759):
update test once we add logic to ignore an incorrect scope.
+ logger = logging.getLogger("abc")
+ assert isinstance(logger.handlers[0], logging.StreamHandler)
+ assert not logger.propagate
+ assert logger.level == logging.DEBUG
+
+ reset_logger("foogle")
+ reset_logger("abc")
+
+
+def test_initialize_logging():
+
+ with mock.patch("os.getenv", return_value="foogle.bar"):
+ with mock.patch("google.api_core.client_logging._BASE_LOGGER_NAME",
"foogle"):
+ initialize_logging()
+
+ base_logger = logging.getLogger("foogle")
+ assert base_logger.handlers == []
+ assert not base_logger.propagate
+ assert base_logger.level == logging.NOTSET
+
+ module_logger = logging.getLogger("foogle.bar")
+ assert isinstance(module_logger.handlers[0], logging.StreamHandler)
+ assert not module_logger.propagate
+ assert module_logger.level == logging.DEBUG
+
+ # Check that `initialize_logging()` is a no-op after the first
time by verifying that user-set configs are not modified:
+ base_logger.propagate = True
+ module_logger.propagate = True
+
+ initialize_logging()
+
+ assert base_logger.propagate
+ assert module_logger.propagate
+
+ reset_logger("foogle")
+ reset_logger("foogle.bar")
+
+
+def test_structured_log_formatter():
+ # TODO(https://github.com/googleapis/python-api-core/issues/761): Test
additional fields when implemented.
+ record = logging.LogRecord(
+ name="Appelation",
+ level=logging.DEBUG,
+ msg="This is a test message.",
+ pathname="some/path",
+ lineno=25,
+ args=None,
+ exc_info=None,
+ )
+
+ # Extra fields:
+ record.rpcName = "bar"
+
+ formatted_msg = StructuredLogFormatter().format(record)
+ parsed_msg = json.loads(formatted_msg)
+
+ assert parsed_msg["name"] == "Appelation"
+ assert parsed_msg["severity"] == "DEBUG"
+ assert parsed_msg["message"] == "This is a test message."
+ assert parsed_msg["rpcName"] == "bar"