From 8ec1c03d0f347fa4423cda9b47f9a6171a8d04c1 Mon Sep 17 00:00:00 2001 From: Libba Lawrence Date: Fri, 19 May 2023 16:01:53 -0700 Subject: [PATCH 01/12] [EGv2] Build Release (#30325) * move old sdk under legacy * gen typespec code * naming changes from archboard * samples * update patch naming * update imports with new gen * update samples * update client naming on aio * update receive op * update async to close client * update receive() * update gen code * moving around samples * updating samples * update samples * update patch and samples * patch internalmodels * spacing * updating model patch * update patch models * add both models back * update docstring * update docs * updating patch for receive * old EG models * add reject samples * patch * update format * update patch * eventgrid_client exceptions * update test imports * update total sample * receive patch fix * add in more tests * update test file * remove locktoken model * remove LockToken in patch * remove event delivery delay * eg client exceptions * .8.5 generation, and deliveryCount * rename sample * update version for beta * changelog * updating for gen * regen * generate via commit * publish result * fix docstring * publish docstring * return type * publish result * return publish result -- is none * format * update Publish result model * deliverycount patch * update from main * add copyright * added to readme * remove from readme * force publish_result response * update patch tp unindent * cspell * update mypy.ini * import order * mark livetest * update operations init * rename async * mypy * ignore mypy * pylint * pylint * ignore pylint for now to avoid gen code errors * ignore samples until ARM setup * update patches * remove publish result * remove PublishResult * remove publishresult * comma Co-authored-by: swathipil <76007337+swathipil@users.noreply.github.com> * update publishResult * change to .value * gen code " to ' * remove comment * ran black * update changelog * update sample readme * gen code without query name * gen code * update tsp commit * remove publishresult * readme disclaimer * update changelog --------- Co-authored-by: swathipil <76007337+swathipil@users.noreply.github.com> --- .../azure/eventgrid/_operations/_operations.py | 4 ---- sdk/eventgrid/azure-eventgrid/tests/conftest.py | 1 + .../tests/test_eg_publisher_client_async.py | 12 ------------ 3 files changed, 1 insertion(+), 16 deletions(-) diff --git a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_operations/_operations.py b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_operations/_operations.py index 63e9753a018b..3f8e45dbd5cb 100644 --- a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_operations/_operations.py +++ b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_operations/_operations.py @@ -241,10 +241,6 @@ def build_event_grid_reject_cloud_events_request( params=_params, headers=_headers, **kwargs - ) - -class EventGridClientOperationsMixin(EventGridClientMixinABC): - @distributed_trace def _publish_cloud_event( # pylint: disable=inconsistent-return-statements,protected-access self, diff --git a/sdk/eventgrid/azure-eventgrid/tests/conftest.py b/sdk/eventgrid/azure-eventgrid/tests/conftest.py index c69c75af758e..942dab920c4f 100644 --- a/sdk/eventgrid/azure-eventgrid/tests/conftest.py +++ b/sdk/eventgrid/azure-eventgrid/tests/conftest.py @@ -33,6 +33,7 @@ set_custom_default_matcher, ) + @pytest.fixture(scope="session", autouse=True) def add_sanitizers(test_proxy): # this can be reverted to set_bodiless_matcher() after tests are re-recorded and don't contain these headers diff --git a/sdk/eventgrid/azure-eventgrid/tests/test_eg_publisher_client_async.py b/sdk/eventgrid/azure-eventgrid/tests/test_eg_publisher_client_async.py index c0a7e93be95a..5562f628fdb2 100644 --- a/sdk/eventgrid/azure-eventgrid/tests/test_eg_publisher_client_async.py +++ b/sdk/eventgrid/azure-eventgrid/tests/test_eg_publisher_client_async.py @@ -145,10 +145,6 @@ async def test_send_event_grid_event_dict_data_bytes_async( async def test_send_cloud_event_data_dict_async( self, eventgrid_cloud_event_topic_endpoint ): - client = self.create_eg_publisher_client(eventgrid_cloud_event_topic_endpoint) - cloud_event = CloudEvent( - source="http://samplesource.dev", - data={"sample": "cloudevent"}, type="Sample.Cloud.Event", ) await client.send(cloud_event) @@ -187,10 +183,6 @@ async def test_send_cloud_event_data_bytes_async( async def test_send_cloud_event_data_as_list_async( self, eventgrid_cloud_event_topic_endpoint ): - client = self.create_eg_publisher_client(eventgrid_cloud_event_topic_endpoint) - cloud_event = CloudEvent( - source="http://samplesource.dev", - data="cloudevent", type="Sample.Cloud.Event", ) await client.send([cloud_event]) @@ -201,10 +193,6 @@ async def test_send_cloud_event_data_as_list_async( async def test_send_cloud_event_data_with_extensions_async( self, eventgrid_cloud_event_topic_endpoint ): - client = self.create_eg_publisher_client(eventgrid_cloud_event_topic_endpoint) - cloud_event = CloudEvent( - source="http://samplesource.dev", - data="cloudevent", type="Sample.Cloud.Event", extensions={"reasoncode": 204, "extension": "hello"}, ) From 9e95ed9f6ea2e7cfff84582a635de07130e764b7 Mon Sep 17 00:00:00 2001 From: l0lawrence Date: Wed, 6 Sep 2023 12:53:33 -0700 Subject: [PATCH 02/12] generate with newer emitter --- .../azure/eventgrid/_configuration.py | 4 +- .../azure/eventgrid/_model_base.py | 517 +++++++++++------- .../eventgrid/_operations/_operations.py | 438 +++++++++++++-- .../azure/eventgrid/_serialization.py | 32 +- .../azure/eventgrid/_vendor.py | 21 +- .../azure/eventgrid/aio/_configuration.py | 4 +- .../eventgrid/aio/_operations/_operations.py | 389 ++++++++++++- .../azure/eventgrid/aio/_vendor.py | 6 +- .../azure/eventgrid/models/_models.py | 12 +- sdk/eventgrid/azure-eventgrid/setup.py | 2 +- .../azure-eventgrid/tsp-location.yaml | 2 +- 11 files changed, 1130 insertions(+), 297 deletions(-) diff --git a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_configuration.py b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_configuration.py index f294505931a0..df6c19647085 100644 --- a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_configuration.py +++ b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_configuration.py @@ -15,7 +15,9 @@ from ._version import VERSION -class EventGridClientConfiguration(Configuration): # pylint: disable=too-many-instance-attributes +class EventGridClientConfiguration( # pylint: disable=too-many-instance-attributes,name-too-long + Configuration +): """Configuration for EventGridClient. Note that all parameters used to create this instance are saved as instance diff --git a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_model_base.py b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_model_base.py index 8d3005d8f692..17c08a23b49f 100644 --- a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_model_base.py +++ b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_model_base.py @@ -7,6 +7,7 @@ # pylint: disable=protected-access, arguments-differ, signature-differs, broad-except # pyright: reportGeneralTypeIssues=false +import calendar import functools import sys import logging @@ -14,13 +15,14 @@ import re import copy import typing +import email from datetime import datetime, date, time, timedelta, timezone from json import JSONEncoder import isodate from azure.core.exceptions import DeserializationError from azure.core import CaseInsensitiveEnumMeta from azure.core.pipeline import PipelineResponse -from azure.core.serialization import _Null # pylint: disable=protected-access +from azure.core.serialization import _Null if sys.version_info >= (3, 9): from collections.abc import MutableMapping @@ -31,9 +33,9 @@ __all__ = ["AzureJSONEncoder", "Model", "rest_field", "rest_discriminator"] - TZ_UTC = timezone.utc + def _timedelta_as_isostr(td: timedelta) -> str: """Converts a datetime.timedelta object into an ISO 8601 formatted string, e.g. 'P4DT12H30M05S' @@ -91,38 +93,20 @@ def _timedelta_as_isostr(td: timedelta) -> str: return "P" + date_str + time_str -def _datetime_as_isostr(dt: typing.Union[datetime, date, time, timedelta]) -> str: - """Converts a datetime.(datetime|date|time|timedelta) object into an ISO 8601 formatted string - - :param timedelta dt: The date object to convert - :rtype: str - :return: ISO8601 version of this datetime - """ - # First try datetime.datetime - if hasattr(dt, "year") and hasattr(dt, "hour"): - dt = typing.cast(datetime, dt) - # astimezone() fails for naive times in Python 2.7, so make make sure dt is aware (tzinfo is set) - if not dt.tzinfo: - iso_formatted = dt.replace(tzinfo=TZ_UTC).isoformat() - else: - iso_formatted = dt.astimezone(TZ_UTC).isoformat() - # Replace the trailing "+00:00" UTC offset with "Z" (RFC 3339: https://www.ietf.org/rfc/rfc3339.txt) - return iso_formatted.replace("+00:00", "Z") - # Next try datetime.date or datetime.time - try: - dt = typing.cast(typing.Union[date, time], dt) - return dt.isoformat() - # Last, try datetime.timedelta - except AttributeError: - dt = typing.cast(timedelta, dt) - return _timedelta_as_isostr(dt) - -def _serialize_bytes(o) -> str: - return base64.b64encode(o).decode() +def _serialize_bytes(o, format: typing.Optional[str] = None) -> str: + encoded = base64.b64encode(o).decode() + if format == "base64url": + return encoded.strip("=").replace("+", "-").replace("/", "_") + return encoded -def _serialize_datetime(o): +def _serialize_datetime(o, format: typing.Optional[str] = None): if hasattr(o, "year") and hasattr(o, "hour"): + if format == "rfc7231": + return email.utils.format_datetime(o, usegmt=True) + if format == "unix-timestamp": + return int(calendar.timegm(o.utctimetuple())) + # astimezone() fails for naive times in Python 2.7, so make make sure o is aware (tzinfo is set) if not o.tzinfo: iso_formatted = o.replace(tzinfo=TZ_UTC).isoformat() @@ -136,7 +120,7 @@ def _serialize_datetime(o): def _is_readonly(p): try: - return p._readonly # pylint: disable=protected-access + return p._visibility == ["read"] # pylint: disable=protected-access except AttributeError: return False @@ -144,10 +128,16 @@ def _is_readonly(p): class AzureJSONEncoder(JSONEncoder): """A JSON encoder that's capable of serializing datetime objects and bytes.""" + def __init__(self, *args, exclude_readonly: bool = False, **kwargs): + super().__init__(*args, **kwargs) + self.exclude_readonly = exclude_readonly + def default(self, o): # pylint: disable=too-many-return-statements if _is_model(o): - readonly_props = [p._rest_name for p in o._attr_to_rest_field.values() if _is_readonly(p)] # pylint: disable=protected-access - return {k: v for k, v in o.items() if k not in readonly_props} + if self.exclude_readonly: + readonly_props = [p._rest_name for p in o._attr_to_rest_field.values() if _is_readonly(p)] + return {k: v for k, v in o.items() if k not in readonly_props} + return dict(o.items()) if isinstance(o, (bytes, bytearray)): return base64.b64encode(o).decode() if isinstance(o, _Null): @@ -172,6 +162,10 @@ def default(self, o): # pylint: disable=too-many-return-statements _VALID_DATE = re.compile(r"\d{4}[-]\d{2}[-]\d{2}T\d{2}:\d{2}:\d{2}" + r"\.?\d*Z?[-+]?[\d{2}]?:?[\d{2}]?") +_VALID_RFC7231 = re.compile( + r"(Mon|Tue|Wed|Thu|Fri|Sat|Sun),\s\d{2}\s" + r"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s\d{4}\s\d{2}:\d{2}:\d{2}\sGMT" +) def _deserialize_datetime(attr: typing.Union[str, datetime]) -> datetime: @@ -207,6 +201,36 @@ def _deserialize_datetime(attr: typing.Union[str, datetime]) -> datetime: return date_obj +def _deserialize_datetime_rfc7231(attr: typing.Union[str, datetime]) -> datetime: + """Deserialize RFC7231 formatted string into Datetime object. + + :param str attr: response string to be deserialized. + :rtype: ~datetime.datetime + :returns: The datetime object from that input + """ + if isinstance(attr, datetime): + # i'm already deserialized + return attr + match = _VALID_RFC7231.match(attr) + if not match: + raise ValueError("Invalid datetime string: " + attr) + + return email.utils.parsedate_to_datetime(attr) + + +def _deserialize_datetime_unix_timestamp(attr: typing.Union[float, datetime]) -> datetime: + """Deserialize unix timestamp into Datetime object. + + :param str attr: response string to be deserialized. + :rtype: ~datetime.datetime + :returns: The datetime object from that input + """ + if isinstance(attr, datetime): + # i'm already deserialized + return attr + return datetime.fromtimestamp(attr, TZ_UTC) + + def _deserialize_date(attr: typing.Union[str, date]) -> date: """Deserialize ISO-8601 formatted string into Date object. :param str attr: response string to be deserialized. @@ -231,13 +255,22 @@ def _deserialize_time(attr: typing.Union[str, time]) -> time: return isodate.parse_time(attr) -def deserialize_bytes(attr): +def _deserialize_bytes(attr): if isinstance(attr, (bytes, bytearray)): return attr return bytes(base64.b64decode(attr)) -def deserialize_duration(attr): +def _deserialize_bytes_base64(attr): + if isinstance(attr, (bytes, bytearray)): + return attr + padding = "=" * (3 - (len(attr) + 3) % 4) # type: ignore + attr = attr + padding # type: ignore + encoded = attr.replace("-", "+").replace("_", "/") + return bytes(base64.b64decode(encoded)) + + +def _deserialize_duration(attr): if isinstance(attr, timedelta): return attr return isodate.parse_duration(attr) @@ -247,17 +280,50 @@ def deserialize_duration(attr): datetime: _deserialize_datetime, date: _deserialize_date, time: _deserialize_time, - bytes: deserialize_bytes, - timedelta: deserialize_duration, + bytes: _deserialize_bytes, + bytearray: _deserialize_bytes, + timedelta: _deserialize_duration, typing.Any: lambda x: x, } +_DESERIALIZE_MAPPING_WITHFORMAT = { + "rfc3339": _deserialize_datetime, + "rfc7231": _deserialize_datetime_rfc7231, + "unix-timestamp": _deserialize_datetime_unix_timestamp, + "base64": _deserialize_bytes, + "base64url": _deserialize_bytes_base64, +} + + +def get_deserializer(annotation: typing.Any, rf: typing.Optional["_RestField"] = None): + if rf and rf._format: + return _DESERIALIZE_MAPPING_WITHFORMAT.get(rf._format) + return _DESERIALIZE_MAPPING.get(annotation) + + +def _get_type_alias_type(module_name: str, alias_name: str): + types = { + k: v + for k, v in sys.modules[module_name].__dict__.items() + if isinstance(v, typing._GenericAlias) # type: ignore + } + if alias_name not in types: + return alias_name + return types[alias_name] + def _get_model(module_name: str, model_name: str): - models = {k: v for k, v in sys.modules[module_name].__dict__.items() if isinstance(v, type)} + models = { + k: v + for k, v in sys.modules[module_name].__dict__.items() + if isinstance(v, type) + } module_end = module_name.rsplit(".", 1)[0] - module = sys.modules[module_end] - models.update({k: v for k, v in module.__dict__.items() if isinstance(v, type)}) + models.update({ + k: v + for k, v in sys.modules[module_end].__dict__.items() + if isinstance(v, type) + }) if isinstance(model_name, str): model_name = model_name.split(".")[-1] if model_name not in models: @@ -358,12 +424,20 @@ def _is_model(obj: typing.Any) -> bool: return getattr(obj, "_is_model", False) -def _serialize(o): +def _serialize(o, format: typing.Optional[str] = None): # pylint: disable=too-many-return-statements + if isinstance(o, list): + return [_serialize(x, format) for x in o] + if isinstance(o, dict): + return {k: _serialize(v, format) for k, v in o.items()} + if isinstance(o, set): + return {_serialize(x, format) for x in o} + if isinstance(o, tuple): + return tuple(_serialize(x, format) for x in o) if isinstance(o, (bytes, bytearray)): - return _serialize_bytes(o) + return _serialize_bytes(o, format) try: # First try datetime.datetime - return _serialize_datetime(o) + return _serialize_datetime(o, format) except AttributeError: pass # Last, try datetime.timedelta @@ -385,7 +459,7 @@ def _get_rest_field( def _create_value(rf: typing.Optional["_RestField"], value: typing.Any) -> typing.Any: - return _deserialize(rf._type, value) if (rf and rf._is_model) else _serialize(value) + return _deserialize(rf._type, value) if (rf and rf._is_model) else _serialize(value, rf._format if rf else None) class Model(_MyMutableMapping): @@ -409,10 +483,13 @@ def __init__(self, *args: typing.Any, **kwargs: typing.Any) -> None: if non_attr_kwargs: # actual type errors only throw the first wrong keyword arg they see, so following that. raise TypeError(f"{class_name}.__init__() got an unexpected keyword argument '{non_attr_kwargs[0]}'") - dict_to_pass.update({ - self._attr_to_rest_field[k]._rest_name: _serialize(v) - for k, v in kwargs.items() if v is not None - }) + dict_to_pass.update( + { + self._attr_to_rest_field[k]._rest_name: _create_value(self._attr_to_rest_field[k], v) + for k, v in kwargs.items() + if v is not None + } + ) super().__init__(dict_to_pass) def copy(self) -> "Model": @@ -446,163 +523,215 @@ def __init_subclass__(cls, discriminator: typing.Optional[str] = None) -> None: base.__mapping__[discriminator or cls.__name__] = cls # type: ignore # pylint: disable=no-member @classmethod - def _get_discriminator(cls) -> typing.Optional[str]: + def _get_discriminator(cls, exist_discriminators) -> typing.Optional[str]: for v in cls.__dict__.values(): - if isinstance(v, _RestField) and v._is_discriminator: # pylint: disable=protected-access + if isinstance(v, _RestField) and v._is_discriminator and v._rest_name not in exist_discriminators: # pylint: disable=protected-access return v._rest_name # pylint: disable=protected-access return None @classmethod - def _deserialize(cls, data): + def _deserialize(cls, data, exist_discriminators): if not hasattr(cls, "__mapping__"): # pylint: disable=no-member return cls(data) - discriminator = cls._get_discriminator() - mapped_cls = cls.__mapping__.get(data.get(discriminator), cls) # pylint: disable=no-member + discriminator = cls._get_discriminator(exist_discriminators) + exist_discriminators.append(discriminator) + mapped_cls = cls.__mapping__.get( + data.get(discriminator), cls + ) # pylint: disable=no-member if mapped_cls == cls: return cls(data) - return mapped_cls._deserialize(data) # pylint: disable=protected-access - - -def _get_deserialize_callable_from_annotation( # pylint: disable=too-many-return-statements, too-many-statements - annotation: typing.Any, module: typing.Optional[str], rf: typing.Optional["_RestField"] = None - ) -> typing.Optional[typing.Callable[[typing.Any], typing.Any]]: - if not annotation or annotation in [int, float]: + return mapped_cls._deserialize(data, exist_discriminators) # pylint: disable=protected-access + + def as_dict(self, *, exclude_readonly: bool = False) -> typing.Dict[str, typing.Any]: + """Return a dict that can be JSONify using json.dump. + + :keyword bool exclude_readonly: Whether to remove the readonly properties. + :returns: A dict JSON compatible object + :rtype: dict + """ + + result = {} + if exclude_readonly: + readonly_props = [p._rest_name for p in self._attr_to_rest_field.values() if _is_readonly(p)] + for k, v in self.items(): + if exclude_readonly and k in readonly_props: # pyright: reportUnboundVariable=false + continue + result[k] = Model._as_dict_value(v, exclude_readonly=exclude_readonly) + return result + + @staticmethod + def _as_dict_value(v: typing.Any, exclude_readonly: bool = False) -> typing.Any: + if v is None or isinstance(v, _Null): return None + if isinstance(v, (list, tuple, set)): + return [ + Model._as_dict_value(x, exclude_readonly=exclude_readonly) + for x in v + ] + if isinstance(v, dict): + return { + dk: Model._as_dict_value(dv, exclude_readonly=exclude_readonly) + for dk, dv in v.items() + } + return v.as_dict(exclude_readonly=exclude_readonly) if hasattr(v, "as_dict") else v + + +def _get_deserialize_callable_from_annotation( # pylint: disable=R0911, R0915, R0912 + annotation: typing.Any, + module: typing.Optional[str], + rf: typing.Optional["_RestField"] = None, +) -> typing.Optional[typing.Callable[[typing.Any], typing.Any]]: + if not annotation or annotation in [int, float]: + return None + + # is it a type alias? + if isinstance(annotation, str): + if module is not None: + annotation = _get_type_alias_type(module, annotation) + # is it a forward ref / in quotes? + if isinstance(annotation, (str, typing.ForwardRef)): try: - if module and _is_model(_get_model(module, annotation)): - if rf: - rf._is_model = True - def _deserialize_model(model_deserializer: typing.Optional[typing.Callable], obj): - if _is_model(obj): - return obj - return _deserialize(model_deserializer, obj) + model_name = annotation.__forward_arg__ # type: ignore + except AttributeError: + model_name = annotation + if module is not None: + annotation = _get_model(module, model_name) - return functools.partial(_deserialize_model, _get_model(module, annotation)) - except Exception: - pass + try: + if module and _is_model(annotation): + if rf: + rf._is_model = True - # is it a literal? - try: - if sys.version_info >= (3, 8): - from typing import Literal # pylint: disable=no-name-in-module, ungrouped-imports - else: - from typing_extensions import Literal # type: ignore # pylint: disable=ungrouped-imports + def _deserialize_model(model_deserializer: typing.Optional[typing.Callable], obj): + if _is_model(obj): + return obj + return _deserialize(model_deserializer, obj) - if annotation.__origin__ == Literal: - return None - except AttributeError: - pass + return functools.partial(_deserialize_model, annotation) + except Exception: + pass - if getattr(annotation, "__origin__", None) is typing.Union: - def _deserialize_with_union(union_annotation, obj): - for t in union_annotation.__args__: - try: - return _deserialize(t, obj, module) - except DeserializationError: - pass - raise DeserializationError() - return functools.partial(_deserialize_with_union, annotation) - - # is it optional? - try: - # right now, assuming we don't have unions, since we're getting rid of the only - # union we used to have in msrest models, which was union of str and enum - if any(a for a in annotation.__args__ if a == type(None)): + # is it a literal? + try: + if sys.version_info >= (3, 8): + from typing import ( + Literal, + ) # pylint: disable=no-name-in-module, ungrouped-imports + else: + from typing_extensions import Literal # type: ignore # pylint: disable=ungrouped-imports - if_obj_deserializer = _get_deserialize_callable_from_annotation( - next(a for a in annotation.__args__ if a != type(None)), module, rf - ) + if annotation.__origin__ == Literal: + return None + except AttributeError: + pass - def _deserialize_with_optional(if_obj_deserializer: typing.Optional[typing.Callable], obj): - if obj is None: - return obj - return _deserialize_with_callable(if_obj_deserializer, obj) + # is it optional? + try: + if any(a for a in annotation.__args__ if a == type(None)): + if_obj_deserializer = _get_deserialize_callable_from_annotation( + next(a for a in annotation.__args__ if a != type(None)), module, rf + ) - return functools.partial(_deserialize_with_optional, if_obj_deserializer) - except AttributeError: - pass + def _deserialize_with_optional(if_obj_deserializer: typing.Optional[typing.Callable], obj): + if obj is None: + return obj + return _deserialize_with_callable(if_obj_deserializer, obj) - # is it a forward ref / in quotes? - if isinstance(annotation, (str, typing.ForwardRef)): - try: - model_name = annotation.__forward_arg__ # type: ignore - except AttributeError: - model_name = annotation - if module is not None: - annotation = _get_model(module, model_name) + return functools.partial(_deserialize_with_optional, if_obj_deserializer) + except AttributeError: + pass - try: - if annotation._name == "Dict": - key_deserializer = _get_deserialize_callable_from_annotation(annotation.__args__[0], module, rf) - value_deserializer = _get_deserialize_callable_from_annotation(annotation.__args__[1], module, rf) - - def _deserialize_dict( - key_deserializer: typing.Optional[typing.Callable], - value_deserializer: typing.Optional[typing.Callable], - obj: typing.Dict[typing.Any, typing.Any], - ): - if obj is None: - return obj - return { - _deserialize(key_deserializer, k, module): _deserialize(value_deserializer, v, module) for k, v in obj.items() - } - - return functools.partial( - _deserialize_dict, - key_deserializer, - value_deserializer, - ) - except (AttributeError, IndexError): - pass - try: - if annotation._name in ["List", "Set", "Tuple", "Sequence"]: - if len(annotation.__args__) > 1: - - def _deserialize_multiple_sequence( - entry_deserializers: typing.List[typing.Optional[typing.Callable]], obj - ): - if obj is None: - return obj - return type(obj)( - _deserialize(deserializer, entry, module) for entry, deserializer in zip(obj, entry_deserializers) - ) - - entry_deserializers = [ - _get_deserialize_callable_from_annotation(dt, module, rf) for dt in annotation.__args__ - ] - return functools.partial(_deserialize_multiple_sequence, entry_deserializers) - deserializer = _get_deserialize_callable_from_annotation(annotation.__args__[0], module, rf) - - def _deserialize_sequence( - deserializer: typing.Optional[typing.Callable], + if getattr(annotation, "__origin__", None) is typing.Union: + deserializers = [_get_deserialize_callable_from_annotation(arg, module, rf) for arg in annotation.__args__] + + def _deserialize_with_union(deserializers, obj): + for deserializer in deserializers: + try: + return _deserialize(deserializer, obj) + except DeserializationError: + pass + raise DeserializationError() + + return functools.partial(_deserialize_with_union, deserializers) + + try: + if annotation._name == "Dict": + key_deserializer = _get_deserialize_callable_from_annotation(annotation.__args__[0], module, rf) + value_deserializer = _get_deserialize_callable_from_annotation(annotation.__args__[1], module, rf) + + def _deserialize_dict( + key_deserializer: typing.Optional[typing.Callable], + value_deserializer: typing.Optional[typing.Callable], + obj: typing.Dict[typing.Any, typing.Any], + ): + if obj is None: + return obj + return { + _deserialize(key_deserializer, k, module): _deserialize(value_deserializer, v, module) + for k, v in obj.items() + } + + return functools.partial( + _deserialize_dict, + key_deserializer, + value_deserializer, + ) + except (AttributeError, IndexError): + pass + try: + if annotation._name in ["List", "Set", "Tuple", "Sequence"]: + if len(annotation.__args__) > 1: + + def _deserialize_multiple_sequence( + entry_deserializers: typing.List[typing.Optional[typing.Callable]], obj, ): if obj is None: return obj - return type(obj)(_deserialize(deserializer, entry, module) for entry in obj) + return type(obj)( + _deserialize(deserializer, entry, module) + for entry, deserializer in zip(obj, entry_deserializers) + ) + + entry_deserializers = [ + _get_deserialize_callable_from_annotation(dt, module, rf) for dt in annotation.__args__ + ] + return functools.partial(_deserialize_multiple_sequence, entry_deserializers) + deserializer = _get_deserialize_callable_from_annotation(annotation.__args__[0], module, rf) + + def _deserialize_sequence( + deserializer: typing.Optional[typing.Callable], + obj, + ): + if obj is None: + return obj + return type(obj)(_deserialize(deserializer, entry, module) for entry in obj) + + return functools.partial(_deserialize_sequence, deserializer) + except (TypeError, IndexError, AttributeError, SyntaxError): + pass - return functools.partial(_deserialize_sequence, deserializer) - except (TypeError, IndexError, AttributeError, SyntaxError): + def _deserialize_default( + annotation, + deserializer_from_mapping, + obj, + ): + if obj is None: + return obj + try: + return _deserialize_with_callable(annotation, obj) + except Exception: pass + return _deserialize_with_callable(deserializer_from_mapping, obj) - def _deserialize_default( - annotation, - deserializer_from_mapping, - obj, - ): - if obj is None: - return obj - try: - return _deserialize_with_callable(annotation, obj) - except Exception: - pass - return _deserialize_with_callable(deserializer_from_mapping, obj) - - return functools.partial(_deserialize_default, annotation, _DESERIALIZE_MAPPING.get(annotation)) + return functools.partial(_deserialize_default, annotation, get_deserializer(annotation, rf)) -def _deserialize_with_callable(deserializer: typing.Optional[typing.Callable[[typing.Any], typing.Any]], value: typing.Any): +def _deserialize_with_callable( + deserializer: typing.Optional[typing.Callable[[typing.Any], typing.Any]], + value: typing.Any, +): try: if value is None: return None @@ -615,18 +744,24 @@ def _deserialize_with_callable(deserializer: typing.Optional[typing.Callable[[ty # for unknown value, return raw value return value if isinstance(deserializer, type) and issubclass(deserializer, Model): - return deserializer._deserialize(value) + return deserializer._deserialize(value, []) return typing.cast(typing.Callable[[typing.Any], typing.Any], deserializer)(value) except Exception as e: raise DeserializationError() from e -def _deserialize(deserializer: typing.Any, value: typing.Any, module: typing.Optional[str] = None) -> typing.Any: +def _deserialize( + deserializer: typing.Any, + value: typing.Any, + module: typing.Optional[str] = None, + rf: typing.Optional["_RestField"] = None, +) -> typing.Any: if isinstance(value, PipelineResponse): value = value.http_response.json() - deserializer = _get_deserialize_callable_from_annotation(deserializer, module) + deserializer = _get_deserialize_callable_from_annotation(deserializer, module, rf) return _deserialize_with_callable(deserializer, value) + class _RestField: def __init__( self, @@ -634,16 +769,18 @@ def __init__( name: typing.Optional[str] = None, type: typing.Optional[typing.Callable] = None, # pylint: disable=redefined-builtin is_discriminator: bool = False, - readonly: bool = False, + visibility: typing.Optional[typing.List[str]] = None, default: typing.Any = _UNSET, + format: typing.Optional[str] = None, ): self._type = type self._rest_name_input = name self._module: typing.Optional[str] = None self._is_discriminator = is_discriminator - self._readonly = readonly + self._visibility = visibility self._is_model = False self._default = default + self._format = format @property def _rest_name(self) -> str: @@ -657,7 +794,9 @@ def __get__(self, obj: Model, type=None): # pylint: disable=redefined-builtin item = obj.get(self._rest_name) if item is None: return item - return _deserialize(self._type, _serialize(item)) + if self._is_model: + return item + return _deserialize(self._type, _serialize(item, self._format), rf=self) def __set__(self, obj: Model, value) -> None: if value is None: @@ -667,9 +806,12 @@ def __set__(self, obj: Model, value) -> None: except KeyError: pass return - if self._is_model and not _is_model(value): - obj.__setitem__(self._rest_name, _deserialize(self._type, value)) - obj.__setitem__(self._rest_name, _serialize(value)) + if self._is_model: + if not _is_model(value): + value = _deserialize(self._type, value) + obj.__setitem__(self._rest_name, value) + return + obj.__setitem__(self._rest_name, _serialize(value, self._format)) def _get_deserialize_callable_from_annotation( self, annotation: typing.Any @@ -681,10 +823,11 @@ def rest_field( *, name: typing.Optional[str] = None, type: typing.Optional[typing.Callable] = None, # pylint: disable=redefined-builtin - readonly: bool = False, + visibility: typing.Optional[typing.List[str]] = None, default: typing.Any = _UNSET, + format: typing.Optional[str] = None, ) -> typing.Any: - return _RestField(name=name, type=type, readonly=readonly, default=default) + return _RestField(name=name, type=type, visibility=visibility, default=default, format=format) def rest_discriminator( diff --git a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_operations/_operations.py b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_operations/_operations.py index 3f8e45dbd5cb..b665dd492629 100644 --- a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_operations/_operations.py +++ b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_operations/_operations.py @@ -6,20 +6,27 @@ # Code generated by Microsoft (R) Python Code Generator. # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- +from io import IOBase import json -from typing import Any, Callable, Dict, List, Optional, TypeVar +import sys +from typing import Any, Callable, Dict, IO, List, Optional, TypeVar, Union, overload from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, ResourceNotModifiedError, map_error from azure.core.pipeline import PipelineResponse -from azure.core.pipeline.transport import HttpResponse -from azure.core.rest import HttpRequest +from azure.core.rest import HttpRequest, HttpResponse from azure.core.tracing.decorator import distributed_trace from azure.core.utils import case_insensitive_dict from .. import models as _models from .._model_base import AzureJSONEncoder, _deserialize from .._serialization import Serializer -from .._vendor import EventGridClientMixinABC, _format_url_section +from .._vendor import EventGridClientMixinABC + +if sys.version_info >= (3, 9): + from collections.abc import MutableMapping +else: + from typing import MutableMapping # type: ignore # pylint: disable=ungrouped-imports +JSON = MutableMapping[str, Any] # pylint: disable=unsubscriptable-object T = TypeVar('T') ClsType = Optional[Callable[[PipelineResponse[HttpRequest, HttpResponse], T, Dict[str, Any]], Any]] @@ -27,7 +34,7 @@ _SERIALIZER.client_side_validation = False -def build_event_grid_publish_cloud_event_request( +def build_event_grid_publish_cloud_event_request( # pylint: disable=name-too-long topic_name: str, **kwargs: Any ) -> HttpRequest: @@ -36,19 +43,22 @@ def build_event_grid_publish_cloud_event_request( content_type: str = kwargs.pop('content_type') api_version: str = kwargs.pop('api_version', _params.pop('api-version', "2023-06-01-preview")) + accept = _headers.pop('Accept', "application/json") + # Construct URL _url = "/topics/{topicName}:publish" path_format_arguments = { "topicName": _SERIALIZER.url("topic_name", topic_name, 'str'), } - _url: str = _format_url_section(_url, **path_format_arguments) # type: ignore + _url: str = _url.format(**path_format_arguments) # type: ignore # Construct parameters _params['api-version'] = _SERIALIZER.query("api_version", api_version, 'str') # Construct headers _headers['content-type'] = _SERIALIZER.header("content_type", content_type, 'str') + _headers['Accept'] = _SERIALIZER.header("accept", accept, 'str') return HttpRequest( method="POST", @@ -59,7 +69,7 @@ def build_event_grid_publish_cloud_event_request( ) -def build_event_grid_publish_cloud_events_request( +def build_event_grid_publish_cloud_events_request( # pylint: disable=name-too-long topic_name: str, **kwargs: Any ) -> HttpRequest: @@ -68,19 +78,22 @@ def build_event_grid_publish_cloud_events_request( content_type: str = kwargs.pop('content_type') api_version: str = kwargs.pop('api_version', _params.pop('api-version', "2023-06-01-preview")) + accept = _headers.pop('Accept', "application/json") + # Construct URL _url = "/topics/{topicName}:publish" path_format_arguments = { "topicName": _SERIALIZER.url("topic_name", topic_name, 'str'), } - _url: str = _format_url_section(_url, **path_format_arguments) # type: ignore + _url: str = _url.format(**path_format_arguments) # type: ignore # Construct parameters _params['api-version'] = _SERIALIZER.query("api_version", api_version, 'str') # Construct headers _headers['content-type'] = _SERIALIZER.header("content_type", content_type, 'str') + _headers['Accept'] = _SERIALIZER.header("accept", accept, 'str') return HttpRequest( method="POST", @@ -91,7 +104,7 @@ def build_event_grid_publish_cloud_events_request( ) -def build_event_grid_receive_cloud_events_request( +def build_event_grid_receive_cloud_events_request( # pylint: disable=name-too-long topic_name: str, event_subscription_name: str, *, @@ -112,7 +125,7 @@ def build_event_grid_receive_cloud_events_request( "eventSubscriptionName": _SERIALIZER.url("event_subscription_name", event_subscription_name, 'str'), } - _url: str = _format_url_section(_url, **path_format_arguments) # type: ignore + _url: str = _url.format(**path_format_arguments) # type: ignore # Construct parameters _params['api-version'] = _SERIALIZER.query("api_version", api_version, 'str') @@ -133,7 +146,7 @@ def build_event_grid_receive_cloud_events_request( ) -def build_event_grid_acknowledge_cloud_events_request( +def build_event_grid_acknowledge_cloud_events_request( # pylint: disable=name-too-long topic_name: str, event_subscription_name: str, **kwargs: Any @@ -141,7 +154,7 @@ def build_event_grid_acknowledge_cloud_events_request( _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) - content_type: str = kwargs.pop('content_type') + content_type: Optional[str] = kwargs.pop('content_type', _headers.pop('content-type', None)) api_version: str = kwargs.pop('api_version', _params.pop('api-version', "2023-06-01-preview")) accept = _headers.pop('Accept', "application/json") @@ -152,13 +165,14 @@ def build_event_grid_acknowledge_cloud_events_request( "eventSubscriptionName": _SERIALIZER.url("event_subscription_name", event_subscription_name, 'str'), } - _url: str = _format_url_section(_url, **path_format_arguments) # type: ignore + _url: str = _url.format(**path_format_arguments) # type: ignore # Construct parameters _params['api-version'] = _SERIALIZER.query("api_version", api_version, 'str') # Construct headers - _headers['content-type'] = _SERIALIZER.header("content_type", content_type, 'str') + if content_type is not None: + _headers['content-type'] = _SERIALIZER.header("content_type", content_type, 'str') _headers['Accept'] = _SERIALIZER.header("accept", accept, 'str') return HttpRequest( @@ -170,7 +184,7 @@ def build_event_grid_acknowledge_cloud_events_request( ) -def build_event_grid_release_cloud_events_request( +def build_event_grid_release_cloud_events_request( # pylint: disable=name-too-long topic_name: str, event_subscription_name: str, **kwargs: Any @@ -178,7 +192,7 @@ def build_event_grid_release_cloud_events_request( _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) - content_type: str = kwargs.pop('content_type') + content_type: Optional[str] = kwargs.pop('content_type', _headers.pop('content-type', None)) api_version: str = kwargs.pop('api_version', _params.pop('api-version', "2023-06-01-preview")) accept = _headers.pop('Accept', "application/json") @@ -189,13 +203,14 @@ def build_event_grid_release_cloud_events_request( "eventSubscriptionName": _SERIALIZER.url("event_subscription_name", event_subscription_name, 'str'), } - _url: str = _format_url_section(_url, **path_format_arguments) # type: ignore + _url: str = _url.format(**path_format_arguments) # type: ignore # Construct parameters _params['api-version'] = _SERIALIZER.query("api_version", api_version, 'str') # Construct headers - _headers['content-type'] = _SERIALIZER.header("content_type", content_type, 'str') + if content_type is not None: + _headers['content-type'] = _SERIALIZER.header("content_type", content_type, 'str') _headers['Accept'] = _SERIALIZER.header("accept", accept, 'str') return HttpRequest( @@ -207,7 +222,7 @@ def build_event_grid_release_cloud_events_request( ) -def build_event_grid_reject_cloud_events_request( +def build_event_grid_reject_cloud_events_request( # pylint: disable=name-too-long topic_name: str, event_subscription_name: str, **kwargs: Any @@ -215,7 +230,7 @@ def build_event_grid_reject_cloud_events_request( _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) - content_type: str = kwargs.pop('content_type') + content_type: Optional[str] = kwargs.pop('content_type', _headers.pop('content-type', None)) api_version: str = kwargs.pop('api_version', _params.pop('api-version', "2023-06-01-preview")) accept = _headers.pop('Accept', "application/json") @@ -226,13 +241,14 @@ def build_event_grid_reject_cloud_events_request( "eventSubscriptionName": _SERIALIZER.url("event_subscription_name", event_subscription_name, 'str'), } - _url: str = _format_url_section(_url, **path_format_arguments) # type: ignore + _url: str = _url.format(**path_format_arguments) # type: ignore # Construct parameters _params['api-version'] = _SERIALIZER.query("api_version", api_version, 'str') # Construct headers - _headers['content-type'] = _SERIALIZER.header("content_type", content_type, 'str') + if content_type is not None: + _headers['content-type'] = _SERIALIZER.header("content_type", content_type, 'str') _headers['Accept'] = _SERIALIZER.header("accept", accept, 'str') return HttpRequest( @@ -241,13 +257,19 @@ def build_event_grid_reject_cloud_events_request( params=_params, headers=_headers, **kwargs + ) + +class EventGridClientOperationsMixin( + EventGridClientMixinABC +): + @distributed_trace - def _publish_cloud_event( # pylint: disable=inconsistent-return-statements,protected-access + def _publish_cloud_event( # pylint: disable=protected-access self, topic_name: str, event: _models._models.CloudEvent, **kwargs: Any - ) -> None: + ) -> _models._models.PublishResult: """Publish Single Cloud Event to namespace topic. In case of success, the server responds with an HTTP 200 status code with an empty JSON object in response. Otherwise, the server can return various error codes. For example, 401: which indicates authorization failure, 403: which @@ -263,8 +285,8 @@ def _publish_cloud_event( # pylint: disable=inconsistent-return-statements,prot :paramtype content_type: str :keyword bool stream: Whether to stream the response of this operation. Defaults to False. You will have to context manage the returned stream. - :return: None - :rtype: None + :return: PublishResult. The PublishResult is compatible with MutableMapping + :rtype: ~azure.eventgrid.models.PublishResult :raises ~azure.core.exceptions.HttpResponseError: """ error_map = { @@ -276,11 +298,11 @@ def _publish_cloud_event( # pylint: disable=inconsistent-return-statements,prot _params = kwargs.pop("params", {}) or {} content_type: str = kwargs.pop('content_type', _headers.pop('content-type', "application/cloudevents+json; charset=utf-8")) - cls: ClsType[None] = kwargs.pop( + cls: ClsType[_models._models.PublishResult] = kwargs.pop( # pylint: disable=protected-access 'cls', None ) - _content = json.dumps(event, cls=AzureJSONEncoder) # type: ignore + _content = json.dumps(event, cls=AzureJSONEncoder, exclude_readonly=True) # type: ignore request = build_event_grid_publish_cloud_event_request( topic_name=topic_name, @@ -305,21 +327,33 @@ def _publish_cloud_event( # pylint: disable=inconsistent-return-statements,prot response = pipeline_response.http_response if response.status_code not in [200]: + if _stream: + response.read() # Load the body in memory and close the socket map_error(status_code=response.status_code, response=response, error_map=error_map) raise HttpResponseError(response=response) + if _stream: + deserialized = response.iter_bytes() + else: + deserialized = _deserialize( + _models._models.PublishResult, # pylint: disable=protected-access + response.json() + ) + if cls: - return cls(pipeline_response, None, {}) + return cls(pipeline_response, deserialized, {}) # type: ignore + + return deserialized # type: ignore @distributed_trace - def _publish_cloud_events( # pylint: disable=inconsistent-return-statements + def _publish_cloud_events( # pylint: disable=protected-access self, topic_name: str, events: List[_models._models.CloudEvent], **kwargs: Any - ) -> None: + ) -> _models._models.PublishResult: """Publish Batch Cloud Event to namespace topic. In case of success, the server responds with an HTTP 200 status code with an empty JSON object in response. Otherwise, the server can return various error codes. For example, 401: which indicates authorization failure, 403: which @@ -335,8 +369,8 @@ def _publish_cloud_events( # pylint: disable=inconsistent-return-statements :paramtype content_type: str :keyword bool stream: Whether to stream the response of this operation. Defaults to False. You will have to context manage the returned stream. - :return: None - :rtype: None + :return: PublishResult. The PublishResult is compatible with MutableMapping + :rtype: ~azure.eventgrid.models.PublishResult :raises ~azure.core.exceptions.HttpResponseError: """ error_map = { @@ -348,11 +382,11 @@ def _publish_cloud_events( # pylint: disable=inconsistent-return-statements _params = kwargs.pop("params", {}) or {} content_type: str = kwargs.pop('content_type', _headers.pop('content-type', "application/cloudevents-batch+json; charset=utf-8")) - cls: ClsType[None] = kwargs.pop( + cls: ClsType[_models._models.PublishResult] = kwargs.pop( # pylint: disable=protected-access 'cls', None ) - _content = json.dumps(events, cls=AzureJSONEncoder) # type: ignore + _content = json.dumps(events, cls=AzureJSONEncoder, exclude_readonly=True) # type: ignore request = build_event_grid_publish_cloud_events_request( topic_name=topic_name, @@ -377,11 +411,23 @@ def _publish_cloud_events( # pylint: disable=inconsistent-return-statements response = pipeline_response.http_response if response.status_code not in [200]: + if _stream: + response.read() # Load the body in memory and close the socket map_error(status_code=response.status_code, response=response, error_map=error_map) raise HttpResponseError(response=response) + if _stream: + deserialized = response.iter_bytes() + else: + deserialized = _deserialize( + _models._models.PublishResult, # pylint: disable=protected-access + response.json() + ) + if cls: - return cls(pipeline_response, None, {}) + return cls(pipeline_response, deserialized, {}) # type: ignore + + return deserialized # type: ignore @@ -453,6 +499,8 @@ def _receive_cloud_events( # pylint: disable=protected-access response = pipeline_response.http_response if response.status_code not in [200]: + if _stream: + response.read() # Load the body in memory and close the socket map_error(status_code=response.status_code, response=response, error_map=error_map) raise HttpResponseError(response=response) @@ -471,12 +519,14 @@ def _receive_cloud_events( # pylint: disable=protected-access - @distributed_trace + @overload def acknowledge_cloud_events( self, topic_name: str, event_subscription_name: str, lock_tokens: _models.AcknowledgeOptions, + *, + content_type: str = "application/json", **kwargs: Any ) -> _models.AcknowledgeResult: """Acknowledge batch of Cloud Events. The server responds with an HTTP 200 status code if at least @@ -490,7 +540,100 @@ def acknowledge_cloud_events( :type event_subscription_name: str :param lock_tokens: AcknowledgeOptions. Required. :type lock_tokens: ~azure.eventgrid.models.AcknowledgeOptions - :keyword content_type: content type. Default value is "application/json; charset=utf-8". + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :keyword bool stream: Whether to stream the response of this operation. Defaults to False. You + will have to context manage the returned stream. + :return: AcknowledgeResult. The AcknowledgeResult is compatible with MutableMapping + :rtype: ~azure.eventgrid.models.AcknowledgeResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + def acknowledge_cloud_events( + self, + topic_name: str, + event_subscription_name: str, + lock_tokens: JSON, + *, + content_type: str = "application/json", + **kwargs: Any + ) -> _models.AcknowledgeResult: + """Acknowledge batch of Cloud Events. The server responds with an HTTP 200 status code if at least + one event is successfully acknowledged. The response body will include the set of successfully + acknowledged lockTokens, along with other failed lockTokens with their corresponding error + information. Successfully acknowledged events will no longer be available to any consumer. + + :param topic_name: Topic Name. Required. + :type topic_name: str + :param event_subscription_name: Event Subscription Name. Required. + :type event_subscription_name: str + :param lock_tokens: AcknowledgeOptions. Required. + :type lock_tokens: JSON + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :keyword bool stream: Whether to stream the response of this operation. Defaults to False. You + will have to context manage the returned stream. + :return: AcknowledgeResult. The AcknowledgeResult is compatible with MutableMapping + :rtype: ~azure.eventgrid.models.AcknowledgeResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + def acknowledge_cloud_events( + self, + topic_name: str, + event_subscription_name: str, + lock_tokens: IO, + *, + content_type: str = "application/json", + **kwargs: Any + ) -> _models.AcknowledgeResult: + """Acknowledge batch of Cloud Events. The server responds with an HTTP 200 status code if at least + one event is successfully acknowledged. The response body will include the set of successfully + acknowledged lockTokens, along with other failed lockTokens with their corresponding error + information. Successfully acknowledged events will no longer be available to any consumer. + + :param topic_name: Topic Name. Required. + :type topic_name: str + :param event_subscription_name: Event Subscription Name. Required. + :type event_subscription_name: str + :param lock_tokens: AcknowledgeOptions. Required. + :type lock_tokens: IO + :keyword content_type: Body Parameter content-type. Content type parameter for binary body. + Default value is "application/json". + :paramtype content_type: str + :keyword bool stream: Whether to stream the response of this operation. Defaults to False. You + will have to context manage the returned stream. + :return: AcknowledgeResult. The AcknowledgeResult is compatible with MutableMapping + :rtype: ~azure.eventgrid.models.AcknowledgeResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + + @distributed_trace + def acknowledge_cloud_events( + self, + topic_name: str, + event_subscription_name: str, + lock_tokens: Union[_models.AcknowledgeOptions, JSON, IO], + **kwargs: Any + ) -> _models.AcknowledgeResult: + """Acknowledge batch of Cloud Events. The server responds with an HTTP 200 status code if at least + one event is successfully acknowledged. The response body will include the set of successfully + acknowledged lockTokens, along with other failed lockTokens with their corresponding error + information. Successfully acknowledged events will no longer be available to any consumer. + + :param topic_name: Topic Name. Required. + :type topic_name: str + :param event_subscription_name: Event Subscription Name. Required. + :type event_subscription_name: str + :param lock_tokens: AcknowledgeOptions. Is one of the following types: AcknowledgeOptions, + JSON, IO Required. + :type lock_tokens: ~azure.eventgrid.models.AcknowledgeOptions or JSON or IO + :keyword content_type: content type. Default value is None. :paramtype content_type: str :keyword bool stream: Whether to stream the response of this operation. Defaults to False. You will have to context manage the returned stream. @@ -506,12 +649,17 @@ def acknowledge_cloud_events( _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = kwargs.pop("params", {}) or {} - content_type: str = kwargs.pop('content_type', _headers.pop('content-type', "application/json; charset=utf-8")) + content_type: Optional[str] = kwargs.pop('content_type', _headers.pop('content-type', None)) cls: ClsType[_models.AcknowledgeResult] = kwargs.pop( 'cls', None ) - _content = json.dumps(lock_tokens, cls=AzureJSONEncoder) # type: ignore + content_type = content_type or "application/json" + _content = None + if isinstance(lock_tokens, (IOBase, bytes)): + _content = lock_tokens + else: + _content = json.dumps(lock_tokens, cls=AzureJSONEncoder, exclude_readonly=True) # type: ignore request = build_event_grid_acknowledge_cloud_events_request( topic_name=topic_name, @@ -537,6 +685,8 @@ def acknowledge_cloud_events( response = pipeline_response.http_response if response.status_code not in [200]: + if _stream: + response.read() # Load the body in memory and close the socket map_error(status_code=response.status_code, response=response, error_map=error_map) raise HttpResponseError(response=response) @@ -555,12 +705,14 @@ def acknowledge_cloud_events( - @distributed_trace + @overload def release_cloud_events( self, topic_name: str, event_subscription_name: str, lock_tokens: _models.ReleaseOptions, + *, + content_type: str = "application/json", **kwargs: Any ) -> _models.ReleaseResult: """Release batch of Cloud Events. The server responds with an HTTP 200 status code if at least one @@ -573,7 +725,97 @@ def release_cloud_events( :type event_subscription_name: str :param lock_tokens: ReleaseOptions. Required. :type lock_tokens: ~azure.eventgrid.models.ReleaseOptions - :keyword content_type: content type. Default value is "application/json; charset=utf-8". + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :keyword bool stream: Whether to stream the response of this operation. Defaults to False. You + will have to context manage the returned stream. + :return: ReleaseResult. The ReleaseResult is compatible with MutableMapping + :rtype: ~azure.eventgrid.models.ReleaseResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + def release_cloud_events( + self, + topic_name: str, + event_subscription_name: str, + lock_tokens: JSON, + *, + content_type: str = "application/json", + **kwargs: Any + ) -> _models.ReleaseResult: + """Release batch of Cloud Events. The server responds with an HTTP 200 status code if at least one + event is successfully released. The response body will include the set of successfully released + lockTokens, along with other failed lockTokens with their corresponding error information. + + :param topic_name: Topic Name. Required. + :type topic_name: str + :param event_subscription_name: Event Subscription Name. Required. + :type event_subscription_name: str + :param lock_tokens: ReleaseOptions. Required. + :type lock_tokens: JSON + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :keyword bool stream: Whether to stream the response of this operation. Defaults to False. You + will have to context manage the returned stream. + :return: ReleaseResult. The ReleaseResult is compatible with MutableMapping + :rtype: ~azure.eventgrid.models.ReleaseResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + def release_cloud_events( + self, + topic_name: str, + event_subscription_name: str, + lock_tokens: IO, + *, + content_type: str = "application/json", + **kwargs: Any + ) -> _models.ReleaseResult: + """Release batch of Cloud Events. The server responds with an HTTP 200 status code if at least one + event is successfully released. The response body will include the set of successfully released + lockTokens, along with other failed lockTokens with their corresponding error information. + + :param topic_name: Topic Name. Required. + :type topic_name: str + :param event_subscription_name: Event Subscription Name. Required. + :type event_subscription_name: str + :param lock_tokens: ReleaseOptions. Required. + :type lock_tokens: IO + :keyword content_type: Body Parameter content-type. Content type parameter for binary body. + Default value is "application/json". + :paramtype content_type: str + :keyword bool stream: Whether to stream the response of this operation. Defaults to False. You + will have to context manage the returned stream. + :return: ReleaseResult. The ReleaseResult is compatible with MutableMapping + :rtype: ~azure.eventgrid.models.ReleaseResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + + @distributed_trace + def release_cloud_events( + self, + topic_name: str, + event_subscription_name: str, + lock_tokens: Union[_models.ReleaseOptions, JSON, IO], + **kwargs: Any + ) -> _models.ReleaseResult: + """Release batch of Cloud Events. The server responds with an HTTP 200 status code if at least one + event is successfully released. The response body will include the set of successfully released + lockTokens, along with other failed lockTokens with their corresponding error information. + + :param topic_name: Topic Name. Required. + :type topic_name: str + :param event_subscription_name: Event Subscription Name. Required. + :type event_subscription_name: str + :param lock_tokens: ReleaseOptions. Is one of the following types: ReleaseOptions, JSON, IO + Required. + :type lock_tokens: ~azure.eventgrid.models.ReleaseOptions or JSON or IO + :keyword content_type: content type. Default value is None. :paramtype content_type: str :keyword bool stream: Whether to stream the response of this operation. Defaults to False. You will have to context manage the returned stream. @@ -589,12 +831,17 @@ def release_cloud_events( _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = kwargs.pop("params", {}) or {} - content_type: str = kwargs.pop('content_type', _headers.pop('content-type', "application/json; charset=utf-8")) + content_type: Optional[str] = kwargs.pop('content_type', _headers.pop('content-type', None)) cls: ClsType[_models.ReleaseResult] = kwargs.pop( 'cls', None ) - _content = json.dumps(lock_tokens, cls=AzureJSONEncoder) # type: ignore + content_type = content_type or "application/json" + _content = None + if isinstance(lock_tokens, (IOBase, bytes)): + _content = lock_tokens + else: + _content = json.dumps(lock_tokens, cls=AzureJSONEncoder, exclude_readonly=True) # type: ignore request = build_event_grid_release_cloud_events_request( topic_name=topic_name, @@ -620,6 +867,8 @@ def release_cloud_events( response = pipeline_response.http_response if response.status_code not in [200]: + if _stream: + response.read() # Load the body in memory and close the socket map_error(status_code=response.status_code, response=response, error_map=error_map) raise HttpResponseError(response=response) @@ -638,12 +887,14 @@ def release_cloud_events( - @distributed_trace + @overload def reject_cloud_events( self, topic_name: str, event_subscription_name: str, lock_tokens: _models.RejectOptions, + *, + content_type: str = "application/json", **kwargs: Any ) -> _models.RejectResult: """Reject batch of Cloud Events. @@ -654,7 +905,91 @@ def reject_cloud_events( :type event_subscription_name: str :param lock_tokens: RejectOptions. Required. :type lock_tokens: ~azure.eventgrid.models.RejectOptions - :keyword content_type: content type. Default value is "application/json; charset=utf-8". + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :keyword bool stream: Whether to stream the response of this operation. Defaults to False. You + will have to context manage the returned stream. + :return: RejectResult. The RejectResult is compatible with MutableMapping + :rtype: ~azure.eventgrid.models.RejectResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + def reject_cloud_events( + self, + topic_name: str, + event_subscription_name: str, + lock_tokens: JSON, + *, + content_type: str = "application/json", + **kwargs: Any + ) -> _models.RejectResult: + """Reject batch of Cloud Events. + + :param topic_name: Topic Name. Required. + :type topic_name: str + :param event_subscription_name: Event Subscription Name. Required. + :type event_subscription_name: str + :param lock_tokens: RejectOptions. Required. + :type lock_tokens: JSON + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :keyword bool stream: Whether to stream the response of this operation. Defaults to False. You + will have to context manage the returned stream. + :return: RejectResult. The RejectResult is compatible with MutableMapping + :rtype: ~azure.eventgrid.models.RejectResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + def reject_cloud_events( + self, + topic_name: str, + event_subscription_name: str, + lock_tokens: IO, + *, + content_type: str = "application/json", + **kwargs: Any + ) -> _models.RejectResult: + """Reject batch of Cloud Events. + + :param topic_name: Topic Name. Required. + :type topic_name: str + :param event_subscription_name: Event Subscription Name. Required. + :type event_subscription_name: str + :param lock_tokens: RejectOptions. Required. + :type lock_tokens: IO + :keyword content_type: Body Parameter content-type. Content type parameter for binary body. + Default value is "application/json". + :paramtype content_type: str + :keyword bool stream: Whether to stream the response of this operation. Defaults to False. You + will have to context manage the returned stream. + :return: RejectResult. The RejectResult is compatible with MutableMapping + :rtype: ~azure.eventgrid.models.RejectResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + + @distributed_trace + def reject_cloud_events( + self, + topic_name: str, + event_subscription_name: str, + lock_tokens: Union[_models.RejectOptions, JSON, IO], + **kwargs: Any + ) -> _models.RejectResult: + """Reject batch of Cloud Events. + + :param topic_name: Topic Name. Required. + :type topic_name: str + :param event_subscription_name: Event Subscription Name. Required. + :type event_subscription_name: str + :param lock_tokens: RejectOptions. Is one of the following types: RejectOptions, JSON, IO + Required. + :type lock_tokens: ~azure.eventgrid.models.RejectOptions or JSON or IO + :keyword content_type: content type. Default value is None. :paramtype content_type: str :keyword bool stream: Whether to stream the response of this operation. Defaults to False. You will have to context manage the returned stream. @@ -670,12 +1005,17 @@ def reject_cloud_events( _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = kwargs.pop("params", {}) or {} - content_type: str = kwargs.pop('content_type', _headers.pop('content-type', "application/json; charset=utf-8")) + content_type: Optional[str] = kwargs.pop('content_type', _headers.pop('content-type', None)) cls: ClsType[_models.RejectResult] = kwargs.pop( 'cls', None ) - _content = json.dumps(lock_tokens, cls=AzureJSONEncoder) # type: ignore + content_type = content_type or "application/json" + _content = None + if isinstance(lock_tokens, (IOBase, bytes)): + _content = lock_tokens + else: + _content = json.dumps(lock_tokens, cls=AzureJSONEncoder, exclude_readonly=True) # type: ignore request = build_event_grid_reject_cloud_events_request( topic_name=topic_name, @@ -701,6 +1041,8 @@ def reject_cloud_events( response = pipeline_response.http_response if response.status_code not in [200]: + if _stream: + response.read() # Load the body in memory and close the socket map_error(status_code=response.status_code, response=response, error_map=error_map) raise HttpResponseError(response=response) diff --git a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_serialization.py b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_serialization.py index e3cc6ce6ed6f..44ca0b58b661 100644 --- a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_serialization.py +++ b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_serialization.py @@ -664,8 +664,9 @@ def _serialize(self, target_obj, data_type=None, **kwargs): _serialized.update(_new_attr) # type: ignore _new_attr = _new_attr[k] # type: ignore _serialized = _serialized[k] - except ValueError: - continue + except ValueError as err: + if isinstance(err, SerializationError): + raise except (AttributeError, KeyError, TypeError) as err: msg = "Attribute {} in object {} cannot be serialized.\n{}".format(attr_name, class_name, str(target_obj)) @@ -731,6 +732,8 @@ def url(self, name, data, data_type, **kwargs): if kwargs.get("skip_quote") is True: output = str(output) + # https://github.com/Azure/autorest.python/issues/2063 + output = output.replace("{", quote("{")).replace("}", quote("}")) else: output = quote(str(output), safe="") except SerializationError: @@ -743,6 +746,8 @@ def query(self, name, data, data_type, **kwargs): :param data: The data to be serialized. :param str data_type: The type to be serialized from. + :keyword bool skip_quote: Whether to skip quote the serialized result. + Defaults to False. :rtype: str :raises: TypeError if serialization fails. :raises: ValueError if data is None @@ -751,10 +756,8 @@ def query(self, name, data, data_type, **kwargs): # Treat the list aside, since we don't want to encode the div separator if data_type.startswith("["): internal_data_type = data_type[1:-1] - data = [self.serialize_data(d, internal_data_type, **kwargs) if d is not None else "" for d in data] - if not kwargs.get("skip_quote", False): - data = [quote(str(d), safe="") for d in data] - return str(self.serialize_iter(data, internal_data_type, **kwargs)) + do_quote = not kwargs.get('skip_quote', False) + return str(self.serialize_iter(data, internal_data_type, do_quote=do_quote, **kwargs)) # Not a list, regular serialization output = self.serialize_data(data, data_type, **kwargs) @@ -893,6 +896,8 @@ def serialize_iter(self, data, iter_type, div=None, **kwargs): not be None or empty. :param str div: If set, this str will be used to combine the elements in the iterable into a combined string. Default is 'None'. + :keyword bool do_quote: Whether to quote the serialized result of each iterable element. + Defaults to False. :rtype: list, str """ if isinstance(data, str): @@ -905,9 +910,18 @@ def serialize_iter(self, data, iter_type, div=None, **kwargs): for d in data: try: serialized.append(self.serialize_data(d, iter_type, **kwargs)) - except ValueError: + except ValueError as err: + if isinstance(err, SerializationError): + raise serialized.append(None) + if kwargs.get('do_quote', False): + serialized = [ + '' if s is None else quote(str(s), safe='') + for s + in serialized + ] + if div: serialized = ["" if s is None else str(s) for s in serialized] serialized = div.join(serialized) @@ -952,7 +966,9 @@ def serialize_dict(self, attr, dict_type, **kwargs): for key, value in attr.items(): try: serialized[self.serialize_unicode(key)] = self.serialize_data(value, dict_type, **kwargs) - except ValueError: + except ValueError as err: + if isinstance(err, SerializationError): + raise serialized[self.serialize_unicode(key)] = None if "xml" in serialization_ctxt: diff --git a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_vendor.py b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_vendor.py index 3aae9cfccf6b..682fa0a3f71f 100644 --- a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_vendor.py +++ b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_vendor.py @@ -6,7 +6,7 @@ # -------------------------------------------------------------------------- from abc import ABC -from typing import List, TYPE_CHECKING, cast +from typing import TYPE_CHECKING from ._configuration import EventGridClientConfiguration @@ -16,23 +16,12 @@ from ._serialization import Deserializer, Serializer - -def _format_url_section(template, **kwargs): - components = template.split("/") - while components: - try: - return template.format(**kwargs) - except KeyError as key: - # Need the cast, as for some reasons "split" is typed as list[str | Any] - formatted_components = cast(List[str], template.split("/")) - components = [ - c for c in formatted_components if "{}".format(key.args[0]) not in c - ] - template = "/".join(components) - -class EventGridClientMixinABC(ABC): +class EventGridClientMixinABC( + ABC +): """DO NOT use this class. It is for internal typing use only.""" _client: "PipelineClient" _config: EventGridClientConfiguration _serialize: "Serializer" _deserialize: "Deserializer" + diff --git a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/aio/_configuration.py b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/aio/_configuration.py index d2308d4f626d..8074ab267aba 100644 --- a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/aio/_configuration.py +++ b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/aio/_configuration.py @@ -15,7 +15,9 @@ from .._version import VERSION -class EventGridClientConfiguration(Configuration): # pylint: disable=too-many-instance-attributes +class EventGridClientConfiguration( # pylint: disable=too-many-instance-attributes,name-too-long + Configuration +): """Configuration for EventGridClient. Note that all parameters used to create this instance are saved as instance diff --git a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/aio/_operations/_operations.py b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/aio/_operations/_operations.py index 9a15d090bd8b..eb2c6cc3182f 100644 --- a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/aio/_operations/_operations.py +++ b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/aio/_operations/_operations.py @@ -6,13 +6,14 @@ # Code generated by Microsoft (R) Python Code Generator. # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- +from io import IOBase import json -from typing import Any, Callable, Dict, List, Optional, TypeVar +import sys +from typing import Any, Callable, Dict, IO, List, Optional, TypeVar, Union, overload from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, ResourceNotModifiedError, map_error from azure.core.pipeline import PipelineResponse -from azure.core.pipeline.transport import AsyncHttpResponse -from azure.core.rest import HttpRequest +from azure.core.rest import AsyncHttpResponse, HttpRequest from azure.core.tracing.decorator_async import distributed_trace_async from azure.core.utils import case_insensitive_dict @@ -20,18 +21,26 @@ from ..._model_base import AzureJSONEncoder, _deserialize from ..._operations._operations import build_event_grid_acknowledge_cloud_events_request, build_event_grid_publish_cloud_event_request, build_event_grid_publish_cloud_events_request, build_event_grid_receive_cloud_events_request, build_event_grid_reject_cloud_events_request, build_event_grid_release_cloud_events_request from .._vendor import EventGridClientMixinABC + +if sys.version_info >= (3, 9): + from collections.abc import MutableMapping +else: + from typing import MutableMapping # type: ignore # pylint: disable=ungrouped-imports +JSON = MutableMapping[str, Any] # pylint: disable=unsubscriptable-object T = TypeVar('T') ClsType = Optional[Callable[[PipelineResponse[HttpRequest, AsyncHttpResponse], T, Dict[str, Any]], Any]] -class EventGridClientOperationsMixin(EventGridClientMixinABC): +class EventGridClientOperationsMixin( + EventGridClientMixinABC +): @distributed_trace_async - async def _publish_cloud_event( # pylint: disable=inconsistent-return-statements,protected-access + async def _publish_cloud_event( # pylint: disable=protected-access self, topic_name: str, event: _models._models.CloudEvent, **kwargs: Any - ) -> None: + ) -> _models._models.PublishResult: """Publish Single Cloud Event to namespace topic. In case of success, the server responds with an HTTP 200 status code with an empty JSON object in response. Otherwise, the server can return various error codes. For example, 401: which indicates authorization failure, 403: which @@ -47,8 +56,8 @@ async def _publish_cloud_event( # pylint: disable=inconsistent-return-statement :paramtype content_type: str :keyword bool stream: Whether to stream the response of this operation. Defaults to False. You will have to context manage the returned stream. - :return: None - :rtype: None + :return: PublishResult. The PublishResult is compatible with MutableMapping + :rtype: ~azure.eventgrid.models.PublishResult :raises ~azure.core.exceptions.HttpResponseError: """ error_map = { @@ -60,11 +69,11 @@ async def _publish_cloud_event( # pylint: disable=inconsistent-return-statement _params = kwargs.pop("params", {}) or {} content_type: str = kwargs.pop('content_type', _headers.pop('content-type', "application/cloudevents+json; charset=utf-8")) - cls: ClsType[None] = kwargs.pop( + cls: ClsType[_models._models.PublishResult] = kwargs.pop( # pylint: disable=protected-access 'cls', None ) - _content = json.dumps(event, cls=AzureJSONEncoder) # type: ignore + _content = json.dumps(event, cls=AzureJSONEncoder, exclude_readonly=True) # type: ignore request = build_event_grid_publish_cloud_event_request( topic_name=topic_name, @@ -89,21 +98,33 @@ async def _publish_cloud_event( # pylint: disable=inconsistent-return-statement response = pipeline_response.http_response if response.status_code not in [200]: + if _stream: + await response.read() # Load the body in memory and close the socket map_error(status_code=response.status_code, response=response, error_map=error_map) raise HttpResponseError(response=response) + if _stream: + deserialized = response.iter_bytes() + else: + deserialized = _deserialize( + _models._models.PublishResult, # pylint: disable=protected-access + response.json() + ) + if cls: - return cls(pipeline_response, None, {}) + return cls(pipeline_response, deserialized, {}) # type: ignore + + return deserialized # type: ignore @distributed_trace_async - async def _publish_cloud_events( # pylint: disable=inconsistent-return-statements + async def _publish_cloud_events( # pylint: disable=protected-access self, topic_name: str, events: List[_models._models.CloudEvent], **kwargs: Any - ) -> None: + ) -> _models._models.PublishResult: """Publish Batch Cloud Event to namespace topic. In case of success, the server responds with an HTTP 200 status code with an empty JSON object in response. Otherwise, the server can return various error codes. For example, 401: which indicates authorization failure, 403: which @@ -119,8 +140,8 @@ async def _publish_cloud_events( # pylint: disable=inconsistent-return-statemen :paramtype content_type: str :keyword bool stream: Whether to stream the response of this operation. Defaults to False. You will have to context manage the returned stream. - :return: None - :rtype: None + :return: PublishResult. The PublishResult is compatible with MutableMapping + :rtype: ~azure.eventgrid.models.PublishResult :raises ~azure.core.exceptions.HttpResponseError: """ error_map = { @@ -132,11 +153,11 @@ async def _publish_cloud_events( # pylint: disable=inconsistent-return-statemen _params = kwargs.pop("params", {}) or {} content_type: str = kwargs.pop('content_type', _headers.pop('content-type', "application/cloudevents-batch+json; charset=utf-8")) - cls: ClsType[None] = kwargs.pop( + cls: ClsType[_models._models.PublishResult] = kwargs.pop( # pylint: disable=protected-access 'cls', None ) - _content = json.dumps(events, cls=AzureJSONEncoder) # type: ignore + _content = json.dumps(events, cls=AzureJSONEncoder, exclude_readonly=True) # type: ignore request = build_event_grid_publish_cloud_events_request( topic_name=topic_name, @@ -161,11 +182,23 @@ async def _publish_cloud_events( # pylint: disable=inconsistent-return-statemen response = pipeline_response.http_response if response.status_code not in [200]: + if _stream: + await response.read() # Load the body in memory and close the socket map_error(status_code=response.status_code, response=response, error_map=error_map) raise HttpResponseError(response=response) + if _stream: + deserialized = response.iter_bytes() + else: + deserialized = _deserialize( + _models._models.PublishResult, # pylint: disable=protected-access + response.json() + ) + if cls: - return cls(pipeline_response, None, {}) + return cls(pipeline_response, deserialized, {}) # type: ignore + + return deserialized # type: ignore @@ -237,6 +270,8 @@ async def _receive_cloud_events( # pylint: disable=protected-access response = pipeline_response.http_response if response.status_code not in [200]: + if _stream: + await response.read() # Load the body in memory and close the socket map_error(status_code=response.status_code, response=response, error_map=error_map) raise HttpResponseError(response=response) @@ -255,12 +290,14 @@ async def _receive_cloud_events( # pylint: disable=protected-access - @distributed_trace_async + @overload async def acknowledge_cloud_events( self, topic_name: str, event_subscription_name: str, lock_tokens: _models.AcknowledgeOptions, + *, + content_type: str = "application/json", **kwargs: Any ) -> _models.AcknowledgeResult: """Acknowledge batch of Cloud Events. The server responds with an HTTP 200 status code if at least @@ -274,7 +311,100 @@ async def acknowledge_cloud_events( :type event_subscription_name: str :param lock_tokens: AcknowledgeOptions. Required. :type lock_tokens: ~azure.eventgrid.models.AcknowledgeOptions - :keyword content_type: content type. Default value is "application/json; charset=utf-8". + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :keyword bool stream: Whether to stream the response of this operation. Defaults to False. You + will have to context manage the returned stream. + :return: AcknowledgeResult. The AcknowledgeResult is compatible with MutableMapping + :rtype: ~azure.eventgrid.models.AcknowledgeResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + async def acknowledge_cloud_events( + self, + topic_name: str, + event_subscription_name: str, + lock_tokens: JSON, + *, + content_type: str = "application/json", + **kwargs: Any + ) -> _models.AcknowledgeResult: + """Acknowledge batch of Cloud Events. The server responds with an HTTP 200 status code if at least + one event is successfully acknowledged. The response body will include the set of successfully + acknowledged lockTokens, along with other failed lockTokens with their corresponding error + information. Successfully acknowledged events will no longer be available to any consumer. + + :param topic_name: Topic Name. Required. + :type topic_name: str + :param event_subscription_name: Event Subscription Name. Required. + :type event_subscription_name: str + :param lock_tokens: AcknowledgeOptions. Required. + :type lock_tokens: JSON + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :keyword bool stream: Whether to stream the response of this operation. Defaults to False. You + will have to context manage the returned stream. + :return: AcknowledgeResult. The AcknowledgeResult is compatible with MutableMapping + :rtype: ~azure.eventgrid.models.AcknowledgeResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + async def acknowledge_cloud_events( + self, + topic_name: str, + event_subscription_name: str, + lock_tokens: IO, + *, + content_type: str = "application/json", + **kwargs: Any + ) -> _models.AcknowledgeResult: + """Acknowledge batch of Cloud Events. The server responds with an HTTP 200 status code if at least + one event is successfully acknowledged. The response body will include the set of successfully + acknowledged lockTokens, along with other failed lockTokens with their corresponding error + information. Successfully acknowledged events will no longer be available to any consumer. + + :param topic_name: Topic Name. Required. + :type topic_name: str + :param event_subscription_name: Event Subscription Name. Required. + :type event_subscription_name: str + :param lock_tokens: AcknowledgeOptions. Required. + :type lock_tokens: IO + :keyword content_type: Body Parameter content-type. Content type parameter for binary body. + Default value is "application/json". + :paramtype content_type: str + :keyword bool stream: Whether to stream the response of this operation. Defaults to False. You + will have to context manage the returned stream. + :return: AcknowledgeResult. The AcknowledgeResult is compatible with MutableMapping + :rtype: ~azure.eventgrid.models.AcknowledgeResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + + @distributed_trace_async + async def acknowledge_cloud_events( + self, + topic_name: str, + event_subscription_name: str, + lock_tokens: Union[_models.AcknowledgeOptions, JSON, IO], + **kwargs: Any + ) -> _models.AcknowledgeResult: + """Acknowledge batch of Cloud Events. The server responds with an HTTP 200 status code if at least + one event is successfully acknowledged. The response body will include the set of successfully + acknowledged lockTokens, along with other failed lockTokens with their corresponding error + information. Successfully acknowledged events will no longer be available to any consumer. + + :param topic_name: Topic Name. Required. + :type topic_name: str + :param event_subscription_name: Event Subscription Name. Required. + :type event_subscription_name: str + :param lock_tokens: AcknowledgeOptions. Is one of the following types: AcknowledgeOptions, + JSON, IO Required. + :type lock_tokens: ~azure.eventgrid.models.AcknowledgeOptions or JSON or IO + :keyword content_type: content type. Default value is None. :paramtype content_type: str :keyword bool stream: Whether to stream the response of this operation. Defaults to False. You will have to context manage the returned stream. @@ -290,12 +420,17 @@ async def acknowledge_cloud_events( _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = kwargs.pop("params", {}) or {} - content_type: str = kwargs.pop('content_type', _headers.pop('content-type', "application/json; charset=utf-8")) + content_type: Optional[str] = kwargs.pop('content_type', _headers.pop('content-type', None)) cls: ClsType[_models.AcknowledgeResult] = kwargs.pop( 'cls', None ) - _content = json.dumps(lock_tokens, cls=AzureJSONEncoder) # type: ignore + content_type = content_type or "application/json" + _content = None + if isinstance(lock_tokens, (IOBase, bytes)): + _content = lock_tokens + else: + _content = json.dumps(lock_tokens, cls=AzureJSONEncoder, exclude_readonly=True) # type: ignore request = build_event_grid_acknowledge_cloud_events_request( topic_name=topic_name, @@ -321,6 +456,8 @@ async def acknowledge_cloud_events( response = pipeline_response.http_response if response.status_code not in [200]: + if _stream: + await response.read() # Load the body in memory and close the socket map_error(status_code=response.status_code, response=response, error_map=error_map) raise HttpResponseError(response=response) @@ -339,12 +476,14 @@ async def acknowledge_cloud_events( - @distributed_trace_async + @overload async def release_cloud_events( self, topic_name: str, event_subscription_name: str, lock_tokens: _models.ReleaseOptions, + *, + content_type: str = "application/json", **kwargs: Any ) -> _models.ReleaseResult: """Release batch of Cloud Events. The server responds with an HTTP 200 status code if at least one @@ -357,7 +496,97 @@ async def release_cloud_events( :type event_subscription_name: str :param lock_tokens: ReleaseOptions. Required. :type lock_tokens: ~azure.eventgrid.models.ReleaseOptions - :keyword content_type: content type. Default value is "application/json; charset=utf-8". + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :keyword bool stream: Whether to stream the response of this operation. Defaults to False. You + will have to context manage the returned stream. + :return: ReleaseResult. The ReleaseResult is compatible with MutableMapping + :rtype: ~azure.eventgrid.models.ReleaseResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + async def release_cloud_events( + self, + topic_name: str, + event_subscription_name: str, + lock_tokens: JSON, + *, + content_type: str = "application/json", + **kwargs: Any + ) -> _models.ReleaseResult: + """Release batch of Cloud Events. The server responds with an HTTP 200 status code if at least one + event is successfully released. The response body will include the set of successfully released + lockTokens, along with other failed lockTokens with their corresponding error information. + + :param topic_name: Topic Name. Required. + :type topic_name: str + :param event_subscription_name: Event Subscription Name. Required. + :type event_subscription_name: str + :param lock_tokens: ReleaseOptions. Required. + :type lock_tokens: JSON + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :keyword bool stream: Whether to stream the response of this operation. Defaults to False. You + will have to context manage the returned stream. + :return: ReleaseResult. The ReleaseResult is compatible with MutableMapping + :rtype: ~azure.eventgrid.models.ReleaseResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + async def release_cloud_events( + self, + topic_name: str, + event_subscription_name: str, + lock_tokens: IO, + *, + content_type: str = "application/json", + **kwargs: Any + ) -> _models.ReleaseResult: + """Release batch of Cloud Events. The server responds with an HTTP 200 status code if at least one + event is successfully released. The response body will include the set of successfully released + lockTokens, along with other failed lockTokens with their corresponding error information. + + :param topic_name: Topic Name. Required. + :type topic_name: str + :param event_subscription_name: Event Subscription Name. Required. + :type event_subscription_name: str + :param lock_tokens: ReleaseOptions. Required. + :type lock_tokens: IO + :keyword content_type: Body Parameter content-type. Content type parameter for binary body. + Default value is "application/json". + :paramtype content_type: str + :keyword bool stream: Whether to stream the response of this operation. Defaults to False. You + will have to context manage the returned stream. + :return: ReleaseResult. The ReleaseResult is compatible with MutableMapping + :rtype: ~azure.eventgrid.models.ReleaseResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + + @distributed_trace_async + async def release_cloud_events( + self, + topic_name: str, + event_subscription_name: str, + lock_tokens: Union[_models.ReleaseOptions, JSON, IO], + **kwargs: Any + ) -> _models.ReleaseResult: + """Release batch of Cloud Events. The server responds with an HTTP 200 status code if at least one + event is successfully released. The response body will include the set of successfully released + lockTokens, along with other failed lockTokens with their corresponding error information. + + :param topic_name: Topic Name. Required. + :type topic_name: str + :param event_subscription_name: Event Subscription Name. Required. + :type event_subscription_name: str + :param lock_tokens: ReleaseOptions. Is one of the following types: ReleaseOptions, JSON, IO + Required. + :type lock_tokens: ~azure.eventgrid.models.ReleaseOptions or JSON or IO + :keyword content_type: content type. Default value is None. :paramtype content_type: str :keyword bool stream: Whether to stream the response of this operation. Defaults to False. You will have to context manage the returned stream. @@ -373,12 +602,17 @@ async def release_cloud_events( _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = kwargs.pop("params", {}) or {} - content_type: str = kwargs.pop('content_type', _headers.pop('content-type', "application/json; charset=utf-8")) + content_type: Optional[str] = kwargs.pop('content_type', _headers.pop('content-type', None)) cls: ClsType[_models.ReleaseResult] = kwargs.pop( 'cls', None ) - _content = json.dumps(lock_tokens, cls=AzureJSONEncoder) # type: ignore + content_type = content_type or "application/json" + _content = None + if isinstance(lock_tokens, (IOBase, bytes)): + _content = lock_tokens + else: + _content = json.dumps(lock_tokens, cls=AzureJSONEncoder, exclude_readonly=True) # type: ignore request = build_event_grid_release_cloud_events_request( topic_name=topic_name, @@ -404,6 +638,8 @@ async def release_cloud_events( response = pipeline_response.http_response if response.status_code not in [200]: + if _stream: + await response.read() # Load the body in memory and close the socket map_error(status_code=response.status_code, response=response, error_map=error_map) raise HttpResponseError(response=response) @@ -422,12 +658,14 @@ async def release_cloud_events( - @distributed_trace_async + @overload async def reject_cloud_events( self, topic_name: str, event_subscription_name: str, lock_tokens: _models.RejectOptions, + *, + content_type: str = "application/json", **kwargs: Any ) -> _models.RejectResult: """Reject batch of Cloud Events. @@ -438,7 +676,91 @@ async def reject_cloud_events( :type event_subscription_name: str :param lock_tokens: RejectOptions. Required. :type lock_tokens: ~azure.eventgrid.models.RejectOptions - :keyword content_type: content type. Default value is "application/json; charset=utf-8". + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :keyword bool stream: Whether to stream the response of this operation. Defaults to False. You + will have to context manage the returned stream. + :return: RejectResult. The RejectResult is compatible with MutableMapping + :rtype: ~azure.eventgrid.models.RejectResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + async def reject_cloud_events( + self, + topic_name: str, + event_subscription_name: str, + lock_tokens: JSON, + *, + content_type: str = "application/json", + **kwargs: Any + ) -> _models.RejectResult: + """Reject batch of Cloud Events. + + :param topic_name: Topic Name. Required. + :type topic_name: str + :param event_subscription_name: Event Subscription Name. Required. + :type event_subscription_name: str + :param lock_tokens: RejectOptions. Required. + :type lock_tokens: JSON + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :keyword bool stream: Whether to stream the response of this operation. Defaults to False. You + will have to context manage the returned stream. + :return: RejectResult. The RejectResult is compatible with MutableMapping + :rtype: ~azure.eventgrid.models.RejectResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + async def reject_cloud_events( + self, + topic_name: str, + event_subscription_name: str, + lock_tokens: IO, + *, + content_type: str = "application/json", + **kwargs: Any + ) -> _models.RejectResult: + """Reject batch of Cloud Events. + + :param topic_name: Topic Name. Required. + :type topic_name: str + :param event_subscription_name: Event Subscription Name. Required. + :type event_subscription_name: str + :param lock_tokens: RejectOptions. Required. + :type lock_tokens: IO + :keyword content_type: Body Parameter content-type. Content type parameter for binary body. + Default value is "application/json". + :paramtype content_type: str + :keyword bool stream: Whether to stream the response of this operation. Defaults to False. You + will have to context manage the returned stream. + :return: RejectResult. The RejectResult is compatible with MutableMapping + :rtype: ~azure.eventgrid.models.RejectResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + + @distributed_trace_async + async def reject_cloud_events( + self, + topic_name: str, + event_subscription_name: str, + lock_tokens: Union[_models.RejectOptions, JSON, IO], + **kwargs: Any + ) -> _models.RejectResult: + """Reject batch of Cloud Events. + + :param topic_name: Topic Name. Required. + :type topic_name: str + :param event_subscription_name: Event Subscription Name. Required. + :type event_subscription_name: str + :param lock_tokens: RejectOptions. Is one of the following types: RejectOptions, JSON, IO + Required. + :type lock_tokens: ~azure.eventgrid.models.RejectOptions or JSON or IO + :keyword content_type: content type. Default value is None. :paramtype content_type: str :keyword bool stream: Whether to stream the response of this operation. Defaults to False. You will have to context manage the returned stream. @@ -454,12 +776,17 @@ async def reject_cloud_events( _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = kwargs.pop("params", {}) or {} - content_type: str = kwargs.pop('content_type', _headers.pop('content-type', "application/json; charset=utf-8")) + content_type: Optional[str] = kwargs.pop('content_type', _headers.pop('content-type', None)) cls: ClsType[_models.RejectResult] = kwargs.pop( 'cls', None ) - _content = json.dumps(lock_tokens, cls=AzureJSONEncoder) # type: ignore + content_type = content_type or "application/json" + _content = None + if isinstance(lock_tokens, (IOBase, bytes)): + _content = lock_tokens + else: + _content = json.dumps(lock_tokens, cls=AzureJSONEncoder, exclude_readonly=True) # type: ignore request = build_event_grid_reject_cloud_events_request( topic_name=topic_name, @@ -485,6 +812,8 @@ async def reject_cloud_events( response = pipeline_response.http_response if response.status_code not in [200]: + if _stream: + await response.read() # Load the body in memory and close the socket map_error(status_code=response.status_code, response=response, error_map=error_map) raise HttpResponseError(response=response) diff --git a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/aio/_vendor.py b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/aio/_vendor.py index 67626c5adc66..2f5401a3a2ee 100644 --- a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/aio/_vendor.py +++ b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/aio/_vendor.py @@ -16,10 +16,12 @@ from .._serialization import Deserializer, Serializer - -class EventGridClientMixinABC(ABC): +class EventGridClientMixinABC( + ABC +): """DO NOT use this class. It is for internal typing use only.""" _client: "AsyncPipelineClient" _config: EventGridClientConfiguration _serialize: "Serializer" _deserialize: "Deserializer" + diff --git a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/models/_models.py b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/models/_models.py index 3fda23b49841..5cf7dd673acd 100644 --- a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/models/_models.py +++ b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/models/_models.py @@ -146,11 +146,11 @@ class CloudEvent(_model_base.Model): unique for each distinct event. Required.""" data: Optional[Any] = rest_field() """Event data specific to the event type.""" - data_base64: Optional[bytes] = rest_field() + data_base64: Optional[bytes] = rest_field(format="base64") """Event data specific to the event type, encoded as a base64 string.""" type: str = rest_field() """Type of event related to the originating occurrence. Required.""" - time: Optional[datetime.datetime] = rest_field() + time: Optional[datetime.datetime] = rest_field(format="rfc3339") """The time (in UTC) the event was generated, in RFC3339 format.""" specversion: str = rest_field() """The version of the CloudEvents specification which the event uses. Required.""" @@ -209,6 +209,14 @@ def __init__(self, *args: Any, **kwargs: Any) -> None:# pylint: disable=useless- super().__init__(*args, **kwargs) +class PublishResult(_model_base.Model): + """The result of the Publish operation. + + """ + + + + class ReceiveDetails(_model_base.Model): """Receive operation details per Cloud Event. diff --git a/sdk/eventgrid/azure-eventgrid/setup.py b/sdk/eventgrid/azure-eventgrid/setup.py index edd7b5532d83..f6fae730f05d 100644 --- a/sdk/eventgrid/azure-eventgrid/setup.py +++ b/sdk/eventgrid/azure-eventgrid/setup.py @@ -63,7 +63,7 @@ }, install_requires=[ "isodate<1.0.0,>=0.6.1", - "azure-core<2.0.0,>=1.24.0", + "azure-core<2.0.0,>=1.28.0", "typing-extensions>=4.3.0; python_version<'3.8.0'", ], python_requires=">=3.7", diff --git a/sdk/eventgrid/azure-eventgrid/tsp-location.yaml b/sdk/eventgrid/azure-eventgrid/tsp-location.yaml index adaa6c9354c8..cbfa42e289e3 100644 --- a/sdk/eventgrid/azure-eventgrid/tsp-location.yaml +++ b/sdk/eventgrid/azure-eventgrid/tsp-location.yaml @@ -1,4 +1,4 @@ cleanup: false -commit: c07d9898ed901330e5ac4996b1bc641adac2e6fd +commit: 322a7c15a332600022161dd5163498c5e9df6626 directory: specification/eventgrid/Azure.Messaging.EventGrid repo: Azure/azure-rest-api-specs \ No newline at end of file From 9143c26af07ef37e11e7879d5d946b9618ebb22c Mon Sep 17 00:00:00 2001 From: l0lawrence Date: Tue, 3 Oct 2023 13:57:28 -0700 Subject: [PATCH 03/12] update tsp --- sdk/eventgrid/azure-eventgrid/tsp-location.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/eventgrid/azure-eventgrid/tsp-location.yaml b/sdk/eventgrid/azure-eventgrid/tsp-location.yaml index cbfa42e289e3..1b03ceda0d0c 100644 --- a/sdk/eventgrid/azure-eventgrid/tsp-location.yaml +++ b/sdk/eventgrid/azure-eventgrid/tsp-location.yaml @@ -1,4 +1,4 @@ cleanup: false -commit: 322a7c15a332600022161dd5163498c5e9df6626 +commit: 58b64dbf8ee221bcbd4414649c7fe13914eb72a1 directory: specification/eventgrid/Azure.Messaging.EventGrid repo: Azure/azure-rest-api-specs \ No newline at end of file From cffb284cb8f1b7662f2e4f44a9f5e5d769556e35 Mon Sep 17 00:00:00 2001 From: l0lawrence Date: Tue, 3 Oct 2023 14:52:08 -0700 Subject: [PATCH 04/12] regen --- .../azure/eventgrid/_client.py | 14 +++++++---- .../azure/eventgrid/_configuration.py | 23 +++++++++++++++---- .../azure/eventgrid/_model_base.py | 13 +++++------ .../azure/eventgrid/_serialization.py | 2 +- .../azure/eventgrid/aio/_client.py | 14 +++++++---- .../azure/eventgrid/aio/_configuration.py | 23 +++++++++++++++---- 6 files changed, 63 insertions(+), 26 deletions(-) diff --git a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_client.py b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_client.py index 839215bd35b5..329e214d89c1 100644 --- a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_client.py +++ b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_client.py @@ -7,7 +7,7 @@ # -------------------------------------------------------------------------- from copy import deepcopy -from typing import Any +from typing import Any, TYPE_CHECKING, Union from azure.core import PipelineClient from azure.core.credentials import AzureKeyCredential @@ -17,14 +17,20 @@ from ._operations import EventGridClientOperationsMixin from ._serialization import Deserializer, Serializer +if TYPE_CHECKING: + # pylint: disable=unused-import,ungrouped-imports + from azure.core.credentials import TokenCredential + class EventGridClient(EventGridClientOperationsMixin): # pylint: disable=client-accepts-api-version-keyword """Azure Messaging EventGrid Client. :param endpoint: The host name of the namespace, e.g. namespaceName1.westus-1.eventgrid.azure.net. Required. :type endpoint: str - :param credential: Credential needed for the client to connect to Azure. Required. - :type credential: ~azure.core.credentials.AzureKeyCredential + :param credential: Credential needed for the client to connect to Azure. Is either a + AzureKeyCredential type or a TokenCredential type. Required. + :type credential: ~azure.core.credentials.AzureKeyCredential or + ~azure.core.credentials.TokenCredential :keyword api_version: The API version to use for this operation. Default value is "2023-06-01-preview". Note that overriding this default value may result in unsupported behavior. @@ -34,7 +40,7 @@ class EventGridClient(EventGridClientOperationsMixin): # pylint: disable=client def __init__( self, endpoint: str, - credential: AzureKeyCredential, + credential: Union[AzureKeyCredential, "TokenCredential"], **kwargs: Any ) -> None: _endpoint = '{endpoint}' diff --git a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_configuration.py b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_configuration.py index df6c19647085..8a5c765af4f5 100644 --- a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_configuration.py +++ b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_configuration.py @@ -6,7 +6,7 @@ # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- -from typing import Any +from typing import Any, TYPE_CHECKING, Union from azure.core.configuration import Configuration from azure.core.credentials import AzureKeyCredential @@ -14,6 +14,10 @@ from ._version import VERSION +if TYPE_CHECKING: + # pylint: disable=unused-import,ungrouped-imports + from azure.core.credentials import TokenCredential + class EventGridClientConfiguration( # pylint: disable=too-many-instance-attributes,name-too-long Configuration @@ -26,8 +30,10 @@ class EventGridClientConfiguration( # pylint: disable=too-many-instance-attri :param endpoint: The host name of the namespace, e.g. namespaceName1.westus-1.eventgrid.azure.net. Required. :type endpoint: str - :param credential: Credential needed for the client to connect to Azure. Required. - :type credential: ~azure.core.credentials.AzureKeyCredential + :param credential: Credential needed for the client to connect to Azure. Is either a + AzureKeyCredential type or a TokenCredential type. Required. + :type credential: ~azure.core.credentials.AzureKeyCredential or + ~azure.core.credentials.TokenCredential :keyword api_version: The API version to use for this operation. Default value is "2023-06-01-preview". Note that overriding this default value may result in unsupported behavior. @@ -37,7 +43,7 @@ class EventGridClientConfiguration( # pylint: disable=too-many-instance-attri def __init__( self, endpoint: str, - credential: AzureKeyCredential, + credential: Union[AzureKeyCredential, "TokenCredential"], **kwargs: Any ) -> None: super(EventGridClientConfiguration, self).__init__(**kwargs) @@ -51,9 +57,16 @@ def __init__( self.endpoint = endpoint self.credential = credential self.api_version = api_version + self.credential_scopes = kwargs.pop('credential_scopes', ['https://eventgrid.azure.net/.default']) kwargs.setdefault('sdk_moniker', 'eventgrid/{}'.format(VERSION)) self._configure(**kwargs) + def _infer_policy(self, **kwargs): + if isinstance(self.credential, AzureKeyCredential): + return policies.AzureKeyCredentialPolicy(self.credential, "Authorization", prefix="SharedAccessKey", **kwargs) + if hasattr(self.credential, 'get_token'): + return policies.BearerTokenCredentialPolicy(self.credential, *self.credential_scopes, **kwargs) + raise TypeError(f"Unsupported credential: {self.credential}") def _configure( self, @@ -69,4 +82,4 @@ def _configure( self.redirect_policy = kwargs.get('redirect_policy') or policies.RedirectPolicy(**kwargs) self.authentication_policy = kwargs.get('authentication_policy') if self.credential and not self.authentication_policy: - self.authentication_policy = policies.AzureKeyCredentialPolicy(self.credential, "SharedAccessKey", **kwargs) + self.authentication_policy = self._infer_policy(**kwargs) diff --git a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_model_base.py b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_model_base.py index 17c08a23b49f..2e328fc6adeb 100644 --- a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_model_base.py +++ b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_model_base.py @@ -128,9 +128,10 @@ def _is_readonly(p): class AzureJSONEncoder(JSONEncoder): """A JSON encoder that's capable of serializing datetime objects and bytes.""" - def __init__(self, *args, exclude_readonly: bool = False, **kwargs): + def __init__(self, *args, exclude_readonly: bool = False, format: typing.Optional[str] = None, **kwargs): super().__init__(*args, **kwargs) self.exclude_readonly = exclude_readonly + self.format = format def default(self, o): # pylint: disable=too-many-return-statements if _is_model(o): @@ -138,18 +139,16 @@ def default(self, o): # pylint: disable=too-many-return-statements readonly_props = [p._rest_name for p in o._attr_to_rest_field.values() if _is_readonly(p)] return {k: v for k, v in o.items() if k not in readonly_props} return dict(o.items()) - if isinstance(o, (bytes, bytearray)): - return base64.b64encode(o).decode() - if isinstance(o, _Null): - return None try: return super(AzureJSONEncoder, self).default(o) except TypeError: + if isinstance(o, _Null): + return None if isinstance(o, (bytes, bytearray)): - return _serialize_bytes(o) + return _serialize_bytes(o, self.format) try: # First try datetime.datetime - return _serialize_datetime(o) + return _serialize_datetime(o, self.format) except AttributeError: pass # Last, try datetime.timedelta diff --git a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_serialization.py b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_serialization.py index 44ca0b58b661..7fd392a19926 100644 --- a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_serialization.py +++ b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_serialization.py @@ -1918,7 +1918,7 @@ def deserialize_date(attr): if re.search(r"[^\W\d_]", attr, re.I + re.U): # type: ignore raise DeserializationError("Date must have only digits and -. Received: %s" % attr) # This must NOT use defaultmonth/defaultday. Using None ensure this raises an exception. - return isodate.parse_date(attr, defaultmonth=None, defaultday=None) + return isodate.parse_date(attr, defaultmonth=0, defaultday=0) @staticmethod def deserialize_time(attr): diff --git a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/aio/_client.py b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/aio/_client.py index d5e929121bc0..e1d0a000fbde 100644 --- a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/aio/_client.py +++ b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/aio/_client.py @@ -7,7 +7,7 @@ # -------------------------------------------------------------------------- from copy import deepcopy -from typing import Any, Awaitable +from typing import Any, Awaitable, TYPE_CHECKING, Union from azure.core import AsyncPipelineClient from azure.core.credentials import AzureKeyCredential @@ -17,14 +17,20 @@ from ._configuration import EventGridClientConfiguration from ._operations import EventGridClientOperationsMixin +if TYPE_CHECKING: + # pylint: disable=unused-import,ungrouped-imports + from azure.core.credentials_async import AsyncTokenCredential + class EventGridClient(EventGridClientOperationsMixin): # pylint: disable=client-accepts-api-version-keyword """Azure Messaging EventGrid Client. :param endpoint: The host name of the namespace, e.g. namespaceName1.westus-1.eventgrid.azure.net. Required. :type endpoint: str - :param credential: Credential needed for the client to connect to Azure. Required. - :type credential: ~azure.core.credentials.AzureKeyCredential + :param credential: Credential needed for the client to connect to Azure. Is either a + AzureKeyCredential type or a TokenCredential type. Required. + :type credential: ~azure.core.credentials.AzureKeyCredential or + ~azure.core.credentials_async.AsyncTokenCredential :keyword api_version: The API version to use for this operation. Default value is "2023-06-01-preview". Note that overriding this default value may result in unsupported behavior. @@ -34,7 +40,7 @@ class EventGridClient(EventGridClientOperationsMixin): # pylint: disable=client def __init__( self, endpoint: str, - credential: AzureKeyCredential, + credential: Union[AzureKeyCredential, "AsyncTokenCredential"], **kwargs: Any ) -> None: _endpoint = '{endpoint}' diff --git a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/aio/_configuration.py b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/aio/_configuration.py index 8074ab267aba..b06679bc2d67 100644 --- a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/aio/_configuration.py +++ b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/aio/_configuration.py @@ -6,7 +6,7 @@ # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- -from typing import Any +from typing import Any, TYPE_CHECKING, Union from azure.core.configuration import Configuration from azure.core.credentials import AzureKeyCredential @@ -14,6 +14,10 @@ from .._version import VERSION +if TYPE_CHECKING: + # pylint: disable=unused-import,ungrouped-imports + from azure.core.credentials_async import AsyncTokenCredential + class EventGridClientConfiguration( # pylint: disable=too-many-instance-attributes,name-too-long Configuration @@ -26,8 +30,10 @@ class EventGridClientConfiguration( # pylint: disable=too-many-instance-attri :param endpoint: The host name of the namespace, e.g. namespaceName1.westus-1.eventgrid.azure.net. Required. :type endpoint: str - :param credential: Credential needed for the client to connect to Azure. Required. - :type credential: ~azure.core.credentials.AzureKeyCredential + :param credential: Credential needed for the client to connect to Azure. Is either a + AzureKeyCredential type or a TokenCredential type. Required. + :type credential: ~azure.core.credentials.AzureKeyCredential or + ~azure.core.credentials_async.AsyncTokenCredential :keyword api_version: The API version to use for this operation. Default value is "2023-06-01-preview". Note that overriding this default value may result in unsupported behavior. @@ -37,7 +43,7 @@ class EventGridClientConfiguration( # pylint: disable=too-many-instance-attri def __init__( self, endpoint: str, - credential: AzureKeyCredential, + credential: Union[AzureKeyCredential, "AsyncTokenCredential"], **kwargs: Any ) -> None: super(EventGridClientConfiguration, self).__init__(**kwargs) @@ -51,9 +57,16 @@ def __init__( self.endpoint = endpoint self.credential = credential self.api_version = api_version + self.credential_scopes = kwargs.pop('credential_scopes', ['https://eventgrid.azure.net/.default']) kwargs.setdefault('sdk_moniker', 'eventgrid/{}'.format(VERSION)) self._configure(**kwargs) + def _infer_policy(self, **kwargs): + if isinstance(self.credential, AzureKeyCredential): + return policies.AzureKeyCredentialPolicy(self.credential, "Authorization", prefix="SharedAccessKey", **kwargs) + if hasattr(self.credential, 'get_token'): + return policies.AsyncBearerTokenCredentialPolicy(self.credential, *self.credential_scopes, **kwargs) + raise TypeError(f"Unsupported credential: {self.credential}") def _configure( self, @@ -69,4 +82,4 @@ def _configure( self.redirect_policy = kwargs.get('redirect_policy') or policies.AsyncRedirectPolicy(**kwargs) self.authentication_policy = kwargs.get('authentication_policy') if self.credential and not self.authentication_policy: - self.authentication_policy = policies.AzureKeyCredentialPolicy(self.credential, "SharedAccessKey", **kwargs) + self.authentication_policy = self._infer_policy(**kwargs) From 1b2dc5a442169f4700822fbfd96258a67376f74d Mon Sep 17 00:00:00 2001 From: l0lawrence Date: Tue, 3 Oct 2023 15:33:15 -0700 Subject: [PATCH 05/12] update tests --- sdk/eventgrid/azure-eventgrid/tests/conftest.py | 1 - .../tests/test_eg_publisher_client_async.py | 12 ++++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/sdk/eventgrid/azure-eventgrid/tests/conftest.py b/sdk/eventgrid/azure-eventgrid/tests/conftest.py index 942dab920c4f..c69c75af758e 100644 --- a/sdk/eventgrid/azure-eventgrid/tests/conftest.py +++ b/sdk/eventgrid/azure-eventgrid/tests/conftest.py @@ -33,7 +33,6 @@ set_custom_default_matcher, ) - @pytest.fixture(scope="session", autouse=True) def add_sanitizers(test_proxy): # this can be reverted to set_bodiless_matcher() after tests are re-recorded and don't contain these headers diff --git a/sdk/eventgrid/azure-eventgrid/tests/test_eg_publisher_client_async.py b/sdk/eventgrid/azure-eventgrid/tests/test_eg_publisher_client_async.py index 5562f628fdb2..c0a7e93be95a 100644 --- a/sdk/eventgrid/azure-eventgrid/tests/test_eg_publisher_client_async.py +++ b/sdk/eventgrid/azure-eventgrid/tests/test_eg_publisher_client_async.py @@ -145,6 +145,10 @@ async def test_send_event_grid_event_dict_data_bytes_async( async def test_send_cloud_event_data_dict_async( self, eventgrid_cloud_event_topic_endpoint ): + client = self.create_eg_publisher_client(eventgrid_cloud_event_topic_endpoint) + cloud_event = CloudEvent( + source="http://samplesource.dev", + data={"sample": "cloudevent"}, type="Sample.Cloud.Event", ) await client.send(cloud_event) @@ -183,6 +187,10 @@ async def test_send_cloud_event_data_bytes_async( async def test_send_cloud_event_data_as_list_async( self, eventgrid_cloud_event_topic_endpoint ): + client = self.create_eg_publisher_client(eventgrid_cloud_event_topic_endpoint) + cloud_event = CloudEvent( + source="http://samplesource.dev", + data="cloudevent", type="Sample.Cloud.Event", ) await client.send([cloud_event]) @@ -193,6 +201,10 @@ async def test_send_cloud_event_data_as_list_async( async def test_send_cloud_event_data_with_extensions_async( self, eventgrid_cloud_event_topic_endpoint ): + client = self.create_eg_publisher_client(eventgrid_cloud_event_topic_endpoint) + cloud_event = CloudEvent( + source="http://samplesource.dev", + data="cloudevent", type="Sample.Cloud.Event", extensions={"reasoncode": 204, "extension": "hello"}, ) From b9f988fc1f347dc4f1a05a32e3c3284ac1733d5b Mon Sep 17 00:00:00 2001 From: l0lawrence Date: Tue, 3 Oct 2023 15:51:16 -0700 Subject: [PATCH 06/12] update tspconfig --- sdk/eventgrid/azure-eventgrid/tsp-location.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/eventgrid/azure-eventgrid/tsp-location.yaml b/sdk/eventgrid/azure-eventgrid/tsp-location.yaml index 1b03ceda0d0c..94b72d10f055 100644 --- a/sdk/eventgrid/azure-eventgrid/tsp-location.yaml +++ b/sdk/eventgrid/azure-eventgrid/tsp-location.yaml @@ -1,4 +1,4 @@ cleanup: false -commit: 58b64dbf8ee221bcbd4414649c7fe13914eb72a1 +commit: a48dbfd411ddcb91ad1e09c47d1def14e79b8905 directory: specification/eventgrid/Azure.Messaging.EventGrid repo: Azure/azure-rest-api-specs \ No newline at end of file From c40e8677456870908acc98d29388132faa89a565 Mon Sep 17 00:00:00 2001 From: l0lawrence Date: Wed, 4 Oct 2023 10:08:54 -0700 Subject: [PATCH 07/12] cspell --- .vscode/cspell.json | 1 + 1 file changed, 1 insertion(+) diff --git a/.vscode/cspell.json b/.vscode/cspell.json index 9d03ea8cab73..fc687efb062a 100644 --- a/.vscode/cspell.json +++ b/.vscode/cspell.json @@ -271,6 +271,7 @@ "mibps", "mgmt", "mhsm", + "Nify", "mipsle", "mktime", "mros", From 2a41037a0e64e219b32afada0959d6bae0648fc6 Mon Sep 17 00:00:00 2001 From: l0lawrence Date: Wed, 4 Oct 2023 13:19:09 -0700 Subject: [PATCH 08/12] version --- sdk/eventgrid/azure-eventgrid/azure/eventgrid/_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_version.py b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_version.py index c8302cef558b..e2f778cc85be 100644 --- a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_version.py +++ b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_version.py @@ -6,4 +6,4 @@ # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- -VERSION = "4.12.0b1" +VERSION = "4.14.1" From 86d421ea441af5b4867daf861d0deb348597cc00 Mon Sep 17 00:00:00 2001 From: l0lawrence Date: Wed, 4 Oct 2023 13:34:23 -0700 Subject: [PATCH 09/12] update serialization --- sdk/eventgrid/azure-eventgrid/tests/test_serialization.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/eventgrid/azure-eventgrid/tests/test_serialization.py b/sdk/eventgrid/azure-eventgrid/tests/test_serialization.py index e40e9c93e874..a83caf6954ae 100644 --- a/sdk/eventgrid/azure-eventgrid/tests/test_serialization.py +++ b/sdk/eventgrid/azure-eventgrid/tests/test_serialization.py @@ -9,7 +9,7 @@ import base64 from azure.core.messaging import CloudEvent -from azure.eventgrid._helpers import _cloud_event_to_generated +from azure.eventgrid._legacy._helpers import _cloud_event_to_generated from azure.eventgrid import SystemEventNames, EventGridEvent from _mocks import ( cloud_storage_dict, From 8b6e4680ca1f71ba430f2bb3da9868e35d7bd63c Mon Sep 17 00:00:00 2001 From: l0lawrence Date: Wed, 4 Oct 2023 15:16:27 -0700 Subject: [PATCH 10/12] update assets --- sdk/eventgrid/azure-eventgrid/assets.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/eventgrid/azure-eventgrid/assets.json b/sdk/eventgrid/azure-eventgrid/assets.json index a00be8330ac3..46490ff40be4 100644 --- a/sdk/eventgrid/azure-eventgrid/assets.json +++ b/sdk/eventgrid/azure-eventgrid/assets.json @@ -2,5 +2,5 @@ "AssetsRepo": "Azure/azure-sdk-assets", "AssetsRepoPrefixPath": "python", "TagPrefix": "python/eventgrid/azure-eventgrid", - "Tag": "python/eventgrid/azure-eventgrid_6f56978914" + "Tag": "python/eventgrid/azure-eventgrid_fce4958e09" } From 53fb34b007690842da43468783f34f0659b29e1a Mon Sep 17 00:00:00 2001 From: l0lawrence Date: Wed, 4 Oct 2023 16:07:57 -0700 Subject: [PATCH 11/12] update mypy --- sdk/eventgrid/azure-eventgrid/azure/eventgrid/__init__.py | 2 +- .../azure/eventgrid/_operations/__init__.py | 2 +- .../azure-eventgrid/azure/eventgrid/aio/__init__.py | 2 +- .../azure/eventgrid/aio/_operations/__init__.py | 2 +- .../sample_acknowledge_operation_async.py | 8 ++++---- .../sample_all_operations_async.py | 8 ++++---- .../sample_publish_operation_async.py | 8 ++++---- .../sample_receive_operation_async.py | 8 ++++---- .../sample_reject_operation_async.py | 8 ++++---- .../sample_release_operation_async.py | 8 ++++---- .../sample_acknowledge_operation.py | 8 ++++---- .../eventgrid_client_samples/sample_all_operations.py | 8 ++++---- .../sample_eg_client_authentication.py | 4 ++-- .../eventgrid_client_samples/sample_publish_operation.py | 8 ++++---- .../eventgrid_client_samples/sample_receive_operation.py | 8 ++++---- .../eventgrid_client_samples/sample_reject_operation.py | 8 ++++---- .../eventgrid_client_samples/sample_release_operation.py | 8 ++++---- 17 files changed, 54 insertions(+), 54 deletions(-) diff --git a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/__init__.py b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/__init__.py index 32166aad43a3..f6da3df3d6bc 100644 --- a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/__init__.py +++ b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/__init__.py @@ -6,7 +6,7 @@ # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- -from ._client import EventGridClient +from ._patch import EventGridClient from ._version import VERSION __version__ = VERSION diff --git a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_operations/__init__.py b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_operations/__init__.py index c166e5de9c64..5d63b0e4eaa0 100644 --- a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_operations/__init__.py +++ b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_operations/__init__.py @@ -6,7 +6,7 @@ # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- -from ._operations import EventGridClientOperationsMixin +from ._patch import EventGridClientOperationsMixin from ._patch import __all__ as _patch_all from ._patch import * # pylint: disable=unused-wildcard-import diff --git a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/aio/__init__.py b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/aio/__init__.py index 6c53eb888303..149d797cbe4e 100644 --- a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/aio/__init__.py +++ b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/aio/__init__.py @@ -6,7 +6,7 @@ # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- -from ._client import EventGridClient +from ._patch import EventGridClient try: from ._patch import __all__ as _patch_all diff --git a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/aio/_operations/__init__.py b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/aio/_operations/__init__.py index c166e5de9c64..5d63b0e4eaa0 100644 --- a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/aio/_operations/__init__.py +++ b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/aio/_operations/__init__.py @@ -6,7 +6,7 @@ # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- -from ._operations import EventGridClientOperationsMixin +from ._patch import EventGridClientOperationsMixin from ._patch import __all__ as _patch_all from ._patch import * # pylint: disable=unused-wildcard-import diff --git a/sdk/eventgrid/azure-eventgrid/samples/async_samples/eventgrid_client_samples/sample_acknowledge_operation_async.py b/sdk/eventgrid/azure-eventgrid/samples/async_samples/eventgrid_client_samples/sample_acknowledge_operation_async.py index d858b811d1f9..bea9e4c5cb7e 100644 --- a/sdk/eventgrid/azure-eventgrid/samples/async_samples/eventgrid_client_samples/sample_acknowledge_operation_async.py +++ b/sdk/eventgrid/azure-eventgrid/samples/async_samples/eventgrid_client_samples/sample_acknowledge_operation_async.py @@ -10,10 +10,10 @@ from azure.eventgrid.models import * from azure.core.exceptions import HttpResponseError -EVENTGRID_KEY = os.environ.get("EVENTGRID_KEY") -EVENTGRID_ENDPOINT = os.environ.get("EVENTGRID_ENDPOINT") -TOPIC_NAME = os.environ.get("TOPIC_NAME") -EVENT_SUBSCRIPTION_NAME = os.environ.get("EVENT_SUBSCRIPTION_NAME") +EVENTGRID_KEY: str = os.environ["EVENTGRID_KEY"] +EVENTGRID_ENDPOINT: str = os.environ["EVENTGRID_ENDPOINT"] +TOPIC_NAME: str = os.environ["TOPIC_NAME"] +EVENT_SUBSCRIPTION_NAME: str = os.environ["EVENT_SUBSCRIPTION_NAME"] # Create a client client = EventGridClient(EVENTGRID_ENDPOINT, AzureKeyCredential(EVENTGRID_KEY)) diff --git a/sdk/eventgrid/azure-eventgrid/samples/async_samples/eventgrid_client_samples/sample_all_operations_async.py b/sdk/eventgrid/azure-eventgrid/samples/async_samples/eventgrid_client_samples/sample_all_operations_async.py index 61d089485bf4..19e5863f7f2b 100644 --- a/sdk/eventgrid/azure-eventgrid/samples/async_samples/eventgrid_client_samples/sample_all_operations_async.py +++ b/sdk/eventgrid/azure-eventgrid/samples/async_samples/eventgrid_client_samples/sample_all_operations_async.py @@ -11,10 +11,10 @@ from azure.core.exceptions import HttpResponseError from azure.eventgrid.aio import EventGridClient -EVENTGRID_KEY = os.environ.get("EVENTGRID_KEY") -EVENTGRID_ENDPOINT = os.environ.get("EVENTGRID_ENDPOINT") -TOPIC_NAME = os.environ.get("TOPIC_NAME") -EVENT_SUBSCRIPTION_NAME = os.environ.get("EVENT_SUBSCRIPTION_NAME") +EVENTGRID_KEY: str = os.environ["EVENTGRID_KEY"] +EVENTGRID_ENDPOINT: str = os.environ["EVENTGRID_ENDPOINT"] +TOPIC_NAME: str = os.environ["TOPIC_NAME"] +EVENT_SUBSCRIPTION_NAME: str = os.environ["EVENT_SUBSCRIPTION_NAME"] # Create a client diff --git a/sdk/eventgrid/azure-eventgrid/samples/async_samples/eventgrid_client_samples/sample_publish_operation_async.py b/sdk/eventgrid/azure-eventgrid/samples/async_samples/eventgrid_client_samples/sample_publish_operation_async.py index c8b321fd7f12..bb519f1cde2c 100644 --- a/sdk/eventgrid/azure-eventgrid/samples/async_samples/eventgrid_client_samples/sample_publish_operation_async.py +++ b/sdk/eventgrid/azure-eventgrid/samples/async_samples/eventgrid_client_samples/sample_publish_operation_async.py @@ -12,10 +12,10 @@ from azure.core.exceptions import HttpResponseError -EVENTGRID_KEY = os.environ.get("EVENTGRID_KEY") -EVENTGRID_ENDPOINT = os.environ.get("EVENTGRID_ENDPOINT") -TOPIC_NAME = os.environ.get("TOPIC_NAME") -EVENT_SUBSCRIPTION_NAME = os.environ.get("EVENT_SUBSCRIPTION_NAME") +EVENTGRID_KEY: str = os.environ["EVENTGRID_KEY"] +EVENTGRID_ENDPOINT: str = os.environ["EVENTGRID_ENDPOINT"] +TOPIC_NAME: str = os.environ["TOPIC_NAME"] +EVENT_SUBSCRIPTION_NAME: str = os.environ["EVENT_SUBSCRIPTION_NAME"] # Create a client client = EventGridClient(EVENTGRID_ENDPOINT, AzureKeyCredential(EVENTGRID_KEY)) diff --git a/sdk/eventgrid/azure-eventgrid/samples/async_samples/eventgrid_client_samples/sample_receive_operation_async.py b/sdk/eventgrid/azure-eventgrid/samples/async_samples/eventgrid_client_samples/sample_receive_operation_async.py index b483a2f0abed..a25f09a40fed 100644 --- a/sdk/eventgrid/azure-eventgrid/samples/async_samples/eventgrid_client_samples/sample_receive_operation_async.py +++ b/sdk/eventgrid/azure-eventgrid/samples/async_samples/eventgrid_client_samples/sample_receive_operation_async.py @@ -10,10 +10,10 @@ from azure.eventgrid.models import * from azure.core.exceptions import HttpResponseError -EVENTGRID_KEY = os.environ.get("EVENTGRID_KEY") -EVENTGRID_ENDPOINT = os.environ.get("EVENTGRID_ENDPOINT") -TOPIC_NAME = os.environ.get("TOPIC_NAME") -EVENT_SUBSCRIPTION_NAME = os.environ.get("EVENT_SUBSCRIPTION_NAME") +EVENTGRID_KEY: str = os.environ["EVENTGRID_KEY"] +EVENTGRID_ENDPOINT: str = os.environ["EVENTGRID_ENDPOINT"] +TOPIC_NAME: str = os.environ["TOPIC_NAME"] +EVENT_SUBSCRIPTION_NAME: str = os.environ["EVENT_SUBSCRIPTION_NAME"] # Create a client client = EventGridClient(EVENTGRID_ENDPOINT, AzureKeyCredential(EVENTGRID_KEY)) diff --git a/sdk/eventgrid/azure-eventgrid/samples/async_samples/eventgrid_client_samples/sample_reject_operation_async.py b/sdk/eventgrid/azure-eventgrid/samples/async_samples/eventgrid_client_samples/sample_reject_operation_async.py index d493e9055736..e46356e08fbf 100644 --- a/sdk/eventgrid/azure-eventgrid/samples/async_samples/eventgrid_client_samples/sample_reject_operation_async.py +++ b/sdk/eventgrid/azure-eventgrid/samples/async_samples/eventgrid_client_samples/sample_reject_operation_async.py @@ -10,10 +10,10 @@ from azure.eventgrid.models import * from azure.core.exceptions import HttpResponseError -EVENTGRID_KEY = os.environ.get("EVENTGRID_KEY") -EVENTGRID_ENDPOINT = os.environ.get("EVENTGRID_ENDPOINT") -TOPIC_NAME = os.environ.get("TOPIC_NAME") -EVENT_SUBSCRIPTION_NAME = os.environ.get("EVENT_SUBSCRIPTION_NAME") +EVENTGRID_KEY: str = os.environ["EVENTGRID_KEY"] +EVENTGRID_ENDPOINT: str = os.environ["EVENTGRID_ENDPOINT"] +TOPIC_NAME: str = os.environ["TOPIC_NAME"] +EVENT_SUBSCRIPTION_NAME: str = os.environ["EVENT_SUBSCRIPTION_NAME"] # Create a client client = EventGridClient(EVENTGRID_ENDPOINT, AzureKeyCredential(EVENTGRID_KEY)) diff --git a/sdk/eventgrid/azure-eventgrid/samples/async_samples/eventgrid_client_samples/sample_release_operation_async.py b/sdk/eventgrid/azure-eventgrid/samples/async_samples/eventgrid_client_samples/sample_release_operation_async.py index df57e7474b61..117dadf79287 100644 --- a/sdk/eventgrid/azure-eventgrid/samples/async_samples/eventgrid_client_samples/sample_release_operation_async.py +++ b/sdk/eventgrid/azure-eventgrid/samples/async_samples/eventgrid_client_samples/sample_release_operation_async.py @@ -10,10 +10,10 @@ from azure.eventgrid.models import * from azure.core.exceptions import HttpResponseError -EVENTGRID_KEY = os.environ.get("EVENTGRID_KEY") -EVENTGRID_ENDPOINT = os.environ.get("EVENTGRID_ENDPOINT") -TOPIC_NAME = os.environ.get("TOPIC_NAME") -EVENT_SUBSCRIPTION_NAME = os.environ.get("EVENT_SUBSCRIPTION_NAME") +EVENTGRID_KEY: str = os.environ["EVENTGRID_KEY"] +EVENTGRID_ENDPOINT: str = os.environ["EVENTGRID_ENDPOINT"] +TOPIC_NAME: str = os.environ["TOPIC_NAME"] +EVENT_SUBSCRIPTION_NAME: str = os.environ["EVENT_SUBSCRIPTION_NAME"] # Create a client client = EventGridClient(EVENTGRID_ENDPOINT, AzureKeyCredential(EVENTGRID_KEY)) diff --git a/sdk/eventgrid/azure-eventgrid/samples/sync_samples/eventgrid_client_samples/sample_acknowledge_operation.py b/sdk/eventgrid/azure-eventgrid/samples/sync_samples/eventgrid_client_samples/sample_acknowledge_operation.py index 96cb87dc59eb..78bfdc1162fb 100644 --- a/sdk/eventgrid/azure-eventgrid/samples/sync_samples/eventgrid_client_samples/sample_acknowledge_operation.py +++ b/sdk/eventgrid/azure-eventgrid/samples/sync_samples/eventgrid_client_samples/sample_acknowledge_operation.py @@ -9,10 +9,10 @@ from azure.eventgrid.models import * from azure.core.exceptions import HttpResponseError -EVENTGRID_KEY = os.environ.get("EVENTGRID_KEY") -EVENTGRID_ENDPOINT = os.environ.get("EVENTGRID_ENDPOINT") -TOPIC_NAME = os.environ.get("TOPIC_NAME") -EVENT_SUBSCRIPTION_NAME = os.environ.get("EVENT_SUBSCRIPTION_NAME") +EVENTGRID_KEY: str = os.environ["EVENTGRID_KEY"] +EVENTGRID_ENDPOINT: str = os.environ["EVENTGRID_ENDPOINT"] +TOPIC_NAME: str = os.environ["TOPIC_NAME"] +EVENT_SUBSCRIPTION_NAME: str = os.environ["EVENT_SUBSCRIPTION_NAME"] # Create a client client = EventGridClient(EVENTGRID_ENDPOINT, AzureKeyCredential(EVENTGRID_KEY)) diff --git a/sdk/eventgrid/azure-eventgrid/samples/sync_samples/eventgrid_client_samples/sample_all_operations.py b/sdk/eventgrid/azure-eventgrid/samples/sync_samples/eventgrid_client_samples/sample_all_operations.py index 9237729b12fd..db6863811b7f 100644 --- a/sdk/eventgrid/azure-eventgrid/samples/sync_samples/eventgrid_client_samples/sample_all_operations.py +++ b/sdk/eventgrid/azure-eventgrid/samples/sync_samples/eventgrid_client_samples/sample_all_operations.py @@ -11,10 +11,10 @@ from azure.core.exceptions import HttpResponseError from azure.eventgrid import EventGridClient -EVENTGRID_KEY = os.environ.get("EVENTGRID_KEY") -EVENTGRID_ENDPOINT = os.environ.get("EVENTGRID_ENDPOINT") -TOPIC_NAME = os.environ.get("TOPIC_NAME") -EVENT_SUBSCRIPTION_NAME = os.environ.get("EVENT_SUBSCRIPTION_NAME") +EVENTGRID_KEY: str = os.environ["EVENTGRID_KEY"] +EVENTGRID_ENDPOINT: str = os.environ["EVENTGRID_ENDPOINT"] +TOPIC_NAME: str = os.environ["TOPIC_NAME"] +EVENT_SUBSCRIPTION_NAME: str = os.environ["EVENT_SUBSCRIPTION_NAME"] # Create a client diff --git a/sdk/eventgrid/azure-eventgrid/samples/sync_samples/eventgrid_client_samples/sample_eg_client_authentication.py b/sdk/eventgrid/azure-eventgrid/samples/sync_samples/eventgrid_client_samples/sample_eg_client_authentication.py index f44b6d76f7c3..a95d1613c823 100644 --- a/sdk/eventgrid/azure-eventgrid/samples/sync_samples/eventgrid_client_samples/sample_eg_client_authentication.py +++ b/sdk/eventgrid/azure-eventgrid/samples/sync_samples/eventgrid_client_samples/sample_eg_client_authentication.py @@ -19,8 +19,8 @@ from azure.eventgrid import EventGridClient from azure.core.credentials import AzureKeyCredential -key = os.environ["EVENTGRID_KEY"] -endpoint = os.environ["EVENTGRID_ENDPOINT"] +key: str = os.environ["EVENTGRID_KEY"] +endpoint: str = os.environ["EVENTGRID_ENDPOINT"] credential = AzureKeyCredential(key) client = EventGridClient(endpoint, credential) diff --git a/sdk/eventgrid/azure-eventgrid/samples/sync_samples/eventgrid_client_samples/sample_publish_operation.py b/sdk/eventgrid/azure-eventgrid/samples/sync_samples/eventgrid_client_samples/sample_publish_operation.py index 10bfb8e0ffe8..fe5460387824 100644 --- a/sdk/eventgrid/azure-eventgrid/samples/sync_samples/eventgrid_client_samples/sample_publish_operation.py +++ b/sdk/eventgrid/azure-eventgrid/samples/sync_samples/eventgrid_client_samples/sample_publish_operation.py @@ -11,10 +11,10 @@ from azure.core.exceptions import HttpResponseError -EVENTGRID_KEY = os.environ.get("EVENTGRID_KEY") -EVENTGRID_ENDPOINT = os.environ.get("EVENTGRID_ENDPOINT") -TOPIC_NAME = os.environ.get("TOPIC_NAME") -EVENT_SUBSCRIPTION_NAME = os.environ.get("EVENT_SUBSCRIPTION_NAME") +EVENTGRID_KEY: str = os.environ["EVENTGRID_KEY"] +EVENTGRID_ENDPOINT: str = os.environ["EVENTGRID_ENDPOINT"] +TOPIC_NAME: str = os.environ["TOPIC_NAME"] +EVENT_SUBSCRIPTION_NAME: str = os.environ["EVENT_SUBSCRIPTION_NAME"] # Create a client client = EventGridClient(EVENTGRID_ENDPOINT, AzureKeyCredential(EVENTGRID_KEY)) diff --git a/sdk/eventgrid/azure-eventgrid/samples/sync_samples/eventgrid_client_samples/sample_receive_operation.py b/sdk/eventgrid/azure-eventgrid/samples/sync_samples/eventgrid_client_samples/sample_receive_operation.py index 222772002bd0..aefd6c39275f 100644 --- a/sdk/eventgrid/azure-eventgrid/samples/sync_samples/eventgrid_client_samples/sample_receive_operation.py +++ b/sdk/eventgrid/azure-eventgrid/samples/sync_samples/eventgrid_client_samples/sample_receive_operation.py @@ -9,10 +9,10 @@ from azure.eventgrid.models import * from azure.core.exceptions import HttpResponseError -EVENTGRID_KEY = os.environ.get("EVENTGRID_KEY") -EVENTGRID_ENDPOINT = os.environ.get("EVENTGRID_ENDPOINT") -TOPIC_NAME = os.environ.get("TOPIC_NAME") -EVENT_SUBSCRIPTION_NAME = os.environ.get("EVENT_SUBSCRIPTION_NAME") +EVENTGRID_KEY: str = os.environ["EVENTGRID_KEY"] +EVENTGRID_ENDPOINT: str = os.environ["EVENTGRID_ENDPOINT"] +TOPIC_NAME: str = os.environ["TOPIC_NAME"] +EVENT_SUBSCRIPTION_NAME: str = os.environ["EVENT_SUBSCRIPTION_NAME"] # Create a client client = EventGridClient(EVENTGRID_ENDPOINT, AzureKeyCredential(EVENTGRID_KEY)) diff --git a/sdk/eventgrid/azure-eventgrid/samples/sync_samples/eventgrid_client_samples/sample_reject_operation.py b/sdk/eventgrid/azure-eventgrid/samples/sync_samples/eventgrid_client_samples/sample_reject_operation.py index d65066e52b44..a24a07a8ed74 100644 --- a/sdk/eventgrid/azure-eventgrid/samples/sync_samples/eventgrid_client_samples/sample_reject_operation.py +++ b/sdk/eventgrid/azure-eventgrid/samples/sync_samples/eventgrid_client_samples/sample_reject_operation.py @@ -9,10 +9,10 @@ from azure.eventgrid.models import * from azure.core.exceptions import HttpResponseError -EVENTGRID_KEY = os.environ.get("EVENTGRID_KEY") -EVENTGRID_ENDPOINT = os.environ.get("EVENTGRID_ENDPOINT") -TOPIC_NAME = os.environ.get("TOPIC_NAME") -EVENT_SUBSCRIPTION_NAME = os.environ.get("EVENT_SUBSCRIPTION_NAME") +EVENTGRID_KEY: str = os.environ["EVENTGRID_KEY"] +EVENTGRID_ENDPOINT: str = os.environ["EVENTGRID_ENDPOINT"] +TOPIC_NAME: str = os.environ["TOPIC_NAME"] +EVENT_SUBSCRIPTION_NAME: str = os.environ["EVENT_SUBSCRIPTION_NAME"] # Create a client client = EventGridClient(EVENTGRID_ENDPOINT, AzureKeyCredential(EVENTGRID_KEY)) diff --git a/sdk/eventgrid/azure-eventgrid/samples/sync_samples/eventgrid_client_samples/sample_release_operation.py b/sdk/eventgrid/azure-eventgrid/samples/sync_samples/eventgrid_client_samples/sample_release_operation.py index dfea2e9489a4..60db8ed9f5e6 100644 --- a/sdk/eventgrid/azure-eventgrid/samples/sync_samples/eventgrid_client_samples/sample_release_operation.py +++ b/sdk/eventgrid/azure-eventgrid/samples/sync_samples/eventgrid_client_samples/sample_release_operation.py @@ -9,10 +9,10 @@ from azure.eventgrid.models import * from azure.core.exceptions import HttpResponseError -EVENTGRID_KEY = os.environ.get("EVENTGRID_KEY") -EVENTGRID_ENDPOINT = os.environ.get("EVENTGRID_ENDPOINT") -TOPIC_NAME = os.environ.get("TOPIC_NAME") -EVENT_SUBSCRIPTION_NAME = os.environ.get("EVENT_SUBSCRIPTION_NAME") +EVENTGRID_KEY: str = os.environ["EVENTGRID_KEY"] +EVENTGRID_ENDPOINT: str = os.environ["EVENTGRID_ENDPOINT"] +TOPIC_NAME: str = os.environ["TOPIC_NAME"] +EVENT_SUBSCRIPTION_NAME: str = os.environ["EVENT_SUBSCRIPTION_NAME"] # Create a client client = EventGridClient(EVENTGRID_ENDPOINT, AzureKeyCredential(EVENTGRID_KEY)) From c74420c86d899fa3c7814d370d16a3cba3ce8619 Mon Sep 17 00:00:00 2001 From: l0lawrence Date: Thu, 5 Oct 2023 08:49:16 -0700 Subject: [PATCH 12/12] remove patched EG - no longer needed --- .../azure/eventgrid/__init__.py | 2 +- .../azure-eventgrid/azure/eventgrid/_patch.py | 41 ------------------- .../azure/eventgrid/aio/__init__.py | 2 +- .../azure/eventgrid/aio/_patch.py | 28 ------------- 4 files changed, 2 insertions(+), 71 deletions(-) diff --git a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/__init__.py b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/__init__.py index f6da3df3d6bc..32166aad43a3 100644 --- a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/__init__.py +++ b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/__init__.py @@ -6,7 +6,7 @@ # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- -from ._patch import EventGridClient +from ._client import EventGridClient from ._version import VERSION __version__ = VERSION diff --git a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_patch.py b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_patch.py index 4ead1bf7ec05..9ac00715fa22 100644 --- a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_patch.py +++ b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_patch.py @@ -7,9 +7,6 @@ """ from typing import List -from azure.core.pipeline.policies import SansIOHTTPPolicy -from azure.core.credentials import AzureKeyCredential -from ._client import EventGridClient as ServiceClientGenerated from ._legacy import ( EventGridPublisherClient, SystemEventNames, @@ -17,43 +14,6 @@ generate_sas, ) - -class EventGridSharedAccessKeyPolicy(SansIOHTTPPolicy): - def __init__( - self, credential: "AzureKeyCredential", **kwargs - ) -> None: # pylint: disable=unused-argument - super(EventGridSharedAccessKeyPolicy, self).__init__() - self._credential = credential - - def on_request(self, request): - request.http_request.headers["Authorization"] = ( - "SharedAccessKey " + self._credential.key - ) - - -class EventGridClient(ServiceClientGenerated): - """Azure Messaging EventGrid Client. - - :param endpoint: The host name of the namespace, e.g. - namespaceName1.westus-1.eventgrid.azure.net. Required. - :type endpoint: str - :param credential: Credential needed for the client to connect to Azure. Required. - :type credential: ~azure.core.credentials.AzureKeyCredential - :keyword api_version: The API version to use for this operation. Default value is - "2023-06-01-preview". Note that overriding this default value may result in unsupported - behavior. - :paramtype api_version: str - """ - - def __init__(self, endpoint: str, credential: AzureKeyCredential, **kwargs) -> None: - if isinstance(credential, AzureKeyCredential): - if not kwargs.get("authentication_policy"): - kwargs["authentication_policy"] = EventGridSharedAccessKeyPolicy( - credential - ) - super().__init__(endpoint=endpoint, credential=credential, **kwargs) - - def patch_sdk(): """Do not remove from this file. `patch_sdk` is a last resort escape hatch that allows you to do customizations @@ -63,7 +23,6 @@ def patch_sdk(): __all__: List[str] = [ - "EventGridClient", "EventGridPublisherClient", "SystemEventNames", "EventGridEvent", diff --git a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/aio/__init__.py b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/aio/__init__.py index 149d797cbe4e..6c53eb888303 100644 --- a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/aio/__init__.py +++ b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/aio/__init__.py @@ -6,7 +6,7 @@ # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- -from ._patch import EventGridClient +from ._client import EventGridClient try: from ._patch import __all__ as _patch_all diff --git a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/aio/_patch.py b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/aio/_patch.py index 1b19aa235f57..506b7ccced9a 100644 --- a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/aio/_patch.py +++ b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/aio/_patch.py @@ -7,35 +7,8 @@ """ from typing import List -from azure.core.credentials import AzureKeyCredential -from .._patch import EventGridSharedAccessKeyPolicy -from ._client import EventGridClient as ServiceClientGenerated from .._legacy.aio import EventGridPublisherClient - -class EventGridClient(ServiceClientGenerated): - """Azure Messaging EventGrid Client. - - :param endpoint: The host name of the namespace, e.g. - namespaceName1.westus-1.eventgrid.azure.net. Required. - :type endpoint: str - :param credential: Credential needed for the client to connect to Azure. Required. - :type credential: ~azure.core.credentials.AzureKeyCredential - :keyword api_version: The API version to use for this operation. Default value is - "2023-06-01-preview". Note that overriding this default value may result in unsupported - behavior. - :paramtype api_version: str - """ - - def __init__(self, endpoint: str, credential: AzureKeyCredential, **kwargs) -> None: - if isinstance(credential, AzureKeyCredential): - if not kwargs.get("authentication_policy"): - kwargs["authentication_policy"] = EventGridSharedAccessKeyPolicy( - credential - ) - super().__init__(endpoint=endpoint, credential=credential, **kwargs) - - def patch_sdk(): """Do not remove from this file. `patch_sdk` is a last resort escape hatch that allows you to do customizations @@ -45,6 +18,5 @@ def patch_sdk(): __all__: List[str] = [ - "EventGridClient", "EventGridPublisherClient", ] # Add all objects you want publicly available to users at this package level