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 
<adrian.glaub...@suse.com>
+
+- 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 <googleapis-packa...@google.com>
 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 <googleapis-packa...@google.com>
 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"

Reply via email to