commit python-msrest for openSUSE:Factory
Hello community, here is the log from the commit of package python-msrest for openSUSE:Factory checked in at 2020-04-01 19:09:32 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-msrest (Old) and /work/SRC/openSUSE:Factory/.python-msrest.new.3248 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "python-msrest" Wed Apr 1 19:09:32 2020 rev:9 rq:790243 version:0.6.11 Changes: -------- --- /work/SRC/openSUSE:Factory/python-msrest/python-msrest.changes 2019-10-10 14:32:08.868373959 +0200 +++ /work/SRC/openSUSE:Factory/.python-msrest.new.3248/python-msrest.changes 2020-04-01 19:12:39.823377929 +0200 @@ -1,0 +2,8 @@ +Tue Mar 31 15:26:34 UTC 2020 - John Paul Adrian Glaubitz <adrian.glaubitz@suse.com> + +- New upstream release + + Version 0.6.11 + + For detailed information about changes see the + README.rst file provided with this package + +------------------------------------------------------------------- @@ -5 +13 @@ - + Version 0.6.20 + + Version 0.6.10 @@ -7 +15 @@ - HISTORY.txt file provided with this package + README.rst file provided with this package @@ -46 +53,0 @@ -- Install HISTORY.rst into doc directory Old: ---- msrest-0.6.10.tar.gz New: ---- msrest-0.6.11.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-msrest.spec ++++++ --- /var/tmp/diff_new_pack.M18d3I/_old 2020-04-01 19:12:42.187378992 +0200 +++ /var/tmp/diff_new_pack.M18d3I/_new 2020-04-01 19:12:42.191378994 +0200 @@ -1,7 +1,7 @@ # # spec file for package python-msrest # -# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2020 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -18,12 +18,12 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} Name: python-msrest -Version: 0.6.10 +Version: 0.6.11 Release: 0 Summary: AutoRest swagger generator Python client runtime License: MIT Group: Development/Languages/Python -Url: https://pypi.python.org/pypi/msrest +URL: https://pypi.python.org/pypi/msrest Source: https://files.pythonhosted.org/packages/source/m/msrest/msrest-%{version}.tar.gz Source1: LICENSE.md BuildRequires: %{python_module setuptools} ++++++ msrest-0.6.10.tar.gz -> msrest-0.6.11.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/msrest-0.6.10/PKG-INFO new/msrest-0.6.11/PKG-INFO --- old/msrest-0.6.10/PKG-INFO 2019-09-04 20:04:43.000000000 +0200 +++ new/msrest-0.6.11/PKG-INFO 2020-01-30 18:02:40.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: msrest -Version: 0.6.10 +Version: 0.6.11 Summary: AutoRest swagger generator Python client runtime. Home-page: https://github.com/Azure/msrest-for-python Author: Microsoft Corporation @@ -27,6 +27,22 @@ Release History --------------- + 2019-01-30 Version 0.6.11 + +++++++++++++++++++++++++ + + **Features** + + - XML mode can now be enabled even if the given Model has no XML metadata #184 + - Add Kerberos Authentication #186 + - Improve error message if expected type is dictionnary and something else is provided #188 + + **Bugfixes** + + - Fix comma separated serialization of array in query #186 + - Fix validation of basic types in some complex scenario #189 + + Thanks to catatonicprime for the contribution + 2019-09-04 Version 0.6.10 +++++++++++++++++++++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/msrest-0.6.10/README.rst new/msrest-0.6.11/README.rst --- old/msrest-0.6.10/README.rst 2019-09-04 20:03:33.000000000 +0200 +++ new/msrest-0.6.11/README.rst 2020-01-30 18:02:00.000000000 +0100 @@ -20,6 +20,22 @@ Release History --------------- +2019-01-30 Version 0.6.11 ++++++++++++++++++++++++++ + +**Features** + +- XML mode can now be enabled even if the given Model has no XML metadata #184 +- Add Kerberos Authentication #186 +- Improve error message if expected type is dictionnary and something else is provided #188 + +**Bugfixes** + +- Fix comma separated serialization of array in query #186 +- Fix validation of basic types in some complex scenario #189 + +Thanks to catatonicprime for the contribution + 2019-09-04 Version 0.6.10 +++++++++++++++++++++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/msrest-0.6.10/msrest/authentication.py new/msrest-0.6.11/msrest/authentication.py --- old/msrest-0.6.10/msrest/authentication.py 2019-09-04 20:03:33.000000000 +0200 +++ new/msrest-0.6.11/msrest/authentication.py 2020-01-30 18:02:00.000000000 +0100 @@ -172,6 +172,39 @@ session.auth = oauth.OAuth2(self.id, token=self.token) return session + +class KerberosAuthentication(Authentication): + """Kerberos Authentication + Kerberos Single Sign On (SSO); requires requests_kerberos is installed. + + :param mutual_authentication: whether to require mutual authentication. Use values from requests_kerberos import REQUIRED, OPTIONAL, or DISABLED + """ + def __init__(self, mutual_authentication=None): + super(KerberosAuthentication, self).__init__() + self.mutual_authentication = mutual_authentication + + def signed_session(self, session=None): + """Create requests session with Negotiate (SPNEGO) headers applied. + + If a session object is provided, configure it directly. Otherwise, + create a new session and return it. + + :param session: The session to configure for authentication + :type session: requests.Session + :rtype: requests.Session + """ + session = super(KerberosAuthentication, self).signed_session(session) + try: + from requests_kerberos import HTTPKerberosAuth + except ImportError: + raise ImportError("In order to use KerberosAuthentication please do 'pip install requests_kerberos' first") + if self.mutual_authentication: + session.auth = HTTPKerberosAuth(mutual_authentication=self.mutual_authentication) + else: + session.auth = HTTPKerberosAuth() + return session + + class ApiKeyCredentials(Authentication): """Represent the ApiKey feature of Swagger. @@ -209,11 +242,12 @@ session.headers.update(self.in_headers) try: # params is actually Union[bytes, MutableMapping[Text, Text]] - session.params.update(self.in_query) # type: ignore + session.params.update(self.in_query) # type: ignore except AttributeError: # requests.params can be bytes raise ValueError("session.params must be a dict to be used in ApiKeyCredentials") return session + class CognitiveServicesCredentials(ApiKeyCredentials): """Cognitive Services authentication. @@ -233,6 +267,7 @@ } ) + class TopicCredentials(ApiKeyCredentials): """Event Grid authentication. @@ -251,6 +286,7 @@ } ) + class DomainCredentials(ApiKeyCredentials): """Event Grid domain authentication. @@ -268,4 +304,3 @@ self._domain_key_header: domain_key, } ) - \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/msrest-0.6.10/msrest/exceptions.py new/msrest-0.6.11/msrest/exceptions.py --- old/msrest-0.6.10/msrest/exceptions.py 2019-09-04 20:03:33.000000000 +0200 +++ new/msrest-0.6.11/msrest/exceptions.py 2020-01-30 18:02:00.000000000 +0100 @@ -107,6 +107,13 @@ "type": "must be of type {!r}" } + @staticmethod + def _format_message(rule, reason, value): + if rule == "type" and value.startswith(r"{"): + internal_type = value.strip(r"{}") + value = "dict[str, {}]".format(internal_type) + return reason.format(value) + def __init__(self, rule, target, value, *args, **kwargs): # type: (str, str, str, str, str) -> None self.rule = rule @@ -114,7 +121,7 @@ message = "Parameter {!r} ".format(target) reason = self._messages.get( rule, "failed to meet validation requirement.") - message += reason.format(value) + message += self._format_message(rule, reason, value) super(ValidationError, self).__init__(message, *args, **kwargs) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/msrest-0.6.10/msrest/pipeline/__init__.py new/msrest-0.6.11/msrest/pipeline/__init__.py --- old/msrest-0.6.10/msrest/pipeline/__init__.py 2019-09-04 20:03:33.000000000 +0200 +++ new/msrest-0.6.11/msrest/pipeline/__init__.py 2020-01-30 18:02:00.000000000 +0100 @@ -268,8 +268,10 @@ for example deserialized headers. It also allows the raw response object to be passed back to the user. - :param output: Deserialized response object. - :param response: Raw response object. + :param output: Deserialized response object. This is the type that would have been returned + directly by the main operation without raw=True. + :param response: Raw response object (by default requests.Response instance) + :type response: ~requests.Response """ def __init__(self, output, response): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/msrest-0.6.10/msrest/serialization.py new/msrest-0.6.11/msrest/serialization.py --- old/msrest-0.6.10/msrest/serialization.py 2019-09-04 20:03:33.000000000 +0200 +++ new/msrest-0.6.11/msrest/serialization.py 2020-01-30 18:02:00.000000000 +0100 @@ -188,12 +188,12 @@ @classmethod def _create_xml_node(cls): - """Create XML node from "_xml_map". + """Create XML node. """ try: xml_map = cls._xml_map except AttributeError: - raise ValueError("This model has no XML definition") + xml_map = {} return _create_xml_node( xml_map.get('name', cls.__name__), @@ -217,6 +217,9 @@ try: debug_name = "{}.{}".format(self.__class__.__name__, attr_name) + # https://github.com/Azure/msrest-for-python/issues/85 + if value is not None and attr_type in Serializer.basic_types.values(): + value = Serializer.serialize_basic(value, attr_type) Serializer.validate(value, debug_name, **self._validation.get(attr_name, {})) except ValidationError as validation_error: validation_result.append(validation_error) @@ -224,19 +227,21 @@ validation_result += _recursive_validate(attr_name, attr_type, value) return validation_result - def serialize(self, keep_readonly=False): + def serialize(self, keep_readonly=False, **kwargs): """Return the JSON that would be sent to azure from this model. This is an alias to `as_dict(full_restapi_key_transformer, keep_readonly=False)`. + If you want XML serialization, you can pass the kwargs is_xml=True. + :param bool keep_readonly: If you want to serialize the readonly attributes :returns: A dict JSON compatible object :rtype: dict """ serializer = Serializer(self._infer_class_models()) - return serializer._serialize(self, keep_readonly=keep_readonly) + return serializer._serialize(self, keep_readonly=keep_readonly, **kwargs) - def as_dict(self, keep_readonly=True, key_transformer=attribute_transformer): + def as_dict(self, keep_readonly=True, key_transformer=attribute_transformer, **kwargs): """Return a dict that can be JSONify using json.dump. Advanced usage might optionaly use a callback as parameter: @@ -261,12 +266,14 @@ - full_restapi_key_transformer - last_restapi_key_transformer + If you want XML serialization, you can pass the kwargs is_xml=True. + :param function key_transformer: A key transformer function. :returns: A dict JSON compatible object :rtype: dict """ serializer = Serializer(self._infer_class_models()) - return serializer._serialize(self, key_transformer=key_transformer, keep_readonly=keep_readonly) + return serializer._serialize(self, key_transformer=key_transformer, keep_readonly=keep_readonly, **kwargs) @classmethod def _infer_class_models(cls): @@ -482,9 +489,9 @@ ### Incorporate this data in the right place ### if is_xml_model_serialization: - xml_desc = attr_desc['xml'] - xml_name = xml_desc['name'] - if "attr" in xml_desc and xml_desc["attr"]: + xml_desc = attr_desc.get('xml', {}) + xml_name = xml_desc.get('name', attr_desc['key']) + if xml_desc.get("attr", False): serialized.set(xml_name, new_attr) continue if isinstance(new_attr, list): @@ -578,6 +585,14 @@ raise errors[0] return self._serialize(data, data_type, **kwargs) + def _http_component_validation(self, data, data_type, name, **kwargs): + if self.client_side_validation: + # https://github.com/Azure/msrest-for-python/issues/85 + if data is not None and data_type in self.basic_types.values(): + data = self.serialize_basic(data, data_type, **kwargs) + data = self.validate(data, name, required=True, **kwargs) + return data + def url(self, name, data, data_type, **kwargs): """Serialize data intended for a URL path. @@ -587,8 +602,7 @@ :raises: TypeError if serialization fails. :raises: ValueError if data is None """ - if self.client_side_validation: - data = self.validate(data, name, required=True, **kwargs) + data = self._http_component_validation(data, data_type, name, **kwargs) try: output = self.serialize_data(data, data_type, **kwargs) if data_type == 'bool': @@ -612,12 +626,25 @@ :raises: TypeError if serialization fails. :raises: ValueError if data is None """ - if self.client_side_validation: - data = self.validate(data, name, required=True, **kwargs) + data = self._http_component_validation(data, data_type, name, **kwargs) try: - if data_type in ['[str]']: - data = ["" if d is None else d for d in data] + # 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)) + # Not a list, regular serialization output = self.serialize_data(data, data_type, **kwargs) if data_type == 'bool': output = json.dumps(output) @@ -639,8 +666,7 @@ :raises: TypeError if serialization fails. :raises: ValueError if data is None """ - if self.client_side_validation: - data = self.validate(data, name, required=True, **kwargs) + data = self._http_component_validation(data, data_type, name, **kwargs) try: if data_type in ['[str]']: data = ["" if d is None else d for d in data] @@ -713,14 +739,16 @@ else: return self._serialize(data, **kwargs) - def _get_custom_serializers(self, data_type, **kwargs): + @classmethod + def _get_custom_serializers(cls, data_type, **kwargs): custom_serializer = kwargs.get("basic_types_serializers", {}).get(data_type) if custom_serializer: return custom_serializer if kwargs.get("is_xml", False): - return self._xml_basic_types_serializers.get(data_type) + return cls._xml_basic_types_serializers.get(data_type) - def serialize_basic(self, data, data_type, **kwargs): + @classmethod + def serialize_basic(cls, data, data_type, **kwargs): """Serialize basic builting data type. Serializes objects to str, int, float or bool. @@ -731,14 +759,15 @@ :param data: Object to be serialized. :param str data_type: Type of object in the iterable. """ - custom_serializer = self._get_custom_serializers(data_type, **kwargs) + custom_serializer = cls._get_custom_serializers(data_type, **kwargs) if custom_serializer: return custom_serializer(data) if data_type == 'str': - return self.serialize_unicode(data) + return cls.serialize_unicode(data) return eval(data_type)(data) - def serialize_unicode(self, data): + @classmethod + def serialize_unicode(cls, data): """Special handling for serializing unicode strings in Py2. Encode to UTF-8 if unicode, otherwise handle as a str. @@ -764,7 +793,9 @@ """Serialize iterable. Supported kwargs: - serialization_ctxt dict : The current entry of _attribute_map, or same format. serialization_ctxt['type'] should be same as data_type. + - serialization_ctxt dict : The current entry of _attribute_map, or same format. + serialization_ctxt['type'] should be same as data_type. + - is_xml bool : If set, serialize as XML :param list attr: Object to be serialized. :param str iter_type: Type of object in the iterable. @@ -778,6 +809,7 @@ raise SerializationError("Refuse str type as a valid iter type.") serialization_ctxt = kwargs.get("serialization_ctxt", {}) + is_xml = kwargs.get("is_xml", False) serialized = [] for d in data: @@ -790,13 +822,15 @@ serialized = ['' if s is None else str(s) for s in serialized] serialized = div.join(serialized) - if 'xml' in serialization_ctxt: + if 'xml' in serialization_ctxt or is_xml: # XML serialization is more complicated - xml_desc = serialization_ctxt['xml'] - xml_name = xml_desc['name'] + xml_desc = serialization_ctxt.get('xml', {}) + xml_name = xml_desc.get('name') + if not xml_name: + xml_name = serialization_ctxt['key'] # Create a wrap node if necessary (use the fact that Element and list have "append") - is_wrapped = "wrapped" in xml_desc and xml_desc["wrapped"] + is_wrapped = xml_desc.get("wrapped", False) node_name = xml_desc.get("itemsName", xml_name) if is_wrapped: final_result = _create_xml_node( @@ -1103,19 +1137,19 @@ return data.get(found_key) def xml_key_extractor(attr, attr_desc, data): - # Test if this model is XML ready first - if 'xml' not in attr_desc: + if isinstance(data, dict): return None - if isinstance(data, dict): + # Test if this model is XML ready first + if not isinstance(data, ET.Element): return None - xml_desc = attr_desc['xml'] - xml_name = xml_desc['name'] + xml_desc = attr_desc.get('xml', {}) + xml_name = xml_desc.get('name', attr_desc['key']) xml_ns = xml_desc.get('ns', None) # If it's an attribute, that's simple - if "attr" in xml_desc and xml_desc["attr"]: + if xml_desc.get("attr", False): return data.get(xml_name) # Integrate namespace if necessary @@ -1127,25 +1161,26 @@ # Look for a children is_iter_type = attr_desc['type'].startswith("[") - is_wrapped = "wrapped" in xml_desc and xml_desc["wrapped"] + is_wrapped = xml_desc.get("wrapped", False) internal_type = attr_desc.get("internalType", None) # Scenario where I take the local name: # - Wrapped node # - Internal type is an enum (considered basic types) # - Internal type has no XML/Name node - if is_wrapped or (internal_type and (issubclass(internal_type, Enum) or 'name' not in internal_type._xml_map)): + internal_type_xml_map = getattr(internal_type, "_xml_map", {}) + if is_wrapped or (internal_type and (issubclass(internal_type, Enum) or 'name' not in internal_type_xml_map)): children = data.findall(xml_name, ns) # If internal type has a local name and it's not a list, I use that name - elif not is_iter_type and internal_type and 'name' in internal_type._xml_map: - xml_name = internal_type._xml_map["name"] - ns = internal_type._xml_map.get("ns", None) + elif not is_iter_type and internal_type and 'name' in internal_type_xml_map: + xml_name = internal_type_xml_map["name"] + ns = internal_type_xml_map.get("ns", None) children = data.findall(xml_name, ns) # That's an array else: if internal_type: # Complex type, ignore itemsName and use the complex type name - items_name = internal_type._xml_map["name"] - ns = internal_type._xml_map.get("ns", None) + items_name = internal_type_xml_map.get('name', internal_type.__name__) + ns = internal_type_xml_map.get("ns", None) else: items_name = xml_desc.get("itemsName", xml_name) children = data.findall(items_name, ns) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/msrest-0.6.10/msrest/version.py new/msrest-0.6.11/msrest/version.py --- old/msrest-0.6.10/msrest/version.py 2019-09-04 20:03:33.000000000 +0200 +++ new/msrest-0.6.11/msrest/version.py 2020-01-30 18:02:00.000000000 +0100 @@ -25,4 +25,4 @@ # -------------------------------------------------------------------------- #: version of this package. Use msrest.__version__ instead -msrest_version = "0.6.10" +msrest_version = "0.6.11" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/msrest-0.6.10/msrest.egg-info/PKG-INFO new/msrest-0.6.11/msrest.egg-info/PKG-INFO --- old/msrest-0.6.10/msrest.egg-info/PKG-INFO 2019-09-04 20:04:43.000000000 +0200 +++ new/msrest-0.6.11/msrest.egg-info/PKG-INFO 2020-01-30 18:02:40.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: msrest -Version: 0.6.10 +Version: 0.6.11 Summary: AutoRest swagger generator Python client runtime. Home-page: https://github.com/Azure/msrest-for-python Author: Microsoft Corporation @@ -27,6 +27,22 @@ Release History --------------- + 2019-01-30 Version 0.6.11 + +++++++++++++++++++++++++ + + **Features** + + - XML mode can now be enabled even if the given Model has no XML metadata #184 + - Add Kerberos Authentication #186 + - Improve error message if expected type is dictionnary and something else is provided #188 + + **Bugfixes** + + - Fix comma separated serialization of array in query #186 + - Fix validation of basic types in some complex scenario #189 + + Thanks to catatonicprime for the contribution + 2019-09-04 Version 0.6.10 +++++++++++++++++++++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/msrest-0.6.10/setup.py new/msrest-0.6.11/setup.py --- old/msrest-0.6.10/setup.py 2019-09-04 20:03:33.000000000 +0200 +++ new/msrest-0.6.11/setup.py 2020-01-30 18:02:00.000000000 +0100 @@ -28,7 +28,7 @@ setup( name='msrest', - version='0.6.10', + version='0.6.11', author='Microsoft Corporation', packages=find_packages(exclude=["tests", "tests.*"]), url=("https://github.com/Azure/msrest-for-python"), diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/msrest-0.6.10/tests/test_serialization.py new/msrest-0.6.11/tests/test_serialization.py --- old/msrest-0.6.10/tests/test_serialization.py 2019-09-04 20:03:33.000000000 +0200 +++ new/msrest-0.6.11/tests/test_serialization.py 2020-01-30 18:02:00.000000000 +0100 @@ -245,6 +245,32 @@ self.s = Serializer({'TestObj': self.TestObj}) return super(TestRuntimeSerialized, self).setUp() + def test_validation_type(self): + # https://github.com/Azure/msrest-for-python/issues/85 + s = Serializer() + + s.query("filter", 186, "int", maximum=666) + s.query("filter", "186", "int", maximum=666) + + class TestValidationObj(Model): + + _attribute_map = { + 'attr_a': {'key':'id', 'type':'int'}, + } + _validation = { + 'attr_a': {'maximum': 4294967295, 'minimum': 1}, + } + + + test_obj = TestValidationObj() + test_obj.attr_a = 186 + errors_found = test_obj.validate() + assert not errors_found + + test_obj.attr_a = '186' + errors_found = test_obj.validate() + assert not errors_found + def test_validation_flag(self): s = Serializer() s.client_side_validation = True @@ -271,6 +297,20 @@ s.header("filter", "", "str", min_length=666) s.body(test_obj, 'TestObj') + def test_serialize_query(self): + s = Serializer() + + assert s.query("filter", "boo", "str") == "boo" + assert s.query("filter", "boo,bar", "str", skip_quote=True) == "boo,bar" + assert s.query("filter", 12, "int") == "12" + + assert s.query("filter", [1, 2, 3], "[int]", div=",") == "1,2,3" + + assert s.query("filter", ['a', 'b', 'c'], "[str]", div=",") == "a,b,c" + assert s.query("filter", ['a', None, 'c'], "[str]", div=",") == "a,,c" + assert s.query("filter", [',', ',', ','], "[str]", div=",") == "%2C,%2C,%2C" + assert s.query("filter", [',', ',', ','], "[str]", div="|", skip_quote=True) == ",|,|," + def test_serialize_direct_model(self): testobj = self.TestObj() testobj.attr_a = "myid" @@ -709,6 +749,10 @@ with self.assertRaises(SerializationError): self.s._serialize(test_obj) + with pytest.raises(ValidationError) as err: + test_obj.validate() + assert "Parameter 'attr_e' must be of type 'dict[str, float]'" in str(err.value) + test_obj.attr_e = {"value": "NotAFloat"} with self.assertRaises(SerializationError): @@ -1290,7 +1334,7 @@ long_type = long except NameError: long_type = int - + class TestModel(Model): _attribute_map = {'data': {'key': 'data', 'type': 'object'}}
participants (1)
-
root