diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9f8c131968c050fb18001b5dc7c5468d0ed26dae..72b4381aebcaf5edd16c10c479df6ca908128ec6 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -47,7 +47,7 @@ pylint: tags: [ docker ] stage: linting script: - - pylint3 --unsafe-load-any-extension=y -d all -e E,F src/caosdb/common + - pylint --unsafe-load-any-extension=y -d all -e E,F src/caosdb/common allow_failure: true diff --git a/CHANGELOG.md b/CHANGELOG.md index b590038ef3ffae1bb29b3e0fa6a9824bb25a1ecb..db5501f1e4fe61b5893bfa305f10e9e263a8490f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,10 +16,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed ### - It is possible now to supply a password for caosdb_admin on the command line and also activate the user directly using "-c". +* Entity.add_property and Entity.add_parent do not accept `**kwargs`-style + keywords anymore. Formerly known keywords have been refactored into named + parameters. +* [#35](https://gitlab.com/caosdb/caosdb-pylib/-/issues/35) Loggers now use the name of + the unit where they are called instead of a static name ### Deprecated ### -* `id_query(ids)` in apiutils +* `id_query(ids)` in apiutils (to be removed with >=0.5.4) +* The whole yamlapi with the following functions (to be removed with >=0.5.4): + * `append_sublist` + * `kv_to_xml` + * `dict_to_xml` + * `yaml_to_xml` + * `process` + * `yaml_file_to_xml` + * `insert_yaml_file` ### Removed ### diff --git a/src/caosdb/apiutils.py b/src/caosdb/apiutils.py index 9192289a0b6518a2d6ec3abcdeca9d1d2c063d6d..b3d5df698baceacf671c5171430dfa48b3c881b5 100644 --- a/src/caosdb/apiutils.py +++ b/src/caosdb/apiutils.py @@ -517,9 +517,9 @@ def getOriginUrlIn(folder): with open(t.name, "r") as t: urlString = "Fetch URL:" - for l in t.readlines(): - if urlString in l: - return l[l.find(urlString) + len(urlString):].strip() + for line in t.readlines(): + if urlString in line: + return line[line.find(urlString) + len(urlString):].strip() return None diff --git a/src/caosdb/common/administration.py b/src/caosdb/common/administration.py index e7ba94182d7a4d8b60c6400cd1d804f62f7bf03c..dff461e7fb0ed5270119907bd4ad859503b3ce21 100644 --- a/src/caosdb/common/administration.py +++ b/src/caosdb/common/administration.py @@ -26,16 +26,12 @@ """missing docstring.""" -from lxml import etree - from caosdb.common.utils import xml2str from caosdb.connection.connection import get_connection -from caosdb.exceptions import (HTTPClientError, - HTTPForbiddenError, - HTTPResourceNotFoundError, - EntityDoesNotExistError, - ServerConfigurationException, - ) +from caosdb.exceptions import (EntityDoesNotExistError, HTTPClientError, + HTTPForbiddenError, HTTPResourceNotFoundError, + ServerConfigurationException) +from lxml import etree def set_server_property(key, value): @@ -156,13 +152,22 @@ def _update_user(name, realm=None, password=None, status=None, return con.put_form_data(entity_uri_segment="User/" + (realm + "/" + name if realm is not None else name), params=params, **kwargs).read() except HTTPResourceNotFoundError as e: e.msg = "User does not exist." - raise + raise e except HTTPForbiddenError as e: e.msg = "You are not permitted to update this user." - raise + raise e except HTTPClientError as e: if e.status == 409: e.msg = "Entity does not exist." + + if e.status == 422: + e.msg = """Maybe the password does not match the required standard? + The current requirements are: + - at least 8 characters + - at least 1 number + - at least 1 lower case character + - at least 1 upper case character + - at least 1 special character""" raise @@ -191,7 +196,13 @@ def _insert_user(name, password=None, status=None, email=None, entity=None, **kw e.msg = "User name is already in use." if e.status == 422: - e.msg = "Maybe the password does not match the required standard?" + e.msg = """Maybe the password does not match the required standard? + The current requirements are: + - at least 8 characters + - at least 1 number + - at least 1 lower case character + - at least 1 upper case character + - at least 1 special character""" raise e diff --git a/src/caosdb/common/models.py b/src/caosdb/common/models.py index b3109fc7ef8bffe0ef3b7c9f30e5774052ddd08b..3aab7fc77a8e80a0aa84c8fc187eb141f13abc67 100644 --- a/src/caosdb/common/models.py +++ b/src/caosdb/common/models.py @@ -339,32 +339,54 @@ class Entity(object): return self - def add_property(self, property=None, value=None, **kwargs): # @ReservedAssignment + def add_property(self, property=None, value=None, id=None, name=None, description=None, datatype=None, + unit=None, importance=None, inheritance=None): # @ReservedAssignment """Add a property to this entity. The first parameter is meant to identify the property entity. So the method expects an instance of Entity, an integer or a string here. The second parameter is the value of the new property. Any - other named parameter may be passed by means of the **kwargs. Accepted keywords are: + other named parameter may be passed by means of the keywwords. Accepted keywords are: id, name, description, importance, inheritance, datatype, and unit. Any other keyword will be ignored right now. But that may change in the future. - @param property: An identifying parameter (name, id or abstract property). - @param value: The value of the new property. - @param **kwargs: Any other specification for this property. Accepted keywords: id, name, description, importance, inheritance, datatype, and unit. - @raise UserWarning: - If the first parameter is None then kwargs['id'] or kwargs['name'] must be defined and not be None. - Otherwise a UserWarning is raised. + Parameters + ---------- + property : int, str, Property, optional + An identifying parameter, by default None + value : int, str, Property, optional + The value of the new property, by default None + id : int, optional + Id of the property, by default None + name : str, optional + Name of the property, by default None + description : str, optional + Description of the property, by default None + datatype : str, optional + Datatype of the property, by default None + unit : str, optional + Unit of the property, by default None + importance :str, optional + Importance of the property, by default None + inheritance : str, optional + Inheritance of the property, by default None - If the first parameter is an integer then it is interpreted as the id and kwargs['id'] must be - undefined or None. Otherwise a UserWarning is raised. + Returns + ------- + Entity - If the first parameter is not None and neither an instance of Entity nor an integer it is - interpreted as the name and kwargs['name'] must be undefined or None. Otherwise a UserWarning is - raised. + Raises + ------ + UserWarning + If the first parameter is None then id or name must be defined and not be None. + UserWarning + If the first parameter is an integer then it is interpreted as the id and id must be + undefined or None. + UserWarning + If the first parameter is not None and neither an instance of Entity nor an integer it is + interpreted as the name and name must be undefined or None. """ - copy_kwargs = kwargs.copy() - name = (kwargs['name'] if 'name' in kwargs else None) - pid = (kwargs['id'] if 'id' in kwargs else None) + + pid = id abstract_property = None if isinstance(property, Entity): @@ -373,20 +395,18 @@ class Entity(object): if pid is not None: raise UserWarning("The first parameter was an integer which would normally be interpreted as the id of the property which is to be added. But you have also specified a parameter 'id' in the method call. This is ambiguous and cannot be processed.") pid = property - copy_kwargs['id'] = pid + id = pid elif property is not None: if name is not None: raise UserWarning("The first parameter was neither an instance of Entity nor an integer. Therefore the string representation of your first parameter would normally be interpreted name of the property which is to be added. But you have also specified a parameter 'name' in the method call. This is ambiguous and cannot be processed.") name = str(property) - copy_kwargs['name'] = name if property is None and name is None and pid is None: raise UserWarning( "This method expects you to pass at least an entity, a name or an id.") - del copy_kwargs['importance'] - del copy_kwargs['inheritance'] - new_property = Property(**copy_kwargs) + new_property = Property(name=name, id=id, description=description, datatype=datatype, + value=value, unit=unit) if abstract_property is not None: new_property._wrap(property) @@ -399,9 +419,7 @@ class Entity(object): new_property.value = value self.properties.append( - property=new_property, importance=( - kwargs['importance'] if 'importance' in kwargs else None), inheritance=( - kwargs['inheritance'] if 'inheritance' in kwargs else None)) + property=new_property, importance=importance, inheritance=inheritance) return self @@ -426,7 +444,7 @@ class Entity(object): return self - def add_parent(self, parent=None, **kwargs): # @ReservedAssignment + def add_parent(self, parent=None, id=None, name=None, inheritance=None): # @ReservedAssignment """Add a parent to this entity. Parameters @@ -434,27 +452,23 @@ class Entity(object): parent : Entity or int or str or None The parent entity, either specified by the Entity object itself, or its id or its name. Default is None. - **kwargs : dict, optional - Additional keyword arguments for specifying the parent by - name or id, and for specifying the mode of inheritance. - - id : int - Integer id of the parent entity. Ignored if `parent` - is not None. - name : str - Name of the parent entity. Ignored if `parent is not - none`. - inheritance : str - One of ``obligatory``, ``recommended``, ``suggested``, or ``fix``. Specifies the - minimum importance which parent properties need to have to be inherited by this - entity. If no `inheritance` is given, no properties will be inherited by the child. - This parameter is case-insensitive. - - Note that the behaviour is currently not yet specified when assigning parents to - Records, it only works for inheritance of RecordTypes (and Properties). - - For more information, it is recommended to look into the - :ref:`data insertion tutorial<tutorial-inheritance-properties>`. + id : int + Integer id of the parent entity. Ignored if `parent` + is not None. + name : str + Name of the parent entity. Ignored if `parent is not + none`. + inheritance : str + One of ``obligatory``, ``recommended``, ``suggested``, or ``fix``. Specifies the + minimum importance which parent properties need to have to be inherited by this + entity. If no `inheritance` is given, no properties will be inherited by the child. + This parameter is case-insensitive. + + Note that the behaviour is currently not yet specified when assigning parents to + Records, it only works for inheritance of RecordTypes (and Properties). + + For more information, it is recommended to look into the + :ref:`data insertion tutorial<tutorial-inheritance-properties>`. Raises ------ @@ -463,8 +477,8 @@ class Entity(object): parameter is passed to this method. """ - name = (kwargs['name'] if 'name' in kwargs else None) - pid = (kwargs['id'] if 'id' in kwargs else None) + + pid = id parent_entity = None if isinstance(parent, Entity): @@ -478,9 +492,6 @@ class Entity(object): raise UserWarning( "This method expects you to pass at least an entity, a name or an id.") - inheritance = (kwargs['inheritance'] - if 'inheritance' in kwargs else None) - addp = Parent(id=pid, name=name, inheritance=inheritance) if parent_entity is not None: @@ -1458,45 +1469,42 @@ class Property(Entity): """CaosDB's Property object.""" - def add_property(self, property=None, value=None, **kwargs): # @ReservedAssignment - copy_kwargs = kwargs.copy() - - if 'importance' not in copy_kwargs: - # set default importance - copy_kwargs['importance'] = FIX + def add_property(self, property=None, value=None, id=None, name=None, description=None, datatype=None, + unit=None, importance=FIX, inheritance=FIX): # @ReservedAssignment - if 'inheritance' not in copy_kwargs: - # set default importance - copy_kwargs['inheritance'] = FIX - - return super(Property, self).add_property( - property=property, value=value, **copy_kwargs) + return super().add_property( + property=property, id=id, name=name, description=description, datatype=datatype, + value=value, unit=unit, importance=importance, inheritance=inheritance) - def add_parent(self, parent=None, **kwargs): + def add_parent(self, parent=None, id=None, name=None, inheritance=FIX): """Add a parent Entity to this Property. Parameters ---------- - parent : Entity or int or str or None, optional - The parent entity - **kwargs : dict, optional - Additional keyword arguments specifying the parent Entity - by id or name, and specifying the inheritance level. See - :py:meth:`Entity.add_parent` for more information. Note - that by default, `inheritance` is set to ``fix``. + Parameters + ---------- + parent : Entity or int or str or None + The parent entity, either specified by the Entity object + itself, or its id or its name. Default is None. + id : int + Integer id of the parent entity. Ignored if `parent` + is not None. + name : str + Name of the parent entity. Ignored if `parent is not + none`. + inheritance : str, default: FIX + One of ``obligatory``, ``recommended``, ``suggested``, or ``fix``. Specifies the + minimum importance which parent properties need to have to be inherited by this + entity. If no `inheritance` is given, no properties will be inherited by the child. + This parameter is case-insensitive. See Also -------- Entity.add_parent """ - copy_kwargs = kwargs.copy() - if 'inheritance' not in copy_kwargs: - # set default importance - copy_kwargs['inheritance'] = FIX - - return super(Property, self).add_parent(parent=parent, **copy_kwargs) + return super(Property, self).add_parent(parent=parent, id=id, name=name, inheritance=inheritance) def __init__(self, name=None, id=None, description=None, datatype=None, value=None, unit=None): @@ -1589,21 +1597,14 @@ class RecordType(Entity): """This class represents CaosDB's RecordType entities.""" - def add_property(self, property=None, value=None, **kwargs): # @ReservedAssignment - copy_kwargs = kwargs.copy() - - if 'importance' not in copy_kwargs: - # set default importance - copy_kwargs['importance'] = RECOMMENDED + def add_property(self, property=None, value=None, id=None, name=None, description=None, datatype=None, + unit=None, importance=RECOMMENDED, inheritance=FIX): # @ReservedAssignment - if 'inheritance' not in copy_kwargs: - # set default importance - copy_kwargs['inheritance'] = FIX - - return super().add_property(property=property, value=value, - **copy_kwargs) + return super().add_property( + property=property, id=id, name=name, description=description, datatype=datatype, + value=value, unit=unit, importance=importance, inheritance=inheritance) - def add_parent(self, parent=None, **kwargs): + def add_parent(self, parent=None, id=None, name=None, inheritance=OBLIGATORY): """Add a parent to this RecordType Parameters @@ -1611,24 +1612,30 @@ class RecordType(Entity): parent : Entity or int or str or None, optional The parent entity, either specified by the Entity object itself, or its id or its name. Default is None. - **kwargs : dict, optional - Additional keyword arguments specifying the parent Entity by id or - name, and specifying the inheritance level. See - :py:meth:`Entity.add_parent` for more information. Note - that by default, `inheritance` is set to ``obligatory``. + Parameters + ---------- + parent : Entity or int or str or None + The parent entity, either specified by the Entity object + itself, or its id or its name. Default is None. + id : int + Integer id of the parent entity. Ignored if `parent` + is not None. + name : str + Name of the parent entity. Ignored if `parent is not + none`. + inheritance : str, default OBLIGATORY + One of ``obligatory``, ``recommended``, ``suggested``, or ``fix``. Specifies the + minimum importance which parent properties need to have to be inherited by this + entity. If no `inheritance` is given, no properties will be inherited by the child. + This parameter is case-insensitive. See Also -------- Entity.add_parent """ - copy_kwargs = kwargs.copy() - - if 'inheritance' not in copy_kwargs: - # set default importance - copy_kwargs['inheritance'] = OBLIGATORY - return super().add_parent(parent=parent, **copy_kwargs) + return super().add_parent(parent=parent, id=id, name=name, inheritance=inheritance) def __init__(self, name=None, id=None, description=None, datatype=None): # @ReservedAssignment Entity.__init__(self, name=name, id=id, description=description, @@ -1645,19 +1652,12 @@ class Record(Entity): """This class represents CaosDB's Record entities.""" - def add_property(self, property=None, value=None, **kwargs): # @ReservedAssignment - copy_kwargs = kwargs.copy() - - if 'importance' not in copy_kwargs: - # set default importance - copy_kwargs['importance'] = FIX - - if 'inheritance' not in copy_kwargs: - # set default importance - copy_kwargs['inheritance'] = FIX + def add_property(self, property=None, value=None, id=None, name=None, description=None, datatype=None, + unit=None, importance=FIX, inheritance=FIX): # @ReservedAssignment return super().add_property( - property=property, value=value, **copy_kwargs) + property=property, id=id, name=name, description=description, datatype=datatype, + value=value, unit=unit, importance=importance, inheritance=inheritance) def __init__(self, name=None, id=None, description=None): # @ReservedAssignment Entity.__init__(self, name=name, id=id, description=description, @@ -1809,19 +1809,12 @@ class File(Record): return checksum.hexdigest() - def add_property(self, property=None, value=None, **kwargs): # @ReservedAssignment - copy_kwargs = kwargs.copy() - - if 'importance' not in copy_kwargs: - # set default importance - copy_kwargs['importance'] = FIX - - if 'inheritance' not in copy_kwargs: - # set default importance - copy_kwargs['inheritance'] = FIX + def add_property(self, property=None, id=None, name=None, description=None, datatype=None, + value=None, unit=None, importance=FIX, inheritance=FIX): # @ReservedAssignment return super().add_property( - property=property, value=value, **copy_kwargs) + property=property, id=id, name=name, description=description, datatype=datatype, + value=value, unit=unit, importance=importance, inheritance=inheritance) class _Properties(list): diff --git a/src/caosdb/connection/authentication/interface.py b/src/caosdb/connection/authentication/interface.py index a364aeb564ee929d995b2f8098bd21e30e9733ab..f2cc5001cf8fa0f6d61ec65346f6a200ba0dfcd8 100644 --- a/src/caosdb/connection/authentication/interface.py +++ b/src/caosdb/connection/authentication/interface.py @@ -36,7 +36,7 @@ from caosdb.exceptions import LoginFailedError # meta class compatible with Python 2 *and* 3: ABC = ABCMeta('ABC', (object, ), {'__slots__': ()}) -_LOGGER = logging.getLogger("authentication") +_LOGGER = logging.getLogger(__name__) class AbstractAuthenticator(ABC): diff --git a/src/caosdb/connection/connection.py b/src/caosdb/connection/connection.py index 9e273a56778737033fda9f342f967f56946b501b..6c3946ee639872b0edb0b5b3c30a808cf8c028d4 100644 --- a/src/caosdb/connection/connection.py +++ b/src/caosdb/connection/connection.py @@ -60,7 +60,7 @@ except ImportError: # pylint: disable=missing-docstring -_LOGGER = logging.getLogger("connection") +_LOGGER = logging.getLogger(__name__) class _WrappedHTTPResponse(CaosDBHTTPResponse): diff --git a/src/caosdb/utils/caosdb_admin.py b/src/caosdb/utils/caosdb_admin.py index 9c18f8962b3561999950059f23453d05edc0584d..9fb94f57683036f5432a40198cc4ae98893665fb 100755 --- a/src/caosdb/utils/caosdb_admin.py +++ b/src/caosdb/utils/caosdb_admin.py @@ -131,11 +131,17 @@ def do_create_user(args): def do_activate_user(args): - admin._update_user(name=args.user_name, status="ACTIVE") + try: + admin._update_user(name=args.user_name, status="ACTIVE") + except HTTPClientError as e: + print(e.msg) def do_deactivate_user(args): - admin._update_user(name=args.user_name, status="INACTIVE") + try: + admin._update_user(name=args.user_name, status="INACTIVE") + except HTTPClientError as e: + print(e.msg) def do_set_user_password(args): @@ -143,7 +149,10 @@ def do_set_user_password(args): password = _promt_for_pw() else: password = args.user_password - admin._update_user(name=args.user_name, password=password) + try: + admin._update_user(name=args.user_name, password=password) + except HTTPClientError as e: + print(e.msg) def do_add_user_roles(args): diff --git a/src/caosdb/yamlapi.py b/src/caosdb/yamlapi.py index 9a69a5276804727084af65c6568b22833e8be596..69eef001a7bfddd0f1462a65b0c343fd4ab9e7de 100644 --- a/src/caosdb/yamlapi.py +++ b/src/caosdb/yamlapi.py @@ -22,7 +22,7 @@ # ** end header # -"""YAML interface for the database (caosdb)""" +"""!!! Deprecated !!! YAML interface for the database (caosdb)""" import yaml from lxml import etree @@ -31,9 +31,14 @@ import re import caosdb import caosdb.common.utils as utils from caosdb.connection.connection import get_connection +import warnings def append_sublist(v, newel, def_entity_type): + warnings.warn(""" + This function is deprecated and will be removed with the next release. + Please use caosdb-advanced-user-tools/models/data_model.py for a + similar functionality.""", DeprecationWarning) if v is None: return for i in v: @@ -46,6 +51,10 @@ def append_sublist(v, newel, def_entity_type): def kv_to_xml(k, v): + warnings.warn(""" + This function is deprecated and will be removed with the next release. + Please use caosdb-advanced-user-tools/models/data_model.py for a + similar functionality.""", DeprecationWarning) newel = Element(k) # code.interact(local=locals()) if isinstance(v, list): # Top level loop @@ -69,10 +78,18 @@ def dict_to_xml(d): d: The dictionary (possibly loaded from yaml) to convert to caosdb-xml. """ + warnings.warn(""" + This function is deprecated and will be removed with the next release. + Please use caosdb-advanced-user-tools/models/data_model.py for a + similar functionality.""", DeprecationWarning) return kv_to_xml("Entities", d) def yaml_to_xml(yamlstr): + warnings.warn(""" + This function is deprecated and will be removed with the next release. + Please use caosdb-advanced-user-tools/models/data_model.py for a + similar functionality.""", DeprecationWarning) """Load a yaml document from yamlstr and converts it to XML. Parameters @@ -86,6 +103,10 @@ def yaml_to_xml(yamlstr): def process(text): """Do some replacements on the original file to obtain valid yaml.""" + warnings.warn(""" + This function is deprecated and will be removed with the next release. + Please use caosdb-advanced-user-tools/models/data_model.py for a + similar functionality.""", DeprecationWarning) processed = re.sub( "^(\\s*)-\\s*\\{?(.*)\\}?\\s*$", "\\1- {\\2}", @@ -98,6 +119,10 @@ def process(text): def yaml_file_to_xml(yamlfilename): + warnings.warn(""" + This function is deprecated and will be removed with the next release. + Please use caosdb-advanced-user-tools/models/data_model.py for a + similar functionality.""", DeprecationWarning) with open(yamlfilename, "r") as f: return yaml_to_xml(process(f.read())) @@ -108,6 +133,10 @@ def insert_yaml_file(yamlfilename, simulate=False): Set 'simulate' to True if you don't actually want to insert the xml, but only receive what would be sent. """ + warnings.warn(""" + This function is deprecated and will be removed with the next release. + Please use caosdb-advanced-user-tools/models/data_model.py for a + similar functionality.""", DeprecationWarning) con = get_connection() prs = etree.XMLParser(remove_blank_text=True) sent_xml = etree.tostring( diff --git a/unittests/test_authentication_plain.py b/unittests/test_authentication_plain.py index 10cbc418df8bd81c81568a4df0cf1e8a4ac498f8..146b59889c71c86ea77fb4ae962118cdda1afb06 100644 --- a/unittests/test_authentication_plain.py +++ b/unittests/test_authentication_plain.py @@ -65,4 +65,6 @@ def test_subclass_configure(): def test_plain_has_logger(): p = PlainTextCredentialsProvider() assert hasattr(p, "logger") - assert p.logger.name == "authentication" + assert "authentication" in p.logger.name + assert "connection" in p.logger.name + assert "caosdb" in p.logger.name diff --git a/unittests/test_yamlapi.py b/unittests/test_yamlapi.py new file mode 100644 index 0000000000000000000000000000000000000000..4af8a53b1172be0ddac71444724dc4b69119d998 --- /dev/null +++ b/unittests/test_yamlapi.py @@ -0,0 +1,88 @@ +# -*- coding: utf-8 -*- +# +# ** header v3.0 +# This file is a part of the CaosDB Project. +# +# Copyright (C) 2021 IndiScale GmbH <info@indiscale.com> +# Copyright (C) 2021 Alexander Kreft <akreft@trineo.org> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. +# +# ** end header +# + +import os +import warnings +import tempfile +from caosdb.yamlapi import (append_sublist, kv_to_xml, + dict_to_xml, yaml_to_xml, + process, yaml_file_to_xml) + +with warnings.catch_warnings(record=True) as w: + # Cause all warnings to always be triggered. + warnings.simplefilter("always") + + append_sublist(None, None, None) + + assert issubclass(w[-1].category, DeprecationWarning) + assert "This function is deprecated" in str(w[-1].message) + +with warnings.catch_warnings(record=True) as w: + # Cause all warnings to always be triggered. + warnings.simplefilter("always") + + kv_to_xml("None", "None") + assert len(w) == 1 + assert issubclass(w[-1].category, DeprecationWarning) + assert "This function is deprecated" in str(w[-1].message) + +with warnings.catch_warnings(record=True) as w: + # Cause all warnings to always be triggered. + warnings.simplefilter("always") + + dict_to_xml(None) + + assert issubclass(w[-1].category, DeprecationWarning) + assert "This function is deprecated" in str(w[-1].message) + +with warnings.catch_warnings(record=True) as w: + # Cause all warnings to always be triggered. + warnings.simplefilter("always") + + yaml_to_xml("None") + + assert issubclass(w[-1].category, DeprecationWarning) + assert "This function is deprecated" in str(w[-1].message) + +with warnings.catch_warnings(record=True) as w: + # Cause all warnings to always be triggered. + warnings.simplefilter("always") + + process("None") + + assert issubclass(w[-1].category, DeprecationWarning) + assert "This function is deprecated" in str(w[-1].message) + +with warnings.catch_warnings(record=True) as w: + # Cause all warnings to always be triggered. + warnings.simplefilter("always") + + with tempfile.TemporaryDirectory() as tmpdirname: + tmpfile = os.path.join(tmpdirname, 'yamlfile') + with open(tmpfile, 'w') as tf: + tf.write("") + yaml_file_to_xml(tmpfile) + + assert issubclass(w[-1].category, DeprecationWarning) + assert "This function is deprecated" in str(w[-1].message)