Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-azure-core for 
openSUSE:Factory checked in at 2026-01-06 17:41:35
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-azure-core (Old)
 and      /work/SRC/openSUSE:Factory/.python-azure-core.new.1928 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-azure-core"

Tue Jan  6 17:41:35 2026 rev:58 rq:1325405 version:1.37.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-azure-core/python-azure-core.changes      
2025-10-18 14:35:03.231488684 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-azure-core.new.1928/python-azure-core.changes
    2026-01-06 17:41:43.434601897 +0100
@@ -1,0 +2,8 @@
+Mon Jan  5 07:58:52 UTC 2026 - John Paul Adrian Glaubitz 
<[email protected]>
+
+- New upstream release
+  + Version 1.37.0
+  + For detailed information about changes see the
+    CHANGELOG.md file provided with this package
+
+-------------------------------------------------------------------

Old:
----
  azure_core-1.36.0.tar.gz

New:
----
  azure_core-1.37.0.tar.gz

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

Other differences:
------------------
++++++ python-azure-core.spec ++++++
--- /var/tmp/diff_new_pack.Vn4r8J/_old  2026-01-06 17:41:44.082628486 +0100
+++ /var/tmp/diff_new_pack.Vn4r8J/_new  2026-01-06 17:41:44.082628486 +0100
@@ -18,7 +18,7 @@
 
 %{?sle15_python_module_pythons}
 Name:           python-azure-core
-Version:        1.36.0
+Version:        1.37.0
 Release:        0
 Summary:        Microsoft Azure Core Library for Python
 License:        MIT

++++++ azure_core-1.36.0.tar.gz -> azure_core-1.37.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/azure_core-1.36.0/CHANGELOG.md 
new/azure_core-1.37.0/CHANGELOG.md
--- old/azure_core-1.36.0/CHANGELOG.md  2025-10-15 01:34:08.000000000 +0200
+++ new/azure_core-1.37.0/CHANGELOG.md  2025-12-11 19:57:42.000000000 +0100
@@ -1,14 +1,24 @@
 # Release History
 
+## 1.37.0 (2025-12-11)
+
+### Features Added
+
+- Added `get_backcompat_attr_name` to `azure.core.serialization`. 
`get_backcompat_attr_name` gets the backcompat name of an attribute using 
backcompat attribute access.  #44084
+
 ## 1.36.0 (2025-10-14)
 
 ### Features Added
 
 - Added `TypeHandlerRegistry` to `azure.core.serialization` to allow 
developers to register custom serializers and deserializers for specific types 
or conditions.  #43051
 
+### Breaking Changes
+
 ### Bugs Fixed
 
 - Fixed repeated import attempts of cchardet and chardet when 
charset_normalizer is used #43092
+- Fixed leaked requests and aiohttp exceptions for streamed responses #43200
+- Improved granularity of ServiceRequestError and ServiceResponseError 
exceptions raised in timeout scenarios from the requests and aiohttp transports 
#43200
 
 ### Other Changes
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/azure_core-1.36.0/PKG-INFO 
new/azure_core-1.37.0/PKG-INFO
--- old/azure_core-1.36.0/PKG-INFO      2025-10-15 01:34:50.758143200 +0200
+++ new/azure_core-1.37.0/PKG-INFO      2025-12-11 19:58:25.433900400 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.4
 Name: azure-core
-Version: 1.36.0
+Version: 1.37.0
 Summary: Microsoft Azure Core Library for Python
 Home-page: 
https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/core/azure-core
 Author: Microsoft Corporation
@@ -323,15 +323,25 @@
 
 # Release History
 
+## 1.37.0 (2025-12-11)
+
+### Features Added
+
+- Added `get_backcompat_attr_name` to `azure.core.serialization`. 
`get_backcompat_attr_name` gets the backcompat name of an attribute using 
backcompat attribute access.  #44084
+
 ## 1.36.0 (2025-10-14)
 
 ### Features Added
 
 - Added `TypeHandlerRegistry` to `azure.core.serialization` to allow 
developers to register custom serializers and deserializers for specific types 
or conditions.  #43051
 
+### Breaking Changes
+
 ### Bugs Fixed
 
 - Fixed repeated import attempts of cchardet and chardet when 
charset_normalizer is used #43092
+- Fixed leaked requests and aiohttp exceptions for streamed responses #43200
+- Improved granularity of ServiceRequestError and ServiceResponseError 
exceptions raised in timeout scenarios from the requests and aiohttp transports 
#43200
 
 ### Other Changes
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/azure_core-1.36.0/azure/core/_version.py 
new/azure_core-1.37.0/azure/core/_version.py
--- old/azure_core-1.36.0/azure/core/_version.py        2025-10-15 
01:34:08.000000000 +0200
+++ new/azure_core-1.37.0/azure/core/_version.py        2025-12-11 
19:57:42.000000000 +0100
@@ -9,4 +9,4 @@
 # regenerated.
 # --------------------------------------------------------------------------
 
-VERSION = "1.36.0"
+VERSION = "1.37.0"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/azure_core-1.36.0/azure/core/pipeline/_tools.py 
new/azure_core-1.37.0/azure/core/pipeline/_tools.py
--- old/azure_core-1.36.0/azure/core/pipeline/_tools.py 2025-10-15 
01:34:08.000000000 +0200
+++ new/azure_core-1.37.0/azure/core/pipeline/_tools.py 2025-12-11 
19:57:42.000000000 +0100
@@ -80,7 +80,5 @@
     """
     try:
         response.read()
+    finally:
         response.close()
-    except Exception as exc:
-        response.close()
-        raise exc
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/azure_core-1.36.0/azure/core/pipeline/_tools_async.py 
new/azure_core-1.37.0/azure/core/pipeline/_tools_async.py
--- old/azure_core-1.36.0/azure/core/pipeline/_tools_async.py   2025-10-15 
01:34:08.000000000 +0200
+++ new/azure_core-1.37.0/azure/core/pipeline/_tools_async.py   2025-12-11 
19:57:42.000000000 +0100
@@ -67,7 +67,5 @@
     """
     try:
         await response.read()
+    finally:
         await response.close()
-    except Exception as exc:
-        await response.close()
-        raise exc
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/azure_core-1.36.0/azure/core/pipeline/transport/_aiohttp.py 
new/azure_core-1.37.0/azure/core/pipeline/transport/_aiohttp.py
--- old/azure_core-1.36.0/azure/core/pipeline/transport/_aiohttp.py     
2025-10-15 01:34:08.000000000 +0200
+++ new/azure_core-1.37.0/azure/core/pipeline/transport/_aiohttp.py     
2025-12-11 19:57:42.000000000 +0100
@@ -474,7 +474,7 @@
         except aiohttp.client_exceptions.ClientResponseError as err:
             raise ServiceResponseError(err, error=err) from err
         except asyncio.TimeoutError as err:
-            raise ServiceResponseError(err, error=err) from err
+            raise ServiceResponseTimeoutError(err, error=err) from err
         except aiohttp.client_exceptions.ClientError as err:
             raise ServiceRequestError(err, error=err) from err
         except Exception as err:
@@ -571,7 +571,7 @@
         except aiohttp.client_exceptions.ClientResponseError as err:
             raise ServiceResponseError(err, error=err) from err
         except asyncio.TimeoutError as err:
-            raise ServiceResponseError(err, error=err) from err
+            raise ServiceResponseTimeoutError(err, error=err) from err
         except aiohttp.client_exceptions.ClientError as err:
             raise ServiceRequestError(err, error=err) from err
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/azure_core-1.36.0/azure/core/pipeline/transport/_requests_basic.py 
new/azure_core-1.37.0/azure/core/pipeline/transport/_requests_basic.py
--- old/azure_core-1.36.0/azure/core/pipeline/transport/_requests_basic.py      
2025-10-15 01:34:08.000000000 +0200
+++ new/azure_core-1.37.0/azure/core/pipeline/transport/_requests_basic.py      
2025-12-11 19:57:42.000000000 +0100
@@ -46,7 +46,9 @@
 from azure.core.configuration import ConnectionConfiguration
 from azure.core.exceptions import (
     ServiceRequestError,
+    ServiceRequestTimeoutError,
     ServiceResponseError,
+    ServiceResponseTimeoutError,
     IncompleteReadError,
     HttpResponseError,
     DecodeError,
@@ -85,7 +87,7 @@
         except CoreDecodeError as e:
             raise DecodeError(e, error=e) from e
         except ReadTimeoutError as e:
-            raise ServiceRequestError(e, error=e) from e
+            raise ServiceResponseTimeoutError(e, error=e) from e
     else:
         # Standard file-like object.
         while True:
@@ -202,6 +204,14 @@
             _LOGGER.warning("Unable to stream download.")
             internal_response.close()
             raise HttpResponseError(err, error=err) from err
+        except requests.ConnectionError as err:
+            internal_response.close()
+            if err.args and isinstance(err.args[0], ReadTimeoutError):
+                raise ServiceResponseTimeoutError(err, error=err) from err
+            raise ServiceResponseError(err, error=err) from err
+        except requests.RequestException as err:
+            internal_response.close()
+            raise ServiceResponseError(err, error=err) from err
         except Exception as err:
             _LOGGER.warning("Unable to stream download.")
             internal_response.close()
@@ -384,13 +394,14 @@
                     "Please report this issue to 
https://github.com/Azure/azure-sdk-for-python/issues.";
                 ) from err
             raise
-        except (
-            NewConnectionError,
-            ConnectTimeoutError,
-        ) as err:
+        except NewConnectionError as err:
             error = ServiceRequestError(err, error=err)
+        except ConnectTimeoutError as err:
+            error = ServiceRequestTimeoutError(err, error=err)
+        except requests.exceptions.ConnectTimeout as err:
+            error = ServiceRequestTimeoutError(err, error=err)
         except requests.exceptions.ReadTimeout as err:
-            error = ServiceResponseError(err, error=err)
+            error = ServiceResponseTimeoutError(err, error=err)
         except requests.exceptions.ConnectionError as err:
             if err.args and isinstance(err.args[0], ProtocolError):
                 error = ServiceResponseError(err, error=err)
@@ -405,7 +416,7 @@
                 _LOGGER.warning("Unable to stream download.")
                 error = HttpResponseError(err, error=err)
         except requests.RequestException as err:
-            error = ServiceRequestError(err, error=err)
+            error = ServiceResponseError(err, error=err)
 
         if error:
             raise error
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/azure_core-1.36.0/azure/core/rest/_aiohttp.py 
new/azure_core-1.37.0/azure/core/rest/_aiohttp.py
--- old/azure_core-1.36.0/azure/core/rest/_aiohttp.py   2025-10-15 
01:34:08.000000000 +0200
+++ new/azure_core-1.37.0/azure/core/rest/_aiohttp.py   2025-12-11 
19:57:42.000000000 +0100
@@ -27,14 +27,23 @@
 import asyncio  # pylint: disable=do-not-import-asyncio
 from itertools import groupby
 from typing import Iterator, cast
+
+import aiohttp
 from multidict import CIMultiDict
+
 from ._http_response_impl_async import (
     AsyncHttpResponseImpl,
     AsyncHttpResponseBackcompatMixin,
 )
 from ..pipeline.transport._aiohttp import AioHttpStreamDownloadGenerator
 from ..utils._pipeline_transport_rest_shared import _pad_attr_name, 
_aiohttp_body_helper
-from ..exceptions import ResponseNotReadError
+from ..exceptions import (
+    ResponseNotReadError,
+    IncompleteReadError,
+    ServiceResponseError,
+    ServiceResponseTimeoutError,
+    ServiceRequestError,
+)
 
 
 class _ItemsView(collections.abc.ItemsView):
@@ -212,7 +221,18 @@
         """
         if not self._content:
             self._stream_download_check()
-            self._content = await self._internal_response.read()
+            try:
+                self._content = await self._internal_response.read()
+            except aiohttp.client_exceptions.ClientPayloadError as err:
+                # This is the case that server closes connection before we 
finish the reading. aiohttp library
+                # raises ClientPayloadError.
+                raise IncompleteReadError(err, error=err) from err
+            except aiohttp.client_exceptions.ClientResponseError as err:
+                raise ServiceResponseError(err, error=err) from err
+            except asyncio.TimeoutError as err:
+                raise ServiceResponseTimeoutError(err, error=err) from err
+            except aiohttp.client_exceptions.ClientError as err:
+                raise ServiceRequestError(err, error=err) from err
         await self._set_read_checks()
         return _aiohttp_body_helper(self)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/azure_core-1.36.0/azure/core/serialization.py 
new/azure_core-1.37.0/azure/core/serialization.py
--- old/azure_core-1.36.0/azure/core/serialization.py   2025-10-15 
01:34:08.000000000 +0200
+++ new/azure_core-1.37.0/azure/core/serialization.py   2025-12-11 
19:57:42.000000000 +0100
@@ -4,6 +4,7 @@
 # Licensed under the MIT License. See License.txt in the project root for
 # license information.
 # --------------------------------------------------------------------------
+# pylint: disable=protected-access
 import base64
 from functools import partial
 from json import JSONEncoder
@@ -19,6 +20,7 @@
     "as_attribute_dict",
     "attribute_list",
     "TypeHandlerRegistry",
+    "get_backcompat_attr_name",
 ]
 TZ_UTC = timezone.utc
 
@@ -317,7 +319,7 @@
     :rtype: bool
     """
     try:
-        return p._visibility == ["read"]  # pylint: disable=protected-access
+        return p._visibility == ["read"]
     except AttributeError:
         return False
 
@@ -332,6 +334,20 @@
     return as_attribute_dict(v, exclude_readonly=exclude_readonly) if 
is_generated_model(v) else v
 
 
+def _get_backcompat_name(rest_field: Any, default_attr_name: str) -> str:
+    """Get the backcompat name for an attribute.
+
+    :param any rest_field: The rest field to get the backcompat name from.
+    :param str default_attr_name: The default attribute name to use if no 
backcompat name
+    :return: The backcompat name.
+    :rtype: str
+    """
+    try:
+        return rest_field._original_tsp_name or default_attr_name
+    except AttributeError:
+        return default_attr_name
+
+
 def _get_flattened_attribute(obj: Any) -> Optional[str]:
     """Get the name of the flattened attribute in a generated TypeSpec model 
if one exists.
 
@@ -348,11 +364,9 @@
     if flattened_items is None:
         return None
 
-    for k, v in obj._attr_to_rest_field.items():  # pylint: 
disable=protected-access
+    for k, v in obj._attr_to_rest_field.items():
         try:
-            if set(v._class_type._attr_to_rest_field.keys()).intersection(  # 
pylint: disable=protected-access
-                set(flattened_items)
-            ):
+            if 
set(v._class_type._attr_to_rest_field.keys()).intersection(set(flattened_items)):
                 return k
         except AttributeError:
             # if the attribute does not have _class_type, it is not a typespec 
generated model
@@ -372,12 +386,12 @@
         raise TypeError("Object is not a generated SDK model.")
     if hasattr(obj, "_attribute_map"):
         # msrest model
-        return list(obj._attribute_map.keys())  # pylint: 
disable=protected-access
+        return list(obj._attribute_map.keys())
     flattened_attribute = _get_flattened_attribute(obj)
     retval: List[str] = []
-    for attr_name, rest_field in obj._attr_to_rest_field.items():  # pylint: 
disable=protected-access
+    for attr_name, rest_field in obj._attr_to_rest_field.items():
         if flattened_attribute == attr_name:
-            retval.extend(attribute_list(rest_field._class_type))  # pylint: 
disable=protected-access
+            retval.extend(attribute_list(rest_field._class_type))
         else:
             retval.append(attr_name)
     return retval
@@ -410,16 +424,16 @@
         # create a reverse mapping from rest field name to attribute name
         rest_to_attr = {}
         flattened_attribute = _get_flattened_attribute(obj)
-        for attr_name, rest_field in obj._attr_to_rest_field.items():  # 
pylint: disable=protected-access
+        for attr_name, rest_field in obj._attr_to_rest_field.items():
 
             if exclude_readonly and _is_readonly(rest_field):
                 # if we're excluding readonly properties, we need to track them
-                readonly_props.add(rest_field._rest_name)  # pylint: 
disable=protected-access
+                readonly_props.add(rest_field._rest_name)
             if flattened_attribute == attr_name:
-                for fk, fv in 
rest_field._class_type._attr_to_rest_field.items():  # pylint: 
disable=protected-access
-                    rest_to_attr[fv._rest_name] = fk  # pylint: 
disable=protected-access
+                for fk, fv in 
rest_field._class_type._attr_to_rest_field.items():
+                    rest_to_attr[fv._rest_name] = fk
             else:
-                rest_to_attr[rest_field._rest_name] = attr_name  # pylint: 
disable=protected-access
+                rest_to_attr[rest_field._rest_name] = attr_name
         for k, v in obj.items():
             if exclude_readonly and k in readonly_props:  # pyright: ignore
                 continue
@@ -429,10 +443,8 @@
             else:
                 is_multipart_file_input = False
                 try:
-                    is_multipart_file_input = next(  # pylint: 
disable=protected-access
-                        rf
-                        for rf in obj._attr_to_rest_field.values()  # pylint: 
disable=protected-access
-                        if rf._rest_name == k  # pylint: 
disable=protected-access
+                    is_multipart_file_input = next(
+                        rf for rf in obj._attr_to_rest_field.values() if 
rf._rest_name == k
                     )._is_multipart_file_input
                 except StopIteration:
                     pass
@@ -444,3 +456,36 @@
     except AttributeError as exc:
         # not a typespec generated model
         raise TypeError("Object must be a generated model instance.") from exc
+
+
+def get_backcompat_attr_name(model: Any, attr_name: str) -> str:
+    """Get the backcompat attribute name for a given attribute.
+
+    This function takes an attribute name and returns the backcompat name 
(original TSP name)
+    if one exists, otherwise returns the attribute name itself.
+
+    :param any model: The model instance.
+    :param str attr_name: The attribute name to get the backcompat name for.
+    :return: The backcompat attribute name (original TSP name) or the 
attribute name itself.
+    :rtype: str
+    """
+    if not is_generated_model(model):
+        raise TypeError("Object must be a generated model instance.")
+
+    # Check if attr_name exists in the model's attributes
+    flattened_attribute = _get_flattened_attribute(model)
+    for field_attr_name, rest_field in model._attr_to_rest_field.items():
+        # Check if this is the attribute we're looking for
+        if field_attr_name == attr_name:
+            # Return the original TSP name if it exists, otherwise the 
attribute name
+            return _get_backcompat_name(rest_field, attr_name)
+
+        # If this is a flattened attribute, check inside it
+        if flattened_attribute == field_attr_name:
+            for fk, fv in rest_field._class_type._attr_to_rest_field.items():
+                if fk == attr_name:
+                    # Return the original TSP name for this flattened property
+                    return _get_backcompat_name(fv, fk)
+
+    # If not found in the model, just return the attribute name as-is
+    return attr_name
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/azure_core-1.36.0/azure_core.egg-info/PKG-INFO 
new/azure_core-1.37.0/azure_core.egg-info/PKG-INFO
--- old/azure_core-1.36.0/azure_core.egg-info/PKG-INFO  2025-10-15 
01:34:50.000000000 +0200
+++ new/azure_core-1.37.0/azure_core.egg-info/PKG-INFO  2025-12-11 
19:58:25.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.4
 Name: azure-core
-Version: 1.36.0
+Version: 1.37.0
 Summary: Microsoft Azure Core Library for Python
 Home-page: 
https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/core/azure-core
 Author: Microsoft Corporation
@@ -323,15 +323,25 @@
 
 # Release History
 
+## 1.37.0 (2025-12-11)
+
+### Features Added
+
+- Added `get_backcompat_attr_name` to `azure.core.serialization`. 
`get_backcompat_attr_name` gets the backcompat name of an attribute using 
backcompat attribute access.  #44084
+
 ## 1.36.0 (2025-10-14)
 
 ### Features Added
 
 - Added `TypeHandlerRegistry` to `azure.core.serialization` to allow 
developers to register custom serializers and deserializers for specific types 
or conditions.  #43051
 
+### Breaking Changes
+
 ### Bugs Fixed
 
 - Fixed repeated import attempts of cchardet and chardet when 
charset_normalizer is used #43092
+- Fixed leaked requests and aiohttp exceptions for streamed responses #43200
+- Improved granularity of ServiceRequestError and ServiceResponseError 
exceptions raised in timeout scenarios from the requests and aiohttp transports 
#43200
 
 ### Other Changes
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/azure_core-1.36.0/azure_core.egg-info/SOURCES.txt 
new/azure_core-1.37.0/azure_core.egg-info/SOURCES.txt
--- old/azure_core-1.36.0/azure_core.egg-info/SOURCES.txt       2025-10-15 
01:34:50.000000000 +0200
+++ new/azure_core-1.37.0/azure_core.egg-info/SOURCES.txt       2025-12-11 
19:58:25.000000000 +0100
@@ -97,6 +97,8 @@
 samples/example_shared_transport_async.py
 samples/example_tracing.py
 samples/example_tracing_async.py
+samples/example_truststore_injection.py
+samples/example_truststore_ssl_context.py
 samples/test_example_async.py
 samples/test_example_policies.py
 samples/test_example_sansio.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/azure_core-1.36.0/samples/README.md 
new/azure_core-1.37.0/samples/README.md
--- old/azure_core-1.36.0/samples/README.md     2025-10-15 01:34:08.000000000 
+0200
+++ new/azure_core-1.37.0/samples/README.md     2025-12-11 19:57:42.000000000 
+0100
@@ -22,5 +22,10 @@
 
 These are some code snippets that show the way in which end users can 
customize the behavior.
 
-[shared_transport.py](https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/core/azure-core/samples/example_shared_transport.py)
 - samples of how to use a shared sync transport
-[shared_transport_async.py](https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/core/azure-core/samples/example_shared_transport_async.py)
 - samples of how to use a shared async transport
+[example_shared_transport.py](https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/core/azure-core/samples/example_shared_transport.py)
 - samples of how to use a shared sync transport
+
+[example_shared_transport_async.py](https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/core/azure-core/samples/example_shared_transport_async.py)
 - samples of how to use a shared async transport
+
+[example_truststore_injection.py](https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/core/azure-core/samples/example_truststore_injection.py)
 - samples of how to use the `truststore` library to leverage OS certificate 
stores via global injection
+
+[example_truststore_ssl_context.py](https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/core/azure-core/samples/example_truststore_ssl_context.py)
 - samples of how to use `truststore.SSLContext` directly with custom transport 
sessions
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/azure_core-1.36.0/samples/example_truststore_injection.py 
new/azure_core-1.37.0/samples/example_truststore_injection.py
--- old/azure_core-1.36.0/samples/example_truststore_injection.py       
1970-01-01 01:00:00.000000000 +0100
+++ new/azure_core-1.37.0/samples/example_truststore_injection.py       
2025-12-11 19:57:42.000000000 +0100
@@ -0,0 +1,90 @@
+# coding: utf-8
+
+# -------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for
+# license information.
+# --------------------------------------------------------------------------
+
+"""
+Example: Using truststore with Azure SDK for Python (Sync and Async)
+
+This sample demonstrates how to use the `truststore` library to leverage
+operating system certificate stores when working with Azure SDK for Python,
+including both synchronous (requests) and asynchronous (aiohttp)
+HTTP clients.
+
+Requirements:
+    pip install truststore azure-identity azure-storage-blob aiohttp
+USAGE:
+    python example_truststore_injection.py
+"""
+
+import asyncio
+import truststore
+
+# Inject truststore BEFORE importing Azure SDK libraries
+truststore.inject_into_ssl()
+
+# Synchronous imports
+from azure.identity import DefaultAzureCredential
+from azure.storage.blob import BlobServiceClient
+
+# Asynchronous imports
+from azure.identity.aio import DefaultAzureCredential as 
AsyncDefaultAzureCredential
+from azure.storage.blob.aio import BlobServiceClient as AsyncBlobServiceClient
+
+
+# =============================================================================
+# Synchronous Example
+# =============================================================================
+
+
+def sync_blob_storage_example():
+    """Synchronous Azure Blob Storage with system certificates."""
+
+    account_url = "https://<your-storage-account>.blob.core.windows.net"
+
+    credential = DefaultAzureCredential()
+    blob_service_client = BlobServiceClient(account_url=account_url, 
credential=credential)
+
+    print("=== Sync Blob Storage ===")
+    for container in blob_service_client.list_containers():
+        print(f"Container: {container['name']}")
+
+    blob_service_client.close()
+    credential.close()
+
+
+# =============================================================================
+# Asynchronous Example (uses aiohttp underneath)
+# =============================================================================
+
+
+async def async_blob_storage_example():
+    """Asynchronous Azure Blob Storage with system certificates (aiohttp)."""
+
+    account_url = "https://<your-storage-account>.blob.core.windows.net"
+
+    # Async credential and client - aiohttp will use the injected truststore
+    credential = AsyncDefaultAzureCredential()
+    blob_service_client = AsyncBlobServiceClient(account_url=account_url, 
credential=credential)
+
+    print("=== Async Blob Storage ===")
+    async for container in blob_service_client.list_containers():
+        print(f"Container: {container['name']}")
+
+    # Always close async clients
+    await blob_service_client.close()
+    await credential.close()
+
+
+async def main():
+    # Run async example
+    await async_blob_storage_example()
+
+
+if __name__ == "__main__":
+    sync_blob_storage_example()
+    asyncio.run(main())
+    truststore.extract_from_ssl()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/azure_core-1.36.0/samples/example_truststore_ssl_context.py 
new/azure_core-1.37.0/samples/example_truststore_ssl_context.py
--- old/azure_core-1.36.0/samples/example_truststore_ssl_context.py     
1970-01-01 01:00:00.000000000 +0100
+++ new/azure_core-1.37.0/samples/example_truststore_ssl_context.py     
2025-12-11 19:57:42.000000000 +0100
@@ -0,0 +1,143 @@
+# coding: utf-8
+
+# -------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for
+# license information.
+# --------------------------------------------------------------------------
+
+"""
+Example: Using truststore.SSLContext with Azure SDK for Python (Sync and Async)
+
+This sample demonstrates how to use `truststore.SSLContext` directly to 
leverage
+operating system certificate stores when working with Azure SDK for Python.
+
+Unlike `truststore.inject_into_ssl()` which globally patches the ssl module,
+this approach gives you more control over which connections use system 
certificates
+by creating custom transport sessions with a truststore-based SSLContext.
+
+Requirements:
+    pip install truststore azure-identity azure-storage-blob aiohttp requests
+USAGE:
+    python example_truststore_ssl_context.py
+"""
+
+import ssl
+import asyncio
+import truststore
+import requests
+import aiohttp
+from requests.adapters import HTTPAdapter
+
+from azure.identity import DefaultAzureCredential
+from azure.identity.aio import DefaultAzureCredential as 
AsyncDefaultAzureCredential
+from azure.storage.blob import BlobServiceClient
+from azure.storage.blob.aio import BlobServiceClient as AsyncBlobServiceClient
+from azure.core.pipeline.transport import RequestsTransport, AioHttpTransport
+
+
+# =============================================================================
+# Helper: Custom HTTPAdapter for requests
+# =============================================================================
+
+
+class TruststoreHTTPAdapter(HTTPAdapter):
+    """Custom HTTPAdapter that uses truststore.SSLContext for SSL 
verification."""
+
+    def __init__(self, ssl_context, **kwargs):
+        self._ssl_context = ssl_context
+        super().__init__(**kwargs)
+
+    def init_poolmanager(self, *args, **kwargs):
+        kwargs["ssl_context"] = self._ssl_context
+        return super().init_poolmanager(*args, **kwargs)
+
+
+# =============================================================================
+# Synchronous Example
+# =============================================================================
+
+
+def sync_blob_storage_with_ssl_context():
+    """Synchronous Azure Blob Storage using truststore.SSLContext directly.
+
+    This approach gives you more control over the SSL context configuration
+    without globally injecting truststore into ssl module.
+    """
+
+    account_url = "https://<your-storage-account>.blob.core.windows.net"
+
+    # Create SSLContext using truststore (uses system certificate stores)
+    ssl_context = truststore.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
+
+    # Create a session with truststore adapter
+    session = requests.Session()
+    adapter = TruststoreHTTPAdapter(ssl_context)
+    session.mount("https://";, adapter)
+
+    # Create transport with the custom session
+    transport = RequestsTransport(session=session, session_owner=False)
+
+    with transport:
+        credential = DefaultAzureCredential()
+        blob_service_client = BlobServiceClient(
+            account_url=account_url,
+            credential=credential,
+            transport=transport,
+        )
+
+        print("=== Sync Blob Storage with SSLContext ===")
+        for container in blob_service_client.list_containers():
+            print(f"Container: {container['name']}")
+
+        blob_service_client.close()
+        credential.close()
+
+    session.close()  # Close the session manually since session_owner=False
+
+
+# =============================================================================
+# Asynchronous Example
+# =============================================================================
+
+
+async def async_blob_storage_with_ssl_context():
+    """Asynchronous Azure Blob Storage using truststore.SSLContext directly.
+
+    This approach gives you more control over the SSL context configuration
+    without globally injecting truststore into ssl module.
+    """
+
+    account_url = "https://<your-storage-account>.blob.core.windows.net"
+
+    # Create SSLContext using truststore (uses system certificate stores)
+    ssl_context = truststore.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
+
+    # Create a TCPConnector with our truststore SSLContext
+    connector = aiohttp.TCPConnector(ssl=ssl_context)
+    session = aiohttp.ClientSession(connector=connector)
+
+    # Create transport with the custom session
+    transport = AioHttpTransport(session=session, session_owner=False)
+
+    async with transport:
+        credential = AsyncDefaultAzureCredential()
+        blob_service_client = AsyncBlobServiceClient(
+            account_url=account_url,
+            credential=credential,
+            transport=transport,
+        )
+
+        print("=== Async Blob Storage with SSLContext ===")
+        async for container in blob_service_client.list_containers():
+            print(f"Container: {container['name']}")
+
+        await blob_service_client.close()
+        await credential.close()
+
+    await session.close()  # Close the session manually since 
session_owner=False
+
+
+if __name__ == "__main__":
+    sync_blob_storage_with_ssl_context()
+    asyncio.run(async_blob_storage_with_ssl_context())
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/azure_core-1.36.0/tests/async_tests/test_basic_transport_async.py 
new/azure_core-1.37.0/tests/async_tests/test_basic_transport_async.py
--- old/azure_core-1.36.0/tests/async_tests/test_basic_transport_async.py       
2025-10-15 01:34:08.000000000 +0200
+++ new/azure_core-1.37.0/tests/async_tests/test_basic_transport_async.py       
2025-12-11 19:57:42.000000000 +0100
@@ -3,6 +3,15 @@
 # Licensed under the MIT License. See LICENSE.txt in the project root for
 # license information.
 # -------------------------------------------------------------------------
+
+import pytest
+import sys
+import asyncio
+from packaging.version import Version
+from unittest import mock
+
+import aiohttp
+
 from azure.core.pipeline.transport import (
     AsyncHttpResponse as PipelineTransportAsyncHttpResponse,
     AsyncHttpTransport,
@@ -21,13 +30,8 @@
     ServiceRequestTimeoutError,
     ServiceResponseTimeoutError,
 )
+
 from utils import HTTP_REQUESTS, request_and_responses_product
-import pytest
-import sys
-import asyncio
-from unittest.mock import Mock
-from packaging.version import Version
-import aiohttp
 
 
 # transport = mock.MagicMock(spec=AsyncHttpTransport)
@@ -1049,47 +1053,66 @@
     assert result  # No exception is good enough here
 
 
[email protected](
-    Version(aiohttp.__version__) >= Version("3.10"),
-    reason="aiohttp 3.10 introduced separate connection timeout",
-)
 @pytest.mark.parametrize("http_request", HTTP_REQUESTS)
 @pytest.mark.asyncio
-async def test_aiohttp_timeout_response(http_request):
+async def test_aiohttp_timeout_response(port, http_request):
     async with AioHttpTransport() as transport:
-        transport.session._connector.connect = 
Mock(side_effect=asyncio.TimeoutError("Too slow!"))
-
-        request = http_request("GET", f"http://localhost:12345/basic/string";)
-
-        with pytest.raises(ServiceResponseTimeoutError) as err:
-            await transport.send(request)
 
-        with pytest.raises(ServiceResponseError) as err:
-            await transport.send(request)
+        request = http_request("GET", f"http://localhost:{port}/basic/string";)
 
-        stream_request = http_request("GET", 
f"http://localhost:12345/streams/basic";)
-        with pytest.raises(ServiceResponseTimeoutError) as err:
-            await transport.send(stream_request, stream=True)
+        with mock.patch.object(
+            aiohttp.ClientResponse, "start", 
side_effect=asyncio.TimeoutError("Too slow!")
+        ) as mock_method:
+            with pytest.raises(ServiceResponseTimeoutError) as err:
+                await transport.send(request)
+
+            with pytest.raises(ServiceResponseError) as err:
+                await transport.send(request)
+
+            stream_resp = http_request("GET", 
f"http://localhost:{port}/streams/basic";)
+            with pytest.raises(ServiceResponseTimeoutError) as err:
+                await transport.send(stream_resp, stream=True)
+
+        stream_resp = await transport.send(stream_resp, stream=True)
+        with mock.patch.object(
+            aiohttp.streams.StreamReader, "read", 
side_effect=asyncio.TimeoutError("Too slow!")
+        ) as mock_method:
+            with pytest.raises(ServiceResponseTimeoutError) as err:
+                try:
+                    # current HttpResponse
+                    await stream_resp.read()
+                except AttributeError:
+                    # legacy HttpResponse
+                    b"".join([b async for b in 
stream_resp.stream_download(None)])
 
 
[email protected](
-    Version(aiohttp.__version__) < Version("3.10"),
-    reason="aiohttp 3.10 introduced separate connection timeout",
-)
 @pytest.mark.parametrize("http_request", HTTP_REQUESTS)
 @pytest.mark.asyncio
 async def test_aiohttp_timeout_request(http_request):
     async with AioHttpTransport() as transport:
-        transport.session._connector.connect = 
Mock(side_effect=asyncio.TimeoutError("Too slow!"))
+        transport.session._connector.connect = 
mock.Mock(side_effect=asyncio.TimeoutError("Too slow!"))
 
         request = http_request("GET", f"http://localhost:12345/basic/string";)
 
-        with pytest.raises(ServiceRequestTimeoutError) as err:
-            await transport.send(request)
-
-        with pytest.raises(ServiceRequestError) as err:
-            await transport.send(request)
-
-        stream_request = http_request("GET", 
f"http://localhost:12345/streams/basic";)
-        with pytest.raises(ServiceRequestTimeoutError) as err:
-            await transport.send(stream_request, stream=True)
+        # aiohttp 3.10 introduced separate connection timeout
+        if Version(aiohttp.__version__) >= Version("3.10"):
+            with pytest.raises(ServiceRequestTimeoutError) as err:
+                await transport.send(request)
+
+            with pytest.raises(ServiceRequestError) as err:
+                await transport.send(request)
+
+            stream_request = http_request("GET", 
f"http://localhost:12345/streams/basic";)
+            with pytest.raises(ServiceRequestTimeoutError) as err:
+                await transport.send(stream_request, stream=True)
+
+        else:
+            with pytest.raises(ServiceResponseTimeoutError) as err:
+                await transport.send(request)
+
+            with pytest.raises(ServiceResponseError) as err:
+                await transport.send(request)
+
+            stream_request = http_request("GET", 
f"http://localhost:12345/streams/basic";)
+            with pytest.raises(ServiceResponseTimeoutError) as err:
+                await transport.send(stream_request, stream=True)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/azure_core-1.36.0/tests/specs_sdk/modeltypes/modeltypes/_utils/model_base.py
 
new/azure_core-1.37.0/tests/specs_sdk/modeltypes/modeltypes/_utils/model_base.py
--- 
old/azure_core-1.36.0/tests/specs_sdk/modeltypes/modeltypes/_utils/model_base.py
    2025-10-15 01:34:08.000000000 +0200
+++ 
new/azure_core-1.37.0/tests/specs_sdk/modeltypes/modeltypes/_utils/model_base.py
    2025-12-11 19:57:42.000000000 +0100
@@ -654,6 +654,10 @@
                 if not rf._rest_name_input:
                     rf._rest_name_input = attr
             cls._attr_to_rest_field: typing.Dict[str, _RestField] = 
dict(attr_to_rest_field.items())
+            cls._backcompat_attr_to_rest_field: typing.Dict[str, _RestField] = 
{
+                Model._get_backcompat_attribute_name(cls._attr_to_rest_field, 
attr): rf
+                for attr, rf in cls._attr_to_rest_field.items()
+            }
             cls._calculated.add(f"{cls.__module__}.{cls.__qualname__}")
 
         return super().__new__(cls)
@@ -664,6 +668,16 @@
                 base.__mapping__[discriminator or cls.__name__] = cls  # type: 
ignore
 
     @classmethod
+    def _get_backcompat_attribute_name(cls, _attr_to_rest_field: 
typing.Dict[str, "_RestField"], attr_name: str) -> str:
+        rest_field = _attr_to_rest_field.get(attr_name)  # pylint: 
disable=protected-access
+        if rest_field is None:
+            return attr_name
+        original_tsp_name = getattr(rest_field, "_original_tsp_name", None)  # 
pylint: disable=protected-access
+        if original_tsp_name:
+            return original_tsp_name
+        return attr_name
+
+    @classmethod
     def _get_discriminator(cls, exist_discriminators) -> 
typing.Optional["_RestField"]:
         for v in cls.__dict__.values():
             if isinstance(v, _RestField) and v._is_discriminator and 
v._rest_name not in exist_discriminators:
@@ -998,6 +1012,7 @@
         format: typing.Optional[str] = None,
         is_multipart_file_input: bool = False,
         xml: typing.Optional[typing.Dict[str, typing.Any]] = None,
+        original_tsp_name: typing.Optional[str] = None,
     ):
         self._type = type
         self._rest_name_input = name
@@ -1009,6 +1024,7 @@
         self._format = format
         self._is_multipart_file_input = is_multipart_file_input
         self._xml = xml if xml is not None else {}
+        self._original_tsp_name = original_tsp_name
 
     @property
     def _class_type(self) -> typing.Any:
@@ -1060,6 +1076,7 @@
     format: typing.Optional[str] = None,
     is_multipart_file_input: bool = False,
     xml: typing.Optional[typing.Dict[str, typing.Any]] = None,
+    original_tsp_name: typing.Optional[str] = None,
 ) -> typing.Any:
     return _RestField(
         name=name,
@@ -1069,6 +1086,7 @@
         format=format,
         is_multipart_file_input=is_multipart_file_input,
         xml=xml,
+        original_tsp_name=original_tsp_name,
     )
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/azure_core-1.36.0/tests/test_basic_transport.py 
new/azure_core-1.37.0/tests/test_basic_transport.py
--- old/azure_core-1.36.0/tests/test_basic_transport.py 2025-10-15 
01:34:08.000000000 +0200
+++ new/azure_core-1.37.0/tests/test_basic_transport.py 2025-12-11 
19:57:42.000000000 +0100
@@ -5,28 +5,35 @@
 # -------------------------------------------------------------------------
 from http.client import HTTPConnection
 from collections import OrderedDict
-import sys
+import logging
+import pytest
+from unittest import mock
+from socket import timeout as SocketTimeout
 
-try:
-    from unittest import mock
-except ImportError:
-    import mock
+from urllib3.util import connection as urllib_connection
+from urllib3.response import HTTPResponse as UrllibResponse
+from urllib3.connection import HTTPConnection as UrllibConnection
 
+from azure.core.rest._http_response_impl import HttpResponseImpl as 
RestHttpResponseImpl
+from azure.core.pipeline._tools import is_rest
 from azure.core.pipeline.transport import HttpResponse as 
PipelineTransportHttpResponse, RequestsTransport
 from azure.core.pipeline.transport._base import HttpTransport, 
_deserialize_response, _urljoin
 from azure.core.pipeline.policies import HeadersPolicy
 from azure.core.pipeline import Pipeline
-from azure.core.exceptions import HttpResponseError
-import logging
-import pytest
+from azure.core.exceptions import (
+    HttpResponseError,
+    ServiceRequestError,
+    ServiceResponseError,
+    ServiceRequestTimeoutError,
+    ServiceResponseTimeoutError,
+)
+
 from utils import (
     HTTP_REQUESTS,
     request_and_responses_product,
     HTTP_CLIENT_TRANSPORT_RESPONSES,
     create_transport_response,
 )
-from azure.core.rest._http_response_impl import HttpResponseImpl as 
RestHttpResponseImpl
-from azure.core.pipeline._tools import is_rest
 
 
 class PipelineTransportMockResponse(PipelineTransportHttpResponse):
@@ -1322,3 +1329,49 @@
     result = transport.send(request)
 
     assert result  # No exception is good enough here
+
+
[email protected]("http_request", HTTP_REQUESTS)
+def test_requests_timeout_response(caplog, port, http_request):
+    transport = RequestsTransport()
+
+    request = http_request("GET", f"http://localhost:{port}/basic/string";)
+
+    with mock.patch.object(UrllibConnection, "getresponse", 
side_effect=SocketTimeout) as mock_method:
+        with pytest.raises(ServiceResponseTimeoutError) as err:
+            transport.send(request, read_timeout=0.0001)
+
+        with pytest.raises(ServiceResponseError) as err:
+            transport.send(request, read_timeout=0.0001)
+
+        stream_request = http_request("GET", 
f"http://localhost:{port}/streams/basic";)
+        with pytest.raises(ServiceResponseTimeoutError) as err:
+            transport.send(stream_request, stream=True, read_timeout=0.0001)
+
+    stream_resp = transport.send(stream_request, stream=True)
+    with mock.patch.object(UrllibResponse, "_handle_chunk", 
side_effect=SocketTimeout) as mock_method:
+        with pytest.raises(ServiceResponseTimeoutError) as err:
+            try:
+                # current HttpResponse
+                stream_resp.read()
+            except AttributeError:
+                # legacy HttpResponse
+                b"".join(stream_resp.stream_download(None))
+
+
[email protected]("http_request", HTTP_REQUESTS)
+def test_requests_timeout_request(caplog, port, http_request):
+    transport = RequestsTransport()
+
+    request = http_request("GET", f"http://localhost:{port}/basic/string";)
+
+    with mock.patch.object(urllib_connection, "create_connection", 
side_effect=SocketTimeout) as mock_method:
+        with pytest.raises(ServiceRequestTimeoutError) as err:
+            transport.send(request, connection_timeout=0.0001)
+
+        with pytest.raises(ServiceRequestTimeoutError) as err:
+            transport.send(request, connection_timeout=0.0001)
+
+        stream_request = http_request("GET", 
f"http://localhost:{port}/streams/basic";)
+        with pytest.raises(ServiceRequestTimeoutError) as err:
+            transport.send(stream_request, stream=True, 
connection_timeout=0.0001)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/azure_core-1.36.0/tests/test_serialization.py 
new/azure_core-1.37.0/tests/test_serialization.py
--- old/azure_core-1.36.0/tests/test_serialization.py   2025-10-15 
01:34:08.000000000 +0200
+++ new/azure_core-1.37.0/tests/test_serialization.py   2025-12-11 
19:57:42.000000000 +0100
@@ -7,11 +7,17 @@
 from enum import Enum
 import json
 import sys
-import traceback
 from typing import Any, Dict, List, Optional, Union, Type
 from io import BytesIO
 
-from azure.core.serialization import AzureJSONEncoder, NULL, 
as_attribute_dict, is_generated_model, attribute_list
+from azure.core.serialization import (
+    AzureJSONEncoder,
+    NULL,
+    as_attribute_dict,
+    get_backcompat_attr_name,
+    is_generated_model,
+    attribute_list,
+)
 from azure.core.exceptions import DeserializationError
 import pytest
 from modeltypes._utils.model_base import (
@@ -1644,3 +1650,463 @@
         deserialized_a = _deserialize(ModelA, json_dict_a)
         assert isinstance(deserialized_a, ModelA)
         assert deserialized_a.type == "A2"
+
+
+class TestBackcompatPropertyMatrix:
+    """
+    Systematic test matrix for DPG model property backcompat scenarios.
+
+    Tests all combinations of 5 key dimensions:
+    1. wireName: same/different from attr_name
+    2. attr_name: normal/padded (reserved word)
+    3. original_tsp_name: None/present (TSP name before padding)
+    4. visibility: readonly/readwrite (affects exclude_readonly)
+    5. structure: regular/nested/flattened models
+
+    COMPLETE TEST MATRIX:
+    
┌───────┬─────────────┬──────────────┬─────────────────┬────────────┬──────────────┬─────────────────────────────┐
+    │ Test  │ Wire Name   │ Attr Name    │ Original TSP    │ Visibility │ 
Structure    │ Expected Behavior           │
+    
├───────┼─────────────┼──────────────┼─────────────────┼────────────┼──────────────┼─────────────────────────────┤
+    │ 1a    │ same        │ normal       │ None            │ readwrite  │ 
regular      │ attr_name                   │
+    │ 1b    │ same        │ normal       │ None            │ readonly   │ 
regular      │ attr_name (exclude test)    │
+    │ 2a    │ different   │ normal       │ None            │ readwrite  │ 
regular      │ attr_name                   │
+    │ 2b    │ different   │ normal       │ None            │ readonly   │ 
regular      │ attr_name (exclude test)    │
+    │ 3a    │ same        │ padded       │ present         │ readwrite  │ 
regular      │ original_tsp_name           │
+    │ 3b    │ same        │ padded       │ present         │ readonly   │ 
regular      │ original_tsp_name (exclude) │
+    │ 4a    │ different   │ padded       │ present         │ readwrite  │ 
regular      │ original_tsp_name           │
+    │ 4b    │ different   │ padded       │ present         │ readonly   │ 
regular      │ original_tsp_name (exclude) │
+    │ 5a    │ various     │ mixed        │ mixed           │ mixed      │ 
nested       │ recursive backcompat        │
+    │ 6a    │ same        │ padded       │ present         │ readwrite  │ 
flat-contain │ flattened + backcompat      │
+    │ 6b    │ various     │ mixed        │ mixed           │ mixed      │ 
flat-props   │ flattened props backcompat  │
+    │ 6c    │ various     │ mixed        │ mixed           │ readonly   │ 
flat-mixed   │ flattened + exclude         │
+    
└───────┴─────────────┴──────────────┴─────────────────┴────────────┴──────────────┴─────────────────────────────┘
+    """
+
+    # ========== DIMENSION 1-4 COMBINATIONS: REGULAR STRUCTURE ==========
+
+    def test_1a_same_wire_normal_attr_no_original_readwrite_regular(self):
+        """Wire=attr, normal attr, no original, readwrite, regular model"""
+
+        class RegularModel(HybridModel):
+            field_name: str = rest_field()
+
+        model = RegularModel(field_name="value")
+
+        # Should use attr_name (same as wire name)
+        assert attribute_list(model) == ["field_name"]
+        assert as_attribute_dict(model) == {"field_name": "value"}
+        assert as_attribute_dict(model, exclude_readonly=True) == 
{"field_name": "value"}
+        assert getattr(model, "field_name") == "value"
+        assert get_backcompat_attr_name(model, "field_name") == "field_name"
+
+    def test_1b_same_wire_normal_attr_no_original_readonly_regular(self):
+        """Wire=attr, normal attr, no original, readonly, regular model"""
+
+        class ReadonlyModel(HybridModel):
+            field_name: str = rest_field(visibility=["read"])
+
+        model = ReadonlyModel(field_name="value")
+
+        # Should use attr_name, but excluded when exclude_readonly=True
+        assert attribute_list(model) == ["field_name"]
+        assert as_attribute_dict(model) == {"field_name": "value"}
+        assert as_attribute_dict(model, exclude_readonly=True) == {}
+        assert getattr(model, "field_name") == "value"
+        assert get_backcompat_attr_name(model, "field_name") == "field_name"
+
+    def test_2a_different_wire_normal_attr_no_original_readwrite_regular(self):
+        """Wire≠attr, normal attr, no original, readwrite, regular model"""
+
+        class DifferentWireModel(HybridModel):
+            client_field: str = rest_field(name="wireField")
+
+        model = DifferentWireModel(client_field="value")
+
+        # Should use attr_name (wire name is different)
+        assert attribute_list(model) == ["client_field"]
+        assert as_attribute_dict(model) == {"client_field": "value"}
+        # Verify wire representation uses different name
+        assert dict(model) == {"wireField": "value"}
+        assert getattr(model, "client_field") == "value"
+        assert get_backcompat_attr_name(model, "client_field") == 
"client_field"
+
+    def test_2b_different_wire_normal_attr_no_original_readonly_regular(self):
+        """Wire≠attr, normal attr, no original, readonly, regular model"""
+
+        class ReadonlyDifferentWireModel(HybridModel):
+            client_field: str = rest_field(name="wireField", 
visibility=["read"])
+
+        model = ReadonlyDifferentWireModel(client_field="value")
+
+        # Should use attr_name, excluded when exclude_readonly=True
+        assert attribute_list(model) == ["client_field"]
+        assert as_attribute_dict(model) == {"client_field": "value"}
+        assert as_attribute_dict(model, exclude_readonly=True) == {}
+        assert getattr(model, "client_field") == "value"
+        assert get_backcompat_attr_name(model, "client_field") == 
"client_field"
+
+    def test_3a_same_wire_padded_attr_with_original_readwrite_regular(self):
+        """Wire=original, padded attr, original present, readwrite, regular 
model"""
+
+        class PaddedModel(HybridModel):
+            keys_property: str = rest_field(original_tsp_name="keys")
+
+        model = PaddedModel(keys_property="value")
+
+        # Should use original_tsp_name when available
+        assert attribute_list(model) == ["keys_property"]
+        assert as_attribute_dict(model) == {"keys_property": "value"}
+        assert get_backcompat_attr_name(model, "keys_property") == "keys"
+        assert getattr(model, "keys_property") == "value"
+        assert set(model.keys()) == {"keys_property"}
+
+    def test_3b_same_wire_padded_attr_with_original_readonly_regular(self):
+        """Wire=original, padded attr, original present, readonly, regular 
model"""
+
+        class ReadonlyPaddedModel(HybridModel):
+            keys_property: str = rest_field(visibility=["read"], 
original_tsp_name="keys")
+
+        model = ReadonlyPaddedModel(keys_property="value")
+
+        assert attribute_list(model) == ["keys_property"]
+        assert as_attribute_dict(model) == {"keys_property": "value"}
+        assert as_attribute_dict(model, exclude_readonly=True) == {}
+        assert get_backcompat_attr_name(model, "keys_property") == "keys"
+        assert getattr(model, "keys_property") == "value"
+        assert set(model.keys()) == {"keys_property"}
+
+    def 
test_4a_different_wire_padded_attr_with_original_readwrite_regular(self):
+        """Wire≠original, padded attr, original present, readwrite, regular 
model"""
+
+        class DifferentWirePaddedModel(HybridModel):
+            clear_property: str = rest_field(name="clearWire", 
original_tsp_name="clear")
+
+        model = DifferentWirePaddedModel(clear_property="value")
+
+        assert attribute_list(model) == ["clear_property"]
+        assert as_attribute_dict(model) == {"clear_property": "value"}
+        # Verify wire uses different name
+        assert dict(model) == {"clearWire": "value"}
+        assert getattr(model, "clear_property") == "value"
+        assert set(model.keys()) == {"clearWire"}
+
+    def 
test_4b_different_wire_padded_attr_with_original_readonly_regular(self):
+        """Wire≠original, padded attr, original present, readonly, regular 
model"""
+
+        class ReadonlyDifferentWirePaddedModel(HybridModel):
+            pop_property: str = rest_field(name="popWire", 
visibility=["read"], original_tsp_name="pop")
+
+        model = ReadonlyDifferentWirePaddedModel(pop_property="value")
+
+        assert attribute_list(model) == ["pop_property"]
+        assert as_attribute_dict(model) == {"pop_property": "value"}
+        assert as_attribute_dict(model, exclude_readonly=True) == {}
+        assert getattr(model, "pop_property") == "value"
+        assert set(model.keys()) == {"popWire"}
+
+    # ========== DIMENSION 5: STRUCTURE VARIATIONS ==========
+
+    def test_5a_nested_model_backcompat_recursive(self):
+        """Nested models with mixed backcompat scenarios"""
+
+        class NestedBackcompatModel(HybridModel):
+            keys_property: str = rest_field(name="keysWire", 
original_tsp_name="keys")
+            normal_field: str = rest_field(name="normalWire")
+
+        class ParentModel(HybridModel):
+            nested: NestedBackcompatModel = rest_field()
+            items_property: str = rest_field(name="itemsWire", 
original_tsp_name="items")
+
+        nested_model = NestedBackcompatModel(keys_property="nested_keys", 
normal_field="nested_normal")
+        parent_model = ParentModel(nested=nested_model, 
items_property="parent_items")
+
+        # Test nested model independently
+        nested_attrs = attribute_list(nested_model)
+        assert set(nested_attrs) == {"keys_property", "normal_field"}
+
+        nested_dict = as_attribute_dict(nested_model)
+        assert nested_dict == {"keys_property": "nested_keys", "normal_field": 
"nested_normal"}
+
+        # Test parent model with recursive backcompat
+        parent_attrs = attribute_list(parent_model)
+        assert set(parent_attrs) == {"nested", "items_property"}
+
+        parent_dict = as_attribute_dict(parent_model)
+        expected_parent = {
+            "nested": {"keys_property": "nested_keys", "normal_field": 
"nested_normal"},
+            "items_property": "parent_items",
+        }
+        assert parent_dict == expected_parent
+
+        assert getattr(nested_model, "keys_property") == "nested_keys"
+        assert getattr(parent_model, "items_property") == "parent_items"
+
+        assert set(nested_model.keys()) == {"keysWire", "normalWire"}
+        assert set(nested_model.items()) == {("keysWire", "nested_keys"), 
("normalWire", "nested_normal")}
+        assert set(parent_model.keys()) == {"nested", "itemsWire"}
+        assert len(parent_model.items()) == 2
+        assert ("nested", parent_model.nested) in parent_model.items()
+        assert ("itemsWire", "parent_items") in parent_model.items()
+
+    def test_6a_flattened_container_with_backcompat(self):
+        """Flattened property where container has backcompat (keys_property → 
keys)"""
+
+        # Helper model for flattening content
+        class ContentModel(HybridModel):
+            name: str = rest_field()
+            description: str = rest_field()
+
+        class FlattenedContainerModel(HybridModel):
+            id: str = rest_field()
+            update_property: ContentModel = 
rest_field(original_tsp_name="update")
+
+            __flattened_items = ["name", "description"]
+
+            def __init__(self, *args: Any, **kwargs: Any) -> None:
+                _flattened_input = {k: kwargs.pop(k) for k in kwargs.keys() & 
self.__flattened_items}
+                super().__init__(*args, **kwargs)
+                for k, v in _flattened_input.items():
+                    setattr(self, k, v)
+
+            def __getattr__(self, name: str) -> Any:
+                if name in self.__flattened_items:
+                    if self.update_property is None:
+                        return None
+                    return getattr(self.update_property, name)
+                raise AttributeError(f"'{self.__class__.__name__}' object has 
no attribute '{name}'")
+
+            def __setattr__(self, key: str, value: Any) -> None:
+                if key in self.__flattened_items:
+                    if self.update_property is None:
+                        self.update_property = 
self._attr_to_rest_field["update_property"]._class_type()
+                    setattr(self.update_property, key, value)
+                else:
+                    super().__setattr__(key, value)
+
+        model = FlattenedContainerModel(id="test_id", name="flattened_name", 
description="flattened_desc")
+
+        # Flattened items should appear at top level
+        attrs = attribute_list(model)
+        assert set(attrs) == {"id", "name", "description"}
+        assert getattr(model, "name") == "flattened_name"
+        assert getattr(model, "description") == "flattened_desc"
+
+        # Flattened dict should use top-level names
+        attr_dict = as_attribute_dict(model)
+        expected = {"id": "test_id", "name": "flattened_name", "description": 
"flattened_desc"}
+        assert attr_dict == expected
+
+        assert get_backcompat_attr_name(model, "update_property") == "update"
+
+        assert set(model.keys()) == {"id", "update_property"}
+
+    def test_6b_flattened_properties_with_backcompat(self):
+        """Flattened properties themselves have backcompat (type_property → 
type)"""
+
+        class BackcompatContentModel(HybridModel):
+            values_property: str = rest_field(name="valuesWire", 
original_tsp_name="values")
+            get_property: str = rest_field(name="getWire", 
original_tsp_name="get")
+
+        class FlattenedPropsBackcompatModel(HybridModel):
+            name: str = rest_field()
+            properties: BackcompatContentModel = rest_field()
+
+            __flattened_items = ["values_property", "get_property"]
+
+            def __init__(self, *args: Any, **kwargs: Any) -> None:
+                _flattened_input = {k: kwargs.pop(k) for k in kwargs.keys() & 
self.__flattened_items}
+                super().__init__(*args, **kwargs)
+                for k, v in _flattened_input.items():
+                    setattr(self, k, v)
+
+            def __getattr__(self, name: str) -> Any:
+                if name in self.__flattened_items:
+                    if self.properties is None:
+                        return None
+                    return getattr(self.properties, name)
+                raise AttributeError(f"'{self.__class__.__name__}' object has 
no attribute '{name}'")
+
+            def __setattr__(self, key: str, value: Any) -> None:
+                if key in self.__flattened_items:
+                    if self.properties is None:
+                        self.properties = 
self._attr_to_rest_field["properties"]._class_type()
+                    setattr(self.properties, key, value)
+                else:
+                    super().__setattr__(key, value)
+
+        model = FlattenedPropsBackcompatModel(
+            name="test_name", values_property="test_values", 
get_property="test_class"
+        )
+
+        # Should use original names for flattened properties
+        attrs = attribute_list(model)
+        assert set(attrs) == {"name", "values_property", "get_property"}
+        assert get_backcompat_attr_name(model, "values_property") == "values"
+        assert "test_name" in model.values()
+
+        attr_dict = as_attribute_dict(model)
+        expected = {"name": "test_name", "values_property": "test_values", 
"get_property": "test_class"}
+        assert attr_dict == expected
+
+    def test_6c_flattened_with_readonly_exclusion(self):
+        """Flattened model with readonly properties and exclude_readonly 
behavior"""
+
+        class ReadonlyContentModel(HybridModel):
+            setdefault_property: str = rest_field(name="readonlyWire", 
original_tsp_name="setdefault")
+            popitem_property: str = rest_field(name="readwriteWire", 
original_tsp_name="popitem")
+
+        class FlattenedReadonlyModel(HybridModel):
+            get_property: str = rest_field(name="getProperty", 
original_tsp_name="get", visibility=["read"])
+            properties: ReadonlyContentModel = rest_field()
+
+            __flattened_items = ["setdefault_property", "popitem_property"]
+
+            def __init__(self, *args: Any, **kwargs: Any) -> None:
+                _flattened_input = {k: kwargs.pop(k) for k in kwargs.keys() & 
self.__flattened_items}
+                super().__init__(*args, **kwargs)
+                for k, v in _flattened_input.items():
+                    setattr(self, k, v)
+
+            def __getattr__(self, name: str) -> Any:
+                if name in self.__flattened_items:
+                    if self.properties is None:
+                        return None
+                    return getattr(self.properties, name)
+                raise AttributeError(f"'{self.__class__.__name__}' object has 
no attribute '{name}'")
+
+            def __setattr__(self, key: str, value: Any) -> None:
+                if key in self.__flattened_items:
+                    if self.properties is None:
+                        self.properties = 
self._attr_to_rest_field["properties"]._class_type()
+                    setattr(self.properties, key, value)
+                else:
+                    super().__setattr__(key, value)
+
+        model = FlattenedReadonlyModel(
+            get_property="test_get", setdefault_property="setdefault", 
popitem_property="readwrite_value"
+        )
+
+        # All properties included by default
+        full_dict = as_attribute_dict(model, exclude_readonly=False)
+        expected_full = {
+            "get_property": "test_get",
+            "setdefault_property": "setdefault",
+            "popitem_property": "readwrite_value",
+        }
+        assert full_dict == expected_full
+
+        # Readonly properties excluded when requested
+        filtered_dict = as_attribute_dict(model, exclude_readonly=True)
+        expected_filtered = {"setdefault_property": "setdefault", 
"popitem_property": "readwrite_value"}
+        assert filtered_dict == expected_filtered
+
+        attribute_list_result = attribute_list(model)
+        expected_attrs = {"get_property", "setdefault_property", 
"popitem_property"}
+        assert set(attribute_list_result) == expected_attrs
+        assert get_backcompat_attr_name(model, "setdefault_property") == 
"setdefault"
+        assert get_backcompat_attr_name(model, "popitem_property") == "popitem"
+        assert getattr(model, "get_property") == "test_get"
+
+    # ========== EDGE CASES ==========
+
+    def test_mixed_combinations_comprehensive(self):
+        """Comprehensive test mixing all backcompat scenarios in one model"""
+
+        class ComprehensiveModel(HybridModel):
+            # Case 1: Normal field, same wire name, no original
+            normal_field: str = rest_field()
+
+            # Case 2: Normal field, different wire name, no original
+            different_wire: str = rest_field(name="wireNameDifferent")
+
+            # Case 3: Padded field with original, same wire name
+            keys_property: str = rest_field(original_tsp_name="keys")
+
+            # Case 4: Padded field with original, different wire name
+            values_property: str = rest_field(name="valuesWire", 
original_tsp_name="values")
+
+            # Case 5: Readonly field with original
+            items_property: str = rest_field(name="itemsWire", 
visibility=["read"], original_tsp_name="items")
+
+        model = ComprehensiveModel(
+            normal_field="normal",
+            different_wire="different",
+            keys_property="keys_val",
+            values_property="values_val",
+            items_property="items_val",
+        )
+
+        # attribute_list should use backcompat names where available
+        attrs = attribute_list(model)
+        expected_attrs = {"normal_field", "different_wire", "keys_property", 
"values_property", "items_property"}
+        assert set(attrs) == expected_attrs
+        assert get_backcompat_attr_name(model, "keys_property") == "keys"
+        assert get_backcompat_attr_name(model, "values_property") == "values"
+        assert get_backcompat_attr_name(model, "items_property") == "items"
+        assert get_backcompat_attr_name(model, "normal_field") == 
"normal_field"
+        assert get_backcompat_attr_name(model, "different_wire") == 
"different_wire"
+        assert getattr(model, "keys_property") == "keys_val"
+        assert getattr(model, "values_property") == "values_val"
+        assert getattr(model, "items_property") == "items_val"
+        assert getattr(model, "normal_field") == "normal"
+        assert getattr(model, "different_wire") == "different"
+
+        # Full as_attribute_dict
+        full_dict = as_attribute_dict(model)
+        expected_full = {
+            "normal_field": "normal",
+            "different_wire": "different",
+            "keys_property": "keys_val",
+            "values_property": "values_val",
+            "items_property": "items_val",
+        }
+        assert full_dict == expected_full
+
+        # Exclude readonly
+        filtered_dict = as_attribute_dict(model, exclude_readonly=True)
+        expected_filtered = {
+            "normal_field": "normal",
+            "different_wire": "different",
+            "keys_property": "keys_val",
+            "values_property": "values_val",
+            # "items_property" excluded because it's readonly
+        }
+        assert filtered_dict == expected_filtered
+
+        # Verify wire representations use correct wire names
+        wire_dict = dict(model)
+        expected_wire = {
+            "normal_field": "normal",  # same as attr
+            "wireNameDifferent": "different",  # different wire name
+            "keys_property": "keys_val",  # same as attr (padded)
+            "valuesWire": "values_val",  # different wire name
+            "itemsWire": "items_val",  # different wire name
+        }
+        assert wire_dict == expected_wire
+
+    def test_no_backcompat_fallback(self):
+        """Test fallback behavior when no backcompat mapping exists"""
+
+        class NoBackcompatModel(HybridModel):
+            padded_attr: str = rest_field(name="wireField")
+            # Note: No original_tsp_name set, so no backcompat should occur
+
+        model = NoBackcompatModel(padded_attr="value")
+
+        # Should fall back to using actual attribute names
+        assert attribute_list(model) == ["padded_attr"]
+        assert as_attribute_dict(model) == {"padded_attr": "value"}
+        assert dict(model) == {"wireField": "value"}
+
+    def test_property_with_padding_in_actual_name(self):
+        """Test handling of properties that have padding in their actual 
attribute names"""
+
+        class PaddingInNameModel(HybridModel):
+            keys_property: str = rest_field(name="myKeys")
+
+        model = PaddingInNameModel(keys_property="value")
+        # Should use actual attribute name since no original_tsp_name is set
+        assert attribute_list(model) == ["keys_property"]
+        assert as_attribute_dict(model) == {"keys_property": "value"}
+        assert dict(model) == {"myKeys": "value"}
+        assert getattr(model, "keys_property") == "value"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/azure_core-1.36.0/tests/test_stream_generator.py 
new/azure_core-1.37.0/tests/test_stream_generator.py
--- old/azure_core-1.36.0/tests/test_stream_generator.py        2025-10-15 
01:34:08.000000000 +0200
+++ new/azure_core-1.37.0/tests/test_stream_generator.py        2025-12-11 
19:57:42.000000000 +0100
@@ -9,6 +9,7 @@
 )
 from azure.core.pipeline import Pipeline, PipelineResponse
 from azure.core.pipeline.transport._requests_basic import 
StreamDownloadGenerator
+from azure.core.exceptions import ServiceResponseError
 
 try:
     from unittest import mock
@@ -73,7 +74,7 @@
     http_response.internal_response = MockInternalResponse()
     stream = StreamDownloadGenerator(pipeline, http_response, decompress=False)
     with mock.patch("time.sleep", return_value=None):
-        with pytest.raises(requests.exceptions.ConnectionError):
+        with pytest.raises(ServiceResponseError):
             stream.__next__()
 
 
@@ -133,5 +134,5 @@
     pipeline = Pipeline(transport)
     pipeline.run = mock_run
     downloader = response.stream_download(pipeline, decompress=False)
-    with pytest.raises(requests.exceptions.ConnectionError):
+    with pytest.raises(ServiceResponseError):
         full_response = b"".join(downloader)

Reply via email to