From 1e2bcfc7f22c05f3608aaa76ade9d8a8867563b9 Mon Sep 17 00:00:00 2001 From: George Schneeloch Date: Wed, 30 Mar 2016 14:49:33 -0400 Subject: [PATCH] Added support for Python 3 --- .coveragerc | 3 +- AUTHORS | 1 + Makefile | 2 +- opaque_keys/__init__.py | 37 +++++---- opaque_keys/edx/asides.py | 5 +- opaque_keys/edx/keys.py | 3 +- opaque_keys/edx/locator.py | 48 +++++------- opaque_keys/edx/tests/__init__.py | 4 +- opaque_keys/edx/tests/test_aside_keys.py | 39 +++++----- opaque_keys/edx/tests/test_asset_locators.py | 33 ++++---- opaque_keys/edx/tests/test_block_types.py | 10 +-- .../edx/tests/test_block_usage_locators.py | 63 ++++++++------- opaque_keys/edx/tests/test_course_locators.py | 28 +++---- .../edx/tests/test_deprecated_locations.py | 28 +++---- .../edx/tests/test_library_locators.py | 39 +++++----- .../edx/tests/test_library_usage_locators.py | 15 ++-- opaque_keys/edx/tests/test_locators.py | 6 +- opaque_keys/tests/test_opaque_keys.py | 76 ++++++++++--------- pytest.ini | 8 ++ setup.py | 1 + test-requirements.txt | 5 ++ tox.ini | 9 +++ 22 files changed, 249 insertions(+), 214 deletions(-) create mode 100644 pytest.ini create mode 100644 tox.ini diff --git a/.coveragerc b/.coveragerc index 8eec25ae..5b768ff6 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,3 +1,4 @@ [run] branch = True -source = ./opaque_keys \ No newline at end of file +source = ./opaque_keys +omit = ./.tox/* diff --git a/AUTHORS b/AUTHORS index 10e37d57..9ed9af44 100644 --- a/AUTHORS +++ b/AUTHORS @@ -8,3 +8,4 @@ David Baumgold Gabe Mulley Braden MacDonald Clinton Blackburn +George Schneeloch diff --git a/Makefile b/Makefile index b8a3c5bf..72147de5 100644 --- a/Makefile +++ b/Makefile @@ -13,4 +13,4 @@ requirements: pip install -r requirements.txt test: - coverage run -m nose + tox diff --git a/opaque_keys/__init__.py b/opaque_keys/__init__.py index acdaa504..a86b2b5c 100644 --- a/opaque_keys/__init__.py +++ b/opaque_keys/__init__.py @@ -10,6 +10,14 @@ from abc import ABCMeta, abstractmethod from functools import total_ordering +from six import ( + iteritems, + python_2_unicode_compatible, + text_type, + viewkeys, + viewitems, + with_metaclass, +) from stevedore.enabled import EnabledExtensionManager @@ -34,8 +42,9 @@ def __new__(mcs, name, bases, attrs): return super(OpaqueKeyMetaclass, mcs).__new__(mcs, name, bases, attrs) +@python_2_unicode_compatible @total_ordering -class OpaqueKey(object): +class OpaqueKey(with_metaclass(OpaqueKeyMetaclass)): """ A base-class for implementing pluggable opaque keys. Individual key subclasses identify particular types of resources, without specifying the actual form of the key (or @@ -89,7 +98,6 @@ class constructor will not validate any of the ``KEY_FIELDS`` arguments, and wil Serialization of an :class:`OpaqueKey` is performed by using the :func:`unicode` builtin. Deserialization is performed by the :meth:`from_string` method. """ - __metaclass__ = OpaqueKeyMetaclass __slots__ = ('_initialized', 'deprecated') KEY_FIELDS = [] @@ -156,7 +164,7 @@ def _to_deprecated_string(self): # ============= SERIALIZATION ============== - def __unicode__(self): + def __str__(self): """ Serialize this :class:`OpaqueKey`, in the form ``:``. """ @@ -265,13 +273,13 @@ def __init__(self, *args, **kwargs): # a flag used to indicate that this instance was deserialized from the # deprecated form and should serialize to the deprecated form - self.deprecated = kwargs.pop('deprecated', False) + self.deprecated = kwargs.pop('deprecated', False) # pylint: disable=assigning-non-slot if self.CHECKED_INIT: self._checked_init(*args, **kwargs) else: self._unchecked_init(**kwargs) - self._initialized = True + self._initialized = True # pylint: disable=assigning-non-slot def _checked_init(self, *args, **kwargs): """ @@ -285,13 +293,13 @@ def _checked_init(self, *args, **kwargs): )) keyed_args = dict(zip(self.KEY_FIELDS, args)) - overlapping_args = keyed_args.viewkeys() & kwargs.viewkeys() + overlapping_args = viewkeys(keyed_args) & viewkeys(kwargs) if overlapping_args: raise TypeError('__init__() got multiple values for keyword argument {!r}'.format(overlapping_args[0])) keyed_args.update(kwargs) - for key in keyed_args.viewkeys(): + for key in viewkeys(keyed_args): if key not in self.KEY_FIELDS: raise TypeError('__init__() got an unexpected argument {!r}'.format(key)) @@ -301,7 +309,7 @@ def _unchecked_init(self, **kwargs): """ Set all kwargs as attributes. """ - for key, value in kwargs.viewitems(): + for key, value in viewitems(kwargs): setattr(self, key, value) def replace(self, **kwargs): @@ -315,7 +323,7 @@ def replace(self, **kwargs): existing_values = {key: getattr(self, key) for key in self.KEY_FIELDS} # pylint: disable=no-member existing_values['deprecated'] = self.deprecated - if all(value == existing_values[key] for (key, value) in kwargs.iteritems()): + if all(value == existing_values[key] for (key, value) in iteritems(kwargs)): return self existing_values.update(kwargs) @@ -325,7 +333,7 @@ def __setattr__(self, name, value): if getattr(self, '_initialized', False): raise AttributeError("Can't set {!r}. OpaqueKeys are immutable.".format(name)) - super(OpaqueKey, self).__setattr__(name, value) + super(OpaqueKey, self).__setattr__(name, value) # pylint: disable=no-member def __delattr__(self, name): raise AttributeError("Can't delete {!r}. OpaqueKeys are immutable.".format(name)) @@ -348,8 +356,8 @@ def __setstate__(self, state_dict): for key in state_dict: if key in self.KEY_FIELDS: # pylint: disable=no-member setattr(self, key, state_dict[key]) - self.deprecated = state_dict['deprecated'] - self._initialized = True + self.deprecated = state_dict['deprecated'] # pylint: disable=assigning-non-slot + self._initialized = True # pylint: disable=assigning-non-slot def __getstate__(self): # used by pickle to get fields on an unpickled object @@ -380,9 +388,6 @@ def __lt__(self, other): def __hash__(self): return hash(self._key) - def __str__(self): - return unicode(self).encode('utf-8') - def __repr__(self): return '{}({})'.format( self.__class__.__name__, @@ -391,4 +396,4 @@ def __repr__(self): def __len__(self): """Return the number of characters in the serialized OpaqueKey""" - return len(unicode(self)) + return len(text_type(self)) diff --git a/opaque_keys/edx/asides.py b/opaque_keys/edx/asides.py index 59e1bf7f..1f2dcf23 100644 --- a/opaque_keys/edx/asides.py +++ b/opaque_keys/edx/asides.py @@ -12,6 +12,7 @@ store scoped data alongside the definition and usage of the particular XBlock usage that they're commenting on. """ +from six import text_type from opaque_keys.edx.keys import AsideDefinitionKey, AsideUsageKey, DefinitionKey, UsageKey @@ -90,7 +91,7 @@ def _to_string(self): This serialization should not include the namespace prefix. """ - return u'{}::{}'.format(_encode(unicode(self.definition_key)), _encode(unicode(self.aside_type))) + return u'{}::{}'.format(_encode(text_type(self.definition_key)), _encode(text_type(self.aside_type))) class AsideUsageKeyV1(AsideUsageKey): # pylint: disable=abstract-method @@ -179,4 +180,4 @@ def _to_string(self): This serialization should not include the namespace prefix. """ - return u'{}::{}'.format(_encode(unicode(self.usage_key)), _encode(unicode(self.aside_type))) + return u'{}::{}'.format(_encode(text_type(self.usage_key)), _encode(text_type(self.aside_type))) diff --git a/opaque_keys/edx/keys.py b/opaque_keys/edx/keys.py index 8de767e9..72e29684 100644 --- a/opaque_keys/edx/keys.py +++ b/opaque_keys/edx/keys.py @@ -4,6 +4,7 @@ """ import json from abc import abstractmethod, abstractproperty +from six import text_type from opaque_keys import OpaqueKey @@ -207,7 +208,7 @@ class i4xEncoder(json.JSONEncoder): # pylint: disable=invalid-name """ def default(self, key): # pylint: disable=method-hidden if isinstance(key, OpaqueKey): - return unicode(key) + return text_type(key) super(i4xEncoder, self).default(key) diff --git a/opaque_keys/edx/locator.py b/opaque_keys/edx/locator.py index f790bc75..80e0032c 100644 --- a/opaque_keys/edx/locator.py +++ b/opaque_keys/edx/locator.py @@ -9,6 +9,7 @@ import re import warnings from abc import abstractproperty +from six import string_types, text_type from bson.errors import InvalidId from bson.objectid import ObjectId @@ -45,12 +46,6 @@ class Locator(OpaqueKey): ALLOWED_ID_CHARS = r'[\w\-~.:]' DEPRECATED_ALLOWED_ID_CHARS = r'[\w\-~.:%]' - def __str__(self): - """ - str(self) returns something like this: "mit.eecs.6002x" - """ - return unicode(self).encode('utf-8') - @abstractproperty def version(self): # pragma: no cover """ @@ -159,9 +154,6 @@ class CourseLocator(BlockLocatorBase, CourseKey): # pylint: disable=abstract-m # Characters that are forbidden in the deprecated format INVALID_CHARS_DEPRECATED = re.compile(r"[^\w.%-]", re.UNICODE) - # stubs to fake out the abstractproperty class instrospection and allow treatment as attrs in instances - org = None - def __init__(self, org=None, course=None, run=None, branch=None, version_guid=None, deprecated=False, **kwargs): """ Construct a CourseLocator @@ -223,7 +215,7 @@ def __init__(self, org=None, course=None, run=None, branch=None, version_guid=No def _check_location_part(cls, val, regexp): # pylint: disable=missing-docstring if val is None: return - if not isinstance(val, basestring): + if not isinstance(val, string_types): raise InvalidKeyError(cls, "{!r} is not a string".format(val)) if regexp.search(val) is not None: raise InvalidKeyError(cls, "Invalid characters in {!r}.".format(val)) @@ -278,7 +270,7 @@ def html_id(self): place, but I have no way to override. We should clearly define the purpose and restrictions of this (e.g., I'm assuming periods are fine). """ - return unicode(self) + return text_type(self) def make_usage_key(self, block_type, block_id): return BlockUsageLocator( @@ -367,7 +359,7 @@ def to_deprecated_string(self): DeprecationWarning, stacklevel=2 ) - return unicode(self) + return text_type(self) @classmethod def _from_deprecated_string(cls, serialized): @@ -421,12 +413,6 @@ class LibraryLocator(BlockLocatorBase, CourseKey): __slots__ = KEY_FIELDS CHECKED_INIT = False - # declare our fields explicitly to avoid pylint warnings - org = None - library = None - branch = None - version_guid = None - def __init__(self, org=None, library=None, branch=None, version_guid=None, **kwargs): """ Construct a LibraryLocator @@ -472,7 +458,7 @@ def __init__(self, org=None, library=None, branch=None, version_guid=None, **kwa **kwargs ) - if self.version_guid is None and (self.org is None or self.library is None): + if self.version_guid is None and (self.org is None or self.library is None): # pylint: disable=no-member raise InvalidKeyError(self.__class__, "Either version_guid or org and library should be set") @property @@ -489,7 +475,7 @@ def course(self): Deprecated. Return a 'course' for compatibility with CourseLocator. """ warnings.warn("Accessing 'course' on a LibraryLocator is deprecated.", DeprecationWarning, stacklevel=2) - return self.library + return self.library # pylint: disable=no-member @property def version(self): @@ -502,7 +488,7 @@ def version(self): DeprecationWarning, stacklevel=2 ) - return self.version_guid + return self.version_guid # pylint: disable=no-member @classmethod def _from_string(cls, serialized): @@ -526,7 +512,7 @@ def html_id(self): """ Return an id which can be used on an html page as an id attr of an html element. """ - return unicode(self) + return text_type(self) def make_usage_key(self, block_type, block_id): return LibraryUsageLocator( @@ -579,12 +565,12 @@ def _to_string(self): Return a string representing this location. """ parts = [] - if self.library: + if self.library: # pylint: disable=no-member parts.extend([self.org, self.course]) - if self.branch: - parts.append(u"{prefix}@{branch}".format(prefix=self.BRANCH_PREFIX, branch=self.branch)) - if self.version_guid: - parts.append(u"{prefix}@{guid}".format(prefix=self.VERSION_PREFIX, guid=self.version_guid)) + if self.branch: # pylint: disable=no-member + parts.append(u"{prefix}@{branch}".format(prefix=self.BRANCH_PREFIX, branch=self.branch)) # pylint: disable=no-member + if self.version_guid: # pylint: disable=no-member + parts.append(u"{prefix}@{guid}".format(prefix=self.VERSION_PREFIX, guid=self.version_guid)) # pylint: disable=no-member return u"+".join(parts) def _to_deprecated_string(self): @@ -977,7 +963,7 @@ def to_deprecated_string(self): DeprecationWarning, stacklevel=2 ) - return unicode(self) + return text_type(self) @classmethod def _from_deprecated_string(cls, serialized): @@ -1176,7 +1162,7 @@ class DefinitionLocator(Locator, DefinitionKey): definition_id = None def __init__(self, block_type, definition_id, deprecated=False): # pylint: disable=unused-argument - if isinstance(definition_id, basestring): + if isinstance(definition_id, string_types): try: definition_id = self.as_object_id(definition_id) except ValueError: @@ -1188,7 +1174,7 @@ def _to_string(self): Return a string representing this location. unicode(self) returns something like this: "519665f6223ebd6980884f2b+type+problem" """ - return u"{}+{}@{}".format(unicode(self.definition_id), self.BLOCK_TYPE_PREFIX, self.block_type) + return u"{}+{}@{}".format(text_type(self.definition_id), self.BLOCK_TYPE_PREFIX, self.block_type) URL_RE = re.compile( r"^(?P[A-F0-9]+)\+{}@(?P{ALLOWED_ID_CHARS}+)$".format( @@ -1298,7 +1284,7 @@ def to_deprecated_string(self): DeprecationWarning, stacklevel=2 ) - return unicode(self) + return text_type(self) @property def tag(self): diff --git a/opaque_keys/edx/tests/__init__.py b/opaque_keys/edx/tests/__init__.py index b780775f..512b7076 100644 --- a/opaque_keys/edx/tests/__init__.py +++ b/opaque_keys/edx/tests/__init__.py @@ -26,8 +26,8 @@ def assertDeprecationWarning(self, count=1): """Asserts that the contained code raises `count` deprecation warnings""" with warnings.catch_warnings(record=True) as caught: yield - self.assertEquals(count, - len([warning for warning in caught if issubclass(warning.category, DeprecationWarning)])) + self.assertEqual(count, + len([warning for warning in caught if issubclass(warning.category, DeprecationWarning)])) class LocatorBaseTest(TestCase): diff --git a/opaque_keys/edx/tests/test_aside_keys.py b/opaque_keys/edx/tests/test_aside_keys.py index d26d8d5f..d836aafd 100644 --- a/opaque_keys/edx/tests/test_aside_keys.py +++ b/opaque_keys/edx/tests/test_aside_keys.py @@ -5,6 +5,7 @@ import itertools from unittest import TestCase +from six import text_type import ddt from opaque_keys.edx.asides import AsideUsageKeyV1, AsideDefinitionKeyV1, _encode, _decode @@ -27,7 +28,7 @@ def test_encode_roundtrip(self, data): """ encoded = _encode(data) decoded = _decode(encoded) - self.assertEquals(data, decoded) + self.assertEqual(data, decoded) @ddt.ddt @@ -40,13 +41,13 @@ class TestAsideKeys(TestCase): @ddt.unpack def test_usage_round_trip_deserialized(self, usage_key, aside_type): key = AsideUsageKeyV1(usage_key, aside_type) - serialized = unicode(key) + serialized = text_type(key) deserialized = AsideUsageKey.from_string(serialized) - self.assertEquals(key, deserialized) - self.assertEquals(usage_key, key.usage_key, usage_key) - self.assertEquals(usage_key, deserialized.usage_key) - self.assertEquals(aside_type, key.aside_type) - self.assertEquals(aside_type, deserialized.aside_type) + self.assertEqual(key, deserialized) + self.assertEqual(usage_key, key.usage_key, usage_key) + self.assertEqual(usage_key, deserialized.usage_key) + self.assertEqual(aside_type, key.aside_type) + self.assertEqual(aside_type, deserialized.aside_type) @ddt.data( 'aside-usage-v1:i4x://org/course/cat/name::aside', @@ -54,8 +55,8 @@ def test_usage_round_trip_deserialized(self, usage_key, aside_type): ) def test_usage_round_trip_serialized(self, aside_key): deserialized = AsideUsageKey.from_string(aside_key) - serialized = unicode(deserialized) - self.assertEquals(aside_key, serialized) + serialized = text_type(deserialized) + self.assertEqual(aside_key, serialized) @ddt.data( (DefinitionLocator('block_type', 'abcd1234abcd1234abcd1234'), 'aside'), @@ -63,21 +64,21 @@ def test_usage_round_trip_serialized(self, aside_key): @ddt.unpack def test_definition_round_trip_deserialized(self, definition_key, aside_type): key = AsideDefinitionKeyV1(definition_key, aside_type) - serialized = unicode(key) + serialized = text_type(key) deserialized = AsideDefinitionKey.from_string(serialized) - self.assertEquals(key, deserialized) - self.assertEquals(definition_key, key.definition_key, definition_key) - self.assertEquals(definition_key, deserialized.definition_key) - self.assertEquals(aside_type, key.aside_type) - self.assertEquals(aside_type, deserialized.aside_type) + self.assertEqual(key, deserialized) + self.assertEqual(definition_key, key.definition_key, definition_key) + self.assertEqual(definition_key, deserialized.definition_key) + self.assertEqual(aside_type, key.aside_type) + self.assertEqual(aside_type, deserialized.aside_type) @ddt.data( 'aside-def-v1:def-v1:abcd1234abcd1234abcd1234+type@block_type::aside' ) def test_definition_round_trip_serialized(self, aside_key): deserialized = AsideDefinitionKey.from_string(aside_key) - serialized = unicode(deserialized) - self.assertEquals(aside_key, serialized) + serialized = text_type(deserialized) + self.assertEqual(aside_key, serialized) @ddt.data( ('aside_type', 'bside'), @@ -93,7 +94,7 @@ def test_usage_key_replace(self, attr, value): key = AsideUsageKeyV1(BlockUsageLocator(CourseLocator('org', 'course', 'run'), 'block_type', 'block_id'), 'aside') new_key = key.replace(**{attr: value}) - self.assertEquals(getattr(new_key, attr), value) + self.assertEqual(getattr(new_key, attr), value) @ddt.data( ('aside_type', 'bside'), @@ -104,4 +105,4 @@ def test_usage_key_replace(self, attr, value): def test_definition_key_replace(self, attr, value): key = AsideDefinitionKeyV1(DefinitionLocator('block_type', 'abcd1234abcd1234abcd1234'), 'aside') new_key = key.replace(**{attr: value}) - self.assertEquals(getattr(new_key, attr), value) + self.assertEqual(getattr(new_key, attr), value) diff --git a/opaque_keys/edx/tests/test_asset_locators.py b/opaque_keys/edx/tests/test_asset_locators.py index eb97cd80..9f51356f 100644 --- a/opaque_keys/edx/tests/test_asset_locators.py +++ b/opaque_keys/edx/tests/test_asset_locators.py @@ -3,6 +3,7 @@ """ from unittest import TestCase +from six import text_type import ddt from opaque_keys import InvalidKeyError @@ -20,23 +21,23 @@ class TestAssetLocators(TestCase): "/c4x/org/course/asset/path", ) def test_deprecated_round_trip_asset_location(self, path): - self.assertEquals( + self.assertEqual( path, - unicode(AssetKey.from_string(path)), + text_type(AssetKey.from_string(path)), ) def test_map_into_course_asset_location(self): original_course = CourseKey.from_string('org/course/run') new_course = CourseKey.from_string('edX/toy/2012_Fall') loc = AssetLocator(original_course, 'asset', 'foo.bar') - self.assertEquals( + self.assertEqual( AssetLocator(new_course, 'asset', 'foo.bar', deprecated=True), loc.map_into_course(new_course) ) def test_make_asset_key(self): course = CourseKey.from_string('org/course/run') - self.assertEquals( + self.assertEqual( AssetLocator(course, 'asset', 'foo.bar', deprecated=True), course.make_asset_key('asset', 'foo.bar') ) @@ -49,18 +50,18 @@ def test_make_asset_key(self): def test_deprecated_son(self, key_cls, prefix, tag, source): source_key = key_cls(*source, deprecated=True) son = source_key.to_deprecated_son(prefix=prefix, tag=tag) - self.assertEquals( + self.assertEqual( son.keys(), [prefix + key for key in ('tag', 'org', 'course', 'category', 'name', 'revision')] ) - self.assertEquals(son[prefix + 'tag'], tag) - self.assertEquals(son[prefix + 'category'], source_key.block_type) - self.assertEquals(son[prefix + 'name'], source_key.block_id) + self.assertEqual(son[prefix + 'tag'], tag) + self.assertEqual(son[prefix + 'category'], source_key.block_type) + self.assertEqual(son[prefix + 'name'], source_key.block_id) - self.assertEquals(son[prefix + 'org'], source_key.course_key.org) - self.assertEquals(son[prefix + 'course'], source_key.course_key.course) - self.assertEquals(son[prefix + 'revision'], source_key.course_key.branch) + self.assertEqual(son[prefix + 'org'], source_key.course_key.org) + self.assertEqual(son[prefix + 'course'], source_key.course_key.course) + self.assertEqual(son[prefix + 'revision'], source_key.course_key.branch) @ddt.data( (AssetKey.from_string('/c4x/o/c/ct/n'), 'run'), @@ -68,7 +69,7 @@ def test_deprecated_son(self, key_cls, prefix, tag, source): ) @ddt.unpack def test_roundtrip_deprecated_son(self, key, run): - self.assertEquals( + self.assertEqual( key.replace(course_key=key.course_key.replace(run=run)), key.__class__._from_deprecated_son(key.to_deprecated_son(), run) # pylint: disable=protected-access ) @@ -80,11 +81,11 @@ def test_old_charset(self): def test_replace(self): asset_key = AssetKey.from_string('/c4x/o/c/asset/path') - self.assertEquals( + self.assertEqual( 'foo', asset_key.replace(path='foo').path ) - self.assertEquals( + self.assertEqual( 'bar', asset_key.replace(asset_type='bar').asset_type ) @@ -108,7 +109,7 @@ def test_empty_path(self): def test_asset_with_special_character(self, paths): for path in paths: asset_locator = AssetKey.from_string(path) - self.assertEquals( + self.assertEqual( path, - unicode(asset_locator), + text_type(asset_locator), ) diff --git a/opaque_keys/edx/tests/test_block_types.py b/opaque_keys/edx/tests/test_block_types.py index 50a38e52..a5cb4915 100644 --- a/opaque_keys/edx/tests/test_block_types.py +++ b/opaque_keys/edx/tests/test_block_types.py @@ -1,9 +1,9 @@ """ Tests of BlockTypeKey subclasses. """ - from unittest import TestCase +from six import text_type import ddt from opaque_keys import InvalidKeyError @@ -26,12 +26,12 @@ def test_parse_deprecated_type(self, key): @ddt.data('problem', 'html', 'vertical') def test_deprecated_roundtrip(self, key): block_type = BlockTypeKey.from_string(key) - serialized = unicode(block_type) + serialized = text_type(block_type) self.assertEqual(key, serialized) def test_deprecated_construction(self): block_type = BlockTypeKeyV1('xblock.v1', 'problem') - serialized = unicode(block_type) + serialized = text_type(block_type) self.assertEqual('problem', serialized) def test_deprecated_equality(self): @@ -46,7 +46,7 @@ def test_deprecated_equality(self): ) def test_roundtrip_from_string(self, key): block_type = BlockTypeKey.from_string(key) - serialized = unicode(block_type) + serialized = text_type(block_type) self.assertEqual(key, serialized) @ddt.data( @@ -57,7 +57,7 @@ def test_roundtrip_from_string(self, key): @ddt.unpack def test_roundtrip_from_key(self, family, block_type): key = BlockTypeKeyV1(family, block_type) - serialized = unicode(key) + serialized = text_type(key) deserialized = BlockTypeKey.from_string(serialized) self.assertEqual(key, deserialized) diff --git a/opaque_keys/edx/tests/test_block_usage_locators.py b/opaque_keys/edx/tests/test_block_usage_locators.py index 4a797172..32d73613 100644 --- a/opaque_keys/edx/tests/test_block_usage_locators.py +++ b/opaque_keys/edx/tests/test_block_usage_locators.py @@ -2,6 +2,7 @@ Thorough tests of BlockUsageLocator, as well as UsageKeys generally """ from itertools import product +from six import text_type import ddt from bson.objectid import ObjectId @@ -44,9 +45,9 @@ class TestBlockUsageLocators(LocatorBaseTest): "i4x://org.dept%sub-prof/course.num%section-4/category/name:12%33-44", ) def test_string_roundtrip(self, url): - self.assertEquals( + self.assertEqual( url, - unicode(UsageKey.from_string(url)) + text_type(UsageKey.from_string(url)) ) @ddt.data( @@ -70,12 +71,12 @@ def test_string_roundtrip(self, url): def test_valid_locations(self, args, kwargs, org, course, run, category, name, revision): # pylint: disable=unused-argument course_key = CourseLocator(org=org, course=course, run=run, branch=revision, deprecated=True) locator = BlockUsageLocator(course_key, block_type=category, block_id=name, deprecated=True) - self.assertEquals(org, locator.course_key.org) - self.assertEquals(course, locator.course_key.course) - self.assertEquals(run, locator.course_key.run) - self.assertEquals(category, locator.block_type) - self.assertEquals(name, locator.block_id) - self.assertEquals(revision, locator.course_key.branch) + self.assertEqual(org, locator.course_key.org) + self.assertEqual(course, locator.course_key.course) + self.assertEqual(run, locator.course_key.run) + self.assertEqual(category, locator.block_type) + self.assertEqual(name, locator.block_id) + self.assertEqual(revision, locator.course_key.branch) @ddt.data( (("foo",), {}), @@ -114,7 +115,7 @@ def test_invalid_locations(self, *args, **kwargs): *GENERAL_PAIRS ) def test_clean(self, pair): - self.assertEquals(BlockUsageLocator.clean(pair[0]), pair[1]) + self.assertEqual(BlockUsageLocator.clean(pair[0]), pair[1]) @ddt.data( ('a:b', 'a:b'), # colons ok in names @@ -123,7 +124,7 @@ def test_clean(self, pair): *GENERAL_PAIRS ) def test_clean_for_url_name(self, pair): - self.assertEquals(BlockUsageLocator.clean_for_url_name(pair[0]), pair[1]) + self.assertEqual(BlockUsageLocator.clean_for_url_name(pair[0]), pair[1]) @ddt.data( ("a:b", "a_b"), # no colons for html use @@ -132,17 +133,17 @@ def test_clean_for_url_name(self, pair): *GENERAL_PAIRS ) def test_clean_for_html(self, pair): - self.assertEquals(BlockUsageLocator.clean_for_html(pair[0]), pair[1]) + self.assertEqual(BlockUsageLocator.clean_for_html(pair[0]), pair[1]) def test_html_id(self): course_key = CourseLocator('org', 'course', 'run') locator = BlockUsageLocator(course_key, block_type='cat', block_id='name:more_name') - self.assertEquals(locator.html_id(), "name:more_name") + self.assertEqual(locator.html_id(), "name:more_name") def test_deprecated_html_id(self): course_key = CourseLocator('org', 'course', 'run', version_guid='rev', deprecated=True) locator = BlockUsageLocator(course_key, block_type='cat', block_id='name:more_name', deprecated=True) - self.assertEquals(locator.html_id(), "i4x-org-course-cat-name_more_name-rev") + self.assertEqual(locator.html_id(), "i4x-org-course-cat-name_more_name-rev") @ddt.data( 'course', @@ -160,7 +161,7 @@ def test_deprecated_html_id(self): def test_replacement(self, key): course_key = CourseLocator('org', 'course', 'run', 'rev', deprecated=True) kwargs = {key: 'newvalue'} - self.assertEquals( + self.assertEqual( getattr(BlockUsageLocator(course_key, 'c', 'n', deprecated=True).replace(**kwargs), key), 'newvalue' ) @@ -184,7 +185,7 @@ def test_map_into_course_location(self, deprecated_source, deprecated_dest): expected = BlockUsageLocator(new_course, 'cat', 'name:more_name', deprecated=deprecated_dest) actual = loc.map_into_course(new_course) - self.assertEquals(expected, actual) + self.assertEqual(expected, actual) @ddt.data( (BlockUsageLocator, '_id.', 'i4x', (CourseLocator('org', 'course', 'run', 'rev', deprecated=True), 'ct', 'n')), @@ -194,15 +195,15 @@ def test_map_into_course_location(self, deprecated_source, deprecated_dest): def test_to_deprecated_son(self, key_cls, prefix, tag, source): source_key = key_cls(*source, deprecated=True) son = source_key.to_deprecated_son(prefix=prefix, tag=tag) - self.assertEquals(son.keys(), - [prefix + key for key in ('tag', 'org', 'course', 'category', 'name', 'revision')]) + self.assertEqual(son.keys(), + [prefix + key for key in ('tag', 'org', 'course', 'category', 'name', 'revision')]) - self.assertEquals(son[prefix + 'tag'], tag) - self.assertEquals(son[prefix + 'org'], source_key.course_key.org) - self.assertEquals(son[prefix + 'course'], source_key.course_key.course) - self.assertEquals(son[prefix + 'category'], source_key.block_type) - self.assertEquals(son[prefix + 'name'], source_key.block_id) - self.assertEquals(son[prefix + 'revision'], source_key.course_key.branch) + self.assertEqual(son[prefix + 'tag'], tag) + self.assertEqual(son[prefix + 'org'], source_key.course_key.org) + self.assertEqual(son[prefix + 'course'], source_key.course_key.course) + self.assertEqual(son[prefix + 'category'], source_key.block_type) + self.assertEqual(son[prefix + 'name'], source_key.block_id) + self.assertEqual(son[prefix + 'revision'], source_key.course_key.branch) @ddt.data( (UsageKey.from_string('i4x://org/course/ct/n'), 'run'), @@ -210,7 +211,7 @@ def test_to_deprecated_son(self, key_cls, prefix, tag, source): ) @ddt.unpack def test_deprecated_son_roundtrip(self, key, run): - self.assertEquals( + self.assertEqual( key.replace(course_key=key.course_key.replace(run=run)), key.__class__._from_deprecated_son(key.to_deprecated_son(), run) # pylint: disable=protected-access ) @@ -235,7 +236,7 @@ def test_block_constructor(self): block_type='problem', block=expected_block_ref ) - self.assertEqual(unicode(testobj), testurn) + self.assertEqual(text_type(testobj), testurn) testobj = testobj.for_version(ObjectId()) agnostic = testobj.version_agnostic() self.assertIsNone(agnostic.version_guid) @@ -341,13 +342,19 @@ def test_repr(self): CourseLocator.BRANCH_PREFIX, BlockUsageLocator.BLOCK_TYPE_PREFIX, BlockUsageLocator.BLOCK_PREFIX ) testobj = UsageKey.from_string(testurn) - expected = "BlockUsageLocator(CourseLocator(u'mit.eecs', u'6002x', " \ - "u'2014_T2', u'published', None), u'problem', u'HW3')" + expected = "BlockUsageLocator(CourseLocator({}, {}, {}, {}, None), {}, {})".format( + repr(text_type('mit.eecs')), + repr(text_type('6002x')), + repr(text_type('2014_T2')), + repr(text_type('published')), + repr(text_type('problem')), + repr(text_type('HW3')), + ) self.assertEqual(expected, repr(testobj)) def test_local_id(self): local_id = LocalId() - self.assertEquals( + self.assertEqual( BlockUsageLocator( CourseLocator('org', 'course', 'run'), 'problem', diff --git a/opaque_keys/edx/tests/test_course_locators.py b/opaque_keys/edx/tests/test_course_locators.py index 493e64f3..019e8b3b 100644 --- a/opaque_keys/edx/tests/test_course_locators.py +++ b/opaque_keys/edx/tests/test_course_locators.py @@ -1,6 +1,8 @@ """ Tests of CourseKeys and CourseLocators """ +from six import text_type + import ddt from bson.objectid import ObjectId @@ -22,9 +24,9 @@ class TestCourseKeys(LocatorBaseTest, TestDeprecated): "foo/bar/baz", ) def test_deprecated_roundtrip(self, course_id): - self.assertEquals( + self.assertEqual( course_id, - unicode(CourseKey.from_string(course_id)) + text_type(CourseKey.from_string(course_id)) ) @ddt.data( @@ -46,23 +48,23 @@ def test_invalid_format_location(self, course_id): def test_make_usage_key(self): depr_course = CourseKey.from_string('org/course/run') - self.assertEquals( - unicode(BlockUsageLocator(depr_course, 'category', 'name', deprecated=True)), - unicode(depr_course.make_usage_key('category', 'name')) + self.assertEqual( + text_type(BlockUsageLocator(depr_course, 'category', 'name', deprecated=True)), + text_type(depr_course.make_usage_key('category', 'name')) ) course = CourseKey.from_string('course-v1:org+course+run') - self.assertEquals( - unicode(BlockUsageLocator(course, 'block_type', 'block_id')), - unicode(course.make_usage_key('block_type', 'block_id')) + self.assertEqual( + text_type(BlockUsageLocator(course, 'block_type', 'block_id')), + text_type(course.make_usage_key('block_type', 'block_id')) ) def test_convert_deprecation(self): depr_course = CourseKey.from_string('org/course/run') course = CourseKey.from_string('course-v1:org+course+run') - self.assertEquals(unicode(depr_course.replace(deprecated=False)), unicode(course)) - self.assertEquals(unicode(course.replace(deprecated=True)), unicode(depr_course)) + self.assertEqual(text_type(depr_course.replace(deprecated=False)), text_type(course)) + self.assertEqual(text_type(course.replace(deprecated=True)), text_type(depr_course)) def test_course_constructor_underspecified(self): with self.assertRaises(InvalidKeyError): @@ -250,7 +252,7 @@ def test_course_constructor_deprecated_offering(self): def test_make_usage_key_from_deprecated_string_roundtrip(self, url): course_key = CourseLocator('org', 'course', 'run') with self.assertDeprecationWarning(count=2): - self.assertEquals( + self.assertEqual( url, course_key.make_usage_key_from_deprecated_string(url).to_deprecated_string() ) @@ -259,7 +261,7 @@ def test_empty_run(self): with self.assertRaises(InvalidKeyError): CourseLocator('org', 'course', '') - self.assertEquals( + self.assertEqual( 'org/course/', - unicode(CourseLocator('org', 'course', '', deprecated=True)) + text_type(CourseLocator('org', 'course', '', deprecated=True)) ) diff --git a/opaque_keys/edx/tests/test_deprecated_locations.py b/opaque_keys/edx/tests/test_deprecated_locations.py index d04e4ba2..576b45cb 100644 --- a/opaque_keys/edx/tests/test_deprecated_locations.py +++ b/opaque_keys/edx/tests/test_deprecated_locations.py @@ -29,11 +29,11 @@ def check_deprecated_replace(self, cls): loc_course_key_replaced = loc.replace(course_key=loc.course_key) self.assertTrue(isinstance(loc_boo, BlockUsageLocator)) self.assertTrue(loc_boo.deprecated) - self.assertNotEquals(id(loc), id(loc_boo)) - self.assertNotEquals(id(loc), id(loc_copy)) - self.assertNotEquals(loc, loc_boo) - self.assertEquals(loc, loc_copy) - self.assertEquals(loc, loc_course_key_replaced) + self.assertNotEqual(id(loc), id(loc_boo)) + self.assertNotEqual(id(loc), id(loc_copy)) + self.assertNotEqual(loc, loc_boo) + self.assertEqual(loc, loc_copy) + self.assertEqual(loc, loc_course_key_replaced) class TestSSCK(TestDeprecated): @@ -66,10 +66,10 @@ def test_deprecated_replace(self): ssck_copy = ssck.replace() self.assertTrue(isinstance(ssck_boo, CourseLocator)) self.assertTrue(ssck_boo.deprecated) - self.assertNotEquals(id(ssck), id(ssck_boo)) - self.assertNotEquals(id(ssck), id(ssck_copy)) - self.assertNotEquals(ssck, ssck_boo) - self.assertEquals(ssck, ssck_copy) + self.assertNotEqual(id(ssck), id(ssck_boo)) + self.assertNotEqual(id(ssck), id(ssck_copy)) + self.assertNotEqual(ssck, ssck_boo) + self.assertEqual(ssck, ssck_copy) class TestV0Strings(TestDeprecated): @@ -114,11 +114,11 @@ def test_clean(self): with self.assertRaises(InvalidKeyError): Location._check_location_part('abc123', re.compile(r'\d')) - self.assertEquals('abc_', Location._clean('abc123', re.compile(r'\d'))) - self.assertEquals('a._%-', Location.clean('a.*:%-')) - self.assertEquals('a.__%-', Location.clean_keeping_underscores('a.*:%-')) - self.assertEquals('a._:%-', Location.clean_for_url_name('a.*:%-')) - self.assertEquals('a_-', Location.clean_for_html('a.*:%-')) + self.assertEqual('abc_', Location._clean('abc123', re.compile(r'\d'))) + self.assertEqual('a._%-', Location.clean('a.*:%-')) + self.assertEqual('a.__%-', Location.clean_keeping_underscores('a.*:%-')) + self.assertEqual('a._:%-', Location.clean_for_url_name('a.*:%-')) + self.assertEqual('a_-', Location.clean_for_html('a.*:%-')) def test_deprecated_replace(self): self.check_deprecated_replace(Location) diff --git a/opaque_keys/edx/tests/test_library_locators.py b/opaque_keys/edx/tests/test_library_locators.py index a0178ed9..3e22547d 100644 --- a/opaque_keys/edx/tests/test_library_locators.py +++ b/opaque_keys/edx/tests/test_library_locators.py @@ -1,6 +1,7 @@ """ Tests of LibraryLocators """ +from six import text_type import ddt from bson.objectid import ObjectId @@ -36,12 +37,12 @@ def test_lib_key_constructor(self): code = 'test-problem-bank' lib_key = LibraryLocator(org=org, library=code) self.assertEqual(lib_key.org, org) - self.assertEqual(lib_key.library, code) + self.assertEqual(lib_key.library, code) # pylint: disable=no-member with self.assertDeprecationWarning(): self.assertEqual(lib_key.course, code) with self.assertDeprecationWarning(): self.assertEqual(lib_key.run, 'library') - self.assertEqual(lib_key.branch, None) + self.assertEqual(lib_key.branch, None) # pylint: disable=no-member def test_constructor_using_course(self): org = 'TestX' @@ -50,7 +51,7 @@ def test_constructor_using_course(self): with self.assertDeprecationWarning(): lib_key2 = LibraryLocator(org=org, course=code) self.assertEqual(lib_key, lib_key2) - self.assertEqual(lib_key2.library, code) + self.assertEqual(lib_key2.library, code) # pylint: disable=no-member def test_version_property_deprecated(self): lib_key = CourseKey.from_string('library-v1:TestX+lib1+version@519665f6223ebd6980884f2b') @@ -70,17 +71,17 @@ def test_lib_key_roundtrip_and_equality(self): org = 'TestX' code = 'test-problem-bank' lib_key = LibraryLocator(org=org, library=code) - lib_key2 = CourseKey.from_string(unicode(lib_key)) + lib_key2 = CourseKey.from_string(text_type(lib_key)) self.assertEqual(lib_key, lib_key2) def test_lib_key_make_usage_key(self): lib_key = CourseKey.from_string('library-v1:TestX+lib1') usage_key = LibraryUsageLocator(lib_key, 'html', 'html17') made = lib_key.make_usage_key('html', 'html17') - self.assertEquals(usage_key, made) - self.assertEquals( - unicode(usage_key), - unicode(made) + self.assertEqual(usage_key, made) + self.assertEqual( + text_type(usage_key), + text_type(made) ) def test_lib_key_not_deprecated(self): @@ -108,26 +109,26 @@ def test_lib_key_branch_support(self): branch = 'future-purposes-perhaps' lib_key = LibraryLocator(org=org, library=code, branch=branch) self.assertEqual(lib_key.org, org) - self.assertEqual(lib_key.library, code) - self.assertEqual(lib_key.branch, branch) - lib_key2 = CourseKey.from_string(unicode(lib_key)) + self.assertEqual(lib_key.library, code) # pylint: disable=no-member + self.assertEqual(lib_key.branch, branch) # pylint: disable=no-member + lib_key2 = CourseKey.from_string(text_type(lib_key)) self.assertEqual(lib_key, lib_key2) - self.assertEqual(lib_key.branch, branch) + self.assertEqual(lib_key.branch, branch) # pylint: disable=no-member def test_for_branch(self): lib_key = LibraryLocator(org='TestX', library='test', branch='initial') branch2 = "br2" branch2_key = lib_key.for_branch(branch2) - self.assertEqual(branch2_key.branch, branch2) + self.assertEqual(branch2_key.branch, branch2) # pylint: disable=no-member normal_branch = lib_key.for_branch(None) - self.assertEqual(normal_branch.branch, None) + self.assertEqual(normal_branch.branch, None) # pylint: disable=no-member def test_version_only_lib_key(self): version_only_lib_key = LibraryLocator(version_guid=ObjectId('519665f6223ebd6980884f2b')) self.assertEqual(version_only_lib_key.org, None) - self.assertEqual(version_only_lib_key.library, None) + self.assertEqual(version_only_lib_key.library, None) # pylint: disable=no-member with self.assertRaises(InvalidKeyError): version_only_lib_key.for_branch("test") @@ -170,10 +171,10 @@ def test_lib_key_constructor_version_guid(self, version_id): version_id_obj = ObjectId(version_id) lib_key = LibraryLocator(version_guid=version_id) - self.assertEqual(lib_key.version_guid, version_id_obj) + self.assertEqual(lib_key.version_guid, version_id_obj) # pylint: disable=no-member self.assertEqual(lib_key.org, None) - self.assertEqual(lib_key.library, None) - self.assertEqual(str(lib_key.version_guid), version_id_str) + self.assertEqual(lib_key.library, None) # pylint: disable=no-member + self.assertEqual(str(lib_key.version_guid), version_id_str) # pylint: disable=no-member # Allow access to _to_string # pylint: disable=protected-access expected_str = u'@'.join((lib_key.VERSION_PREFIX, version_id_str)) @@ -201,7 +202,7 @@ def test_changing_course(self): def test_make_asset_key(self): lib_key = CourseKey.from_string('library-v1:TestX+lib1') - self.assertEquals( + self.assertEqual( AssetLocator(lib_key, 'asset', 'foo.bar'), lib_key.make_asset_key('asset', 'foo.bar') ) diff --git a/opaque_keys/edx/tests/test_library_usage_locators.py b/opaque_keys/edx/tests/test_library_usage_locators.py index 80bc45ad..6f9f6b52 100644 --- a/opaque_keys/edx/tests/test_library_usage_locators.py +++ b/opaque_keys/edx/tests/test_library_usage_locators.py @@ -2,6 +2,7 @@ """ Tests of LibraryUsageLocator """ +from six import text_type import ddt from bson.objectid import ObjectId from opaque_keys import InvalidKeyError @@ -27,9 +28,9 @@ class TestLibraryUsageLocators(LocatorBaseTest): BLOCK_PREFIX), ) def test_string_roundtrip(self, url): - self.assertEquals( + self.assertEqual( url, - unicode(UsageKey.from_string(url)) + text_type(UsageKey.from_string(url)) ) @ddt.data( @@ -45,11 +46,11 @@ def test_constructor(self, org, lib, block_type, block_id): BLOCK_TYPE_PREFIX, block_type, BLOCK_PREFIX, block_id )) - self.assertEquals(lib_usage_key, lib_usage_key2) - self.assertEquals(lib_usage_key.library_key, lib_key) - self.assertEquals(lib_usage_key.library_key, lib_key) - self.assertEquals(lib_usage_key.branch, None) - self.assertEquals(lib_usage_key.run, LibraryLocator.RUN) + self.assertEqual(lib_usage_key, lib_usage_key2) + self.assertEqual(lib_usage_key.library_key, lib_key) + self.assertEqual(lib_usage_key.library_key, lib_key) + self.assertEqual(lib_usage_key.branch, None) + self.assertEqual(lib_usage_key.run, LibraryLocator.RUN) self.assertIsInstance(lib_usage_key2, LibraryUsageLocator) self.assertIsInstance(lib_usage_key2.library_key, LibraryLocator) diff --git a/opaque_keys/edx/tests/test_locators.py b/opaque_keys/edx/tests/test_locators.py index 914c7165..036778ef 100644 --- a/opaque_keys/edx/tests/test_locators.py +++ b/opaque_keys/edx/tests/test_locators.py @@ -4,6 +4,8 @@ from unittest import TestCase import random + +from six import text_type from bson.objectid import ObjectId from opaque_keys.edx.locator import Locator, CourseLocator, DefinitionLocator, VersionTree @@ -28,8 +30,8 @@ def test_description_locator_url(self): object_id = '{:024x}'.format(random.randrange(16 ** 24)) definition_locator = DefinitionLocator('html', object_id) self.assertEqual('def-v1:{}+{}@html'.format(object_id, DefinitionLocator.BLOCK_TYPE_PREFIX), - unicode(definition_locator)) - self.assertEqual(definition_locator, DefinitionKey.from_string(unicode(definition_locator))) + text_type(definition_locator)) + self.assertEqual(definition_locator, DefinitionKey.from_string(text_type(definition_locator))) def test_description_locator_version(self): object_id = '{:024x}'.format(random.randrange(16 ** 24)) diff --git a/opaque_keys/tests/test_opaque_keys.py b/opaque_keys/tests/test_opaque_keys.py index 2b183ccf..6dfc2087 100644 --- a/opaque_keys/tests/test_opaque_keys.py +++ b/opaque_keys/tests/test_opaque_keys.py @@ -7,6 +7,8 @@ import pickle from unittest import TestCase +from six import text_type + from opaque_keys import OpaqueKey, InvalidKeyError @@ -69,7 +71,7 @@ class Base10Key(DummyKey): def _to_string(self): # For some reason, pylint doesn't think this key has a `value` attribute - return unicode(self.value) # pylint: disable=no-member + return text_type(self.value) # pylint: disable=no-member @classmethod def _from_string(cls, serialized): @@ -108,21 +110,21 @@ class KeyTests(TestCase): def test_namespace_from_string(self): hex_key = DummyKey.from_string('hex:0x10') self.assertIsInstance(hex_key, HexKey) - self.assertEquals(hex_key.value, 16) - self.assertEquals(hex_key._to_string(), '0x10') # pylint: disable=protected-access - self.assertEquals(len(hex_key), len('hex:') + len('0x10')) + self.assertEqual(hex_key.value, 16) + self.assertEqual(hex_key._to_string(), '0x10') # pylint: disable=protected-access + self.assertEqual(len(hex_key), len('hex:0x10')) base_key = DummyKey.from_string('base10:15') self.assertIsInstance(base_key, Base10Key) - self.assertEquals(base_key.value, 15) - self.assertEquals(base_key._to_string(), '15') # pylint: disable=protected-access - self.assertEquals(len(base_key), len('base10:') + len('15')) + self.assertEqual(base_key.value, 15) + self.assertEqual(base_key._to_string(), '15') # pylint: disable=protected-access + self.assertEqual(len(base_key), len('base10:15')) dict_key = DummyKey.from_string('dict:{"foo": "bar"}') self.assertIsInstance(dict_key, DictKey) - self.assertEquals(dict_key.value, {"foo": "bar"}) - self.assertEquals(dict_key._to_string(), '{"foo": "bar"}') # pylint: disable=protected-access - self.assertEquals(len(dict_key), len('dict:') + len('{"foo": "bar"}')) + self.assertEqual(dict_key.value, {"foo": "bar"}) + self.assertEqual(dict_key._to_string(), '{"foo": "bar"}') # pylint: disable=protected-access + self.assertEqual(len(dict_key), len('dict:{"foo": "bar"}')) def test_bad_keys(self): with self.assertRaises(InvalidKeyError): @@ -164,12 +166,12 @@ def test_immutability(self): del key.value def test_equality(self): - self.assertEquals(DummyKey.from_string('hex:0x10'), DummyKey.from_string('hex:0x10')) - self.assertNotEquals(DummyKey.from_string('hex:0x10'), DummyKey.from_string('base10:16')) + self.assertEqual(DummyKey.from_string('hex:0x10'), DummyKey.from_string('hex:0x10')) + self.assertNotEqual(DummyKey.from_string('hex:0x10'), DummyKey.from_string('base10:16')) def test_hash_equality(self): - self.assertEquals(hash(DummyKey.from_string('hex:0x10')), hash(DummyKey.from_string('hex:0x10'))) - self.assertNotEquals(hash(DummyKey.from_string('hex:0x10')), hash(DummyKey.from_string('base10:16'))) + self.assertEqual(hash(DummyKey.from_string('hex:0x10')), hash(DummyKey.from_string('hex:0x10'))) + self.assertNotEqual(hash(DummyKey.from_string('hex:0x10')), hash(DummyKey.from_string('base10:16'))) def test_constructor(self): with self.assertRaises(TypeError): @@ -187,20 +189,20 @@ def test_constructor(self): with self.assertRaises(TypeError): HexKeyTwoFields(10, value=10) - self.assertEquals(HexKey(10).value, 10) - self.assertEquals(HexKey(value=10).value, 10) + self.assertEqual(HexKey(10).value, 10) + self.assertEqual(HexKey(value=10).value, 10) def test_replace(self): hex10 = HexKey(10) hex11 = hex10.replace(value=11) hex_copy = hex10.replace() - self.assertNotEquals(id(hex10), id(hex11)) - self.assertEquals(id(hex10), id(hex_copy)) - self.assertNotEquals(hex10, hex11) - self.assertEquals(hex10, hex_copy) - self.assertEquals(HexKey(10), hex10) - self.assertEquals(HexKey(11), hex11) + self.assertNotEqual(id(hex10), id(hex11)) + self.assertEqual(id(hex10), id(hex_copy)) + self.assertNotEqual(hex10, hex11) + self.assertEqual(hex10, hex_copy) + self.assertEqual(HexKey(10), hex10) + self.assertEqual(HexKey(11), hex11) def test_replace_deprecated_property(self): deprecated_hex10 = HexKey(10, deprecated=True) @@ -208,11 +210,11 @@ def test_replace_deprecated_property(self): not_deprecated_hex10 = deprecated_hex10.replace(deprecated=False) deprecated_hex10_copy = deprecated_hex10.replace() - self.assertNotEquals(deprecated_hex10, deprecated_hex11) - self.assertEquals(deprecated_hex10, deprecated_hex10_copy) - self.assertNotEquals(HexKey(10), deprecated_hex10) - self.assertNotEquals(HexKey(11), deprecated_hex11) - self.assertEquals(HexKey(10, deprecated=False), not_deprecated_hex10) + self.assertNotEqual(deprecated_hex10, deprecated_hex11) + self.assertEqual(deprecated_hex10, deprecated_hex10_copy) + self.assertNotEqual(HexKey(10), deprecated_hex10) + self.assertNotEqual(HexKey(11), deprecated_hex11) + self.assertEqual(HexKey(10, deprecated=False), not_deprecated_hex10) self.assertTrue(deprecated_hex11.deprecated) self.assertTrue(deprecated_hex10_copy.deprecated) @@ -223,16 +225,16 @@ def test_copy(self): copied = copy.copy(original) deep = copy.deepcopy(original) - self.assertEquals(original, copied) - self.assertEquals(id(original), id(copied)) + self.assertEqual(original, copied) + self.assertEqual(id(original), id(copied)) # For some reason, pylint doesn't think DictKey has a `value` attribute - self.assertEquals(id(original.value), id(copied.value)) # pylint: disable=no-member + self.assertEqual(id(original.value), id(copied.value)) # pylint: disable=no-member - self.assertEquals(original, deep) - self.assertEquals(id(original), id(deep)) - self.assertEquals(id(original.value), id(deep.value)) # pylint: disable=no-member + self.assertEqual(original, deep) + self.assertEqual(id(original), id(deep)) + self.assertEqual(id(original.value), id(deep.value)) # pylint: disable=no-member - self.assertEquals(copy.deepcopy([original]), [original]) + self.assertEqual(copy.deepcopy([original]), [original]) def test_subclass(self): with self.assertRaises(InvalidKeyError): @@ -282,6 +284,6 @@ def test_pickle(self): deprecated_hex10 = ten.replace(deprecated=True) dec_ten = Base10Key(value=10) - self.assertEquals(ten, pickle.loads(pickle.dumps(ten))) - self.assertEquals(deprecated_hex10, pickle.loads(pickle.dumps(deprecated_hex10))) - self.assertEquals(dec_ten, pickle.loads(pickle.dumps(dec_ten))) + self.assertEqual(ten, pickle.loads(pickle.dumps(ten))) + self.assertEqual(deprecated_hex10, pickle.loads(pickle.dumps(deprecated_hex10))) + self.assertEqual(dec_ten, pickle.loads(pickle.dumps(dec_ten))) diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 00000000..48017df0 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,8 @@ +[pytest] +addopts = --cov . --cov-config .coveragerc --pep8 --pylint --cov-report term --cov-report html +norecursedirs = .git .tox .* CVS _darcs {arch} *.egg +pep8ignore = + */migrations/* ALL + +pep8maxlinelength = 150 +testpaths = opaque_keys diff --git a/setup.py b/setup.py index 4ec1d77f..3e2690b0 100644 --- a/setup.py +++ b/setup.py @@ -7,6 +7,7 @@ url="https://github.com/edx/opaque-keys", packages=find_packages(), install_requires=[ + "six", "stevedore", "pymongo" ], diff --git a/test-requirements.txt b/test-requirements.txt index e27abbef..d63b37ea 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -5,3 +5,8 @@ mock nose pep8 sphinx +pytest +pytest-cov +pytest-pep8 +pytest-pylint +tox diff --git a/tox.ini b/tox.ini new file mode 100644 index 00000000..0dedb968 --- /dev/null +++ b/tox.ini @@ -0,0 +1,9 @@ +[tox] +envlist = py27,py34 +skip_missing_interpreters = True +skipsdist = True + +[testenv] +deps = + -r{toxinidir}/requirements.txt +commands = {posargs:py.test}