From 78d8ac042a4487fd959c654c0f39e2bd8677d487 Mon Sep 17 00:00:00 2001 From: Axel Hecht Date: Tue, 2 Mar 2021 21:56:09 +0100 Subject: [PATCH] Bug 1692430, black & flake8, pyupgrade, and automation (#5) * Drop mocked OrderedDict * Black & flake8 * pyupgrade * Black & flake8 setup.py * Add automated testing and linting --- .github/workflows/python.yml | 52 +++ lib/silme/__init__.py | 31 +- lib/silme/core/__init__.py | 2 +- lib/silme/core/entity.py | 51 ++- lib/silme/core/list.py | 18 +- lib/silme/core/package.py | 87 +++-- lib/silme/core/structure.py | 65 ++-- lib/silme/core/types/__init__.py | 3 +- lib/silme/core/types/factory.py | 18 +- lib/silme/core/types/lazydict.py | 84 +---- lib/silme/core/types/odict.py | 105 ------ lib/silme/format/__init__.py | 13 +- lib/silme/format/dtd/__init__.py | 26 +- lib/silme/format/dtd/parser.py | 52 +-- lib/silme/format/dtd/serializer.py | 36 +- lib/silme/format/dtd/structure.py | 16 +- lib/silme/format/inc/__init__.py | 16 +- lib/silme/format/inc/parser.py | 37 +- lib/silme/format/inc/serializer.py | 46 ++- lib/silme/format/inc/structure.py | 1 + lib/silme/format/ini/__init__.py | 18 +- lib/silme/format/ini/parser.py | 40 ++- lib/silme/format/ini/serializer.py | 31 +- lib/silme/format/ini/structure.py | 35 +- lib/silme/format/properties/__init__.py | 18 +- lib/silme/format/properties/parser.py | 45 +-- lib/silme/format/properties/serializer.py | 41 ++- lib/silme/format/properties/structure.py | 1 + pyproject.toml | 6 + setup.cfg | 6 + setup.py | 42 +-- tests/silme/core/test_entity.py | 149 ++++---- tests/silme/core/test_list.py | 122 ++++--- tests/silme/core/test_package.py | 153 ++++---- tests/silme/core/test_structure.py | 171 +++++---- tests/silme/core/types/lazydict.py | 415 ++++++++++++---------- 36 files changed, 1024 insertions(+), 1028 deletions(-) create mode 100644 .github/workflows/python.yml delete mode 100644 lib/silme/core/types/odict.py create mode 100644 pyproject.toml create mode 100644 setup.cfg diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml new file mode 100644 index 0000000..ae926a9 --- /dev/null +++ b/.github/workflows/python.yml @@ -0,0 +1,52 @@ +name: Python + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + test: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: [3.7, 3.8, 3.9] + + steps: + - uses: actions/checkout@v2 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip + python -m pip install tox + - name: Test + run: | + tox + + flake8: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: 3.9 + - name: Install dependencies + run: | + python -m pip install --upgrade pip + python -m pip install flake8==3.8.4 + - name: Lint with flake8 + run: | + flake8 . + + black: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - uses: psf/black@stable diff --git a/lib/silme/__init__.py b/lib/silme/__init__.py index 9530564..b8558f9 100644 --- a/lib/silme/__init__.py +++ b/lib/silme/__init__.py @@ -1,31 +1,24 @@ -VERSION = (0, 11, 0, '', 0) +VERSION = (0, 11, 0, "", 0) -short_names = { - 'alpha': 'a', - 'beta': 'b', - 'pre': 'pre', - 'final': '', - 'rc': 'rc' -} +short_names = {"alpha": "a", "beta": "b", "pre": "pre", "final": "", "rc": "rc"} def get_short_version(): - version = '%s.%s' % (VERSION[0], VERSION[1]) + version = "{}.{}".format(VERSION[0], VERSION[1]) if VERSION[2]: - version = '%s.%s' % (version, VERSION[2]) - version = '%s%s' % (version, - short_names.get(VERSION[3], VERSION[3])) - if VERSION[3] not in ('pre', 'final') and VERSION[4]: - version = '%s%s' % (version, VERSION[4]) + version = "{}.{}".format(version, VERSION[2]) + version = "{}{}".format(version, short_names.get(VERSION[3], VERSION[3])) + if VERSION[3] not in ("pre", "final") and VERSION[4]: + version = "{}{}".format(version, VERSION[4]) return version def get_version(): - version = '%s.%s' % (VERSION[0], VERSION[1]) + version = "{}.{}".format(VERSION[0], VERSION[1]) if VERSION[2]: - version = '%s.%s' % (version, VERSION[2]) + version = "{}.{}".format(version, VERSION[2]) if VERSION[3]: - version = '%s %s' % (version, VERSION[3]) - if VERSION[3] not in ('pre', 'final') and VERSION[4]: - version = '%s %s' % (version, VERSION[4]) + version = "{} {}".format(version, VERSION[3]) + if VERSION[3] not in ("pre", "final") and VERSION[4]: + version = "{} {}".format(version, VERSION[4]) return version diff --git a/lib/silme/core/__init__.py b/lib/silme/core/__init__.py index f3d2dd4..bebaab1 100644 --- a/lib/silme/core/__init__.py +++ b/lib/silme/core/__init__.py @@ -3,4 +3,4 @@ from .list import EntityList from .structure import Blob, Structure, Comment from .package import Package -__all__ = ['Blob', 'Entity', 'EntityList', 'Structure', 'Comment', 'Package'] +__all__ = ["Blob", "Entity", "EntityList", "Structure", "Comment", "Package"] diff --git a/lib/silme/core/entity.py b/lib/silme/core/entity.py index 48789d3..44459d1 100644 --- a/lib/silme/core/entity.py +++ b/lib/silme/core/entity.py @@ -10,27 +10,16 @@ by subclasses of Entity class, and possibly one of the Value classes. By default silme.core.Value returns one of its more specific subclasses. """ import copy -from silme.core.types.odict import OrderedDict +from collections import OrderedDict -__all__ = ['is_string', 'string', 'is_entity', 'Entity'] +__all__ = ["is_string", "is_entity", "Entity"] -try: - basestring - string = unicode - def is_string(v): - """ - Tests if the argument is a string - """ - return isinstance(v, basestring) -except: - string = str - - def is_string(v): - """ - Tests if the argument is a string - """ - return isinstance(v, str) +def is_string(v): + """ + Tests if the argument is a string + """ + return isinstance(v, str) def is_entity(v): @@ -40,9 +29,9 @@ def is_entity(v): return isinstance(v, Entity) -class Value(object): +class Value: def __new__(cls, *args, **kwargs): - #if cls is not Value: + # if cls is not Value: # return object.__new__(cls) try: i = args[0] @@ -60,24 +49,26 @@ class Value(object): return ComplexValue(*args, **kwargs) -class SimpleValue(string, Value): +class SimpleValue(str, Value): """ A simple, string based value for an entity """ + def get(self, *args, **kwargs): return self def __setitem__(self, key, value): - raise TypeError("'%s' object does not support item assignment" % - type(self).__name__) + raise TypeError( + "'%s' object does not support item assignment" % type(self).__name__ + ) def __getitem__(self, key): - raise TypeError("'%s' object is unsubscriptable" % - type(self).__name__) + raise TypeError("'%s' object is unsubscriptable" % type(self).__name__) def __delitem__(self, key): - raise TypeError("'%s' object does not support item deletion" % - type(self).__name__) + raise TypeError( + "'%s' object does not support item deletion" % type(self).__name__ + ) class ComplexValue(Value): @@ -103,6 +94,7 @@ class ComplexValue(Value): else: return val + class ListValue(list, ComplexValue): """ A value that is a list of values @@ -116,19 +108,21 @@ class DictValue(OrderedDict, ComplexValue): """ A value that is a dictionary of values """ + def get(self, key=None, *args, **kwargs): if key is not None: return self[key] return list(self.values())[0] -class Entity(object): +class Entity: """ An entity is a basic localization data unit with a unique id and a value An ID represents a handler which a developer uses to call for the given entity and a value is any sort of localizable data bound to that id. """ + _select_value = None def __init__(self, id, value=None): @@ -181,4 +175,3 @@ class Entity(object): @property def values(self): return copy.copy(self._value) - diff --git a/lib/silme/core/list.py b/lib/silme/core/list.py index 505f260..0d59d16 100644 --- a/lib/silme/core/list.py +++ b/lib/silme/core/list.py @@ -22,11 +22,12 @@ class EntityList(ComplexDict): """ EntityList is a list of entities bundled together. """ + uri = None def __init__(self, id, *args, **kwargs): self.id = id - super(EntityList, self).__init__() + super().__init__() for i in args: if is_entitylist(i): for entity in i.entities(): @@ -36,8 +37,8 @@ class EntityList(ComplexDict): def __repr__(self): if not self: - return '%s()' % (self.__class__.__name__,) - return '%s(%r)' % (self.__class__.__name__, tuple(self.keys())) + return f"{self.__class__.__name__}()" + return "{}({!r})".format(self.__class__.__name__, tuple(self.keys())) def add(self, entity): """Adds new entity to EntityList""" @@ -54,8 +55,7 @@ class EntityList(ComplexDict): return list(self.values()) def value(self, id): - """Returns entity value from EntityList. - """ + """Returns entity value from EntityList.""" return self[id].value @@ -64,8 +64,9 @@ class ValueList(EntityList): ValueList is a list of entity values - similar to EntityList but with an intention to store only the values of entities. """ + def __init__(self, id, *args, **kwargs): - super(ValueList, self).__init__(id, *args, **kwargs) + super().__init__(id, *args, **kwargs) def add(self, entity): """Adds new entity to the ValueList""" @@ -79,8 +80,9 @@ class ValueList(EntityList): def entities(self): """Raises a TypeError since ValueList does not support this method""" - raise TypeError("'%s' object does not support entities method" % - type(self).__name__) + raise TypeError( + "'%s' object does not support entities method" % type(self).__name__ + ) def value(self, id): """Returns entity value from the ValueList diff --git a/lib/silme/core/package.py b/lib/silme/core/package.py index 59af02b..ec956f5 100644 --- a/lib/silme/core/package.py +++ b/lib/silme/core/package.py @@ -2,11 +2,12 @@ from silme.core.list import is_entitylist from silme.core.structure import Blob, Structure from silme.core.types import LazyDict -class Package(object): + +class Package: """ Package is a container that stores set of data structures (Structures, EntityLists, Blobs) and sub-packages. - + It's easiest to think of it as a filesystem directory that can store files and nested directories. It abstracts the package from the file system, so once you load @@ -16,6 +17,7 @@ class Package(object): If you load a directory into memory and then serialize it back to disk, the two directories should be identical minus any modifications you made. """ + uri = None def __init__(self, id, lazy=True): @@ -25,17 +27,15 @@ class Package(object): self.id = id def __len__(self): - return len(self._packages)+len(self._structures) + return len(self._packages) + len(self._structures) def __iter__(self): - for i in self._packages.items(): - yield i - for i in self._structures.items(): - yield i + yield from self._packages.items() + yield from self._structures.items() raise StopIteration def __repr__(self): - return '%s(%s)' % (self.__class__.__name__, self.id) + return f"{self.__class__.__name__}({self.id})" def __contains__(self, id): if id in self._packages.keys(): @@ -73,10 +73,10 @@ class Package(object): def add_structure(self, struct, path=None): """ Adds a structure to the Package. - + Optional parameter path allows to define exact position inside the package where the structure should be added. - + For example l10npack.add_structure(l10nstruct, 'pkg1/pkg2') is equal to l10npack.get_package('pkg1').get_package('pkg2').add_structure(l10nstruct) with the difference that it will create missing sub packages if needed. @@ -84,22 +84,21 @@ class Package(object): if not path: self._structures[struct.id] = struct else: - path = path.split('/') + path = path.split("/") if path[0] in self._packages: - self._packages[path[0]].add_structure(struct, - '/'.join(path[1:])) + self._packages[path[0]].add_structure(struct, "/".join(path[1:])) else: sub_l10n_pack = Package(path[0]) self.add_package(sub_l10n_pack) - sub_l10n_pack.add_structure(struct, '/'.join(path[1:])) + sub_l10n_pack.add_structure(struct, "/".join(path[1:])) def add_package(self, package, path=None): """ Adds a package to Package. - + Optional parameter path allows to declare place inside the package where the subpackage should be added. - + For example l10npack.add_package(subl10npack, 'pkg1/pkg2') is similar to l10npack.get_package('pkg1').get_package('pkg2').add_package(subl10npack) with the difference that it will create missing sub packages. @@ -107,14 +106,13 @@ class Package(object): if not path: self._packages[package.id] = package else: - path = path.split('/') + path = path.split("/") if path[0] in self._packages: - self._packages[path[0]].add_package(package, - '/'.join(path[1:])) + self._packages[path[0]].add_package(package, "/".join(path[1:])) else: sub_l10n_pack = Package(path[0]) self._packages[path[0]] = sub_l10n_pack - sub_l10n_pack.add_package(package, '/'.join(path[1:])) + sub_l10n_pack.add_package(package, "/".join(path[1:])) def packages(self, ids=False): """ @@ -127,28 +125,28 @@ class Package(object): else: return list(self._packages.values()) - def structures(self, type='all', ids=False): + def structures(self, type="all", ids=False): """ Returns a list of structures inside Package. If parameter ids is set to True list of names is returned instead of structures. """ - if type == 'all': + if type == "all": if ids: return list(self._structures.keys()) else: return list(self._structures.values()) else: l10n_structures = {} - if type == 'list': + if type == "list": type = is_entitylist - elif type == 'structure': - type = lambda x:isinstance(x, Structure) - elif type == 'blob': - type = lambda x:isinstance(x, Blob) + elif type == "structure": + type = lambda x: isinstance(x, Structure) + elif type == "blob": + type = lambda x: isinstance(x, Blob) for struct in self._structures: if type(self._structures[struct]): - l10n_structures[struct] = self._structures[struct] + l10n_structures[struct] = self._structures[struct] if ids: return list(l10n_structures.keys()) else: @@ -157,26 +155,27 @@ class Package(object): def entities(self, recursive=True, path=False): """ Returns a list of all entities inside the Package - + If optional parameter recursive is set to True it will return all packages from this package and its subpackages. """ entities = [] - - + if path is True: - spath = '' + spath = "" elif path is not False: - spath='%s/%s' % (path, self.id) if path else self.id + spath = f"{path}/{self.id}" if path else self.id else: spath = path if recursive: for pack in self._packages.values(): entities.extend(pack.entities(path=spath)) for i in self._structures: - if isinstance(self._structures[i], Structure) or is_entitylist(self._structures[i]): + if isinstance(self._structures[i], Structure) or is_entitylist( + self._structures[i] + ): elist = self._structures[i].entities() - spath2 = '%s/%s' % (spath, i) if spath else i + spath2 = f"{spath}/{i}" if spath else i entities.extend([(e, spath2) for e in elist]) return entities @@ -190,32 +189,32 @@ class Package(object): try: return self._structures[id] except KeyError: - raise KeyError('No such structure: %s' % id) - + raise KeyError("No such structure: %s" % id) + def package(self, id): try: return self._packages[id] except KeyError: - raise KeyError('No such package: %s' % id) + raise KeyError("No such package: %s" % id) def element(self, path): """ Returns an element from inside Package by its path. - + l10npack.element('pkg1/pkg2/structure.po') will return the same as l10npack.package('pkg1').get_package('pkg2').structure('structure.po') - + If the path is empty the result will be None """ if not path: return None - elems = path.split('/') + elems = path.split("/") if len(elems) == 0: return None - if len(elems) == 2 and elems[1] == '': + if len(elems) == 2 and elems[1] == "": elems = elems[:-1] if len(elems) == 1: @@ -230,13 +229,13 @@ class Package(object): return None else: try: - return self._packages[elems[0]].element('/'.join(elems[1:])) + return self._packages[elems[0]].element("/".join(elems[1:])) except KeyError: raise def remove_structure(self, id): del self._structures[id] - + def remove_package(self, id): del self._packages[id] diff --git a/lib/silme/core/structure.py b/lib/silme/core/structure.py index fc6144d..527e8f0 100644 --- a/lib/silme/core/structure.py +++ b/lib/silme/core/structure.py @@ -21,7 +21,7 @@ from silme.core.list import EntityList from functools import partial -class Blob(object): +class Blob: """ A Blob is a data stream that is not localizable, but may be a part of a package of structures. @@ -32,6 +32,7 @@ class Blob(object): The main use case for the class is to preserve the non-translatable data in a in-memory representation of a package (a directory etc.) """ + uri = None id = None source = None @@ -40,7 +41,7 @@ class Blob(object): self.id = id def __repr__(self): - return '%s(%s)' % (self.__class__.__name__, self.id) + return f"{self.__class__.__name__}({self.id})" class Structure(list, Blob): @@ -53,6 +54,7 @@ class Structure(list, Blob): edit it, and save it back preserving as much of the file structure as possible which in turn may be important for all VCS's based workflows. """ + _process_cb = None # process callback function def __init__(self, id): @@ -76,7 +78,7 @@ class Structure(list, Blob): """ if type(pos) == tuple: p = self.entity_pos(pos[1]) - return p + 1 if pos[0] == 'after' else p + return p + 1 if pos[0] == "after" else p elif pos is None: return None else: @@ -110,9 +112,9 @@ class Structure(list, Blob): return self.entity(id).value def keys(self): - """returns a list of id's of entities from the Structure - """ + """returns a list of id's of entities from the Structure""" return [item.id for item in self if isinstance(item, Entity)] + ids = keys def entities(self): @@ -122,31 +124,27 @@ class Structure(list, Blob): return [item for item in self if is_entity(item)] def entitylist(self): - """Returns an EntityList object with entities from the Structure. - """ - return EntityList(self.id, - *[item for item in self if is_entity(item)]) + """Returns an EntityList object with entities from the Structure.""" + return EntityList(self.id, *[item for item in self if is_entity(item)]) def entities_with_path(self, path_prefix): """Returns a dict of all entities from the Structure in a form of d[entity.id] = (entity, path) """ - spath = '%s/%s' % (path_prefix, self.id) if path_prefix else self.id - return dict([(item.id, - (item, spath)) for item in self if is_entity(item)]) + spath = f"{path_prefix}/{self.id}" if path_prefix else self.id + return {item.id: (item, spath) for item in self if is_entity(item)} def __contains__(self, id): - """returns True if an entity with given id exists - """ + """returns True if an entity with given id exists""" for item in self: if is_entity(item) and item.id == id: return True return False + has_entity = __contains__ def modify_entity(self, id, value): - """modifies an entity value - """ + """modifies an entity value""" found = False for item in self: if is_entity(item) and item.id == id: @@ -156,32 +154,29 @@ class Structure(list, Blob): if found: return True else: - raise KeyError('No such entity') + raise KeyError("No such entity") def entity(self, id): - """returns an entity for a given id - """ + """returns an entity for a given id""" for item in self: if is_entity(item) and item.id == id: return item - raise KeyError('No such entity') + raise KeyError("No such entity") def entity_pos(self, id): - """returns the position of an entity in the Structure - """ + """returns the position of an entity in the Structure""" for i, item in enumerate(self): if is_entity(item) and item.id == id: return i - raise KeyError('No such entity') + raise KeyError("No such entity") def remove_entity(self, id): - """removes an entity for the given id or raises KeyError - """ + """removes an entity for the given id or raises KeyError""" for i, item in enumerate(self): if is_entity(item) and item.id == id: del self[i] return True - raise KeyError('[%s] No such entity: %s' % (self.id, id)) + raise KeyError(f"[{self.id}] No such entity: {id}") def add_comment(self, comment, pos=None): self.add_at_pos(comment, pos) @@ -208,9 +203,9 @@ class Structure(list, Blob): elif item is None: return 0 else: - raise Exception('Cannot add element of type "' + - type(item).__name__ + - '" to the Structure') + raise Exception( + f'Cannot add element of type "{type(item).__name__}" to the Structure' + ) def add_elements(self, sequence, pos=None): """ @@ -226,7 +221,7 @@ class Structure(list, Blob): if isinstance(sequence, dict): sequence = sequence.values() pos = self._get_pos(pos) - #a=a[:2]+b+a[2:] ? + # a=a[:2]+b+a[2:] ? for i in sequence: shift += self.add(i, pos=(None if pos is None else pos + shift)) return shift @@ -244,7 +239,7 @@ class Structure(list, Blob): return self._process_cb() except TypeError: - raise Exception('process callback function not specified') + raise Exception("process callback function not specified") def set_process_cb(self, cb): self._process_cb = partial(cb, self) @@ -263,13 +258,13 @@ class Comment(Structure): self.id = None def __repr__(self): - string = ' 1: - raise TypeError('expected at most 1 arguments, got %d' % len(args)) - try: - self.__end - except AttributeError: - self.clear() - self.update(*args, **kwds) - - def clear(self): - self.__end = end = [] - end += [None, end, end] # sentinel node for doubly linked list - self.__map = {} # key --> [key, prev, next] - dict.clear(self) - - def __setitem__(self, key, value): - if key not in self: - end = self.__end - curr = end[1] - curr[2] = end[1] = self.__map[key] = [key, curr, end] - dict.__setitem__(self, key, value) - - def __delitem__(self, key): - dict.__delitem__(self, key) - key, prev, next = self.__map.pop(key) - prev[2] = next - next[1] = prev - - def __iter__(self): - end = self.__end - curr = end[2] - while curr is not end: - yield curr[0] - curr = curr[2] - - def __reversed__(self): - end = self.__end - curr = end[1] - while curr is not end: - yield curr[0] - curr = curr[1] - - def popitem(self, last=True): - if not self: - raise KeyError('dictionary is empty') - key = reversed(self).next() if last else iter(self).next() - value = self.pop(key) - return key, value - - def __reduce__(self): - items = [[k, self[k]] for k in self] - tmp = self.__map, self.__end - del self.__map, self.__end - inst_dict = vars(self).copy() - self.__map, self.__end = tmp - if inst_dict: - return (self.__class__, (items,), inst_dict) - return self.__class__, (items,) - - def keys(self): - return list(self) - - setdefault = DictMixin.setdefault - update = DictMixin.update - pop = DictMixin.pop - values = DictMixin.values - items = DictMixin.items - iterkeys = DictMixin.iterkeys - itervalues = DictMixin.itervalues - iteritems = DictMixin.iteritems - - def __repr__(self): - if not self: - return '%s()' % (self.__class__.__name__,) - return '%s(%r)' % (self.__class__.__name__, self.items()) - - def copy(self): - return self.__class__(self) - - @classmethod - def fromkeys(cls, iterable, value=None): - d = cls() - for key in iterable: - d[key] = value - return d - - def __eq__(self, other): - if isinstance(other, OrderedDict): - return len(self)==len(other) and \ - all(p==q for p, q in zip(self.items(), other.items())) - return dict.__eq__(self, other) - - def __ne__(self, other): - return not self == other diff --git a/lib/silme/format/__init__.py b/lib/silme/format/__init__.py index a291d75..6728421 100644 --- a/lib/silme/format/__init__.py +++ b/lib/silme/format/__init__.py @@ -1,7 +1,8 @@ import os import sys -class Manager(object): + +class Manager: formats = {} names = {} path = [] @@ -9,7 +10,7 @@ class Manager(object): @classmethod def _import(cls, fp): added = list(set(cls.path).difference(sys.path)) - sys.path = added + sys.path # we want to have the locally added in front + sys.path = added + sys.path # we want to have the locally added in front module = __import__(fp, globals(), locals(), [], 1) sys.path = list(set(sys.path).difference(added)) return module @@ -40,9 +41,9 @@ class Manager(object): try: module = cls._import(name) module.register(cls) - except: + except Exception: pass - + @classmethod def get(cls, name=None, path=None): if name: @@ -52,11 +53,11 @@ class Manager(object): try: module = cls._import(name) except ImportError: - raise KeyError ('no matching format') + raise KeyError("no matching format") return module.FormatParser() elif path: try: return cls.formats[os.path.splitext(path)[1][1:].lower()] except KeyError: pass - raise KeyError('no matching parser') + raise KeyError("no matching parser") diff --git a/lib/silme/format/dtd/__init__.py b/lib/silme/format/dtd/__init__.py index e3ccd0d..790ab1c 100644 --- a/lib/silme/format/dtd/__init__.py +++ b/lib/silme/format/dtd/__init__.py @@ -1,37 +1,39 @@ from .parser import DTDParser as Parser from .serializer import DTDSerializer as Serializer -class FormatParser(): - name = 'dtd' - desc = 'DTD reader/writer' - extensions = ['dtd'] - encoding = 'utf_8' # allowed encoding - fallback = ['utf_8_sig'] - + +class FormatParser: + name = "dtd" + desc = "DTD reader/writer" + extensions = ["dtd"] + encoding = "utf_8" # allowed encoding + fallback = ["utf_8_sig"] + @classmethod - def dump_structure (cls, l10nobject): + def dump_structure(cls, l10nobject): text = Serializer.serialize(l10nobject) return text @classmethod - def dump_entitylist (cls, elist): + def dump_entitylist(cls, elist): text = Serializer.dump_entitylist(elist) return text @classmethod - def get_idlist (cls, text): + def get_idlist(cls, text): l10nobject = Parser.parse_to_idlist(text) return l10nobject @classmethod - def get_entitylist (cls, text): + def get_entitylist(cls, text): l10nobject = Parser.parse_to_entitylist(text) return l10nobject @classmethod - def get_structure (cls, text): + def get_structure(cls, text): l10nobject = Parser.parse(text) return l10nobject + def register(Manager): Manager.register(FormatParser) diff --git a/lib/silme/format/dtd/parser.py b/lib/silme/format/dtd/parser.py index 16551cd..9b54ca9 100644 --- a/lib/silme/format/dtd/parser.py +++ b/lib/silme/format/dtd/parser.py @@ -4,17 +4,22 @@ from silme.core.list import EntityList import re -class DTDParser(object): - name_start_char = u':A-Z_a-z\xC0-\xD6\xD8-\xF6\xF8-\u02FF' + \ - u'\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF'+\ - u'\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD' - name_char = name_start_char + r'\-\.0-9' + u'\xB7\u0300-\u036F\u203F-\u2040' - name = u'[' + name_start_char + u'][' + name_char + u']*' +class DTDParser: + name_start_char = ( + ":A-Z_a-z\xC0-\xD6\xD8-\xF6\xF8-\u02FF" + "\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF" + "\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD" + ) + name_char = name_start_char + r"\-\.0-9" + "\xB7\u0300-\u036F\u203F-\u2040" + name = "[" + name_start_char + "][" + name_char + "]*" patterns = { - 'id': re.compile(u']*>', re.S | re.U), - 'entity': re.compile(u'', re.S | re.U), - 'comment': re.compile(u'\)', re.M | re.S) + "id": re.compile(r"]*>", re.S | re.U), + "entity": re.compile( + r"", + re.S | re.U, + ), + "comment": re.compile(r"\)", re.M | re.S), } @classmethod @@ -25,35 +30,36 @@ class DTDParser(object): @classmethod def parse_to_idlist(cls, text): - text = cls.patterns['comment'].sub('', text) - ids = [m[0] for m in cls.patterns['id'].findall(text)] + text = cls.patterns["comment"].sub("", text) + ids = [m[0] for m in cls.patterns["id"].findall(text)] return ids @classmethod def parse_to_entitylist(cls, text): elist = EntityList(id=None) - text = cls.patterns['comment'].sub('', text) - for match in cls.patterns['entity'].findall(text): + text = cls.patterns["comment"].sub("", text) + for match in cls.patterns["entity"].findall(text): elist.add(Entity(match[0], match[1][1:-1])) return elist @classmethod def parse_entity(cls, text): - match = cls.patterns['entity'].match(text) + match = cls.patterns["entity"].match(text) if not match: raise Exception() entity = Entity(match.group(0)) entity.set_value(match.group(1)[1:-1]) return entity - @classmethod - def build_element_list(cls, text, obj, type='comment', code='default', pointer=0, end=None): + def build_element_list( + cls, text, obj, type="comment", code="default", pointer=0, end=None + ): cls.split_comments(text, obj, code) @classmethod - def split_comments(cls, text, obj, code='default', pointer=0, end=None): - pattern = cls.patterns['comment'] + def split_comments(cls, text, obj, code="default", pointer=0, end=None): + pattern = cls.patterns["comment"] if end: match = pattern.search(text, pointer, end) else: @@ -74,8 +80,8 @@ class DTDParser(object): cls.split_entities(text, obj, code=code, pointer=pointer) @classmethod - def split_entities(cls, text, obj, code='default', pointer=0, end=None): - pattern = cls.patterns['entity'] + def split_entities(cls, text, obj, code="default", pointer=0, end=None): + pattern = cls.patterns["entity"] if end: match = pattern.search(text, pointer, end) else: @@ -87,8 +93,10 @@ class DTDParser(object): groups = match.groups() entity = Entity(groups[0]) entity.set_value(groups[1][1:-1]) - entity.params['source'] = { - 'type': 'dtd', 'string': match.group(0), 'valpos': match.start(2)+1-st0 + entity.params["source"] = { + "type": "dtd", + "string": match.group(0), + "valpos": match.start(2) + 1 - st0, } obj.append(entity) pointer = match.end(0) diff --git a/lib/silme/format/dtd/serializer.py b/lib/silme/format/dtd/serializer.py index 3cee298..3b81152 100644 --- a/lib/silme/format/dtd/serializer.py +++ b/lib/silme/format/dtd/serializer.py @@ -1,30 +1,32 @@ -from ...core import Entity, EntityList, Comment +from ...core import Comment from silme.core.entity import is_entity -from .structure import DTDStructure from .parser import DTDParser as Parser -class DTDSerializer(): + +class DTDSerializer: @classmethod def serialize(cls, l10nobject): - string = u''.join([cls.dump_element(element) for element in l10nobject]) + string = "".join([cls.dump_element(element) for element in l10nobject]) return string @classmethod - def dump_element (cls, element, fallback=None): + def dump_element(cls, element, fallback=None): if is_entity(element): return cls.dump_entity(element, fallback=fallback) - elif isinstance(element,Comment): + elif isinstance(element, Comment): return cls.dump_comment(element) else: return element @classmethod - def dump_entity (cls, entity, fallback=None): - if 'source' in entity.params and entity.params['source']['type']=='dtd': - match = Parser.patterns['entity'].match(entity.params['source']['string']) + def dump_entity(cls, entity, fallback=None): + if "source" in entity.params and entity.params["source"]["type"] == "dtd": + match = Parser.patterns["entity"].match(entity.params["source"]["string"]) - middle = entity.params['source']['string'][match.end(1):match.start(2)+1] - end = entity.params['source']['string'][match.end(2)-1:] + middle = entity.params["source"]["string"][ + match.end(1) : match.start(2) + 1 + ] + end = entity.params["source"]["string"][match.end(2) - 1 :] if middle.endswith('"') and '"' in entity.value: middle = middle.replace('"', "'") @@ -33,24 +35,24 @@ class DTDSerializer(): middle = middle.replace("'", '"') end = end.replace("'", '"') - string = entity.params['source']['string'][0:match.start(1)] + string = entity.params["source"]["string"][0 : match.start(1)] string += entity.id string += middle string += entity.value string += end else: - string = u'' + string = "' return string @classmethod def dump_entitylist(cls, elist): - string = u''.join([cls.dump_entity(entity)+'\n' for entity in elist.values()]) + string = "".join([cls.dump_entity(entity) + "\n" for entity in elist.values()]) return string @classmethod - def dump_comment (cls, comment): - string = u'' + string += "-->" return string diff --git a/lib/silme/format/dtd/structure.py b/lib/silme/format/dtd/structure.py index 81e605f..731b258 100644 --- a/lib/silme/format/dtd/structure.py +++ b/lib/silme/format/dtd/structure.py @@ -1,19 +1,21 @@ -from silme.core import Entity, Structure, Comment +from silme.core import Entity, Structure import re + def process_entity(entity, subs): for code in entity._value.keys(): - entity._value[code] = re.sub('\&([^$]+)\;', - lambda m:subs[m.group(1)], - entity._value[code]) + entity._value[code] = re.sub( + r"\&([^$]+)\;", lambda m: subs[m.group(1)], entity._value[code] + ) + def process(self): - if 'exents' not in self.params or \ - not self.params['exents']: + if "exents" not in self.params or not self.params["exents"]: return for elem in self: if isinstance(elem, Entity): - process_entity(elem, self.params['exents']) + process_entity(elem, self.params["exents"]) + class DTDStructure(Structure): def __init__(self, id): diff --git a/lib/silme/format/inc/__init__.py b/lib/silme/format/inc/__init__.py index 14945eb..b9dcc0c 100644 --- a/lib/silme/format/inc/__init__.py +++ b/lib/silme/format/inc/__init__.py @@ -2,30 +2,30 @@ from .parser import IncParser as Parser from .serializer import IncSerializer as Serializer -class FormatParser(object): - name = 'inc' +class FormatParser: + name = "inc" desc = "INC reader/writer" - extensions = ['inc'] - encoding = 'utf_8' # allowed encoding + extensions = ["inc"] + encoding = "utf_8" # allowed encoding fallback = None @classmethod - def dump_structure (cls, l10nobject): + def dump_structure(cls, l10nobject): text = Serializer.serialize(l10nobject) return text @classmethod - def dump_entitylist (cls, elist): + def dump_entitylist(cls, elist): text = Serializer.dump_entitylist(elist) return text @classmethod - def get_entitylist (cls, text): + def get_entitylist(cls, text): l10nobject = Parser.parse_to_entitylist(text) return l10nobject @classmethod - def get_structure (cls, text): + def get_structure(cls, text): l10nobject = Parser.parse(text) return l10nobject diff --git a/lib/silme/format/inc/parser.py b/lib/silme/format/inc/parser.py index 846d092..c7472a1 100644 --- a/lib/silme/format/inc/parser.py +++ b/lib/silme/format/inc/parser.py @@ -2,12 +2,14 @@ from ...core import EntityList, Entity, Comment from .structure import IncStructure import re -class IncParser(): - patterns = {} - patterns['entity'] = re.compile(r'#define[ \t]+(?P\w+)(?:[ \t](?P[^\n]*))?', re.M) - patterns['comment'] = re.compile('^(# [^\n]*\n?)+',re.M) -#define firefox_about About Us +class IncParser: + patterns = {} + patterns["entity"] = re.compile( + r"#define[ \t]+(?P\w+)(?:[ \t](?P[^\n]*))?", re.M + ) + patterns["comment"] = re.compile("^(# [^\n]*\n?)+", re.M) + # define firefox_about About Us @classmethod def parse(cls, text): @@ -19,15 +21,15 @@ class IncParser(): @classmethod def parse_to_entitylist(cls, text): entitylist = EntityList(id=None) - text = cls.patterns['comment'].sub('', text) - matchlist = cls.patterns['entity'].findall(text) + text = cls.patterns["comment"].sub("", text) + matchlist = cls.patterns["entity"].findall(text) for match in matchlist: entitylist.add(Entity(match[0], match[1])) return entitylist @classmethod def parse_entity(cls, text): - match = self.patterns['entity'].match(text) + match = cls.patterns["entity"].match(text) if not match: raise Exception() entity = Entity(match.group(1)) @@ -35,12 +37,12 @@ class IncParser(): return entity @classmethod - def build_element_list (cls, text, object, type='comment', pointer=0, end=None): + def build_element_list(cls, text, object, type="comment", pointer=0, end=None): cls.split_comments(text, object) @classmethod def split_comments(cls, text, object, pointer=0, end=None): - pattern = cls.patterns['comment'] + pattern = cls.patterns["comment"] if end: match = pattern.search(text, pointer, end) else: @@ -49,9 +51,8 @@ class IncParser(): st0 = match.start(0) if st0 > pointer: cls.split_entities(text, object, pointer=pointer, end=st0) - groups = match.groups() comment = Comment() - cls.split_entities(match.group(0)[2:].replace('\n# ','\n'), comment) + cls.split_entities(match.group(0)[2:].replace("\n# ", "\n"), comment) object.append(comment) pointer = match.end(0) if end: @@ -63,7 +64,7 @@ class IncParser(): @classmethod def split_entities(cls, text, object, pointer=0, end=None): - pattern = cls.patterns['entity'] + pattern = cls.patterns["entity"] if end: match = pattern.search(text, pointer, end) else: @@ -74,10 +75,12 @@ class IncParser(): object.append(text[pointer:st0]) groups = match.groups() entity = Entity(groups[0]) - entity.set_value(groups[1] or '') - entity.params['source'] = {'type':'inc', - 'string':match.group(0), - 'valpos':match.start(2)-st0} + entity.set_value(groups[1] or "") + entity.params["source"] = { + "type": "inc", + "string": match.group(0), + "valpos": match.start(2) - st0, + } object.append(entity) pointer = match.end(0) if end: diff --git a/lib/silme/format/inc/serializer.py b/lib/silme/format/inc/serializer.py index e442963..7534914 100644 --- a/lib/silme/format/inc/serializer.py +++ b/lib/silme/format/inc/serializer.py @@ -1,52 +1,60 @@ -from ...core import EntityList, Entity, Comment -from .structure import IncStructure +from ...core import Entity, Comment from .parser import IncParser as Parser import re -class IncSerializer(): + +class IncSerializer: @classmethod def serialize(cls, l10nobject): - string = u''.join([cls.dump_element(element) for element in l10nobject]) + string = "".join([cls.dump_element(element) for element in l10nobject]) return string @classmethod def dump_element(cls, element, fallback=None): if isinstance(element, Entity): return cls.dump_entity(element, fallback=fallback) - elif isinstance(element,Comment): + elif isinstance(element, Comment): return cls.dump_comment(element) else: return element @classmethod - def dump_entity (cls, entity, fallback=None): - if 'source' in entity.params and entity.params['source']['type']=='properties': - match = Parser.patterns['entity'].match(entity.params['source']['string']) - string = entity.params['source']['string'][0:match.start(1)] + def dump_entity(cls, entity, fallback=None): + if ( + "source" in entity.params + and entity.params["source"]["type"] == "properties" + ): + match = Parser.patterns["entity"].match(entity.params["source"]["string"]) + string = entity.params["source"]["string"][0 : match.start(1)] string += entity.id - string += entity.params['source']['string'][match.end(1):match.start(2)] + string += entity.params["source"]["string"][match.end(1) : match.start(2)] string += entity.get_value(fallback) - string += entity.params['source']['string'][match.end(2):] + string += entity.params["source"]["string"][match.end(2) :] else: - string = u'#define %s %s' % (entity.id, entity.get_value(fallback)) + string = "#define {} {}".format(entity.id, entity.get_value(fallback)) return string @classmethod def dump_entitylist(cls, elist, fallback=None): if not fallback: fallback = elist.fallback - string = u''.join([cls.dump_entity(entity, fallback)+'\n' for entity in elist.get_entities()]) + string = "".join( + [ + cls.dump_entity(entity, fallback) + "\n" + for entity in elist.get_entities() + ] + ) return string @classmethod - def dump_comment (cls, comment): - string = u'' + def dump_comment(cls, comment): + string = "" for element in comment: string += cls.dump_element(element) if string: - pattern = re.compile('\n') - string = pattern.sub('\n# ', string) - string = '# ' + string - if string.endswith('# '): + pattern = re.compile("\n") + string = pattern.sub("\n# ", string) + string = "# " + string + if string.endswith("# "): string = string[:-2] return string diff --git a/lib/silme/format/inc/structure.py b/lib/silme/format/inc/structure.py index a1b3a67..edaa646 100644 --- a/lib/silme/format/inc/structure.py +++ b/lib/silme/format/inc/structure.py @@ -1,4 +1,5 @@ from ...core.structure import Structure + class IncStructure(Structure): pass diff --git a/lib/silme/format/ini/__init__.py b/lib/silme/format/ini/__init__.py index 950cb34..08186f9 100644 --- a/lib/silme/format/ini/__init__.py +++ b/lib/silme/format/ini/__init__.py @@ -1,31 +1,31 @@ from .parser import Parser -from .structure import Structure from .serializer import Serializer -class FormatParser(): - name = 'ini' + +class FormatParser: + name = "ini" desc = "Ini reader/writer" - extensions = ['ini'] - encoding = 'utf_8' # allowed encoding + extensions = ["ini"] + encoding = "utf_8" # allowed encoding fallback = None @classmethod - def dump_structure (cls, l10nobject): + def dump_structure(cls, l10nobject): text = Serializer.serialize(l10nobject) return text @classmethod - def dump_entitylist (cls, elist): + def dump_entitylist(cls, elist): text = Serializer.dump_entitylist(elist) return text @classmethod - def get_entitylist (cls, text): + def get_entitylist(cls, text): l10nobject = Parser.parse_to_entitylist(text) return l10nobject @classmethod - def get_structure (cls, text): + def get_structure(cls, text): l10nobject = Parser.parse(text) return l10nobject diff --git a/lib/silme/format/ini/parser.py b/lib/silme/format/ini/parser.py index dabe1bb..ba2756d 100644 --- a/lib/silme/format/ini/parser.py +++ b/lib/silme/format/ini/parser.py @@ -1,14 +1,16 @@ from ...core import EntityList, Entity, Comment from .structure import Structure, Section -from silme.core.list import EntityList import re -class Parser(): - patterns = {} - patterns['entity'] = re.compile('^[ \t]*([^#!\s\n][^=:\n]*?)[ \t]*[:=][ \t]*(.*?)(? pointer)) and len(text) > pointer: cls.split_comments(text, struct, pointer=pointer, end=end) - - @classmethod def split_comments(cls, text, object, pointer=0, end=None): - pattern = cls.patterns['comment'] + pattern = cls.patterns["comment"] if end: match = pattern.search(text, pointer, end) else: @@ -76,7 +76,7 @@ class Parser(): if st0 > pointer: cls.split_entities(text, object, pointer=pointer, end=st0) comment = Comment() - comment.add(match.group(0)[1:].replace('\n;', '\n').replace('\n#', '\n')) + comment.add(match.group(0)[1:].replace("\n;", "\n").replace("\n#", "\n")) object.append(comment) pointer = match.end(0) if end: @@ -88,7 +88,7 @@ class Parser(): @classmethod def split_entities(cls, text, object, pointer=0, end=None): - pattern = cls.patterns['entity'] + pattern = cls.patterns["entity"] if end: match = pattern.search(text, pointer, end) else: @@ -100,9 +100,11 @@ class Parser(): groups = match.groups() entity = Entity(groups[0]) entity.set_value(groups[1]) - entity.params['source'] = {'type':'ini', - 'string':match.group(0), - 'valpos':match.start(2)-st0} + entity.params["source"] = { + "type": "ini", + "string": match.group(0), + "valpos": match.start(2) - st0, + } object.append(entity) pointer = match.end(0) if end: diff --git a/lib/silme/format/ini/serializer.py b/lib/silme/format/ini/serializer.py index 9611355..08be7db 100644 --- a/lib/silme/format/ini/serializer.py +++ b/lib/silme/format/ini/serializer.py @@ -4,10 +4,11 @@ from .parser import Parser from silme.core.entity import is_entity import re -class Serializer(): + +class Serializer: @classmethod def serialize(cls, l10nobject): - string = ''.join([cls.dump_element(element) for element in l10nobject]) + string = "".join([cls.dump_element(element) for element in l10nobject]) return string @classmethod @@ -23,36 +24,36 @@ class Serializer(): @classmethod def dump_entity(cls, entity): - if 'source' in entity.params and entity.params['source']['type']=='ini': - match = Parser.patterns['entity'].match(entity.params['source']['string']) - string = entity.params['source']['string'][0:match.start(1)] + if "source" in entity.params and entity.params["source"]["type"] == "ini": + match = Parser.patterns["entity"].match(entity.params["source"]["string"]) + string = entity.params["source"]["string"][0 : match.start(1)] string += entity.id - string += entity.params['source']['string'][match.end(1):match.start(2)] + string += entity.params["source"]["string"][match.end(1) : match.start(2)] string += entity.value - string += entity.params['source']['string'][match.end(2):] + string += entity.params["source"]["string"][match.end(2) :] else: - string = entity.id+'='+entity.value + string = entity.id + "=" + entity.value return string @classmethod def dump_entitylist(cls, elist): - string = ''.join([cls.dump_entity(entity)+'\n' for entity in elist.values()]) + string = "".join([cls.dump_entity(entity) + "\n" for entity in elist.values()]) return string @classmethod def dump_comment(cls, comment): - string = '' + string = "" for element in comment: string += cls.dump_element(element) if string: - pattern = re.compile('\n') - string = pattern.sub('\n#', string) - string = '#' + string - if string.endswith('#'): + pattern = re.compile("\n") + string = pattern.sub("\n#", string) + string = "#" + string + if string.endswith("#"): string = string[:-1] return string @classmethod def dump_section(cls, section): - string = '[%s]%s' % (section.id, cls.serialize(section)) + string = "[{}]{}".format(section.id, cls.serialize(section)) return string diff --git a/lib/silme/format/ini/structure.py b/lib/silme/format/ini/structure.py index 7b3b70f..03e5224 100644 --- a/lib/silme/format/ini/structure.py +++ b/lib/silme/format/ini/structure.py @@ -1,10 +1,11 @@ from silme.core.structure import Structure as BaseStructure, Comment from silme.core.entity import is_string, is_entity + class Structure(BaseStructure): def __init__(self, id): BaseStructure.__init__(self, id) - self.first_section = False # did we encounter sections? + self.first_section = False # did we encounter sections? def add(self, item, pos=None): """adds an element (string, entity or comment) to the Structure @@ -25,16 +26,18 @@ class Structure(BaseStructure): elif item is None: return 0 else: - raise Exception('Cannot add element of type "' + - type(item).__name__ + - '" to the Structure') + raise Exception( + 'Cannot add element of type "' + + type(item).__name__ + + '" to the Structure' + ) def add_section(self, section, pos=None): pos = self._get_pos(pos) if pos is None: self.first_section = len(self) elif self.first_section is False or self.first_section < pos: - self.first_section = pos + self.first_section = pos self.add_at_pos(section, pos) return 1 @@ -45,8 +48,9 @@ class Structure(BaseStructure): ('before', 'entity.id'), ('after', 'entity.id') """ pos = self._get_pos(pos) - if self.first_section is not False and \ - (pos is None or pos > self.first_section): + if self.first_section is not False and ( + pos is None or pos > self.first_section + ): raise Exception("Cannot add entity after section") self.add_at_pos(entity, pos) return 1 @@ -65,8 +69,7 @@ class Structure(BaseStructure): raise KeyError("No such entity or section") def __contains__(self, id): - """returns True if an entity with given id exists - """ + """returns True if an entity with given id exists""" for item in self: if is_entity(item) and item.id == id: return True @@ -75,12 +78,11 @@ class Structure(BaseStructure): return False def section(self, key): - """returns a section for a given id - """ + """returns a section for a given id""" for item in self: if isinstance(item, Section) and item.id == key: return item - raise KeyError('No such section') + raise KeyError("No such section") class Section(Structure): @@ -103,7 +105,8 @@ class Section(Structure): elif item is None: return 0 else: - raise Exception('Cannot add element of type "' + - type(item).__name__ + - '" to the Structure') - + raise Exception( + 'Cannot add element of type "' + + type(item).__name__ + + '" to the Structure' + ) diff --git a/lib/silme/format/properties/__init__.py b/lib/silme/format/properties/__init__.py index f6c169b..3455dc2 100644 --- a/lib/silme/format/properties/__init__.py +++ b/lib/silme/format/properties/__init__.py @@ -7,25 +7,25 @@ if sys.version_info[0] > 2: unichr = chr -class FormatParser(object): - name = 'properties' +class FormatParser: + name = "properties" desc = "Java Properties reader/writer" - extensions = ['properties'] - encoding = 'utf_8' # allowed encoding - fallback = ['utf_8_sig'] + extensions = ["properties"] + encoding = "utf_8" # allowed encoding + fallback = ["utf_8_sig"] @classmethod - def dump_structure (cls, l10nobject): + def dump_structure(cls, l10nobject): text = Serializer.serialize(l10nobject) return text @classmethod - def dump_entitylist (cls, elist): + def dump_entitylist(cls, elist): text = Serializer.dump_entitylist(elist) return text @classmethod - def get_entitylist (cls, text, code='default'): + def get_entitylist(cls, text, code="default"): # remove the \ufeff character from the beginning of the file, dirty hack for now if text and (text[0] == unichr(65279)): text = text[1:] @@ -33,7 +33,7 @@ class FormatParser(object): return l10nobject @classmethod - def get_structure (cls, text, code='default'): + def get_structure(cls, text, code="default"): # remove the \ufeff character from the beginning of the file, dirty hack for now if text and (text[0] == unichr(65279)): text = text[1:] diff --git a/lib/silme/format/properties/parser.py b/lib/silme/format/properties/parser.py index afbacdb..d8c5cc8 100644 --- a/lib/silme/format/properties/parser.py +++ b/lib/silme/format/properties/parser.py @@ -1,16 +1,18 @@ from ...core import EntityList, Entity, Comment from .structure import PropertiesStructure -from silme.core.list import EntityList import re -class PropertiesParser(): - patterns = {} - patterns['entity'] = re.compile('^[ \t]*([^#!\s\n][^=:\n]*?)[ \t]*[:=][ \t]*(.*?)(? pointer: cls.split_entities(text, object, code=code, pointer=pointer, end=st0) - groups = match.groups() comment = Comment() - comment.add(match.group(0)[1:].replace('\n#', '\n')) + comment.add(match.group(0)[1:].replace("\n#", "\n")) object.append(comment) pointer = match.end(0) if end: @@ -63,8 +66,8 @@ class PropertiesParser(): cls.split_entities(text, object, code=code, pointer=pointer) @classmethod - def split_entities(cls, text, object, code='default', pointer=0, end=None): - pattern = cls.patterns['entity'] + def split_entities(cls, text, object, code="default", pointer=0, end=None): + pattern = cls.patterns["entity"] if end: match = pattern.search(text, pointer, end) else: @@ -76,9 +79,11 @@ class PropertiesParser(): groups = match.groups() entity = Entity(groups[0]) entity.set_value(groups[1]) - entity.params['source'] = {'type':'properties', - 'string':match.group(0), - 'valpos':match.start(2)-st0} + entity.params["source"] = { + "type": "properties", + "string": match.group(0), + "valpos": match.start(2) - st0, + } object.append(entity) pointer = match.end(0) if end: diff --git a/lib/silme/format/properties/serializer.py b/lib/silme/format/properties/serializer.py index 8e2ec72..833a3f1 100644 --- a/lib/silme/format/properties/serializer.py +++ b/lib/silme/format/properties/serializer.py @@ -1,51 +1,54 @@ -from ...core import EntityList, Entity, Comment +from ...core import Comment from silme.core.entity import is_entity -from .structure import PropertiesStructure from .parser import PropertiesParser as Parser import re -class PropertiesSerializer(): + +class PropertiesSerializer: @classmethod def serialize(cls, l10nobject): - string = u''.join([cls.dump_element(element) for element in l10nobject]) + string = "".join([cls.dump_element(element) for element in l10nobject]) return string @classmethod def dump_element(cls, element, fallback=None): if is_entity(element): return cls.dump_entity(element) - elif isinstance(element,Comment): + elif isinstance(element, Comment): return cls.dump_comment(element) else: return element @classmethod - def dump_entity (cls, entity): - if 'source' in entity.params and entity.params['source']['type']=='properties': - match = Parser.patterns['entity'].match(entity.params['source']['string']) - string = entity.params['source']['string'][0:match.start(1)] + def dump_entity(cls, entity): + if ( + "source" in entity.params + and entity.params["source"]["type"] == "properties" + ): + match = Parser.patterns["entity"].match(entity.params["source"]["string"]) + string = entity.params["source"]["string"][0 : match.start(1)] string += entity.id - string += entity.params['source']['string'][match.end(1):match.start(2)] + string += entity.params["source"]["string"][match.end(1) : match.start(2)] string += entity.value - string += entity.params['source']['string'][match.end(2):] + string += entity.params["source"]["string"][match.end(2) :] else: - string = entity.id+u' = '+entity.value + string = entity.id + " = " + entity.value return string @classmethod def dump_entitylist(cls, elist): - string = u''.join([cls.dump_entity(entity)+'\n' for entity in elist.values()]) + string = "".join([cls.dump_entity(entity) + "\n" for entity in elist.values()]) return string @classmethod - def dump_comment (cls, comment): - string = u'' + def dump_comment(cls, comment): + string = "" for element in comment: string += cls.dump_element(element) if string: - pattern = re.compile('\n') - string = pattern.sub('\n#', string) - string = '#' + string - if string.endswith('#'): + pattern = re.compile("\n") + string = pattern.sub("\n#", string) + string = "#" + string + if string.endswith("#"): string = string[:-1] return string diff --git a/lib/silme/format/properties/structure.py b/lib/silme/format/properties/structure.py index 16a73e9..2143316 100644 --- a/lib/silme/format/properties/structure.py +++ b/lib/silme/format/properties/structure.py @@ -1,4 +1,5 @@ from ...core.structure import Structure + class PropertiesStructure(Structure): pass diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..ebeb20f --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,6 @@ +[build-system] +requires = ["setuptools>=40.8.0", "wheel"] +build-backend = "setuptools.build_meta" + +[tool.black] +line-length = 88 diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..81b6fc7 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,6 @@ +[flake8] +max-line-length = 88 +ignore = + E203, + E731, + W503, diff --git a/setup.py b/setup.py index 8927900..a6f5e00 100644 --- a/setup.py +++ b/setup.py @@ -1,16 +1,17 @@ -"""Python localization library +from setuptools import setup, find_packages +import sys +import os.path + +"""Python localization library New library for localization written in Python. """ docstrings = __doc__.split("\n") -from setuptools import setup, find_packages -import sys -import os.path -sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'lib')) +sys.path.insert(0, os.path.join(os.path.dirname(__file__), "lib")) -import silme +import silme # noqa: E402 classifiers = """\ Development Status :: 4 - Beta @@ -27,17 +28,18 @@ Topic :: Software Development :: Libraries :: Python Modules Topic :: Software Development :: Localization """ -setup(name="silme", - version=silme.get_short_version(), - author="Zbigniew Braniecki", - author_email="gandalf@mozilla.com", - description=docstrings[0], - long_description="\n".join(docstrings[2:]), - license="MPL 1.1/GPL 2.0/LGPL 2.1", - url="https://github.com/mathjazz/silme", - classifiers=filter(None, classifiers.split("\n")), - platforms=["any"], - package_dir={'': 'lib'}, - packages=find_packages('lib'), - keywords="localization, l10n" - ) +setup( + name="silme", + version=silme.get_short_version(), + author="Zbigniew Braniecki", + author_email="gandalf@mozilla.com", + description=docstrings[0], + long_description="\n".join(docstrings[2:]), + license="MPL 1.1/GPL 2.0/LGPL 2.1", + url="https://github.com/mathjazz/silme", + classifiers=filter(None, classifiers.split("\n")), + platforms=["any"], + package_dir={"": "lib"}, + packages=find_packages("lib"), + keywords="localization, l10n", +) diff --git a/tests/silme/core/test_entity.py b/tests/silme/core/test_entity.py index 8ec7a58..816edd7 100644 --- a/tests/silme/core/test_entity.py +++ b/tests/silme/core/test_entity.py @@ -1,141 +1,140 @@ import unittest -import sys from silme.core.entity import Entity, ComplexValue -from silme.core.types import OrderedDict +from collections import OrderedDict + class EntityTestCase(unittest.TestCase): - def setUp(self): - self.entity = Entity('test') + self.entity = Entity("test") def test_id(self): - self.assertEqual(self.entity.id, 'test') + self.assertEqual(self.entity.id, "test") def test_value1(self): - self.entity.value = 'testvalue' - self.assertEqual(self.entity.value, 'testvalue') + self.entity.value = "testvalue" + self.assertEqual(self.entity.value, "testvalue") self.assertEqual(self.entity.get_value(), self.entity.value) def test_value3(self): - self.entity = Entity('test', 'testvalue') - self.assertEqual(self.entity.value, 'testvalue') + self.entity = Entity("test", "testvalue") + self.assertEqual(self.entity.value, "testvalue") self.assertEqual(self.entity.get_value(), self.entity.value) def test_value5(self): self.assertEqual(self.entity.get_value(), None) def test_value6(self): - self.entity.value = 'foo' - self.assertEqual(self.entity.value, 'foo') + self.entity.value = "foo" + self.assertEqual(self.entity.value, "foo") def test_list1(self): - self.entity.value = ['foo','foo2'] - self.assertEqual(self.entity.value, 'foo') + self.entity.value = ["foo", "foo2"] + self.assertEqual(self.entity.value, "foo") def test_list2(self): - self.entity.value = ['foo','foo2'] - self.assertEqual(self.entity[0], 'foo') - self.assertEqual(self.entity[1], 'foo2') + self.entity.value = ["foo", "foo2"] + self.assertEqual(self.entity[0], "foo") + self.assertEqual(self.entity[1], "foo2") def test_list3(self): - self.entity.value = ['foo','foo2'] - self.assertEqual(self.entity.get_value(0), 'foo') - self.assertEqual(self.entity.get_value(1), 'foo2') + self.entity.value = ["foo", "foo2"] + self.assertEqual(self.entity.get_value(0), "foo") + self.assertEqual(self.entity.get_value(1), "foo2") def test_list4(self): - self.entity = Entity('test', ['old','old2']) - self.entity[0] = 'foo' - self.entity[1] = 'foo2' - self.assertEqual(self.entity.get_value(0), 'foo') - self.assertEqual(self.entity.get_value(1), 'foo2') + self.entity = Entity("test", ["old", "old2"]) + self.entity[0] = "foo" + self.entity[1] = "foo2" + self.assertEqual(self.entity.get_value(0), "foo") + self.assertEqual(self.entity.get_value(1), "foo2") def test_list5(self): - self.entity.value = ['foo','foo2'] + self.entity.value = ["foo", "foo2"] del self.entity[1] - self.assertEqual(self.entity.get_value(0), 'foo') + self.assertEqual(self.entity.get_value(0), "foo") self.assertRaises(IndexError, self.entity.get_value, 1) def test_dict1(self): - self.entity = Entity('test', {'male':'Foo','female':'Foo2'}) - self.assertTrue(self.entity.value in ('Foo', 'Foo2')) + self.entity = Entity("test", {"male": "Foo", "female": "Foo2"}) + self.assertTrue(self.entity.value in ("Foo", "Foo2")) def test_dict2(self): - self.entity.value = {'male':'Foo','female':'Foo2'} - self.assertTrue(self.entity.value in ('Foo', 'Foo2')) + self.entity.value = {"male": "Foo", "female": "Foo2"} + self.assertTrue(self.entity.value in ("Foo", "Foo2")) def test_dict3(self): - self.entity.value = {'male':'Foo','female':'Foo2'} - self.assertTrue(self.entity.get_value() in ('Foo', 'Foo2')) + self.entity.value = {"male": "Foo", "female": "Foo2"} + self.assertTrue(self.entity.get_value() in ("Foo", "Foo2")) def test_dict4(self): - self.entity.value = {'male':'Foo','female':'Foo2'} - self.assertEqual(self.entity.get_value('male'), 'Foo') - self.assertEqual(self.entity.get_value('female'), 'Foo2') + self.entity.value = {"male": "Foo", "female": "Foo2"} + self.assertEqual(self.entity.get_value("male"), "Foo") + self.assertEqual(self.entity.get_value("female"), "Foo2") def test_dict5(self): - self.entity.value = {'male':'Foo','female':'Foo2'} - self.assertEqual(self.entity['male'], 'Foo') - self.assertEqual(self.entity['female'], 'Foo2') + self.entity.value = {"male": "Foo", "female": "Foo2"} + self.assertEqual(self.entity["male"], "Foo") + self.assertEqual(self.entity["female"], "Foo2") def test_dict6(self): - self.entity.value = {'male':'Foo','female':'Foo2'} - self.entity['male']='Foo3' - self.assertEqual(self.entity['male'], 'Foo3') - self.assertEqual(self.entity['female'], 'Foo2') + self.entity.value = {"male": "Foo", "female": "Foo2"} + self.entity["male"] = "Foo3" + self.assertEqual(self.entity["male"], "Foo3") + self.assertEqual(self.entity["female"], "Foo2") def test_dict7(self): - self.entity.value = {'male':'Foo','female':'Foo2'} - del self.entity['male'] - self.assertEqual(self.entity['female'], 'Foo2') - self.assertRaises(KeyError, self.entity.get_value, 'male') - + self.entity.value = {"male": "Foo", "female": "Foo2"} + del self.entity["male"] + self.assertEqual(self.entity["female"], "Foo2") + self.assertRaises(KeyError, self.entity.get_value, "male") def test_complex5(self): - self.entity.value = ComplexValue({'male':'Foo2','female':'Foo3'}) - self.assertEqual(self.entity['male'], 'Foo2') + self.entity.value = ComplexValue({"male": "Foo2", "female": "Foo3"}) + self.assertEqual(self.entity["male"], "Foo2") def test_complex6(self): - self.entity.value = ComplexValue(['foo','foo4']) - self.assertEqual(self.entity[1], 'foo4') + self.entity.value = ComplexValue(["foo", "foo4"]) + self.assertEqual(self.entity[1], "foo4") def test_complex7(self): - self.entity.value = ComplexValue('Foo') + self.entity.value = ComplexValue("Foo") self.assertRaises(TypeError, self.entity.__getitem__, 0) def test_complex8(self): - self.entity.value = ComplexValue('Foo') + self.entity.value = ComplexValue("Foo") self.assertRaises(TypeError, self.entity.__getitem__, 0) - self.entity.value = ComplexValue(['Foo3','Foo4']) - self.assertEqual(self.entity[1], 'Foo4') - self.entity.value = ComplexValue({'one':'Foo5','few':'Foo6','many':'Foo7'}) - self.assertEqual(self.entity['few'], 'Foo6') + self.entity.value = ComplexValue(["Foo3", "Foo4"]) + self.assertEqual(self.entity[1], "Foo4") + self.entity.value = ComplexValue({"one": "Foo5", "few": "Foo6", "many": "Foo7"}) + self.assertEqual(self.entity["few"], "Foo6") def test_complex9(self): - self.entity.value = ComplexValue('Foo') - self.assertEqual(self.entity.value, 'Foo') - self.entity.value = ComplexValue(['Foo3','Foo4']) - self.assertEqual(self.entity.value, 'Foo3') - self.entity.value = ComplexValue(OrderedDict((('one','Foo5'),('few','Foo6'),('many','Foo7')))) - self.assertEqual(self.entity.value, 'Foo5') + self.entity.value = ComplexValue("Foo") + self.assertEqual(self.entity.value, "Foo") + self.entity.value = ComplexValue(["Foo3", "Foo4"]) + self.assertEqual(self.entity.value, "Foo3") + self.entity.value = ComplexValue( + OrderedDict((("one", "Foo5"), ("few", "Foo6"), ("many", "Foo7"))) + ) + self.assertEqual(self.entity.value, "Foo5") def test_custom1(self): def plural_form(value, n=1): - return value[0 if n==1 else 1] - - + return value[0 if n == 1 else 1] + self.entity._select_value = plural_form - self.entity.value = ['Firefox', 'Firefoxes'] - self.assertEqual(self.entity.value, 'Firefox') - self.assertEqual(self.entity.get_value(1), 'Firefox') - self.assertEqual(self.entity.get_value(5), 'Firefoxes') + self.entity.value = ["Firefox", "Firefoxes"] + self.assertEqual(self.entity.value, "Firefox") + self.assertEqual(self.entity.get_value(1), "Firefox") + self.assertEqual(self.entity.get_value(5), "Firefoxes") def test_values1(self): - vals = ['foo', 'foo2'] + vals = ["foo", "foo2"] self.entity.value = vals vals.pop() self.assertNotEqual(self.entity.values, vals) - #x = self.entity.values - #x.pop() - #self.assertEqual(x, vals) - #self.assertNotEqual(self.entity.values, x) + # x = self.entity.values + # x.pop() + # self.assertEqual(x, vals) + # self.assertNotEqual(self.entity.values, x) diff --git a/tests/silme/core/test_list.py b/tests/silme/core/test_list.py index 623c89d..aa258f2 100644 --- a/tests/silme/core/test_list.py +++ b/tests/silme/core/test_list.py @@ -1,127 +1,125 @@ -import random import unittest -import sys import silme.core -class EntityTestCase(unittest.TestCase): +class EntityTestCase(unittest.TestCase): def setUp(self): - self.entity_list = silme.core.EntityList('test') + self.entity_list = silme.core.EntityList("test") def test_init1(self): - self.assertEqual(self.entity_list.id, 'test') + self.assertEqual(self.entity_list.id, "test") def test_init2(self): - self.assertRaises(AttributeError, silme.core.EntityList, 'test', 'foo') + self.assertRaises(AttributeError, silme.core.EntityList, "test", "foo") def test_init3(self): - entity1 = silme.core.Entity('x') - entity2 = silme.core.Entity('y') - self.entity_list = silme.core.EntityList('test', entity1, entity2) - self.assertEqual(self.entity_list['x'], entity1) - self.assertEqual(self.entity_list['y'], entity2) + entity1 = silme.core.Entity("x") + entity2 = silme.core.Entity("y") + self.entity_list = silme.core.EntityList("test", entity1, entity2) + self.assertEqual(self.entity_list["x"], entity1) + self.assertEqual(self.entity_list["y"], entity2) def test_init4(self): - entity1 = silme.core.Entity('x') - entity2 = silme.core.Entity('y') - entity_list = silme.core.EntityList('test', entity1, entity2) - self.entity_list = silme.core.EntityList('id2', entity_list) - self.assertEqual(self.entity_list['x'], entity1) - self.assertEqual(self.entity_list['y'], entity2) - + entity1 = silme.core.Entity("x") + entity2 = silme.core.Entity("y") + entity_list = silme.core.EntityList("test", entity1, entity2) + self.entity_list = silme.core.EntityList("id2", entity_list) + self.assertEqual(self.entity_list["x"], entity1) + self.assertEqual(self.entity_list["y"], entity2) + def test_has_entity1(self): - entity1 = silme.core.Entity('x') + entity1 = silme.core.Entity("x") self.entity_list.add(entity1) - self.assertEqual('x' in self.entity_list, True) + self.assertEqual("x" in self.entity_list, True) def test_get_entities1(self): - entity1 = silme.core.Entity('x') - entity2 = silme.core.Entity('y') + entity1 = silme.core.Entity("x") + entity2 = silme.core.Entity("y") self.entity_list.add(entity1) self.entity_list.add(entity2) - l = self.entity_list.entities() - self.assertTrue(l[0].id in ('x', 'y')) - self.assertTrue(l[1].id in ('x', 'y')) - self.assertNotEqual(l[0].id, l[1].id) + entities = self.entity_list.entities() + self.assertTrue(entities[0].id in ("x", "y")) + self.assertTrue(entities[1].id in ("x", "y")) + self.assertNotEqual(entities[0].id, entities[1].id) def test_iter_entities(self): - entity1 = silme.core.Entity('x') - entity2 = silme.core.Entity('y') - entity3 = silme.core.Entity('z') + entity1 = silme.core.Entity("x") + entity2 = silme.core.Entity("y") + entity3 = silme.core.Entity("z") self.entity_list.add(entity1) self.entity_list.add(entity2) self.entity_list.add(entity3) for id in self.entity_list: - self.assertTrue(id in ('x','y','z')) + self.assertTrue(id in ("x", "y", "z")) def test_entity_ids1(self): - entity1 = silme.core.Entity('x') - entity2 = silme.core.Entity('y') + entity1 = silme.core.Entity("x") + entity2 = silme.core.Entity("y") self.entity_list.add(entity1) self.entity_list.add(entity2) ids = self.entity_list.keys() - self.assertEqual('x' in ids, True) - self.assertEqual('y' in ids, True) - + self.assertEqual("x" in ids, True) + self.assertEqual("y" in ids, True) + def test_modify_entity1(self): - entity1 = silme.core.Entity('x') + entity1 = silme.core.Entity("x") self.entity_list.add(entity1) - self.entity_list.modify('x', 'test2') - self.assertEqual(self.entity_list['x'].value, 'test2') + self.entity_list.modify("x", "test2") + self.assertEqual(self.entity_list["x"].value, "test2") def test_modify_entity2(self): - entity1 = silme.core.Entity('x', 'foo') - entity1.set_value('heh') + entity1 = silme.core.Entity("x", "foo") + entity1.set_value("heh") self.entity_list.add(entity1) - self.entity_list.modify('x', 'test2') - self.assertEqual(self.entity_list['x'].get_value(), 'test2') + self.entity_list.modify("x", "test2") + self.assertEqual(self.entity_list["x"].get_value(), "test2") def test_entity1(self): - entity1 = silme.core.Entity('x', 'foo') + entity1 = silme.core.Entity("x", "foo") self.entity_list.add(entity1) - self.assertEqual(self.entity_list['x'], entity1) + self.assertEqual(self.entity_list["x"], entity1) def test_get_value(self): - entity1 = silme.core.Entity('x') - entity1.set_value('test') + entity1 = silme.core.Entity("x") + entity1.set_value("test") self.entity_list.add(entity1) - self.assertEqual(self.entity_list.value('x'), 'test') + self.assertEqual(self.entity_list.value("x"), "test") def test_ordered_list(self): - self.entity_list = silme.core.EntityList('test', ordered=True) - ids = ('id1', 'id2', 'id3') + self.entity_list = silme.core.EntityList("test", ordered=True) + ids = ("id1", "id2", "id3") for i in ids: self.entity_list.add(silme.core.Entity(i)) n = 0 for i in self.entity_list.keys(): self.assertEqual(i, ids[n]) - n+=1 + n += 1 n = 0 for i in self.entity_list: self.assertEqual(i, ids[n]) - n+=1 + n += 1 def test_lazy_list(self): - self.entity_list = silme.core.EntityList('test', lazy=True) + self.entity_list = silme.core.EntityList("test", lazy=True) def resolve(key, value): return silme.core.Entity(key, value) - self.entity_list.set_stub('id1', resolve, 'Foo1') + self.entity_list.set_stub("id1", resolve, "Foo1") self.assertTrue(len(self.entity_list._stubs), 1) - self.assertTrue(self.entity_list._stubs, set('id1')) - e = self.entity_list['id1'] - self.assertEqual(e.id, 'id1') - self.assertEqual(e.value, 'Foo1') + self.assertTrue(self.entity_list._stubs, set("id1")) + e = self.entity_list["id1"] + self.assertEqual(e.id, "id1") + self.assertEqual(e.value, "Foo1") self.assertEqual(len(self.entity_list._stubs), 0) def test_value_list1(self): - vlist = silme.core.list.ValueList('test') - vlist.add(silme.core.Entity('id1', 'Foo1')) - self.assertEqual(vlist['id1'], 'Foo1') + vlist = silme.core.list.ValueList("test") + vlist.add(silme.core.Entity("id1", "Foo1")) + self.assertEqual(vlist["id1"], "Foo1") def test_value_list2(self): - vlist = silme.core.list.ValueList('test') - vlist.add(silme.core.Entity('id1', 'Foo1')) + vlist = silme.core.list.ValueList("test") + vlist.add(silme.core.Entity("id1", "Foo1")) self.assertRaises(TypeError, vlist.entities) diff --git a/tests/silme/core/test_package.py b/tests/silme/core/test_package.py index 9bd2c1c..3999a56 100644 --- a/tests/silme/core/test_package.py +++ b/tests/silme/core/test_package.py @@ -1,88 +1,89 @@ -import random import unittest -import sys import silme.core -class EntityTestCase(unittest.TestCase): +class EntityTestCase(unittest.TestCase): def setUp(self): - self.l10npackage = silme.core.Package('test') + self.l10npackage = silme.core.Package("test") def test_id(self): - self.assertEqual(self.l10npackage.id, 'test') + self.assertEqual(self.l10npackage.id, "test") def test_add_structure(self): - l10nobject = silme.core.Structure('foo') + l10nobject = silme.core.Structure("foo") self.l10npackage.add_structure(l10nobject) self.assertEqual(len(self.l10npackage.structures()), 1) def test_add_structure2(self): - l10nobject = silme.core.Structure('foo') - self.l10npackage.add_structure(l10nobject, 'test2/test3') + l10nobject = silme.core.Structure("foo") + self.l10npackage.add_structure(l10nobject, "test2/test3") self.assertEqual(len(self.l10npackage.packages()), 1) - self.assertEqual(self.l10npackage.packages()[0].id, 'test2') - self.assertEqual(self.l10npackage.packages()[0].packages()[0].id, 'test3') - self.assertEqual(self.l10npackage.packages()[0].packages()[0].structure('foo').id, 'foo') + self.assertEqual(self.l10npackage.packages()[0].id, "test2") + self.assertEqual(self.l10npackage.packages()[0].packages()[0].id, "test3") + self.assertEqual( + self.l10npackage.packages()[0].packages()[0].structure("foo").id, "foo" + ) def test_add_package(self): - l10npack = silme.core.Package('foo') + l10npack = silme.core.Package("foo") self.l10npackage.add_package(l10npack) self.assertEqual(len(self.l10npackage.packages()), 1) def test_add_package2(self): - l10npack = silme.core.Package('foo') - self.l10npackage.add_package(l10npack, 'test2/test3') + l10npack = silme.core.Package("foo") + self.l10npackage.add_package(l10npack, "test2/test3") self.assertEqual(len(self.l10npackage.packages()), 1) - self.assertEqual(self.l10npackage.packages()[0].id, 'test2') - self.assertEqual(self.l10npackage.packages()[0].packages()[0].id, 'test3') - self.assertEqual(self.l10npackage.packages()[0].packages()[0].package('foo').id, 'foo') + self.assertEqual(self.l10npackage.packages()[0].id, "test2") + self.assertEqual(self.l10npackage.packages()[0].packages()[0].id, "test3") + self.assertEqual( + self.l10npackage.packages()[0].packages()[0].package("foo").id, "foo" + ) def test_get_objects(self): - self.l10npackage.add_structure(silme.core.Structure('foo')) - self.l10npackage.add_structure(silme.core.Structure('foo2')) - self.l10npackage.add_structure(silme.core.Structure('foo3')) - self.assertEqual(self.l10npackage.structures()[0].id, 'foo') - self.assertEqual(self.l10npackage.structures()[1].id, 'foo2') - self.assertEqual(self.l10npackage.structures()[2].id, 'foo3') + self.l10npackage.add_structure(silme.core.Structure("foo")) + self.l10npackage.add_structure(silme.core.Structure("foo2")) + self.l10npackage.add_structure(silme.core.Structure("foo3")) + self.assertEqual(self.l10npackage.structures()[0].id, "foo") + self.assertEqual(self.l10npackage.structures()[1].id, "foo2") + self.assertEqual(self.l10npackage.structures()[2].id, "foo3") def test_get_objects2(self): - self.l10npackage.add_structure(silme.core.Structure('foo')) - self.l10npackage.add_structure(silme.core.Structure('foo2')) - self.l10npackage.add_structure(silme.core.Structure('foo3')) - self.assertEqual(self.l10npackage.structures(ids=True), ['foo', 'foo2', 'foo3']) - + self.l10npackage.add_structure(silme.core.Structure("foo")) + self.l10npackage.add_structure(silme.core.Structure("foo2")) + self.l10npackage.add_structure(silme.core.Structure("foo3")) + self.assertEqual(self.l10npackage.structures(ids=True), ["foo", "foo2", "foo3"]) def test_get_packages(self): - self.l10npackage.add_package(silme.core.Package('foo')) - self.l10npackage.add_package(silme.core.Package('foo2')) - self.l10npackage.add_package(silme.core.Package('foo3')) - self.assertEqual(self.l10npackage.packages()[0].id, 'foo') - self.assertEqual(self.l10npackage.packages()[1].id, 'foo2') - self.assertEqual(self.l10npackage.packages()[2].id, 'foo3') + self.l10npackage.add_package(silme.core.Package("foo")) + self.l10npackage.add_package(silme.core.Package("foo2")) + self.l10npackage.add_package(silme.core.Package("foo3")) + self.assertEqual(self.l10npackage.packages()[0].id, "foo") + self.assertEqual(self.l10npackage.packages()[1].id, "foo2") + self.assertEqual(self.l10npackage.packages()[2].id, "foo3") def test_get_packages2(self): - self.l10npackage.add_package(silme.core.Package('foo')) - self.l10npackage.add_package(silme.core.Package('foo2')) - self.l10npackage.add_package(silme.core.Package('foo3')) - self.assertEqual(self.l10npackage.packages(ids=True), ['foo', 'foo2', 'foo3']) + self.l10npackage.add_package(silme.core.Package("foo")) + self.l10npackage.add_package(silme.core.Package("foo2")) + self.l10npackage.add_package(silme.core.Package("foo3")) + self.assertEqual(self.l10npackage.packages(ids=True), ["foo", "foo2", "foo3"]) def test_get_entities(self): - l10nobject = silme.core.Structure('foo') - l10nobject.add_entity(silme.core.Entity('entid')) - l10nobject2 = silme.core.Structure('foo2') - l10nobject2.add_entity(silme.core.Entity('entid2')) + l10nobject = silme.core.Structure("foo") + l10nobject.add_entity(silme.core.Entity("entid")) + l10nobject2 = silme.core.Structure("foo2") + l10nobject2.add_entity(silme.core.Entity("entid2")) self.l10npackage.add_structure(l10nobject) self.l10npackage.add_structure(l10nobject2) entities = self.l10npackage.entities() self.assertEqual(len(entities), 2) def test_get_entities2(self): - l10nobject = silme.core.Structure('foo') - l10nobject.add_entity(silme.core.Entity('entid')) - l10nobject2 = silme.core.Structure('foo2') - l10nobject.add_entity(silme.core.Entity('entid2')) - l10npack = silme.core.Package('test2') + l10nobject = silme.core.Structure("foo") + l10nobject.add_entity(silme.core.Entity("entid")) + l10nobject2 = silme.core.Structure("foo2") + l10nobject.add_entity(silme.core.Entity("entid2")) + l10npack = silme.core.Package("test2") l10npack.add_structure(l10nobject) l10npack.add_structure(l10nobject2) self.l10npackage.add_package(l10npack) @@ -92,53 +93,61 @@ class EntityTestCase(unittest.TestCase): self.assertEqual(len(entities), 0) def test_get_entities_with_path(self): - l10nobject = silme.core.Structure('foo') - l10nobject.add_entity(silme.core.Entity('entid')) - l10nobject2 = silme.core.Structure('foo2') - l10nobject.add_entity(silme.core.Entity('entid2')) - l10npack = silme.core.Package('test2') + l10nobject = silme.core.Structure("foo") + l10nobject.add_entity(silme.core.Entity("entid")) + l10nobject2 = silme.core.Structure("foo2") + l10nobject.add_entity(silme.core.Entity("entid2")) + l10npack = silme.core.Package("test2") l10npack.add_structure(l10nobject) l10npack.add_structure(l10nobject2) self.l10npackage.add_package(l10npack) entities = self.l10npackage.entities(recursive=True, path=True) - self.assertEqual(entities[0][1], 'test2/foo') - entities = self.l10npackage.package('test2').entities(recursive=True, path=True) - self.assertEqual(entities[0][1], 'foo') + self.assertEqual(entities[0][1], "test2/foo") + entities = self.l10npackage.package("test2").entities(recursive=True, path=True) + self.assertEqual(entities[0][1], "foo") def test_package_lazy_by_default(self): self.assertEqual(self.l10npackage.lazy, True) def test_package__stub_exceptions_if_not_lazy(self): - pack = silme.core.Package('id1', lazy=False) - self.assertRaises(Exception, pack.add_package_stub, - 'id1', - lambda x:silme.core.Package('test1')) - self.assertRaises(Exception, pack.add_structure_stub, - 'id1', - lambda x:silme.core.Structure('id1')) + pack = silme.core.Package("id1", lazy=False) + self.assertRaises( + Exception, + pack.add_package_stub, + "id1", + lambda x: silme.core.Package("test1"), + ) + self.assertRaises( + Exception, + pack.add_structure_stub, + "id1", + lambda x: silme.core.Structure("id1"), + ) def test_package_add_structure_stub(self): def resolver(id): return silme.core.Structure(id) - pack = silme.core.Package('id1', lazy=True) - pack.add_structure_stub('id1', resolver) + + pack = silme.core.Package("id1", lazy=True) + pack.add_structure_stub("id1", resolver) self.assertEqual(len(pack), 1) - self.assertEqual('id1' in pack, True) + self.assertEqual("id1" in pack, True) self.assertEqual(len(pack.structures(ids=True)), 1) self.assertEqual(len(pack._structures._stubs), 1) - self.assertEqual(pack.has_structure('id1'), True) - self.assertEqual(pack.structure('id1').id, 'id1') + self.assertEqual(pack.has_structure("id1"), True) + self.assertEqual(pack.structure("id1").id, "id1") self.assertEqual(len(pack._structures._stubs), 0) def test_package_add_package_stub(self): def resolver(id): return silme.core.Package(id) - pack = silme.core.Package('id1', lazy=True) - pack.add_package_stub('id1', resolver) + + pack = silme.core.Package("id1", lazy=True) + pack.add_package_stub("id1", resolver) self.assertEqual(len(pack), 1) - self.assertEqual('id1' in pack, True) + self.assertEqual("id1" in pack, True) self.assertEqual(len(pack.packages(ids=True)), 1) self.assertEqual(len(pack._packages._stubs), 1) - self.assertEqual(pack.has_package('id1'), True) - self.assertEqual(pack.package('id1').id, 'id1') + self.assertEqual(pack.has_package("id1"), True) + self.assertEqual(pack.package("id1").id, "id1") self.assertEqual(len(pack._packages._stubs), 0) diff --git a/tests/silme/core/test_structure.py b/tests/silme/core/test_structure.py index 2c880ff..70cab1b 100644 --- a/tests/silme/core/test_structure.py +++ b/tests/silme/core/test_structure.py @@ -1,154 +1,153 @@ -import random import unittest -import sys import re import silme.core -class structureTestCase(unittest.TestCase): +class structureTestCase(unittest.TestCase): def setUp(self): - self.structure = silme.core.Structure('id') + self.structure = silme.core.Structure("id") def test_id(self): - self.structure.id = 'test' - self.assertEqual(self.structure.id, 'test') + self.structure.id = "test" + self.assertEqual(self.structure.id, "test") - def test_add_element(self): - entity = silme.core.Entity('entid') - entity2 = silme.core.Entity('entid2') + def test_add_at_pos(self): + entity = silme.core.Entity("entid") + entity2 = silme.core.Entity("entid2") self.structure.add_at_pos(entity, 0) self.structure.add_at_pos(entity2, 0) - self.assertEqual(self.structure.get_entity_pos('entid'), 1) - self.assertEqual(self.structure.get_entity_pos('entid2'), 0) + self.assertEqual(self.structure.entity_pos("entid"), 1) + self.assertEqual(self.structure.entity_pos("entid2"), 0) def test_add_entity(self): - entity = silme.core.Entity('entid') - entity2 = silme.core.Entity('entid2') - entity3 = silme.core.Entity('entid3') - entity4 = silme.core.Entity('entid4') + entity = silme.core.Entity("entid") + entity2 = silme.core.Entity("entid2") + entity3 = silme.core.Entity("entid3") + entity4 = silme.core.Entity("entid4") # make sure add_entity returns 1 - self.assertEqual(self.structure.add_entity(entity), 1) + self.assertEqual(self.structure.add_entity(entity), 1) self.structure.add_entity(entity2, 1) self.structure.add_entity(entity3, 0) self.structure.add_entity(entity4, 1) - self.assertEqual(self.structure.entity_pos('entid'), 2) - self.assertEqual(self.structure.entity_pos('entid2'), 3) - self.assertEqual(self.structure.entity_pos('entid3'), 0) - self.assertEqual(self.structure.entity_pos('entid4'), 1) + self.assertEqual(self.structure.entity_pos("entid"), 2) + self.assertEqual(self.structure.entity_pos("entid2"), 3) + self.assertEqual(self.structure.entity_pos("entid3"), 0) + self.assertEqual(self.structure.entity_pos("entid4"), 1) def test_get_value(self): - entity = silme.core.Entity('entid') - entity.set_value('foo') + entity = silme.core.Entity("entid") + entity.set_value("foo") self.structure.add_entity(entity) - self.assertEqual(self.structure.value('entid'), 'foo') + self.assertEqual(self.structure.value("entid"), "foo") - - def test_get_entity(self): - self.structure.add_entity(silme.core.Entity('entid')) - self.structure.add_entity(silme.core.Entity('entid2')) - self.assertEqual(len(self.structure.get_entities()), 2) - self.assertEqual(self.structure.get_entities()[0].id, 'entid') - self.assertEqual(self.structure.get_entities()[1].id, 'entid2') + def test_entities(self): + self.structure.add_entity(silme.core.Entity("entid")) + self.structure.add_entity(silme.core.Entity("entid2")) + self.assertEqual(len(self.structure.entities()), 2) + self.assertEqual(self.structure.entities()[0].id, "entid") + self.assertEqual(self.structure.entities()[1].id, "entid2") def test_get_entity_ids(self): - self.structure.add_entity(silme.core.Entity('entid')) - self.structure.add_entity(silme.core.Entity('entid2')) - self.assertEqual(self.structure.ids(), ['entid', 'entid2']) + self.structure.add_entity(silme.core.Entity("entid")) + self.structure.add_entity(silme.core.Entity("entid2")) + self.assertEqual(self.structure.ids(), ["entid", "entid2"]) def test_has_entity(self): - self.structure.add_entity(silme.core.Entity('entid')) - self.structure.add_entity(silme.core.Entity('entid2')) + self.structure.add_entity(silme.core.Entity("entid")) + self.structure.add_entity(silme.core.Entity("entid2")) self.assertEqual(len(self.structure.entities()), 2) - self.assertEqual(self.structure.has_entity('entid'), True) - self.assertEqual(self.structure.has_entity('entid3'), False) + self.assertEqual(self.structure.has_entity("entid"), True) + self.assertEqual(self.structure.has_entity("entid3"), False) def test_modify_entity(self): - entity = silme.core.Entity('entid') - entity.set_value('testvalue') + entity = silme.core.Entity("entid") + entity.set_value("testvalue") self.structure.add_entity(entity) - self.assertEqual(self.structure.modify_entity('entid', 'newvalue'), True) - self.assertEqual(entity.get_value(), 'newvalue') + self.assertEqual(self.structure.modify_entity("entid", "newvalue"), True) + self.assertEqual(entity.get_value(), "newvalue") def test_modify_entity2(self): - entity = silme.core.Entity('entid') - entity.set_value('testvalue') + entity = silme.core.Entity("entid") + entity.set_value("testvalue") self.structure.add_entity(entity) - self.assertRaises(KeyError, self.structure.modify_entity, 'endid', 'newvalue') + self.assertRaises(KeyError, self.structure.modify_entity, "endid", "newvalue") def test_modify_entity3(self): - entity = silme.core.Entity('entid') - entity.default_code = 'pl' - entity.set_value('testvalue') + entity = silme.core.Entity("entid") + entity.default_code = "pl" + entity.set_value("testvalue") self.structure.add_entity(entity) - self.structure.modify_entity('entid', 'newvalue') - self.assertEqual(entity.get_value(), 'newvalue') - + self.structure.modify_entity("entid", "newvalue") + self.assertEqual(entity.get_value(), "newvalue") + def test_get_entity(self): - entity = silme.core.Entity('entid') + entity = silme.core.Entity("entid") self.structure.add_entity(entity) - self.assertEqual(self.structure.entity('entid'), entity) - self.assertRaises(KeyError, self.structure.entity, 'endid') + self.assertEqual(self.structure.entity("entid"), entity) + self.assertRaises(KeyError, self.structure.entity, "endid") def test_get_entity_pos(self): - entity = silme.core.Entity('entid') - self.structure.add_string('foo') - self.structure.add_entity(silme.core.Entity('entityid2')) - self.structure.add_string('foo') + entity = silme.core.Entity("entid") + self.structure.add_string("foo") + self.structure.add_entity(silme.core.Entity("entityid2")) + self.structure.add_string("foo") self.structure.add_entity(entity) - self.structure.add_string('foo') - self.assertEqual(self.structure.entity_pos('entid'), 3) + self.structure.add_string("foo") + self.assertEqual(self.structure.entity_pos("entid"), 3) def test_remove_entity(self): - entity = silme.core.Entity('entid') - self.structure.add_entity(silme.core.Entity('entityid3')) + entity = silme.core.Entity("entid") + self.structure.add_entity(silme.core.Entity("entityid3")) self.structure.add_entity(entity) - self.structure.add_entity(silme.core.Entity('entityid2')) - self.assertEqual(self.structure.remove_entity('entid'), True) - self.assertRaises(KeyError, self.structure.entity, 'endid') - + self.structure.add_entity(silme.core.Entity("entityid2")) + self.assertEqual(self.structure.remove_entity("entid"), True) + self.assertRaises(KeyError, self.structure.entity, "endid") + def test_add_element(self): - entity = silme.core.Entity('entid') + entity = silme.core.Entity("entid") comment = silme.core.Comment() - comment.add('foo') - str = 'foo' + comment.add("foo") + str = "foo" self.assertEqual(self.structure.add(entity), 1) self.assertEqual(self.structure.add(comment), 1) self.assertEqual(self.structure.add(str), 1) - self.assertRaises(Exception, self.structure.add, sys) + self.assertRaises(Exception, self.structure.add, {}) def test_add_elements(self): - entity = silme.core.Entity('entid') + entity = silme.core.Entity("entid") comment = silme.core.Comment() - comment.add('foo') - str = 'foo' + comment.add("foo") + str = "foo" list = [entity, comment, entity, str] self.assertEqual(self.structure.add_elements(list), 4) def test_get_entitylist(self): - self.structure.add_string('foo') - self.structure.add_entity(silme.core.Entity('entid')) - self.structure.add_string('foo') - self.structure.add_entity(silme.core.Entity('entid2')) - self.structure.add_string('foo') + self.structure.add_string("foo") + self.structure.add_entity(silme.core.Entity("entid")) + self.structure.add_string("foo") + self.structure.add_entity(silme.core.Entity("entid2")) + self.structure.add_string("foo") entitylist = self.structure.entitylist() self.assertEqual(len(entitylist.entities()), 2) - self.assertEqual(entitylist['entid'].id, 'entid') - self.assertEqual(entitylist['entid2'].id, 'entid2') + self.assertEqual(entitylist["entid"].id, "entid") + self.assertEqual(entitylist["entid2"].id, "entid2") def test_process(self): def process_entity(entity, subs): - entity.value = re.sub(r'\&([^$]+)\;', - lambda m:subs[m.group(1)], - str(entity.value)) + entity.value = re.sub( + r"\&([^$]+)\;", lambda m: subs[m.group(1)], str(entity.value) + ) + def process(self): for elem in self: if isinstance(elem, silme.core.Entity): - process_entity(elem, self.params['exents']) + process_entity(elem, self.params["exents"]) + self.structure.set_process_cb(process) - entity1 = silme.core.Entity('id', 'Test &varMe; it') + entity1 = silme.core.Entity("id", "Test &varMe; it") self.structure.params = {} - self.structure.params['exents'] = {'varMe': 'Woo'} + self.structure.params["exents"] = {"varMe": "Woo"} self.structure.add_entity(entity1) self.structure.process() - self.assertEqual(self.structure.value('id'), 'Test Woo it') + self.assertEqual(self.structure.value("id"), "Test Woo it") diff --git a/tests/silme/core/types/lazydict.py b/tests/silme/core/types/lazydict.py index 88d7f44..ccb3eae 100644 --- a/tests/silme/core/types/lazydict.py +++ b/tests/silme/core/types/lazydict.py @@ -1,8 +1,8 @@ import unittest -import sys from silme.core.types.lazydict import LazyDict + class LazyDictTestCase(unittest.TestCase): def test_constructor(self): # calling built-in types without argument must return empty @@ -18,65 +18,66 @@ class LazyDictTestCase(unittest.TestCase): def test_keys(self): d = LazyDict() self.assertEqual(set(d.keys()), set()) - d = LazyDict({'a': 1, 'b': 2}) + d = LazyDict({"a": 1, "b": 2}) k = d.keys() - self.assertTrue('a' in d) - self.assertTrue('b' in d) - self.assertEqual(set(k), {'a','b'}) + self.assertTrue("a" in d) + self.assertTrue("b" in d) + self.assertEqual(set(k), {"a", "b"}) self.assertRaises(TypeError, d.keys, None) def test_values(self): d = LazyDict() self.assertEqual(set(d.values()), set()) - d = LazyDict({1:2}) + d = LazyDict({1: 2}) self.assertEqual(set(d.values()), {2}) self.assertRaises(TypeError, d.values, None) - #self.assertEqual(repr(dict(a=1).values()), "dict_values([1])") + # self.assertEqual(repr(dict(a=1).values()), "dict_values([1])") def test_items(self): d = LazyDict() self.assertEqual(set(d.items()), set()) - d = LazyDict({1:2}) + d = LazyDict({1: 2}) self.assertEqual(set(d.items()), {(1, 2)}) self.assertRaises(TypeError, d.items, None) def test_contains(self): d = LazyDict() - self.assertNotIn('a', d) - self.assertFalse('a' in d) - self.assertTrue('a' not in d) - d = LazyDict({'a': 1, 'b': 2}) - self.assertIn('a', d) - self.assertIn('b', d) - self.assertNotIn('c', d) + self.assertNotIn("a", d) + self.assertFalse("a" in d) + self.assertTrue("a" not in d) + d = LazyDict({"a": 1, "b": 2}) + self.assertIn("a", d) + self.assertIn("b", d) + self.assertNotIn("c", d) self.assertRaises(TypeError, d.__contains__) def test_len(self): d = LazyDict() self.assertEqual(len(d), 0) - d = LazyDict({'a': 1, 'b': 2}) + d = LazyDict({"a": 1, "b": 2}) self.assertEqual(len(d), 2) def test_getitem(self): - d = LazyDict({'a': 1, 'b': 2}) - self.assertEqual(d['a'], 1) - self.assertEqual(d['b'], 2) - d['c'] = 3 - d['a'] = 4 - self.assertEqual(d['c'], 3) - self.assertEqual(d['a'], 4) - del d['b'] - self.assertEqual(d, {'a': 4, 'c': 3}) + d = LazyDict({"a": 1, "b": 2}) + self.assertEqual(d["a"], 1) + self.assertEqual(d["b"], 2) + d["c"] = 3 + d["a"] = 4 + self.assertEqual(d["c"], 3) + self.assertEqual(d["a"], 4) + del d["b"] + self.assertEqual(d, {"a": 4, "c": 3}) self.assertRaises(TypeError, d.__getitem__) - class BadEq(object): + class BadEq: def __eq__(self, other): raise Exc() + def __hash__(self): return 24 @@ -84,10 +85,12 @@ class LazyDictTestCase(unittest.TestCase): d[BadEq()] = 42 self.assertRaises(KeyError, d.__getitem__, 23) - class Exc(Exception): pass + class Exc(Exception): + pass - class BadHash(object): + class BadHash: fail = False + def __hash__(self): if self.fail: raise Exc() @@ -100,7 +103,7 @@ class LazyDictTestCase(unittest.TestCase): self.assertRaises(Exc, d.__getitem__, x) def test_clear(self): - d = LazyDict({1:1, 2:2, 3:3}) + d = LazyDict({1: 1, 2: 2, 3: 3}) d.clear() self.assertEqual(d, {}) @@ -108,33 +111,39 @@ class LazyDictTestCase(unittest.TestCase): def test_update(self): d = LazyDict() - d.update({1:100}) - d.update({2:20}) - d.update({1:1, 2:2, 3:3}) - self.assertEqual(d, {1:1, 2:2, 3:3}) + d.update({1: 100}) + d.update({2: 20}) + d.update({1: 1, 2: 2, 3: 3}) + self.assertEqual(d, {1: 1, 2: 2, 3: 3}) d.update() - self.assertEqual(d, {1:1, 2:2, 3:3}) + self.assertEqual(d, {1: 1, 2: 2, 3: 3}) self.assertRaises((TypeError, AttributeError), d.update, None) class SimpleUserDict: def __init__(self): - self.d = {1:1, 2:2, 3:3} + self.d = {1: 1, 2: 2, 3: 3} + def keys(self): return self.d.keys() + def __getitem__(self, i): return self.d[i] + d.clear() d.update(SimpleUserDict()) - self.assertEqual(d, {1:1, 2:2, 3:3}) + self.assertEqual(d, {1: 1, 2: 2, 3: 3}) - class Exc(Exception): pass + class Exc(Exception): + pass d.clear() + class FailingUserDict: def keys(self): raise Exc + self.assertRaises(Exc, d.update, FailingUserDict()) class FailingUserDict: @@ -142,43 +151,57 @@ class LazyDictTestCase(unittest.TestCase): class BogonIter: def __init__(self): self.i = 1 + def __iter__(self): return self + def __next__(self): if self.i: self.i = 0 - return 'a' + return "a" raise Exc + next = __next__ + return BogonIter() + def __getitem__(self, key): return key + self.assertRaises(Exc, d.update, FailingUserDict()) class FailingUserDict: def keys(self): class BogonIter: def __init__(self): - self.i = ord('a') + self.i = ord("a") + def __iter__(self): return self + def __next__(self): - if self.i <= ord('z'): + if self.i <= ord("z"): rtn = chr(self.i) self.i += 1 return rtn raise StopIteration + next = __next__ + return BogonIter() + def __getitem__(self, key): raise Exc + self.assertRaises(Exc, d.update, FailingUserDict()) - class badseq(object): + class badseq: def __iter__(self): return self + def __next__(self): raise Exc() + next = __next__ self.assertRaises(Exc, {}.update, badseq()) @@ -186,30 +209,38 @@ class LazyDictTestCase(unittest.TestCase): self.assertRaises(ValueError, {}.update, [(1, 2, 3)]) def test_fromkeys(self): - self.assertEqual(LazyDict().fromkeys('abc'), {'a':None, 'b':None, 'c':None}) + self.assertEqual(LazyDict().fromkeys("abc"), {"a": None, "b": None, "c": None}) d = LazyDict() - self.assertIsNot(d.fromkeys('abc'), d) - self.assertEqual(d.fromkeys('abc'), LazyDict({'a':None, 'b':None, 'c':None})) - self.assertEqual(d.fromkeys((4,5),0), LazyDict({4:0, 5:0})) + self.assertIsNot(d.fromkeys("abc"), d) + self.assertEqual(d.fromkeys("abc"), LazyDict({"a": None, "b": None, "c": None})) + self.assertEqual(d.fromkeys((4, 5), 0), LazyDict({4: 0, 5: 0})) self.assertEqual(d.fromkeys([]), LazyDict()) + def g(): yield 1 - self.assertEqual(d.fromkeys(g()), LazyDict({1:None})) + + self.assertEqual(d.fromkeys(g()), LazyDict({1: None})) self.assertRaises(TypeError, {}.fromkeys, 3) - class dictlike(LazyDict): pass - self.assertEqual(dictlike.fromkeys('a'), LazyDict({'a':None})) - self.assertEqual(dictlike().fromkeys('a'), LazyDict({'a':None})) - self.assertTrue(type(dictlike.fromkeys('a')) is dictlike) - self.assertTrue(type(dictlike().fromkeys('a')) is dictlike) + + class dictlike(LazyDict): + pass + + self.assertEqual(dictlike.fromkeys("a"), LazyDict({"a": None})) + self.assertEqual(dictlike().fromkeys("a"), LazyDict({"a": None})) + self.assertTrue(type(dictlike.fromkeys("a")) is dictlike) + self.assertTrue(type(dictlike().fromkeys("a")) is dictlike) + class mydict(LazyDict): def __new__(cls): return LazyDict() - ud = mydict.fromkeys('ab') - self.assertEqual(ud, LazyDict({'a':None, 'b':None})) + + ud = mydict.fromkeys("ab") + self.assertEqual(ud, LazyDict({"a": None, "b": None})) self.assertTrue(isinstance(ud, LazyDict)) self.assertRaises(TypeError, dict.fromkeys) - class Exc(Exception): pass + class Exc(Exception): + pass class baddict1(LazyDict): def __init__(self): @@ -225,42 +256,44 @@ class LazyDictTestCase(unittest.TestCase): # test fast path for dictionary inputs d = LazyDict(zip(range(6), range(6))) - self.assertEqual(LazyDict.fromkeys(d, 0), LazyDict(zip(range(6), [0]*6))) + self.assertEqual(LazyDict.fromkeys(d, 0), LazyDict(zip(range(6), [0] * 6))) def test_copy(self): - d = LazyDict({1:1, 2:2, 3:3}) - self.assertEqual(d.copy(), LazyDict({1:1, 2:2, 3:3})) + d = LazyDict({1: 1, 2: 2, 3: 3}) + self.assertEqual(d.copy(), LazyDict({1: 1, 2: 2, 3: 3})) self.assertEqual(LazyDict().copy(), LazyDict()) self.assertRaises(TypeError, d.copy, None) def test_get(self): d = LazyDict() - self.assertIs(d.get('c'), None) - self.assertEqual(d.get('c', 3), 3) - d = LazyDict({'a': 1, 'b': 2}) - self.assertIs(d.get('c'), None) - self.assertEqual(d.get('c', 3), 3) - self.assertEqual(d.get('a'), 1) - self.assertEqual(d.get('a', 3), 1) + self.assertIs(d.get("c"), None) + self.assertEqual(d.get("c", 3), 3) + d = LazyDict({"a": 1, "b": 2}) + self.assertIs(d.get("c"), None) + self.assertEqual(d.get("c", 3), 3) + self.assertEqual(d.get("a"), 1) + self.assertEqual(d.get("a", 3), 1) self.assertRaises(TypeError, d.get) self.assertRaises(TypeError, d.get, None, None, None) def test_setdefault(self): # dict.setdefault() d = LazyDict() - self.assertIs(d.setdefault('key0'), None) - d.setdefault('key0', []) - self.assertIs(d.setdefault('key0'), None) - d.setdefault('key', []).append(3) - self.assertEqual(d['key'][0], 3) - d.setdefault('key', []).append(4) - self.assertEqual(len(d['key']), 2) + self.assertIs(d.setdefault("key0"), None) + d.setdefault("key0", []) + self.assertIs(d.setdefault("key0"), None) + d.setdefault("key", []).append(3) + self.assertEqual(d["key"][0], 3) + d.setdefault("key", []).append(4) + self.assertEqual(len(d["key"]), 2) self.assertRaises(TypeError, d.setdefault) - class Exc(Exception): pass + class Exc(Exception): + pass - class BadHash(object): + class BadHash: fail = False + def __hash__(self): if self.fail: raise Exc() @@ -278,7 +311,7 @@ class LazyDictTestCase(unittest.TestCase): # -1: b has same structure as a # +1: b is a.copy() for log2size in range(12): - size = 2**log2size + size = 2 ** log2size a = LazyDict() b = LazyDict() for i in range(size): @@ -302,9 +335,9 @@ class LazyDictTestCase(unittest.TestCase): def test_pop(self): # Tests for pop with specified key d = LazyDict() - k, v = 'abc', 'def' + k, v = "abc", "def" d[k] = v - self.assertRaises(KeyError, d.pop, 'ghi') + self.assertRaises(KeyError, d.pop, "ghi") self.assertEqual(d.pop(k), v) self.assertEqual(len(d), 0) @@ -315,7 +348,7 @@ class LazyDictTestCase(unittest.TestCase): # (for 64-bit archs). See SF bug #689659. x = 4503599627370496 y = 4503599627370496 - h = LazyDict({x: 'anything', y: 'something else'}) + h = LazyDict({x: "anything", y: "something else"}) self.assertEqual(h[x], h[y]) self.assertEqual(d.pop(k, v), v) @@ -324,10 +357,12 @@ class LazyDictTestCase(unittest.TestCase): self.assertRaises(TypeError, d.pop) - class Exc(Exception): pass + class Exc(Exception): + pass - class BadHash(object): + class BadHash: fail = False + def __hash__(self): if self.fail: raise Exc() @@ -341,18 +376,18 @@ class LazyDictTestCase(unittest.TestCase): def test_mutatingiteration(self): # changing dict size during iteration - #d = LazyDict() - #d[1] = 1 - #with self.assertRaises(RuntimeError): + # d = LazyDict() + # d[1] = 1 + # with self.assertRaises(RuntimeError): # for i in d: # d[i+1] = 1 pass def test_repr(self): - #d = LazyDict() - #self.assertEqual(repr(d), 'LazyDict()') - #d[1] = 2 - #self.assertEqual(repr(d), 'LazyDict(dict_keys([1]))') + # d = LazyDict() + # self.assertEqual(repr(d), 'LazyDict()') + # d[1] = 2 + # self.assertEqual(repr(d), 'LazyDict(dict_keys([1]))') pass def test_missing(self): @@ -362,18 +397,22 @@ class LazyDictTestCase(unittest.TestCase): # (E) subclass defines __missing__ method raising RuntimeError # (F) subclass sets __missing__ instance variable (no effect) # (G) subclass doesn't define __missing__ at a all + class D(dict): def __missing__(self, key): return 42 + d = D({1: 2, 3: 4}) self.assertEqual(d[1], 2) self.assertEqual(d[3], 4) self.assertTrue(2 not in d) self.assertTrue(2 not in d.keys()) self.assertEqual(d[2], 42) + class E(dict): def __missing__(self, key): raise RuntimeError(key) + e = E() try: e[42] @@ -381,10 +420,12 @@ class LazyDictTestCase(unittest.TestCase): self.assertEqual(err.args, (42,)) else: self.fail("e[42] didn't raise RuntimeError") + class F(dict): def __init__(self): # An instance variable __missing__ should have no effect self.__missing__ = lambda key: None + f = F() try: f[42] @@ -392,8 +433,10 @@ class LazyDictTestCase(unittest.TestCase): self.assertEqual(err.args, (42,)) else: self.fail("f[42] didn't raise KeyError") + class G(dict): pass + g = G() try: g[42] @@ -402,7 +445,6 @@ class LazyDictTestCase(unittest.TestCase): else: self.fail("g[42] didn't raise KeyError") - def test_tuple_keyerror(self): # SF #1576657 d = LazyDict() @@ -429,9 +471,9 @@ class LazyDictTestCase(unittest.TestCase): d = LazyDict() x1 = BadDictKey() - x2 = BadDictKey() d[x1] = 1 - #for stmt in ['d[x2] = 2', + # x2 = BadDictKey() + # for stmt in ['d[x2] = 2', # 'z = d[x2]', # 'x2 in d', # 'x2 in d', @@ -442,82 +484,84 @@ class LazyDictTestCase(unittest.TestCase): # with self.assertRaises(CustomException): # exec stmt in locals() -########## + ########## def test_lazy_keys(self): def resolver(id): - p = {'b': 2, 'c': 3} + p = {"b": 2, "c": 3} return p[id] - d = LazyDict({'a': 1}) - d.set_stub('b', resolver) - d.set_stub('c', resolver) - d['d'] = 4 + + d = LazyDict({"a": 1}) + d.set_stub("b", resolver) + d.set_stub("c", resolver) + d["d"] = 4 k = d.keys() - self.assertTrue('a' in d) - self.assertTrue('b' in d) - self.assertTrue('c' in d) - self.assertTrue('d' in d) - self.assertEqual(set(k), {'a','b','c','d'}) + self.assertTrue("a" in d) + self.assertTrue("b" in d) + self.assertTrue("c" in d) + self.assertTrue("d" in d) + self.assertEqual(set(k), {"a", "b", "c", "d"}) def test_lazy_values(self): def resolver(id): - p = {'c': 3} + p = {"c": 3} return p[id] + d = LazyDict() self.assertEqual(set(d.values()), set()) - d = LazyDict({1:2}) - d.set_stub('c', resolver) + d = LazyDict({1: 2}) + d.set_stub("c", resolver) v = d.values() - self.assertEqual(set(v), {2,3}) + self.assertEqual(set(v), {2, 3}) self.assertRaises(TypeError, d.values, None) def test_lazy_items(self): d = LazyDict() - d.set_stub(1, lambda x:x) + d.set_stub(1, lambda x: x) self.assertEqual(set(d.items()), {(1, 1)}) - d = LazyDict({1:2}) - d.set_stub(2, lambda x:x) + d = LazyDict({1: 2}) + d.set_stub(2, lambda x: x) self.assertEqual(set(d.items()), {(1, 2), (2, 2)}) def test_lazy_contains(self): d = LazyDict() - self.assertNotIn('a', d) - self.assertFalse('a' in d) - self.assertTrue('a' not in d) - d = LazyDict({'a': 1, 'b': 2}) - self.assertIn('a', d) - self.assertIn('b', d) - self.assertNotIn('c', d) + self.assertNotIn("a", d) + self.assertFalse("a" in d) + self.assertTrue("a" not in d) + d = LazyDict({"a": 1, "b": 2}) + self.assertIn("a", d) + self.assertIn("b", d) + self.assertNotIn("c", d) self.assertRaises(TypeError, d.__contains__) def test_lazy_len(self): - d = LazyDict({'1':1}) + d = LazyDict({"1": 1}) self.assertEqual(len(d), 1) - d['2'] = 2 + d["2"] = 2 self.assertEqual(len(d), 2) - d.set_stub('3', lambda x: x) + d.set_stub("3", lambda x: x) self.assertEqual(len(d), 3) - def test_lazy_getitem(self): - d = LazyDict({'a': 1, 'b': 2}) - self.assertEqual(d['a'], 1) - self.assertEqual(d['b'], 2) - d['c'] = 3 - d['a'] = 4 - self.assertEqual(d['c'], 3) - self.assertEqual(d['a'], 4) - del d['b'] - self.assertEqual(d, {'a': 4, 'c': 3}) + d = LazyDict({"a": 1, "b": 2}) + self.assertEqual(d["a"], 1) + self.assertEqual(d["b"], 2) + d["c"] = 3 + d["a"] = 4 + self.assertEqual(d["c"], 3) + self.assertEqual(d["a"], 4) + del d["b"] + self.assertEqual(d, {"a": 4, "c": 3}) self.assertRaises(TypeError, d.__getitem__) - class BadEq(object): + class BadEq: def __eq__(self, other): raise Exc() + def __hash__(self): return 24 @@ -525,10 +569,12 @@ class LazyDictTestCase(unittest.TestCase): d[BadEq()] = 42 self.assertRaises(KeyError, d.__getitem__, 23) - class Exc(Exception): pass + class Exc(Exception): + pass - class BadHash(object): + class BadHash: fail = False + def __hash__(self): if self.fail: raise Exc() @@ -541,8 +587,8 @@ class LazyDictTestCase(unittest.TestCase): self.assertRaises(Exc, d.__getitem__, x) def test_lazy_clear(self): - d = LazyDict({1:1, 2:2, 3:3}) - d.set_stub(4, lambda x:x) + d = LazyDict({1: 1, 2: 2, 3: 3}) + d.set_stub(4, lambda x: x) d.clear() self.assertEqual(d, {}) self.assertEqual(set(d.keys()), set()) @@ -552,74 +598,79 @@ class LazyDictTestCase(unittest.TestCase): def test_lazy_update(self): d = LazyDict() - d.set_stub(4, lambda x:x) - d.update(LazyDict({1:100})) - d.update(LazyDict({2:20})) - d.update({4:5}) - d.update(LazyDict({1:1, 2:2, 3:3})) - self.assertEqual(d, {1:1, 2:2, 3:3, 4:5}) + d.set_stub(4, lambda x: x) + d.update(LazyDict({1: 100})) + d.update(LazyDict({2: 20})) + d.update({4: 5}) + d.update(LazyDict({1: 1, 2: 2, 3: 3})) + self.assertEqual(d, {1: 1, 2: 2, 3: 3, 4: 5}) d.update() - self.assertEqual(d, {1:1, 2:2, 3:3, 4:5}) + self.assertEqual(d, {1: 1, 2: 2, 3: 3, 4: 5}) self.assertRaises((TypeError, AttributeError), d.update, None) class SimpleUserDict: def __init__(self): - self.d = {1:1, 2:2, 3:3} + self.d = {1: 1, 2: 2, 3: 3} + def keys(self): return self.d.keys() + def __getitem__(self, i): return self.d[i] + d.clear() d.update(SimpleUserDict()) - self.assertEqual(d, {1:1, 2:2, 3:3}) + self.assertEqual(d, {1: 1, 2: 2, 3: 3}) def test_lazy_copy(self): - d = LazyDict({'1':1}) - d['2'] = 2 + d = LazyDict({"1": 1}) + d["2"] = 2 x = d.copy() self.assertEqual(len(x), 2) - i = {'num': 0} + i = {"num": 0} + def r(key, i): - i['num'] += 1 - return i['num'] - d.set_stub('3', r, i) + i["num"] += 1 + return i["num"] + + d.set_stub("3", r, i) x = d.copy() - self.assertEqual(d['3'], 1) + self.assertEqual(d["3"], 1) self.assertEqual(len(d._stubs), 0) self.assertEqual(len(x._stubs), 1) - self.assertEqual(x['3'], 2) + self.assertEqual(x["3"], 2) self.assertEqual(len(x._stubs), 0) x = d.copy() - self.assertEqual(d['3'], 1) - self.assertEqual(x['3'], 1) + self.assertEqual(d["3"], 1) + self.assertEqual(x["3"], 1) def test_lazy_get(self): - d = LazyDict({'a': 1, 'b': 2}) - d.set_stub('d', lambda x:x) - self.assertIs(d.get('c'), None) - self.assertEqual(d.get('c', 3), 3) - self.assertEqual(d.get('a'), 1) - self.assertEqual(d.get('a', 3), 1) - self.assertEqual(d.get('d'), 'd') - self.assertEqual(d.get('d', 3), 'd') + d = LazyDict({"a": 1, "b": 2}) + d.set_stub("d", lambda x: x) + self.assertIs(d.get("c"), None) + self.assertEqual(d.get("c", 3), 3) + self.assertEqual(d.get("a"), 1) + self.assertEqual(d.get("a", 3), 1) + self.assertEqual(d.get("d"), "d") + self.assertEqual(d.get("d", 3), "d") self.assertRaises(TypeError, d.get) self.assertRaises(TypeError, d.get, None, None, None) def test_lazy_setdefault(self): d = LazyDict() - self.assertIs(d.setdefault('key0'), None) - d.set_stub('key0', lambda x:'value0') - self.assertIs(d.setdefault('key0'), 'value0') - d.set_stub('key0', lambda x:'value0') - self.assertEqual(d.setdefault('key1', 'value1'), 'value1') - self.assertEqual(d['key1'], 'value1') - self.assertEqual(d.setdefault('key0', 'value2'), 'value0') + self.assertIs(d.setdefault("key0"), None) + d.set_stub("key0", lambda x: "value0") + self.assertIs(d.setdefault("key0"), "value0") + d.set_stub("key0", lambda x: "value0") + self.assertEqual(d.setdefault("key1", "value1"), "value1") + self.assertEqual(d["key1"], "value1") + self.assertEqual(d.setdefault("key0", "value2"), "value0") def test_lazy_popitem(self): d = LazyDict({1: 1}) - d.set_stub(2, lambda x:x) + d.set_stub(2, lambda x: x) k, v = d.popitem() self.assertEqual(k, v) k, v = d.popitem() @@ -630,9 +681,9 @@ class LazyDictTestCase(unittest.TestCase): def test_lazy_pop(self): d = LazyDict() - k, v = ('abc', 'def') - d.set_stub(k, lambda x:'def') - self.assertRaises(KeyError, d.pop, 'ghi') + k, v = ("abc", "def") + d.set_stub(k, lambda x: "def") + self.assertRaises(KeyError, d.pop, "ghi") self.assertEqual(d.pop(k), v) self.assertEqual(len(d), 0) @@ -640,25 +691,25 @@ class LazyDictTestCase(unittest.TestCase): self.assertRaises(KeyError, d.pop, k) self.assertEqual(d.pop(k, v), v) - d.set_stub(k, lambda x:v) + d.set_stub(k, lambda x: v) self.assertEqual(d.pop(k, 1), v) self.assertRaises(TypeError, d.pop) def test_lazy_delitem(self): d = LazyDict() - d['1'] = 1 - d['2'] = 2 - del d['1'] + d["1"] = 1 + d["2"] = 2 + del d["1"] self.assertEqual(len(d), 1) - self.assertRaises(KeyError, d.__getitem__, '1') - d.set_stub('1', lambda x:x) + self.assertRaises(KeyError, d.__getitem__, "1") + d.set_stub("1", lambda x: x) self.assertEqual(len(d), 2) - del d['1'] + del d["1"] self.assertEqual(len(d), 1) - self.assertRaises(KeyError, d.__getitem__, '1') - d.set_stub('1', lambda x:x) - self.assertEqual(d['1'], '1') - del d['1'] + self.assertRaises(KeyError, d.__getitem__, "1") + d.set_stub("1", lambda x: x) + self.assertEqual(d["1"], "1") + del d["1"] self.assertEqual(len(d), 1) - self.assertRaises(KeyError, d.__getitem__, '1') + self.assertRaises(KeyError, d.__getitem__, "1")