diff --git a/README.md b/README.md index 3bb6c82a..57f7cf41 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ pip install odml ## Tutorial and examples - We have assembled a set of - [tutorials](http://github.com/G-Node/python-odml/blob/master/doc/tutorial.rst "Python Tutorial"). + [tutorials](https://python-odml.readthedocs.io/en/latest/tutorial.html "Python Tutorial"). ## Python convenience scripts diff --git a/odml/__init__.py b/odml/__init__.py index bba3d1b7..6d35f2db 100644 --- a/odml/__init__.py +++ b/odml/__init__.py @@ -12,9 +12,29 @@ from .info import VERSION from .tools.parser_utils import SUPPORTED_PARSERS as PARSERS -if _python_version.major < 3 or _python_version.major == 3 and _python_version.minor < 6: + +def _format_warning(warn_msg, *args, **kwargs): + """ + Used to provide users with deprecation warnings via the warnings module + but without spamming them with full stack traces. + """ + final_msg = "%s\n" % str(warn_msg) + # If available add category name to the message + if args and hasattr(args[0], "__name__"): + final_msg = "%s: %s" % (args[0].__name__, final_msg) + + return final_msg + + +# Monkey patch formatting 'warnings' messages for the whole module. +warnings.formatwarning = _format_warning + +if _python_version.major < 3: + msg = "Python 2 has been deprecated.\n\todML support for Python 2 will be dropped August 2020." + warnings.warn(msg, category=DeprecationWarning, stacklevel=2) +elif _python_version.major == 3 and _python_version.minor < 6: msg = "The '%s' package is not tested with your Python version. " % __name__ - msg += "Please consider upgrading to the latest Python distribution." + msg += "\n\tPlease consider upgrading to the latest Python distribution." warnings.warn(msg) __version__ = VERSION diff --git a/odml/property.py b/odml/property.py index 7ed6f740..54d267fa 100644 --- a/odml/property.py +++ b/odml/property.py @@ -3,6 +3,7 @@ This module provides the Base Property class. """ import uuid +import warnings from . import base from . import dtypes @@ -12,6 +13,10 @@ from .util import format_cardinality +MSG_VALUE_DEPRECATION = "The attribute 'value' is deprecated and will be removed, " \ + "use 'values' instead." + + def odml_tuple_import(t_count, new_value): """ Checks via a heuristic if the values in a string fit the general @@ -131,6 +136,8 @@ def __init__(self, name=None, values=None, parent=None, unit=None, self._values = [] self.values = values if not values and (value or isinstance(value, (bool, int))): + # Using stacklevel=2 to avoid file name and code line in the message output. + warnings.warn(MSG_VALUE_DEPRECATION, category=DeprecationWarning, stacklevel=2) self.values = value self.parent = parent @@ -285,7 +292,9 @@ def value(self): """ Deprecated alias of 'values'. Will be removed with the next minor release. """ - print("The attribute 'value' is deprecated. Please use 'values' instead.") + # Using stacklevel=2 to avoid file name and code line in the message output. + warnings.warn(MSG_VALUE_DEPRECATION, category=DeprecationWarning, stacklevel=2) + return self.values @value.setter @@ -295,7 +304,8 @@ def value(self, new_value): :param new_value: a single value or list of values. """ - print("The attribute 'value' is deprecated. Please use 'values' instead.") + # Using stacklevel=2 to avoid file name and code line in the message output. + warnings.warn(MSG_VALUE_DEPRECATION, category=DeprecationWarning, stacklevel=2) self.values = new_value def value_str(self, index=0): diff --git a/odml/section.py b/odml/section.py index db431adb..536a56ef 100644 --- a/odml/section.py +++ b/odml/section.py @@ -3,6 +3,7 @@ This module provides the Base Section class. """ import uuid +import warnings try: from collections.abc import Iterable @@ -774,21 +775,32 @@ def reorder(self, new_index): return self._reorder(self.parent.sections, new_index) - def create_property(self, name, value=None, dtype=None, oid=None): + def create_property(self, name, values=None, dtype=None, oid=None, value=None): """ Create a new property that is a child of this section. :param name: The name of the property. - :param value: Some data value, it can be a single value or - a list of homogeneous values. + :param values: Some data value, it can be a single value or + a list of homogeneous values. :param dtype: The data type of the values stored in the property, if dtype is not given, the type is deduced from the values. Check odml.DType for supported data types. :param oid: object id, UUID string as specified in RFC 4122. If no id is provided, an id will be generated and assigned. + :param value: Deprecated alias of 'values'. Any content of 'value' is ignored, + if 'values' is set. + :return: The new property. """ - prop = BaseProperty(name=name, value=value, dtype=dtype, oid=oid) + if value and values: + print("Warning: Both 'values' and 'value' were set; ignoring 'value'.") + + if not values and (value or isinstance(value, (bool, int))): + msg = "The attribute 'value' is deprecated and will be removed, use 'values' instead." + warnings.warn(msg, category=DeprecationWarning, stacklevel=2) + values = value + + prop = BaseProperty(name=name, values=values, dtype=dtype, oid=oid) prop.parent = self return prop diff --git a/odml/tools/converters/version_converter.py b/odml/tools/converters/version_converter.py index bd05da39..1f4527a5 100644 --- a/odml/tools/converters/version_converter.py +++ b/odml/tools/converters/version_converter.py @@ -13,6 +13,7 @@ from lxml import etree as ET from ..parser_utils import ParserException +from ..xmlparser import XML_HEADER from ...format import Document, Section, Property from ...info import FORMAT_VERSION @@ -531,5 +532,5 @@ def write_to_file(self, filename, backend="XML"): if data and "\n') + file.write("%s\n" % XML_HEADER) file.write(data) diff --git a/odml/tools/version_converter.py b/odml/tools/version_converter.py index 91f82730..50e32b14 100644 --- a/odml/tools/version_converter.py +++ b/odml/tools/version_converter.py @@ -2,9 +2,11 @@ This module provides backwards compatibility for the VersionConverter class. It is deprecated and will be removed in future versions. """ +import warnings from .converters import VersionConverter -print("[DEPRECATION WARNING] The VersionConverter file has been moved to " - "'odml.tools.converters' and will be removed from 'odml.tools' in future " - "odML releases. Please update the imports in your code accordingly.") +_MSG = "The VersionConverter file has been moved to "\ + "'odml.tools.converters' and will be removed from 'odml.tools' in future "\ + "odML releases. Please update the imports in your code accordingly." +warnings.warn(_MSG, category=DeprecationWarning, stacklevel=2) diff --git a/test/test_doc.py b/test/test_doc.py index 6091687e..dc5de56c 100644 --- a/test/test_doc.py +++ b/test/test_doc.py @@ -2,6 +2,8 @@ import os import unittest +from glob import glob + try: from urllib.request import pathname2url except ImportError: @@ -10,11 +12,23 @@ from odml import Document, Section, Property from odml.doc import BaseDocument from odml.dtypes import FORMAT_DATE +from .util import ODML_CACHE_DIR as CACHE_DIR, TEST_RESOURCES_DIR as RES_DIR class TestSection(unittest.TestCase): def setUp(self): - pass + self.local_repo_file = "local_repository_file_v1.1.xml" + + def tearDown(self): + """ + Remove all files loaded to the terminology cache directory + to avoid test cross pollution. + """ + temp_file_glob = "*%s" % self.local_repo_file + find_us = os.path.join(CACHE_DIR, temp_file_glob) + + for file_path in glob(find_us): + os.remove(file_path) def test_simple_attributes(self): author = "HPL" @@ -95,8 +109,7 @@ def test_date(self): doc.date = "some format" def test_get_terminology_equivalent(self): - dir_path = os.path.dirname(os.path.realpath(__file__)) - repo_file = os.path.join(dir_path, "resources", "local_repository_file_v1.1.xml") + repo_file = os.path.join(RES_DIR, self.local_repo_file) local_url = "file://%s" % pathname2url(repo_file) doc = Document(repository=local_url) diff --git a/test/test_doc_integration.py b/test/test_doc_integration.py index 4b415f07..02ff1d3e 100644 --- a/test/test_doc_integration.py +++ b/test/test_doc_integration.py @@ -5,17 +5,17 @@ import os import shutil -import tempfile import unittest import odml +from .util import create_test_dir class TestDocumentIntegration(unittest.TestCase): def setUp(self): # Set up test environment - self.tmp_dir = tempfile.mkdtemp(suffix=".odml") + self.tmp_dir = create_test_dir(__file__) self.json_file = os.path.join(self.tmp_dir, "test.json") self.xml_file = os.path.join(self.tmp_dir, "test.xml") @@ -26,7 +26,7 @@ def setUp(self): self.doc = doc def tearDown(self): - if os.path.exists(self.tmp_dir): + if self.tmp_dir and os.path.exists(self.tmp_dir): shutil.rmtree(self.tmp_dir) def save_load(self): diff --git a/test/test_dtypes_integration.py b/test/test_dtypes_integration.py index 2b1ab50d..89b01b40 100644 --- a/test/test_dtypes_integration.py +++ b/test/test_dtypes_integration.py @@ -7,17 +7,17 @@ import datetime as dt import os import shutil -import tempfile import unittest import odml +from .util import create_test_dir class TestTypesIntegration(unittest.TestCase): def setUp(self): # Set up test environment - self.tmp_dir = tempfile.mkdtemp(suffix=".odml") + self.tmp_dir = create_test_dir(__file__) self.json_file = os.path.join(self.tmp_dir, "test.json") self.xml_file = os.path.join(self.tmp_dir, "test.xml") @@ -29,7 +29,7 @@ def setUp(self): self.doc = doc def tearDown(self): - if os.path.exists(self.tmp_dir): + if self.tmp_dir and os.path.exists(self.tmp_dir): shutil.rmtree(self.tmp_dir) def test_time(self): diff --git a/test/test_fileio.py b/test/test_fileio.py index 47c6e716..5f2ff54a 100644 --- a/test/test_fileio.py +++ b/test/test_fileio.py @@ -1,19 +1,21 @@ -import unittest -import sys import os -import odml +import sys +import unittest try: from StringIO import StringIO except ImportError: from io import StringIO +import odml + +from .util import TEST_RESOURCES_DIR as RES_DIR + class TestTypes(unittest.TestCase): def setUp(self): - self.dir_path = os.path.dirname(os.path.realpath(__file__)) - self.file = os.path.join(self.dir_path, 'resources', 'example.odml') + self.file = os.path.join(RES_DIR, "example.odml") # Do not allow anything to be printed on STDOUT self.captured_stdout = StringIO() sys.stdout = self.captured_stdout @@ -21,8 +23,9 @@ def setUp(self): def test_load_save(self): doc = odml.load(self.file) self.assertTrue(isinstance(doc, odml.doc.BaseDocument)) - odml.save(doc, self.file + '_copy') - os.remove(self.file + '_copy') + file_name = "%s_copy" % self.file + odml.save(doc, file_name) + os.remove(file_name) def test_display(self): doc = odml.load(self.file) @@ -30,11 +33,12 @@ def test_display(self): def test_invalid_parser(self): with self.assertRaises(NotImplementedError): - odml.load(self.file, 'html') + odml.load(self.file, "html") doc = odml.load(self.file) with self.assertRaises(NotImplementedError): - odml.save(doc, self.file + '_copy_html', 'html') + file_name = "%s_copy_html" % self.file + odml.save(doc, file_name, "html") with self.assertRaises(NotImplementedError): - odml.display(doc, 'html') + odml.display(doc, "html") diff --git a/test/test_format_converter.py b/test/test_format_converter.py index a89f34e4..be244035 100644 --- a/test/test_format_converter.py +++ b/test/test_format_converter.py @@ -1,9 +1,12 @@ import os +import shutil import tempfile import unittest + from contextlib import contextmanager from odml.tools.converters import FormatConverter +from .util import create_test_dir FC = FormatConverter @@ -20,6 +23,11 @@ def setUp(self): """ + self.tmp_dir = None + + def tearDown(self): + if self.tmp_dir and os.path.exists(self.tmp_dir): + shutil.rmtree(self.tmp_dir) @contextmanager def assertNotRaises(self, exc_type): @@ -28,6 +36,13 @@ def assertNotRaises(self, exc_type): except exc_type: raise self.failureException('{} raised'.format(exc_type.__name__)) + def _create_open_file(self, in_dir): + in_file = tempfile.NamedTemporaryFile(mode='a+', suffix=".xml", dir=in_dir) + in_file.write(self.doc) + in_file.seek(0) + + return in_file + def test_convert(self): if os.name == 'nt': raise unittest.SkipTest("Skipping test on Windows") @@ -50,10 +65,10 @@ def test_convert_dir_no_output_dir(self, recursive=False, func=None): if os.name == 'nt': raise unittest.SkipTest("Skipping test on Windows") - work_dir = tempfile.mkdtemp() - in_dir = tempfile.mkdtemp(dir=work_dir) - in_file = self.create_open_file(in_dir) - in_file2 = self.create_open_file(in_dir) + self.tmp_dir = create_test_dir(__file__) + in_dir = tempfile.mkdtemp(dir=self.tmp_dir) + in_file = self._create_open_file(in_dir) + in_file2 = self._create_open_file(in_dir) if not func: FC.convert_dir(in_dir, None, recursive, "odml") @@ -64,7 +79,7 @@ def test_convert_dir_no_output_dir(self, recursive=False, func=None): func([in_dir, "odml"]) files = [] - for dir_path, dir_names, file_names in os.walk(work_dir): + for dir_path, dir_names, file_names in os.walk(self.tmp_dir): for file_name in file_names: files.append(os.path.join(dir_path, file_name)) @@ -89,10 +104,11 @@ def test_convert_dir_with_output_dir_specified(self, func=None): raise unittest.SkipTest("Skipping test on Windows") # Testing FC.convert_dir(in_dir, out_dir, False, "odml") - in_dir = tempfile.mkdtemp() - out_dir = tempfile.mkdtemp() - in_file = self.create_open_file(in_dir) - in_file2 = self.create_open_file(in_dir) + self.tmp_dir = create_test_dir(__file__) + in_dir = tempfile.mkdtemp(dir=self.tmp_dir) + out_dir = tempfile.mkdtemp(dir=self.tmp_dir) + in_file = self._create_open_file(in_dir) + in_file2 = self._create_open_file(in_dir) if not func: FC.convert_dir(in_dir, out_dir, False, "odml") @@ -124,15 +140,10 @@ def test_convert_dir_with_output_dir_specified(self, func=None): in_file.close() in_file2.close() - def create_open_file(self, in_dir): - in_file = tempfile.NamedTemporaryFile(mode='a+', suffix=".xml", dir=in_dir) - in_file.write(self.doc) - in_file.seek(0) - return in_file - def test_check_io_directory(self): - out_dir = tempfile.mkdtemp() - in_dir = tempfile.mkdtemp() + self.tmp_dir = create_test_dir(__file__) + out_dir = tempfile.mkdtemp(dir=self.tmp_dir) + in_dir = tempfile.mkdtemp(dir=self.tmp_dir) with self.assertRaises(ValueError): FC._check_input_output_directory(None, None) with self.assertRaises(ValueError): diff --git a/test/test_links.py b/test/test_links.py index 64beeea0..b9a2d44d 100644 --- a/test/test_links.py +++ b/test/test_links.py @@ -1,4 +1,5 @@ import unittest + from . import test_samplefile as samplefile diff --git a/test/test_parser_json.py b/test/test_parser_json.py index 00494c8a..b3b0260b 100644 --- a/test/test_parser_json.py +++ b/test/test_parser_json.py @@ -5,11 +5,12 @@ import json import os -import tempfile +import shutil import unittest from odml.tools import dict_parser from odml.tools.parser_utils import ParserException, InvalidVersionException +from .util import create_test_dir, TEST_RESOURCES_DIR as RES_DIR _INVALID_ATTRIBUTE_HANDLING_DOC = """ @@ -109,21 +110,13 @@ class TestJSONParser(unittest.TestCase): def setUp(self): - dir_path = os.path.dirname(os.path.realpath(__file__)) - self.basepath = os.path.join(dir_path, "resources") - + self.base_path = RES_DIR self.json_reader = dict_parser.DictReader(show_warnings=False) + self.tmp_dir_path = create_test_dir(__file__) - dir_name = os.path.basename(os.path.splitext(__file__)[0]) - tmp_base_path = os.path.join(tempfile.gettempdir(), "odml_test") - if not os.path.exists(tmp_base_path): - os.mkdir(tmp_base_path) - - tmp_dir_path = os.path.join(tmp_base_path, dir_name) - if not os.path.exists(tmp_dir_path): - os.mkdir(tmp_dir_path) - - self.tmp_dir_path = tmp_dir_path + def tearDown(self): + if self.tmp_dir_path and os.path.exists(self.tmp_dir_path): + shutil.rmtree(self.tmp_dir_path) def _prepare_doc(self, file_name, file_content): file_path = os.path.join(self.tmp_dir_path, file_name) @@ -140,7 +133,7 @@ def test_missing_root(self): filename = "missing_root.json" message = "Missing root element" - with open(os.path.join(self.basepath, filename)) as json_data: + with open(os.path.join(self.base_path, filename)) as json_data: parsed_doc = json.load(json_data) with self.assertRaises(ParserException) as exc: @@ -152,7 +145,7 @@ def test_missing_version(self): filename = "missing_version.json" message = "Could not find odml-version" - with open(os.path.join(self.basepath, filename)) as json_data: + with open(os.path.join(self.base_path, filename)) as json_data: parsed_doc = json.load(json_data) with self.assertRaises(ParserException) as exc: @@ -163,7 +156,7 @@ def test_missing_version(self): def test_invalid_version(self): filename = "invalid_version.json" - with open(os.path.join(self.basepath, filename)) as json_data: + with open(os.path.join(self.base_path, filename)) as json_data: parsed_doc = json.load(json_data) with self.assertRaises(InvalidVersionException): diff --git a/test/test_parser_odml.py b/test/test_parser_odml.py index 67cedf43..ba233109 100644 --- a/test/test_parser_odml.py +++ b/test/test_parser_odml.py @@ -5,21 +5,19 @@ import os import shutil -import tempfile import unittest from odml import Document, Section, Property from odml.tools import odmlparser +from .util import create_test_dir, TEST_RESOURCES_DIR as RES_DIR class TestOdmlParser(unittest.TestCase): def setUp(self): # Set up test environment - dir_path = os.path.dirname(os.path.realpath(__file__)) - self.basefile = os.path.join(dir_path, "resources", "example.odml") - - self.tmp_dir = tempfile.mkdtemp(suffix=".odml") + base_file = os.path.join(RES_DIR, "example.odml") + self.tmp_dir = create_test_dir(__file__) self.json_file = os.path.join(self.tmp_dir, "test.json") self.xml_file = os.path.join(self.tmp_dir, "test.xml") @@ -36,10 +34,10 @@ def setUp(self): self.json_writer = odmlparser.ODMLWriter(parser='JSON') self.rdf_writer = odmlparser.ODMLWriter(parser='RDF') - self.odml_doc = self.xml_reader.from_file(self.basefile) + self.odml_doc = self.xml_reader.from_file(base_file) def tearDown(self): - if os.path.exists(self.tmp_dir): + if self.tmp_dir and os.path.exists(self.tmp_dir): shutil.rmtree(self.tmp_dir) def test_json_yaml_xml(self): diff --git a/test/test_parser_xml.py b/test/test_parser_xml.py index a83ac349..51d38d74 100644 --- a/test/test_parser_xml.py +++ b/test/test_parser_xml.py @@ -3,13 +3,13 @@ from odml.tools import xmlparser from odml.tools.parser_utils import ParserException, InvalidVersionException +from .util import TEST_RESOURCES_DIR as RES_DIR class TestXMLParser(unittest.TestCase): def setUp(self): - dir_path = os.path.dirname(os.path.realpath(__file__)) - self.basepath = os.path.join(dir_path, "resources") + self.base_path = RES_DIR self.xml_reader = xmlparser.XMLReader() self.xml_reader_ignore = xmlparser.XMLReader(ignore_errors=True) @@ -19,7 +19,7 @@ def test_invalid_root(self): message = "Expecting " with self.assertRaises(ParserException) as exc: - _ = self.xml_reader.from_file(os.path.join(self.basepath, filename)) + _ = self.xml_reader.from_file(os.path.join(self.base_path, filename)) self.assertIn(message, str(exc.exception)) @@ -28,7 +28,7 @@ def test_missing_version(self): message = "Could not find format version attribute" with self.assertRaises(ParserException) as exc: - _ = self.xml_reader.from_file(os.path.join(self.basepath, filename)) + _ = self.xml_reader.from_file(os.path.join(self.base_path, filename)) self.assertIn(message, str(exc.exception)) @@ -36,13 +36,13 @@ def test_invalid_version(self): filename = "invalid_version.xml" with self.assertRaises(InvalidVersionException): - _ = self.xml_reader.from_file(os.path.join(self.basepath, filename)) + _ = self.xml_reader.from_file(os.path.join(self.base_path, filename)) def test_ignore_errors(self): filename = "ignore_errors.xml" with self.assertRaises(ParserException): - _ = self.xml_reader.from_file(os.path.join(self.basepath, filename)) + _ = self.xml_reader.from_file(os.path.join(self.base_path, filename)) - doc = self.xml_reader_ignore.from_file(os.path.join(self.basepath, filename)) + doc = self.xml_reader_ignore.from_file(os.path.join(self.base_path, filename)) doc.pprint() diff --git a/test/test_parser_yaml.py b/test/test_parser_yaml.py index 09ccab25..631f70ea 100644 --- a/test/test_parser_yaml.py +++ b/test/test_parser_yaml.py @@ -4,12 +4,13 @@ """ import os -import tempfile +import shutil import unittest import yaml from odml.tools import dict_parser from odml.tools.parser_utils import ParserException, InvalidVersionException +from .util import create_test_dir, TEST_RESOURCES_DIR as RES_DIR _INVALID_ATTRIBUTE_HANDLING_DOC = """ @@ -69,21 +70,13 @@ class TestYAMLParser(unittest.TestCase): def setUp(self): - dir_path = os.path.dirname(os.path.realpath(__file__)) - self.basepath = os.path.join(dir_path, "resources") - + self.base_path = RES_DIR self.yaml_reader = dict_parser.DictReader(show_warnings=False) + self.tmp_dir_path = create_test_dir(__file__) - dir_name = os.path.basename(os.path.splitext(__file__)[0]) - tmp_base_path = os.path.join(tempfile.gettempdir(), "odml_test") - if not os.path.exists(tmp_base_path): - os.mkdir(tmp_base_path) - - tmp_dir_path = os.path.join(tmp_base_path, dir_name) - if not os.path.exists(tmp_dir_path): - os.mkdir(tmp_dir_path) - - self.tmp_dir_path = tmp_dir_path + def tearDown(self): + if self.tmp_dir_path and os.path.exists(self.tmp_dir_path): + shutil.rmtree(self.tmp_dir_path) def _prepare_doc(self, file_name, file_content): file_path = os.path.join(self.tmp_dir_path, file_name) @@ -100,7 +93,7 @@ def test_missing_root(self): filename = "missing_root.yaml" message = "Missing root element" - with open(os.path.join(self.basepath, filename)) as raw_data: + with open(os.path.join(self.base_path, filename)) as raw_data: parsed_doc = yaml.safe_load(raw_data) with self.assertRaises(ParserException) as exc: @@ -112,7 +105,7 @@ def test_missing_version(self): filename = "missing_version.yaml" message = "Could not find odml-version" - with open(os.path.join(self.basepath, filename)) as raw_data: + with open(os.path.join(self.base_path, filename)) as raw_data: parsed_doc = yaml.safe_load(raw_data) with self.assertRaises(ParserException) as exc: @@ -123,7 +116,7 @@ def test_missing_version(self): def test_invalid_version(self): filename = "invalid_version.yaml" - with open(os.path.join(self.basepath, filename)) as raw_data: + with open(os.path.join(self.base_path, filename)) as raw_data: parsed_doc = yaml.safe_load(raw_data) with self.assertRaises(InvalidVersionException): diff --git a/test/test_property_integration.py b/test/test_property_integration.py index 985b454a..85a54ad8 100644 --- a/test/test_property_integration.py +++ b/test/test_property_integration.py @@ -5,17 +5,18 @@ import os import shutil -import tempfile import unittest import odml +from .util import create_test_dir + class TestPropertyIntegration(unittest.TestCase): def setUp(self): # Set up test environment - self.tmp_dir = tempfile.mkdtemp(suffix=".odml") + self.tmp_dir = create_test_dir(__file__) self.json_file = os.path.join(self.tmp_dir, "test.json") self.xml_file = os.path.join(self.tmp_dir, "test.xml") @@ -27,7 +28,7 @@ def setUp(self): self.doc = doc def tearDown(self): - if os.path.exists(self.tmp_dir): + if self.tmp_dir and os.path.exists(self.tmp_dir): shutil.rmtree(self.tmp_dir) def save_load(self): diff --git a/test/test_samplefile.py b/test/test_samplefile.py index 7fb07313..dd1644d5 100644 --- a/test/test_samplefile.py +++ b/test/test_samplefile.py @@ -1,7 +1,6 @@ import os import re import sys -import tempfile import unittest try: @@ -13,6 +12,7 @@ from odml.info import FORMAT_VERSION from odml.tools import xmlparser +from .util import create_test_dir try: unicode = unicode @@ -162,7 +162,7 @@ def test_xml_writer_version(self): # self.assertEqual(doc._xml_version, FORMAT_VERSION) def test_save(self): - base_path = tempfile.gettempdir() + base_path = create_test_dir(__file__) for module in [xmlparser.XMLWriter]: path = os.path.join(base_path, "temp.odml") doc = module(self.doc) @@ -369,7 +369,8 @@ def test_get_property_by_path(self): self.assertRaises(ValueError, sec1.get_property_by_path, wrong_path) def test_save_version(self): - tmp_file = os.path.join(tempfile.gettempdir(), "example.odml") + tmp_dir = create_test_dir(__file__) + tmp_file = os.path.join(tmp_dir, "example.odml") self.doc.version = '2.4' writer = xmlparser.XMLWriter(self.doc) diff --git a/test/test_section_integration.py b/test/test_section_integration.py index 9f79d920..4f8374d5 100644 --- a/test/test_section_integration.py +++ b/test/test_section_integration.py @@ -5,17 +5,18 @@ import os import shutil -import tempfile import unittest import odml +from .util import create_test_dir + class TestSectionIntegration(unittest.TestCase): def setUp(self): # Set up test environment - self.tmp_dir = tempfile.mkdtemp(suffix=".odml") + self.tmp_dir = create_test_dir(__file__) self.json_file = os.path.join(self.tmp_dir, "test.json") self.xml_file = os.path.join(self.tmp_dir, "test.xml") @@ -26,7 +27,7 @@ def setUp(self): self.doc = doc def tearDown(self): - if os.path.exists(self.tmp_dir): + if self.tmp_dir and os.path.exists(self.tmp_dir): shutil.rmtree(self.tmp_dir) def save_load(self): diff --git a/test/test_terminology.py b/test/test_terminology.py index 8ff55ae8..9c03deb9 100644 --- a/test/test_terminology.py +++ b/test/test_terminology.py @@ -3,7 +3,6 @@ """ import os -import tempfile import unittest from glob import glob @@ -15,8 +14,7 @@ from urllib import pathname2url from odml import Document, save, Section, terminology - -CACHE_DIR = os.path.join(tempfile.gettempdir(), "odml.cache") +from .util import ODML_CACHE_DIR as CACHE_DIR, create_test_dir class TestTerminology(unittest.TestCase): @@ -25,7 +23,7 @@ def setUp(self): """ Set up local temporary terminology files in a temporary folder """ - tmp_dir = tempfile.mkdtemp("_odml") + tmp_dir = create_test_dir(__file__) tmp_name = os.path.basename(tmp_dir) main_name = "%s_main.xml" % tmp_name diff --git a/test/test_validation.py b/test/test_validation.py index b58f13a1..d5aded91 100644 --- a/test/test_validation.py +++ b/test/test_validation.py @@ -6,6 +6,7 @@ import odml.validation import odml.terminology from . import test_samplefile as samplefile +from .util import TEST_RESOURCES_DIR as RES_DIR try: from StringIO import StringIO @@ -19,7 +20,6 @@ class TestValidation(unittest.TestCase): def setUp(self): self.doc = samplefile.SampleFileCreator().create_document() - self.dir_path = os.path.dirname(os.path.realpath(__file__)) @staticmethod def filter_repository_errors(errors): @@ -405,7 +405,7 @@ def test_load_section_xml(self): Test if loading xml document raises validation errors for Sections with undefined type. """ - path = os.path.join(self.dir_path, "resources", "validation_section.xml") + path = os.path.join(RES_DIR, "validation_section.xml") doc = odml.load(path) self.load_section_validation(doc) @@ -415,7 +415,7 @@ def test_load_section_json(self): Test if loading json document raises validation errors for Sections with undefined type. """ - path = os.path.join(self.dir_path, "resources", "validation_section.json") + path = os.path.join(RES_DIR, "validation_section.json") doc = odml.load(path, "JSON") self.load_section_validation(doc) @@ -425,7 +425,7 @@ def test_load_section_yaml(self): Test if loading yaml document raises validation errors for Sections with undefined type. """ - path = os.path.join(self.dir_path, "resources", "validation_section.yaml") + path = os.path.join(RES_DIR, "validation_section.yaml") doc = odml.load(path, "YAML") self.load_section_validation(doc) @@ -459,7 +459,7 @@ def test_load_dtypes_xml(self): for Properties with undefined dtypes. """ - path = os.path.join(self.dir_path, "resources", "validation_dtypes.xml") + path = os.path.join(RES_DIR, "validation_dtypes.xml") doc = odml.load(path) self.load_dtypes_validation(doc) @@ -469,7 +469,7 @@ def test_load_dtypes_json(self): for Properties with undefined dtypes. """ - path = os.path.join(self.dir_path, "resources", "validation_dtypes.json") + path = os.path.join(RES_DIR, "validation_dtypes.json") doc = odml.load(path, "JSON") self.load_dtypes_validation(doc) @@ -479,6 +479,6 @@ def test_load_dtypes_yaml(self): for Properties with undefined dtypes. """ - path = os.path.join(self.dir_path, "resources", "validation_dtypes.yaml") + path = os.path.join(RES_DIR, "validation_dtypes.yaml") doc = odml.load(path, "YAML") self.load_dtypes_validation(doc) diff --git a/test/test_version_converter.py b/test/test_version_converter.py index 43887c4a..f6b5e294 100644 --- a/test/test_version_converter.py +++ b/test/test_version_converter.py @@ -1,14 +1,15 @@ import io import os import shutil -import tempfile import unittest from contextlib import contextmanager +from glob import glob from lxml import etree as ET from odml.terminology import REPOSITORY_BASE from odml.tools.converters import VersionConverter +from .util import ODML_CACHE_DIR as CACHE_DIR, create_test_dir, TEST_RESOURCES_DIR as RES_DIR try: unicode = unicode @@ -18,8 +19,7 @@ class TestVersionConverter(unittest.TestCase): def setUp(self): - dir_path = os.path.dirname(os.path.realpath(__file__)) - self.basepath = os.path.join(dir_path, "resources") + self.base_path = RES_DIR self.VC = VersionConverter @@ -52,9 +52,16 @@ def setUp(self): self.tmp_dir = None def tearDown(self): + """ + Cleanup any created temporary files. + """ if self.tmp_dir and os.path.exists(self.tmp_dir): shutil.rmtree(self.tmp_dir) + find_us = os.path.join(CACHE_DIR, "*local_repository_file_v1*") + for file_path in glob(find_us): + os.remove(file_path) + @contextmanager def assertNotRaises(self, exc_type): try: @@ -139,12 +146,10 @@ def test_convert_odml_file_document(self): The test checks for the proper conversion of all valid Document tags and exclusion of non-Document tags. """ - - dir_path = os.path.dirname(os.path.realpath(__file__)) - repo_file = os.path.join(dir_path, "resources", "local_repository_file_v1.1.xml") + repo_file = os.path.join(RES_DIR, "local_repository_file_v1.1.xml") local_url = "file://%s" % repo_file - repo_old_file = os.path.join(dir_path, "resources", "local_repository_file_v1.0.xml") + repo_old_file = os.path.join(RES_DIR, "local_repository_file_v1.0.xml") local_old_url = "file://%s" % repo_old_file doc = """ @@ -215,12 +220,10 @@ def test_convert_odml_file_section(self): The test checks for the proper conversion of all valid Section tags and exclusion of non-Section tags. """ - - dir_path = os.path.dirname(os.path.realpath(__file__)) - repo_file = os.path.join(dir_path, "resources", "local_repository_file_v1.1.xml") + repo_file = os.path.join(RES_DIR, "local_repository_file_v1.1.xml") local_url = "file://%s" % repo_file - repo_old_file = os.path.join(dir_path, "resources", "local_repository_file_v1.0.xml") + repo_old_file = os.path.join(RES_DIR, "local_repository_file_v1.0.xml") local_old_url = "file://%s" % repo_old_file doc = """ @@ -792,7 +795,7 @@ def test_handle_include(self): def test_convert_xml_file(self): # Test minimal reading from an xml file. - basefile = os.path.join(self.basepath, "version_conversion.xml") + basefile = os.path.join(self.base_path, "version_conversion.xml") root = self.VC(basefile)._parse_xml().getroot() self.assertIsNotNone(root.find("section")) @@ -809,7 +812,7 @@ def test_convert_xml_file(self): def test_convert_yaml_file(self): # Test minimal reading from a yaml file. - basefile = os.path.join(self.basepath, "version_conversion.yaml") + basefile = os.path.join(self.base_path, "version_conversion.yaml") root = self.VC(basefile)._parse_yaml().getroot() self.assertIsNotNone(root.find("section")) @@ -826,7 +829,7 @@ def test_convert_yaml_file(self): def test_convert_json_file(self): # Test minimal reading from a json file. - basefile = os.path.join(self.basepath, "version_conversion.json") + basefile = os.path.join(self.base_path, "version_conversion.json") root = self.VC(basefile)._parse_json().getroot() self.assertIsNotNone(root.find("section")) @@ -842,8 +845,8 @@ def test_convert_json_file(self): self.assertIsNotNone(prop.find("value")) def test_write_to_file(self): - infile = os.path.join(self.basepath, "version_conversion.xml") - self.tmp_dir = tempfile.mkdtemp(suffix=".odml") + infile = os.path.join(self.base_path, "version_conversion.xml") + self.tmp_dir = create_test_dir(__file__) # Test write to named file outfile = os.path.join(self.tmp_dir, "test.odml") diff --git a/test/test_version_converter_integration.py b/test/test_version_converter_integration.py index ebeac0f8..81ea7364 100644 --- a/test/test_version_converter_integration.py +++ b/test/test_version_converter_integration.py @@ -5,27 +5,25 @@ import os import shutil -import tempfile import unittest from odml import load from odml.tools.converters import VersionConverter as VC +from .util import create_test_dir, TEST_RESOURCES_DIR as RES_DIR class TestVersionConverterIntegration(unittest.TestCase): def setUp(self): # Set up test environment - dir_path = os.path.dirname(os.path.realpath(__file__)) + self.jsonfile = os.path.join(RES_DIR, "version_conversion_int.json") + self.xmlfile = os.path.join(RES_DIR, "version_conversion_int.xml") + self.yamlfile = os.path.join(RES_DIR, "version_conversion_int.yaml") - self.jsonfile = os.path.join(dir_path, "resources", "version_conversion_int.json") - self.xmlfile = os.path.join(dir_path, "resources", "version_conversion_int.xml") - self.yamlfile = os.path.join(dir_path, "resources", "version_conversion_int.yaml") - - self.tmp_dir = tempfile.mkdtemp(suffix=".odml") + self.tmp_dir = create_test_dir(__file__) self.outfile = os.path.join(self.tmp_dir, "version_conversion.xml") def tearDown(self): - if os.path.exists(self.tmp_dir): + if self.tmp_dir and os.path.exists(self.tmp_dir): shutil.rmtree(self.tmp_dir) def test_convert_xml(self): diff --git a/test/test_xml_writer.py b/test/test_xml_writer.py index c79136b0..579ae141 100644 --- a/test/test_xml_writer.py +++ b/test/test_xml_writer.py @@ -1,6 +1,5 @@ import os import shutil -import tempfile import unittest import odml @@ -8,16 +7,15 @@ from odml.tools.xmlparser import XML_HEADER, EXTERNAL_STYLE_HEADER, \ INFILE_STYLE_HEADER, INFILE_STYLE_TEMPLATE from odml.tools import XMLWriter +from .util import create_test_dir, TEST_RESOURCES_DIR as RES_DIR class TestXMLWriter(unittest.TestCase): def setUp(self): # Set up test environment - dir_path = os.path.dirname(os.path.realpath(__file__)) + self.xmlfile = os.path.join(RES_DIR, "version_conversion_int.xml") - self.xmlfile = os.path.join(dir_path, "resources", "version_conversion_int.xml") - - self.tmp_dir = tempfile.mkdtemp(suffix=".odml") + self.tmp_dir = create_test_dir(__file__) self.outfile = os.path.join(self.tmp_dir, "xml_writer.xml") doc = odml.Document() @@ -28,7 +26,7 @@ def setUp(self): self.writer = XMLWriter(doc) def tearDown(self): - if os.path.exists(self.tmp_dir): + if self.tmp_dir and os.path.exists(self.tmp_dir): shutil.rmtree(self.tmp_dir) def test_write_default(self): diff --git a/test/util.py b/test/util.py new file mode 100644 index 00000000..f3445a1f --- /dev/null +++ b/test/util.py @@ -0,0 +1,28 @@ +""" +Utilities for the odml test package. +""" +import os +import tempfile + +ODML_CACHE_DIR = os.path.join(tempfile.gettempdir(), "odml.cache") + +TEST_RESOURCES_DIR = os.path.join(os.path.dirname(os.path.realpath(__file__)), + "resources") + +TEST_TEMP_DIR = os.path.join(tempfile.gettempdir(), "odml_test") +if not os.path.exists(TEST_TEMP_DIR): + os.mkdir(TEST_TEMP_DIR) + + +def create_test_dir(script_name): + """ + Takes the name of a test script and creates a like-named directory + in the main test directory if it does not yet exist. + + :param script_name: String that will be used to create the test directory + + :return: Path to the test directory. + """ + dir_name = "_%s" % os.path.basename(os.path.splitext(script_name)[0]) + + return tempfile.mkdtemp(suffix=dir_name, dir=TEST_TEMP_DIR)