From ee5e1213d6f9d1bbe2c0dc9a60097faab935bf30 Mon Sep 17 00:00:00 2001 From: timbu Date: Wed, 2 Mar 2016 21:55:59 +0000 Subject: [PATCH] quick python3 version --- .travis.yml | 5 +- requirements.txt | 2 +- taal/__init__.py | 14 +- taal/kaiso/__init__.py | 35 ---- taal/kaiso/context_managers.py | 45 ----- taal/kaiso/manager.py | 246 --------------------------- taal/kaiso/types.py | 35 ---- test_requirements.txt | 8 +- tests/__init__.py | 2 + tests/conftest.py | 69 -------- tests/kaiso/__init__.py | 13 -- tests/kaiso/test_change_instance.py | 133 --------------- tests/kaiso/test_context_managers.py | 28 --- tests/kaiso/test_manager.py | 225 ------------------------ tests/kaiso/test_types.py | 130 -------------- tests/models.py | 35 +--- tests/test_models.py | 2 - tests/test_strategies.py | 5 +- 18 files changed, 17 insertions(+), 1015 deletions(-) delete mode 100644 taal/kaiso/__init__.py delete mode 100644 taal/kaiso/context_managers.py delete mode 100644 taal/kaiso/manager.py delete mode 100644 taal/kaiso/types.py delete mode 100644 tests/kaiso/__init__.py delete mode 100644 tests/kaiso/test_change_instance.py delete mode 100644 tests/kaiso/test_context_managers.py delete mode 100644 tests/kaiso/test_manager.py delete mode 100644 tests/kaiso/test_types.py diff --git a/.travis.yml b/.travis.yml index 55b1f50..d69c2e5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,12 +1,9 @@ language: python python: - - "2.7" + - "3.5" before_install: - - wget -O - http://debian.neo4j.org/neotechnology.gpg.key | sudo apt-key add - - - echo 'deb http://debian.neo4j.org/repo stable/' | sudo tee /etc/apt/sources.list.d/neo4j.list - sudo apt-get update -qq - - sudo apt-get install neo4j=2.0.3 install: - python setup.py -q install diff --git a/requirements.txt b/requirements.txt index a73a060..36807be 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ -sqlalchemy>=0.9 +sqlalchemy>=1.0.12 diff --git a/taal/__init__.py b/taal/__init__.py index 4ca9c2b..e80dde8 100644 --- a/taal/__init__.py +++ b/taal/__init__.py @@ -61,6 +61,9 @@ def __eq__(self, other): other_data = (other.context, other.message_id, other.pending_value) return self_data == other_data + def __hash__(self): + return hash((self.context, self.message_id, self.pending_value)) + class TranslationStrategies(object): NONE_VALUE = 'NONE_VALUE' @@ -85,7 +88,6 @@ class Translator(object): Given a sqlalchemy session, a model to store translations, and a language, bind a translator to a(n other) sqlalchemy session - and/or a kaiso manager to get translation magic Language may be either a string, or a callable returning a string, for more dynamic behaviour. @@ -130,16 +132,12 @@ def language(self): return self.get_language() def bind(self, target): - """ register e.g. a sqlalchey session or a kaiso manager """ - from taal.kaiso import manager if isinstance(target, Session): from taal.sqlalchemy.events import ( register_translator, register_session) register_translator(target, self) register_session(target) - elif isinstance(target, manager.Manager): - manager.register_translator(target, self) else: raise BindError("Unknown target {}".format(target)) @@ -181,7 +179,7 @@ def translate(self, translatable, strategy=None, cache=None): elif isinstance(translatable, dict): return dict( (key, self.translate(val, strategy=strategy, cache=cache)) - for key, val in translatable.iteritems() + for key, val in translatable.items() ) elif isinstance(translatable, list): return list( @@ -233,7 +231,7 @@ def _collect_translatables(self, translatable, collection=None): collection.add((translatable.context, translatable.message_id)) elif isinstance(translatable, dict): [self._collect_translatables(val, collection) - for val in translatable.itervalues()] + for val in translatable.values()] elif isinstance(translatable, list): [self._collect_translatables(item, collection) for item in translatable] @@ -463,7 +461,7 @@ def register(self, context_manager): self._registry[context] = context_manager def list_contexts_and_message_ids(self, **kwargs): - for context, context_manager_cls in self._registry.iteritems(): + for context, context_manager_cls in self._registry.items(): context_manager = context_manager_cls(**kwargs) for message_id in context_manager.list_message_ids(): yield (context, message_id) diff --git a/taal/kaiso/__init__.py b/taal/kaiso/__init__.py deleted file mode 100644 index dac244f..0000000 --- a/taal/kaiso/__init__.py +++ /dev/null @@ -1,35 +0,0 @@ -from __future__ import absolute_import - -from kaiso.attributes import String - -from taal import is_translatable_value -from taal.constants import PLACEHOLDER, TRANSPARENT_VALUES, PlaceholderValue - -TYPE_CONTEXT = "taal:kaiso_type" - - -class TranslatableString(String): - @staticmethod - def to_primitive(value, for_db): - acceptable_values = TRANSPARENT_VALUES + (PLACEHOLDER,) - - if for_db and value not in acceptable_values: - raise RuntimeError( - "Cannot save directly to translated fields. " - "Value was '{}'".format(value)) - - return value - - @staticmethod - def to_python(value): - - if not is_translatable_value(value): - return value - - if value == PLACEHOLDER: - # Before translation, return a placeholder that's more likely to - # generate an error than a normal string. - return PlaceholderValue - - raise RuntimeError( - "Unexpected value found in placeholder column: '{}'".format(value)) diff --git a/taal/kaiso/context_managers.py b/taal/kaiso/context_managers.py deleted file mode 100644 index 5b152f2..0000000 --- a/taal/kaiso/context_managers.py +++ /dev/null @@ -1,45 +0,0 @@ -import json - -from taal import TranslationContextManager, translation_manager -from taal.kaiso import TYPE_CONTEXT - - -class TypeTranslationContextManager(TranslationContextManager): - """ TranslationContextManager for Kaiso types """ - - context = TYPE_CONTEXT - - def __init__(self, manager, **kwargs): - self.manager = manager - - def list_message_ids(self): - manager = self.manager - type_hierarchy = manager.get_type_hierarchy() - return (type_[0] for type_ in type_hierarchy) - -translation_manager.register(TypeTranslationContextManager) - - -class AttributeTranslationContextManager(TranslationContextManager): - """ TranslationContextManager for Kaiso attributes """ - - context = "taal:kaiso_attr" - - def __init__(self, manager, **kwargs): - self.manager = manager - - @staticmethod - def get_message_id(type_id, attr_name): - return json.dumps( - [type_id, attr_name] - ) - - def list_message_ids(self): - manager = self.manager - type_hierarchy = manager.get_type_hierarchy() - for type_id, bases, attrs in type_hierarchy: - for attr in attrs: - yield self.get_message_id( - type_id, attr) - -translation_manager.register(AttributeTranslationContextManager) diff --git a/taal/kaiso/manager.py b/taal/kaiso/manager.py deleted file mode 100644 index 6b06f63..0000000 --- a/taal/kaiso/manager.py +++ /dev/null @@ -1,246 +0,0 @@ -import copy -from weakref import WeakKeyDictionary - -from kaiso.exceptions import DeserialisationError -from kaiso.persistence import Manager as KaisoManager -from kaiso.types import PersistableType, get_type_id - -from taal import ( - TranslatableString as TaalTranslatableString, is_translatable_value) -from taal.constants import PLACEHOLDER -from taal.exceptions import NoTranslatorRegistered -from taal.kaiso import TranslatableString, TYPE_CONTEXT -from taal.kaiso.types import get_context, get_message_id - - -MISSING = object() -translator_registry = WeakKeyDictionary() - - -def register_translator(owner, translator): - translator_registry[owner] = translator - - -def get_translator(owner): - try: - return translator_registry[owner] - except KeyError: - raise NoTranslatorRegistered( - "No translator registered for {}".format(owner)) - - -def iter_translatables(descriptor): - """ yield translatable attributes given a descriptor """ - for attr_name, attr_type in descriptor.attributes.items(): - if isinstance(attr_type, TranslatableString): - yield attr_name - - -def collect_translatables(manager, obj): - """ Return translatables from ``obj``. - - Mutates ``obj`` to replace translations with placeholders. - - Expects translator.save_translation or translator.delete_translations - to be called for each collected translatable. - """ - if isinstance(obj, PersistableType): - # object is a type; nothing to do - return [] - - translatables = [] - - descriptor = manager.type_registry.get_descriptor(type(obj)) - message_id = get_message_id(manager, obj) - - for attr_name in iter_translatables(descriptor): - attr = getattr(obj, attr_name) - - if is_translatable_value(attr): - setattr(obj, attr_name, PLACEHOLDER) - - if isinstance(attr, TaalTranslatableString): - # not changed since value was loaded, so don't collect for - # updating the translations table - continue - - context = get_context(manager, obj, attr_name) - translatable = TaalTranslatableString( - context, message_id, attr) - translatables.append(translatable) - - return translatables - - -class Manager(KaisoManager): - - def serialize(self, obj, for_db=False): - if for_db or type(obj) is PersistableType: - return super(Manager, self).serialize(obj) - - message_id = get_message_id(self, obj) - data = super(Manager, self).serialize(obj) - descriptor = self.type_registry.get_descriptor(type(obj)) - for attr_name, attr_type in descriptor.attributes.items(): - if isinstance(attr_type, TranslatableString): - value = data[attr_name] - if is_translatable_value(value): - context = get_context(self, obj, attr_name) - data[attr_name] = TaalTranslatableString( - context, message_id) - return data - - def deserialize(self, object_dict): - # we don't need to do any translation here; we just need to - # pop off any values for translatable fields during deserialization - # and put them back afterwards - - try: - type_id = object_dict['__type__'] - except KeyError: - raise DeserialisationError( - 'properties "{}" missing __type__ key'.format(object_dict)) - - if type_id == get_type_id(PersistableType): - return super(Manager, self).deserialize(object_dict) - - descriptor = self.type_registry.get_descriptor_by_id(type_id) - translatables = {} - - # deserialize a copy so we don't mutate object_dict - object_dict_copy = copy.copy(object_dict) - - for attr_name, attr_type in descriptor.attributes.items(): - if isinstance(attr_type, TranslatableString): - if attr_name not in object_dict_copy: - continue - translatables[attr_name] = object_dict_copy.pop(attr_name) - - obj = super(Manager, self).deserialize(object_dict_copy) - for attr_name, value in translatables.items(): - setattr(obj, attr_name, value) - - return obj - - def save(self, obj): - translatables = collect_translatables(self, obj) - result = super(Manager, self).save(obj) - - if translatables: - translator = get_translator(self) - for translatable in translatables: - if is_translatable_value(translatable.pending_value): - translator.save_translation(translatable) - else: - # delete all translations (in every language) if the - # value is None or the empty string - translator.delete_translations(translatable) - - return result - - def delete(self, obj): - translatables = collect_translatables(self, obj) - result = super(Manager, self).delete(obj) - - if translatables: - translator = get_translator(self) - for translatable in translatables: - translator.delete_translations(translatable) - - return result - - def get_labeled_type_hierarchy(self, start_type_id=None): - type_hierarchy = super( - Manager, self).get_type_hierarchy(start_type_id) - - for type_id, bases, attrs in type_hierarchy: - label = TaalTranslatableString( - context=TYPE_CONTEXT, - message_id=type_id - ) - yield (type_id, label, bases, attrs) - - def change_instance_type(self, obj, type_id, updated_values=None): - - if updated_values is None: - updated_values = {} - - updated_values = updated_values.copy() - - old_descriptor = self.type_registry.get_descriptor(type(obj)) - new_descriptor = self.type_registry.get_descriptor_by_id(type_id) - - old_message_id = get_message_id(self, obj) - old_translatables = {} - - # collect any translatable fields on the original object - # also, replace any values with placeholders for the super() call - - for attr_name in iter_translatables(old_descriptor): - attr = getattr(obj, attr_name) - if is_translatable_value(attr): - setattr(obj, attr_name, PLACEHOLDER) - context = get_context(self, obj, attr_name) - translatable = TaalTranslatableString( - context, old_message_id, attr) - old_translatables[attr_name] = translatable - - new_translatables = {} - - # collect any translatable fields from the new type - # also, replace any values in updated_values with placeholders - # for the super() call - - # note that we can't collect the context/message_id until after - # we call super(), since they may be about to change - # (context will definitely change, and message_id might, if we add or - # remove unique attributes) - - for attr_name in iter_translatables(new_descriptor): - attr = updated_values.get(attr_name, MISSING) - if attr is None: - continue - if attr is MISSING: - attr = None - - if is_translatable_value(attr): - updated_values[attr_name] = PLACEHOLDER - translatable = TaalTranslatableString( - None, None, attr) - new_translatables[attr_name] = translatable - - new_obj = super(Manager, self).change_instance_type( - obj, type_id, updated_values) - - # we are now able to fill in context/message_id for the new object - - new_message_id = get_message_id(self, new_obj) - for attr_name, translatable in new_translatables.items(): - translatable.message_id = new_message_id - translatable.context = get_context(self, new_obj, attr_name) - - to_delete = set(old_translatables) - set(new_translatables) - to_rename = set(old_translatables) & set(new_translatables) - to_add = set(new_translatables) - set(old_translatables) - - translator = get_translator(self) - - for key in to_delete: - translatable = old_translatables[key] - translator.delete_translations(translatable) - - for key in to_rename: - old_translatable = old_translatables[key] - new_translatable = new_translatables[key] - translator.move_translations(old_translatable, new_translatable) - if new_translatable.pending_value is not None: - # updated_values contained a key for a field already existing - # on the old type. save the updated translation - translator.save_translation(new_translatable) - - for key in to_add: - translatable = new_translatables[key] - if translatable.pending_value is not None: - translator.save_translation(translatable) - - return new_obj diff --git a/taal/kaiso/types.py b/taal/kaiso/types.py deleted file mode 100644 index 4ec2ad5..0000000 --- a/taal/kaiso/types.py +++ /dev/null @@ -1,35 +0,0 @@ -import json - -from kaiso.types import get_type_id -from kaiso.serialize import object_to_db_value - -from taal import TranslatableString - - -def get_context(manager, obj, attribute_name): - type_id = get_type_id(type(obj)) - return "taal:kaiso_field:{}:{}".format(type_id, attribute_name) - - -def get_message_id(manager, obj): - unique_attrs = set() - for cls, attr_name in manager.type_registry.get_unique_attrs(type(obj)): - value = getattr(obj, attr_name) - if value is not None: - unique_attrs.add(( - get_type_id(cls).lower(), # backwards compat; was index name - attr_name, - object_to_db_value(value), - )) - - return json.dumps(sorted(unique_attrs)) - - -def make_from_obj(manager, obj, attribute_name, pending_value=None): - context = get_context(manager, obj, attribute_name) - message_id = get_message_id(manager, obj) - return TranslatableString( - context=context, - message_id=message_id, - pending_value=pending_value - ) diff --git a/test_requirements.txt b/test_requirements.txt index 68f2c68..991ac2e 100644 --- a/test_requirements.txt +++ b/test_requirements.txt @@ -1,10 +1,10 @@ -r requirements.txt - coverage==3.7.1 flake8==2.2.5 -kaiso==0.30.2 mock==1.0.1 -mysql-python==1.2.5 +PyMySQL==0.7.2 pyflakes==0.8.1 -pytest==2.6.4 +pytest==2.9.0 pytest-cov==1.8.1 + + diff --git a/tests/__init__.py b/tests/__init__.py index e69de29..063cd2c 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -0,0 +1,2 @@ +import pymysql +pymysql.install_as_MySQLdb() diff --git a/tests/conftest.py b/tests/conftest.py index acd2a5b..4b0729d 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -33,61 +33,6 @@ def pytest_collection_modifyitems(items): item.keywords["neo4j"] = pytest.mark.neo4j -@pytest.fixture -def manager(request): - # kaiso manager - from kaiso.persistence import Manager - - neo4j_uri = request.config.getoption('neo4j_uri') - Manager(neo4j_uri, skip_setup=True).destroy() - manager = Manager(neo4j_uri) - return manager - - -@pytest.fixture -def translating_manager(request): - # taal manager - from taal.kaiso.manager import Manager - - neo4j_uri = request.config.getoption('neo4j_uri') - Manager(neo4j_uri, skip_setup=True).destroy() - manager = Manager(neo4j_uri) - return manager - - -@pytest.fixture -def type_heirarchy(manager): - """ Saves the type heirarchy defined in ``tests.kaiso`` using a normal - kaiso manager - """ - from tests.kaiso import Fish - manager.save(Fish) - - -@pytest.fixture -def bound_manager(request, session_cls, translating_manager): - # importing at the module level messes up coverage - from taal import Translator - from tests.models import Translation - - manager = translating_manager - - translator = Translator(Translation, session_cls(), 'language') - translator.bind(manager) - return manager - - -@pytest.fixture -def translating_type_heirarchy(bound_manager): - """ Saves the type heirarchy defined in ``tests.kaiso`` using a - bound, translating manager - """ - from tests.kaiso import Fish - - manager = bound_manager - manager.save(Fish) - - @pytest.fixture(scope="session") def clean_engine(request): # importing at the module level messes up coverage @@ -141,17 +86,3 @@ def bound_session(request, session, session_cls): translator = Translator(Translation, session_cls(), 'language') translator.bind(session) return session - - -@pytest.fixture(autouse=True) -def temporary_static_types(request): - from kaiso.test_helpers import TemporaryStaticTypes - - # need to import these before "freezing" the list of static types - from kaiso.persistence import TypeSystem - from tests.kaiso import Fish - TypeSystem, Fish # pyflakes - - patcher = TemporaryStaticTypes() - patcher.start() - request.addfinalizer(patcher.stop) diff --git a/tests/kaiso/__init__.py b/tests/kaiso/__init__.py deleted file mode 100644 index 3beade2..0000000 --- a/tests/kaiso/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -from __future__ import absolute_import - -from kaiso.attributes import Uuid, String -from kaiso.types import Entity - - -class Animal(Entity): - id = Uuid(unique=True) - name = String() - - -class Fish(Animal): - pass diff --git a/tests/kaiso/test_change_instance.py b/tests/kaiso/test_change_instance.py deleted file mode 100644 index b31f475..0000000 --- a/tests/kaiso/test_change_instance.py +++ /dev/null @@ -1,133 +0,0 @@ -from __future__ import absolute_import - -from kaiso.attributes import Integer -from kaiso.types import Entity -import pytest - -from taal import Translator -from taal import kaiso as taal_kaiso - -from tests.models import Translation - - -@pytest.fixture -def change_instance_hierarchy(bound_manager): - manager = bound_manager - - class Common(Entity): - id = Integer(unique=True) - common = taal_kaiso.TranslatableString() - - class Old(Common): - old = taal_kaiso.TranslatableString() - - class New(Common): - new = taal_kaiso.TranslatableString() - - manager.save(Old) - manager.save(New) - obj = Old(id=1, common="common", old="old") - manager.save(obj) - return obj - - -def test_change_instance_type( - bound_manager, session, change_instance_hierarchy): - manager = bound_manager - obj = change_instance_hierarchy - - assert session.query(Translation).count() == 2 - - retrieved = manager.deserialize(manager.serialize(obj)) - new = manager.change_instance_type(retrieved, 'New') - - # make sure we reset our session - session.rollback() - - data = manager.serialize(new) - translator = Translator(Translation, session, 'language') - translated = translator.translate(data) - - assert translated['common'] == 'common' - assert session.query(Translation).count() == 1 - - -def test_updated_values( - session, bound_manager, change_instance_hierarchy): - manager = bound_manager - obj = change_instance_hierarchy - - retrieved = manager.deserialize(manager.serialize(obj)) - new = manager.change_instance_type(retrieved, 'New', {'new': 'new'}) - - data = manager.serialize(new) - translator = Translator(Translation, session, 'language') - translated = translator.translate(data) - - assert translated['common'] == 'common' - assert translated['new'] == 'new' - assert session.query(Translation).count() == 2 - - -def test_update_existing_values( - session, bound_manager, change_instance_hierarchy): - manager = bound_manager - obj = change_instance_hierarchy - - retrieved = manager.deserialize(manager.serialize(obj)) - new = manager.change_instance_type(retrieved, 'New', {'common': 'new'}) - - data = manager.serialize(new) - translator = Translator(Translation, session, 'language') - translated = translator.translate(data) - - assert translated['common'] == 'new' - assert session.query(Translation).count() == 1 - - -def test_update_removed_values( - session, bound_manager, change_instance_hierarchy): - manager = bound_manager - obj = change_instance_hierarchy - - retrieved = manager.deserialize(manager.serialize(obj)) - new = manager.change_instance_type(retrieved, 'New', {'old': 'new'}) - - data = manager.serialize(new) - translator = Translator(Translation, session, 'language') - translated = translator.translate(data) - - assert translated['common'] == 'common' - assert session.query(Translation).count() == 1 - - -def test_update_unknown_values( - session, bound_manager, change_instance_hierarchy): - manager = bound_manager - obj = change_instance_hierarchy - - retrieved = manager.deserialize(manager.serialize(obj)) - new = manager.change_instance_type(retrieved, 'New', {'unknown': 'new'}) - - data = manager.serialize(new) - translator = Translator(Translation, session, 'language') - translated = translator.translate(data) - - assert translated['common'] == 'common' - assert session.query(Translation).count() == 1 - - -def test_update_unsetting_existing_values( - session, bound_manager, change_instance_hierarchy): - manager = bound_manager - obj = change_instance_hierarchy - - retrieved = manager.deserialize(manager.serialize(obj)) - new = manager.change_instance_type(retrieved, 'New', {'common': None}) - - data = manager.serialize(new) - translator = Translator(Translation, session, 'language') - translated = translator.translate(data) - - assert translated['common'] is None - assert session.query(Translation).count() == 0 diff --git a/tests/kaiso/test_context_managers.py b/tests/kaiso/test_context_managers.py deleted file mode 100644 index d3492f3..0000000 --- a/tests/kaiso/test_context_managers.py +++ /dev/null @@ -1,28 +0,0 @@ -from __future__ import absolute_import - -from taal import translation_manager -from taal.kaiso.context_managers import ( - TypeTranslationContextManager, AttributeTranslationContextManager) - - -def test_kaiso_context_managers(manager, type_heirarchy): - type_context_manager = TypeTranslationContextManager(manager) - message_ids = set(type_context_manager.list_message_ids()) - assert message_ids == set(['Entity', 'Animal', 'Fish']) - - attr_context_manager = AttributeTranslationContextManager(manager) - message_ids = set(attr_context_manager.list_message_ids()) - assert message_ids == set(['["Animal", "id"]', '["Animal", "name"]']) - - -def test_kaiso_translation_manager(manager, type_heirarchy): - context_message_id_pairs = set( - translation_manager.list_contexts_and_message_ids( - manager=manager)) - assert context_message_id_pairs == set([ - ('taal:kaiso_type', 'Entity'), - ('taal:kaiso_type', 'Animal'), - ('taal:kaiso_type', 'Fish'), - ('taal:kaiso_attr', '["Animal", "id"]'), - ('taal:kaiso_attr', '["Animal", "name"]'), - ]) diff --git a/tests/kaiso/test_manager.py b/tests/kaiso/test_manager.py deleted file mode 100644 index e3026de..0000000 --- a/tests/kaiso/test_manager.py +++ /dev/null @@ -1,225 +0,0 @@ -from __future__ import absolute_import - -from kaiso.exceptions import DeserialisationError -import pytest - -from taal import TranslatableString, Translator -from taal.constants import PLACEHOLDER, PlaceholderValue -from taal.exceptions import NoTranslatorRegistered -from taal.kaiso import TYPE_CONTEXT -from taal.kaiso.manager import collect_translatables -from taal.kaiso.types import get_context, get_message_id - -from tests.models import Translation, CustomFieldsEntity - - -def test_labeled_hierarchy(session, translating_type_heirarchy, bound_manager): - manager = bound_manager - - translator = Translator(Translation, session, 'en') - translator.bind(manager) - - hierarchy = manager.get_labeled_type_hierarchy() - entity = next(hierarchy) - - assert isinstance(entity[1], TranslatableString) - - -def test_translating_class_labels(session, translating_type_heirarchy, - bound_manager): - manager = bound_manager - - translator = Translator(Translation, session, 'en') - translatable = TranslatableString( - context=TYPE_CONTEXT, - message_id='Entity', pending_value='English Entity') - - translator.save_translation(translatable) - translator.bind(manager) - - hierarchy = manager.get_labeled_type_hierarchy() - entity = next(hierarchy) - - translated = translator.translate(entity[1]) - assert translated == 'English Entity' - - -def test_collect_translatables(bound_manager): - manager = bound_manager - - obj = CustomFieldsEntity(id=1, name="value", extra1="", extra2=None) - manager.save(CustomFieldsEntity) - manager.save(obj) - - translatables = collect_translatables(manager, obj) - - expected_values = { - "name": PLACEHOLDER, - "extra1": PLACEHOLDER, - "extra2": None - } - - for translatable in translatables: - attr_name = translatable.context.split(":")[-1] - expected_value = expected_values.pop(attr_name) - assert translatable.context == get_context(manager, obj, attr_name) - assert translatable.message_id == get_message_id(manager, obj) - assert translatable.pending_value == expected_value - - assert expected_values == {} - - -def test_serialize(session, translating_type_heirarchy, bound_manager): - manager = bound_manager - - translator = Translator(Translation, session, 'en') - translator.bind(manager) - - obj = CustomFieldsEntity(id=1, name='English name', extra1="", extra2=None) - manager.save(CustomFieldsEntity) - manager.save(obj) - - retrieved = manager.get(CustomFieldsEntity, id=1) - assert retrieved.name == PlaceholderValue - assert retrieved.extra1 == PlaceholderValue - assert retrieved.extra2 is None - - serialized = manager.serialize(retrieved) - assert isinstance(serialized['name'], TranslatableString) - assert isinstance(serialized['extra1'], TranslatableString) - assert serialized['extra2'] is None - - translated = translator.translate(serialized) - assert translated['name'] == 'English name' - assert translated['extra1'] == "" - assert translated['extra2'] is None - - -def test_deserialize_instance( - session, translating_type_heirarchy, bound_manager): - manager = bound_manager - - object_dict = { - '__type__': 'CustomFieldsEntity', - 'id': 1, - 'name': 'English name', - 'extra1': None, - } - - obj = manager.deserialize(object_dict) - assert obj.id == 1 - assert obj.name == 'English name' - assert obj.extra1 is None - - -def test_cannot_deserialize_without_type_key(bound_manager): - manager = bound_manager - - object_dict = { - 'name': 'English name', - } - - with pytest.raises(DeserialisationError): - manager.deserialize(object_dict) - - -def test_deserialize_type(bound_manager): - manager = bound_manager - - object_dict = { - '__type__': 'PersistableType', - 'id': 'CustomFieldsEntity', - } - obj = manager.deserialize(object_dict) - assert obj is CustomFieldsEntity - - -def test_save(session_cls, bound_manager): - manager = bound_manager - - def check_value(obj, attr_name, expected_value): - context = get_context(manager, obj, attr_name) - assert session_cls().query(Translation).filter_by( - context=context).one().value == expected_value - - manager.save(CustomFieldsEntity) - - obj = CustomFieldsEntity(id=1, name="value", extra1="", extra2=None) - manager.save(obj) - assert session_cls().query(Translation).count() == 2 - check_value(obj, "name", "value") - check_value(obj, "extra1", "") - - obj.extra1 = "non-empty string" - manager.save(obj) - assert session_cls().query(Translation).count() == 2 - check_value(obj, "extra1", "non-empty string") - - obj.extra2 = "not null" - manager.save(obj) - assert session_cls().query(Translation).count() == 3 - check_value(obj, "extra2", "not null") - - obj.extra1 = "" - manager.save(obj) - assert session_cls().query(Translation).count() == 3 - - obj.extra2 = None - manager.save(obj) - assert session_cls().query(Translation).count() == 2 - - -def test_load_and_save(translating_manager, session): - translator = Translator(Translation, session, 'language') - manager = translating_manager - translator.bind(manager) - - manager.save(CustomFieldsEntity) - obj = CustomFieldsEntity(id=1, identifier='foo', name='name') - manager.save(obj) - loaded = manager.serialize( - manager.get(CustomFieldsEntity, id=1) - ) - loaded['identifier'] = 'bar' - - manager.save( - manager.deserialize(loaded) - ) - - reloaded = manager.get(CustomFieldsEntity, id=1) - - assert translator.translate( - manager.serialize(reloaded)['name'] - ) == 'name' - - -def test_delete(session_cls, bound_manager): - manager = bound_manager - - manager.save(CustomFieldsEntity) - - obj1 = CustomFieldsEntity(id=1, name="value", extra1="", extra2=None) - obj2 = CustomFieldsEntity(id=2, name="value", extra1="", extra2=None) - manager.save(obj1) - manager.save(obj2) - assert session_cls().query(Translation).count() == 4 - - manager.delete(obj1) - assert session_cls().query(Translation).count() == 2 - - manager.delete(obj2) - assert session_cls().query(Translation).count() == 0 - - -def test_missing_bind(session, translating_manager): - manager = translating_manager - manager.save(CustomFieldsEntity) - obj = CustomFieldsEntity(id=1, name='English name') - with pytest.raises(NoTranslatorRegistered): - manager.save(obj) - - -def test_serializing_type(translating_manager): - # regression test - data = translating_manager.serialize(CustomFieldsEntity) - assert 'id' in data diff --git a/tests/kaiso/test_types.py b/tests/kaiso/test_types.py deleted file mode 100644 index cdbbb06..0000000 --- a/tests/kaiso/test_types.py +++ /dev/null @@ -1,130 +0,0 @@ -from __future__ import absolute_import - -import json - -import pytest - -from taal import TranslatableString, Translator -from taal.kaiso.types import get_context, get_message_id, make_from_obj - -from tests.models import ( - CustomFieldsEntity, NoCustomFieldsEntity, Translation, - create_translation_for_entity, MultipleUniques, InheritedUniques) - - -def test_field(manager): - manager.save(CustomFieldsEntity) - item = CustomFieldsEntity(id=0, identifier="foo") - manager.save(item) - - retrieved = manager.get(CustomFieldsEntity, id=0) - assert retrieved.identifier == "foo" - - -def test_cant_set_translatable_field_directly(manager): - manager.save(CustomFieldsEntity) - item = CustomFieldsEntity(name="foo") - with pytest.raises(RuntimeError) as excinfo: - manager.save(item) - assert excinfo.value.message.startswith( - "Cannot save directly to translated fields") - - -def test_load_unexpected_value(bound_manager): - manager = bound_manager - - manager.save(CustomFieldsEntity) - item = CustomFieldsEntity(id=1) - manager.save(item) - manager.query('MATCH (n:CustomFieldsEntity {id: 1}) SET n.name = "foo"') - - with pytest.raises(RuntimeError) as excinfo: - manager.get(CustomFieldsEntity, id=1) - assert excinfo.value.message.startswith( - "Unexpected value found in placeholder column") - - -def test_context_message_id(session, manager): - manager.save(CustomFieldsEntity) - item = CustomFieldsEntity(id=0) - manager.save(item) - - create_translation_for_entity( - session, manager, 'english', item, 'name', 'English name') - translation = session.query(Translation).one() - expected_context = "taal:kaiso_field:CustomFieldsEntity:name" - expected_message_id = json.dumps([("customfieldsentity", "id", 0)]) - - assert translation.context == expected_context - assert translation.message_id == expected_message_id - - -def test_message_id_for_multiple_uniques(manager): - manager.save(MultipleUniques) - item = MultipleUniques() - manager.save(item) - message_id = get_message_id(manager, item) - expected_message_id = json.dumps([ - ("multipleuniques", "id1", 1), - ("multipleuniques", "id2", 1), - ]) - assert message_id == expected_message_id - - -def test_message_id_for_inherited_uniques(manager): - manager.save(InheritedUniques) - item = InheritedUniques() - manager.save(item) - message_id = get_message_id(manager, item) - expected_message_id = json.dumps([ - ("inheriteduniques", "id3", 1), - ("multipleuniques", "id1", 1), - ("multipleuniques", "id2", 1), - ]) - assert message_id == expected_message_id - - -def test_get_translation(session, manager): - manager.save(CustomFieldsEntity) - item = CustomFieldsEntity() - manager.save(item) - - create_translation_for_entity( - session, manager, 'english', item, 'name', 'English name') - - context = get_context(manager, item, 'name') - message_id = get_message_id(manager, item) - translatable = TranslatableString( - context=context, message_id=message_id) - - translator = Translator(Translation, session, 'english') - translated_data = translator.translate(translatable) - - assert translated_data == 'English name' - - -def test_delete(session_cls, bound_manager): - manager = bound_manager - manager.save(CustomFieldsEntity) - item = CustomFieldsEntity(id=0, name="Name", extra1="", extra2=None) - manager.save(item) - - # make a fresh session each time - assert session_cls().query(Translation).count() == 2 - manager.delete(item) - assert session_cls().query(Translation).count() == 0 - - -def test_delete_no_translations(bound_manager): - manager = bound_manager - manager.save(NoCustomFieldsEntity) - item = NoCustomFieldsEntity(id=0) - manager.save(item) - manager.delete(item) - - -def test_make_from_obj(manager): - obj = CustomFieldsEntity(id=1) - translatable = make_from_obj(manager, obj, 'name', 'English name') - assert translatable.message_id == '[["customfieldsentity", "id", 1]]' - assert translatable.pending_value == 'English name' diff --git a/tests/models.py b/tests/models.py index e05c37a..5ebc76f 100644 --- a/tests/models.py +++ b/tests/models.py @@ -4,12 +4,9 @@ Column, Integer as SaInteger, String as SaString, Text, ForeignKey) from sqlalchemy.orm import relationship from sqlalchemy.ext.declarative import declarative_base -from kaiso.types import Entity -from kaiso.attributes import Integer as KaisoInteger, String as KaisoString from taal.models import TranslationMixin -from taal import kaiso as taal_kaiso, sqlalchemy as taal_sqlalchemy -from taal.kaiso import types as taal_kaiso_types +from taal import sqlalchemy as taal_sqlalchemy from taal.sqlalchemy import types as taal_sqlalchemy_types @@ -20,28 +17,6 @@ class Translation(TranslationMixin, Base): __tablename__ = "translations" -class CustomFieldsEntity(Entity): - id = KaisoInteger(unique=True) - identifier = KaisoString() - name = taal_kaiso.TranslatableString() - extra1 = taal_kaiso.TranslatableString() - extra2 = taal_kaiso.TranslatableString() - - -class NoCustomFieldsEntity(Entity): - id = KaisoInteger(unique=True) - identifier = KaisoString() - - -class MultipleUniques(Entity): - id1 = KaisoInteger(unique=True, default=1) - id2 = KaisoInteger(unique=True, default=1) - - -class InheritedUniques(MultipleUniques): - id3 = KaisoInteger(unique=True, default=1) - - class Parent(Base): __tablename__ = "test_parent" @@ -102,11 +77,3 @@ def create_translation_for_model( message_id = taal_sqlalchemy_types.get_message_id(obj) return _create_translation( session, language, context, message_id, translation_str) - - -def create_translation_for_entity( - session, manager, language, obj, field, translation_str): - context = taal_kaiso_types.get_context(manager, obj, field) - message_id = taal_kaiso_types.get_message_id(manager, obj) - return _create_translation( - session, language, context, message_id, translation_str) diff --git a/tests/test_models.py b/tests/test_models.py index 5b27b61..72305fa 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -7,7 +7,6 @@ from tests.models import Translation -@pytest.mark.usefixtures('manager') class TestModels(object): def test_create(self, session): translation = Translation( @@ -83,7 +82,6 @@ def test_case_sensitivity(self, session): translator.translate(translatable) -@pytest.mark.usefixtures('manager') class TestWriting(object): def test_save_translation(self, session, session_cls): translator = Translator(Translation, session, 'language') diff --git a/tests/test_strategies.py b/tests/test_strategies.py index 4819c85..cb3c002 100644 --- a/tests/test_strategies.py +++ b/tests/test_strategies.py @@ -13,7 +13,6 @@ SAMPLE_LANGUAGE = 'language ಠ_ಠ' -@pytest.mark.usefixtures('manager') class TestStrategies(object): def test_none_value(self, session): translator = Translator(Translation, session, SAMPLE_LANGUAGE) @@ -92,7 +91,7 @@ def test_invalid(self): language=None, strategy='invalid ಠ_ಠ', ) - assert 'Invalid strategy `invalid ಠ_ಠ`' in unicode(exc) + assert 'Invalid strategy `invalid ಠ_ಠ`' in str(exc) def test_invalid_override(self): translator = Translator( @@ -102,4 +101,4 @@ def test_invalid_override(self): ) with pytest.raises(ValueError) as exc: translator.translate(None, strategy='invalid ಠ_ಠ') - assert 'Invalid strategy `invalid ಠ_ಠ`' in unicode(exc) + assert 'Invalid strategy `invalid ಠ_ಠ`' in str(exc)