Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-opentelemetry-util-http for 
openSUSE:Factory checked in at 2026-03-30 18:30:48
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-opentelemetry-util-http (Old)
 and      /work/SRC/openSUSE:Factory/.python-opentelemetry-util-http.new.1999 
(New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-opentelemetry-util-http"

Mon Mar 30 18:30:48 2026 rev:8 rq:1343489 version:0.61b0

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/python-opentelemetry-util-http/python-opentelemetry-util-http.changes
    2026-01-06 17:43:59.864181360 +0100
+++ 
/work/SRC/openSUSE:Factory/.python-opentelemetry-util-http.new.1999/python-opentelemetry-util-http.changes
  2026-03-30 18:33:49.897410387 +0200
@@ -1,0 +2,6 @@
+Mon Mar 23 22:10:15 UTC 2026 - Dirk Müller <[email protected]>
+
+- - update to 0.61b0:
+  * Add Python 3.14 support
+
+-------------------------------------------------------------------

Old:
----
  opentelemetry_util_http-0.60b0.tar.gz

New:
----
  opentelemetry_util_http-0.61b0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-opentelemetry-util-http.spec ++++++
--- /var/tmp/diff_new_pack.qrw8RQ/_old  2026-03-30 18:33:50.661442329 +0200
+++ /var/tmp/diff_new_pack.qrw8RQ/_new  2026-03-30 18:33:50.665442497 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package python-opentelemetry-util-http
 #
-# Copyright (c) 2025 SUSE LLC and contributors
+# Copyright (c) 2026 SUSE LLC and contributors
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -18,7 +18,7 @@
 
 %{?sle15_python_module_pythons}
 Name:           python-opentelemetry-util-http
-Version:        0.60b0
+Version:        0.61b0
 Release:        0
 Summary:        Instrumentation Tools & Auto Instrumentation for OpenTelemetry 
Python
 License:        Apache-2.0

++++++ opentelemetry_util_http-0.60b0.tar.gz -> 
opentelemetry_util_http-0.61b0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/opentelemetry_util_http-0.60b0/PKG-INFO 
new/opentelemetry_util_http-0.61b0/PKG-INFO
--- old/opentelemetry_util_http-0.60b0/PKG-INFO 2020-02-02 01:00:00.000000000 
+0100
+++ new/opentelemetry_util_http-0.61b0/PKG-INFO 2020-02-02 01:00:00.000000000 
+0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.4
 Name: opentelemetry-util-http
-Version: 0.60b0
+Version: 0.61b0
 Summary: Web util for OpenTelemetry
 Project-URL: Homepage, 
https://github.com/open-telemetry/opentelemetry-python-contrib/tree/main/util/opentelemetry-util-http
 Project-URL: Repository, 
https://github.com/open-telemetry/opentelemetry-python-contrib
@@ -16,6 +16,7 @@
 Classifier: Programming Language :: Python :: 3.11
 Classifier: Programming Language :: Python :: 3.12
 Classifier: Programming Language :: Python :: 3.13
+Classifier: Programming Language :: Python :: 3.14
 Requires-Python: >=3.9
 Description-Content-Type: text/x-rst
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/opentelemetry_util_http-0.60b0/pyproject.toml 
new/opentelemetry_util_http-0.61b0/pyproject.toml
--- old/opentelemetry_util_http-0.60b0/pyproject.toml   2020-02-02 
01:00:00.000000000 +0100
+++ new/opentelemetry_util_http-0.61b0/pyproject.toml   2020-02-02 
01:00:00.000000000 +0100
@@ -23,6 +23,7 @@
   "Programming Language :: Python :: 3.11",
   "Programming Language :: Python :: 3.12",
   "Programming Language :: Python :: 3.13",
+  "Programming Language :: Python :: 3.14",
 ]
 
 [project.urls]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/opentelemetry_util_http-0.60b0/src/opentelemetry/util/http/__init__.py 
new/opentelemetry_util_http-0.61b0/src/opentelemetry/util/http/__init__.py
--- old/opentelemetry_util_http-0.60b0/src/opentelemetry/util/http/__init__.py  
2020-02-02 01:00:00.000000000 +0100
+++ new/opentelemetry_util_http-0.61b0/src/opentelemetry/util/http/__init__.py  
2020-02-02 01:00:00.000000000 +0100
@@ -19,7 +19,7 @@
 from re import IGNORECASE as RE_IGNORECASE
 from re import compile as re_compile
 from re import search
-from typing import Callable, Iterable, Optional, overload
+from typing import Callable, Iterable, overload
 from urllib.parse import parse_qs, urlencode, urlparse, urlunparse
 
 from opentelemetry.semconv._incubating.attributes.http_attributes import (
@@ -48,6 +48,12 @@
 OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_RESPONSE = (
     "OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_RESPONSE"
 )
+OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_CLIENT_REQUEST = (
+    "OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_CLIENT_REQUEST"
+)
+OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_CLIENT_RESPONSE = (
+    "OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_CLIENT_RESPONSE"
+)
 
 OTEL_PYTHON_INSTRUMENTATION_HTTP_CAPTURE_ALL_METHODS = (
     "OTEL_PYTHON_INSTRUMENTATION_HTTP_CAPTURE_ALL_METHODS"
@@ -251,6 +257,35 @@
     return []
 
 
+def get_custom_header_attributes(
+    headers: Mapping[str, str | list[str]] | None,
+    captured_headers: list[str] | None,
+    sensitive_headers: list[str] | None,
+    normalize_function: Callable[[str], str],
+) -> dict[str, list[str]]:
+    """Extract and sanitize HTTP headers for span attributes.
+
+    Args:
+        headers: The HTTP headers to process, either from a request or 
response.
+            Can be None if no headers are available.
+        captured_headers: List of header regexes to capture as span attributes.
+            If None or empty, no headers will be captured.
+        sensitive_headers: List of header regexes whose values should be 
sanitized
+            (redacted). If None, no sanitization is applied.
+        normalize_function: Function to normalize header names.
+
+    Returns:
+        Dictionary of normalized header attribute names to their values
+        as lists of strings.
+    """
+    if not headers or not captured_headers:
+        return {}
+    sanitize: SanitizeValue = SanitizeValue(sensitive_headers or ())
+    return sanitize.sanitize_header_values(
+        headers, captured_headers, normalize_function
+    )
+
+
 def _parse_active_request_count_attrs(req_attrs):
     active_requests_count_attrs = {
         key: req_attrs[key]
@@ -307,7 +342,24 @@
     return url
 
 
-def detect_synthetic_user_agent(user_agent: Optional[str]) -> Optional[str]:
+def normalize_user_agent(
+    user_agent: str | bytes | bytearray | memoryview | None,
+) -> str | None:
+    """Convert user-agent header values into a usable string."""
+    # Different servers/frameworks surface headers as str, bytes, bytearray or 
memoryview;
+    # keep decoding logic centralized so instrumentation modules just call 
this helper.
+    if user_agent is None:
+        return None
+    if isinstance(user_agent, str):
+        return user_agent
+    if isinstance(user_agent, (bytes, bytearray)):
+        return user_agent.decode("latin-1")
+    if isinstance(user_agent, memoryview):
+        return user_agent.tobytes().decode("latin-1")
+    return str(user_agent)
+
+
+def detect_synthetic_user_agent(user_agent: str | None) -> str | None:
     """
     Detect synthetic user agent type based on user agent string contents.
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/opentelemetry_util_http-0.60b0/src/opentelemetry/util/http/version.py 
new/opentelemetry_util_http-0.61b0/src/opentelemetry/util/http/version.py
--- old/opentelemetry_util_http-0.60b0/src/opentelemetry/util/http/version.py   
2020-02-02 01:00:00.000000000 +0100
+++ new/opentelemetry_util_http-0.61b0/src/opentelemetry/util/http/version.py   
2020-02-02 01:00:00.000000000 +0100
@@ -12,4 +12,4 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-__version__ = "0.60b0"
+__version__ = "0.61b0"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/opentelemetry_util_http-0.60b0/tests/test_detect_synthetic_user_agent.py 
new/opentelemetry_util_http-0.61b0/tests/test_detect_synthetic_user_agent.py
--- 
old/opentelemetry_util_http-0.60b0/tests/test_detect_synthetic_user_agent.py    
    2020-02-02 01:00:00.000000000 +0100
+++ 
new/opentelemetry_util_http-0.61b0/tests/test_detect_synthetic_user_agent.py    
    2020-02-02 01:00:00.000000000 +0100
@@ -17,7 +17,10 @@
 from opentelemetry.semconv._incubating.attributes.user_agent_attributes import 
(
     UserAgentSyntheticTypeValues,
 )
-from opentelemetry.util.http import detect_synthetic_user_agent
+from opentelemetry.util.http import (
+    detect_synthetic_user_agent,
+    normalize_user_agent,
+)
 
 
 class TestDetectSyntheticUserAgent(unittest.TestCase):
@@ -86,3 +89,44 @@
         result = detect_synthetic_user_agent(user_agent)
         # alwayson should be checked first and return 'test'
         self.assertEqual(result, UserAgentSyntheticTypeValues.TEST.value)
+
+    def test_bytes_like_user_agent(self):
+        """Test that bytes-like user agents are decoded and detected."""
+
+        test_cases = [
+            (b"alwayson-monitor/1.0", UserAgentSyntheticTypeValues.TEST.value),
+            (
+                bytearray(b"googlebot/2.1"),
+                UserAgentSyntheticTypeValues.BOT.value,
+            ),
+            (memoryview(b"MyApp/1.0"), None),
+        ]
+
+        for user_agent_raw, expected in test_cases:
+            with self.subTest(user_agent=user_agent_raw):
+                normalized = normalize_user_agent(user_agent_raw)
+                result = detect_synthetic_user_agent(normalized)
+                self.assertEqual(result, expected)
+
+
+class TestNormalizeUserAgent(unittest.TestCase):
+    def test_preserves_string(self):
+        self.assertEqual(normalize_user_agent("Mozilla"), "Mozilla")
+
+    def test_decodes_bytes(self):
+        self.assertEqual(
+            normalize_user_agent(b"Custom-Client/1.0"), "Custom-Client/1.0"
+        )
+
+    def test_decodes_bytearray(self):
+        self.assertEqual(
+            normalize_user_agent(bytearray(b"Bot/2.0")), "Bot/2.0"
+        )
+
+    def test_decodes_memoryview(self):
+        self.assertEqual(
+            normalize_user_agent(memoryview(b"Monitor/3.0")), "Monitor/3.0"
+        )
+
+    def test_none(self):
+        self.assertIsNone(normalize_user_agent(None))

Reply via email to