From 60669579a7e3189112ce4ecb983928040af79e73 Mon Sep 17 00:00:00 2001 From: Jon Dufresne Date: Sun, 30 Dec 2018 10:54:34 -0500 Subject: Replace odict with Python's collection.OrderedDict The odict class duplicates collection.OrderedDict from Python's standard lib. Simplify the code by using builtin Python features. https://docs.python.org/3/library/collections.html#collections.OrderedDict --- CHANGES | 13 ++++++++ babel/messages/catalog.py | 9 +++--- babel/messages/frontend.py | 5 ++-- babel/util.py | 74 ++-------------------------------------------- tests/test_util.py | 14 --------- 5 files changed, 24 insertions(+), 91 deletions(-) diff --git a/CHANGES b/CHANGES index 6d9b0e5..622b4c5 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,19 @@ Babel Changelog =============== +UNRELEASED +---------- + +Possibly incompatible changes +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +These may be backward incompatible in some cases, as some more-or-less internal +APIs have changed. Please feel free to file issues if you bump into anything +strange and we'll try to help! + +* General: Internal uses of ``babel.util.odict`` have been replaced with + ``collections.OrderedDict`` from The Python standard library. + Version 2.6.0 ------------- diff --git a/babel/messages/catalog.py b/babel/messages/catalog.py index 6d61a38..649d0e2 100644 --- a/babel/messages/catalog.py +++ b/babel/messages/catalog.py @@ -13,6 +13,7 @@ import re import time from cgi import parse_header +from collections import OrderedDict from datetime import datetime, time as time_ from difflib import get_close_matches from email import message_from_string @@ -22,7 +23,7 @@ from babel import __version__ as VERSION from babel.core import Locale, UnknownLocaleError from babel.dates import format_datetime from babel.messages.plurals import get_plural -from babel.util import odict, distinct, LOCALTZ, FixedOffsetTimezone +from babel.util import distinct, LOCALTZ, FixedOffsetTimezone from babel._compat import string_types, number_types, PY2, cmp, text_type, force_text __all__ = ['Message', 'Catalog', 'TranslationError'] @@ -269,7 +270,7 @@ class Catalog(object): self.domain = domain self.locale = locale self._header_comment = header_comment - self._messages = odict() + self._messages = OrderedDict() self.project = project or 'PROJECT' self.version = version or 'VERSION' @@ -295,7 +296,7 @@ class Catalog(object): self.revision_date = revision_date self.fuzzy = fuzzy - self.obsolete = odict() # Dictionary of obsolete messages + self.obsolete = OrderedDict() # Dictionary of obsolete messages self._num_plurals = None self._plural_expr = None @@ -754,7 +755,7 @@ class Catalog(object): """ messages = self._messages remaining = messages.copy() - self._messages = odict() + self._messages = OrderedDict() # Prepare for fuzzy matching fuzzy_candidates = [] diff --git a/babel/messages/frontend.py b/babel/messages/frontend.py index 16cb900..9213cca 100644 --- a/babel/messages/frontend.py +++ b/babel/messages/frontend.py @@ -17,6 +17,7 @@ import re import shutil import sys import tempfile +from collections import OrderedDict from datetime import datetime from locale import getpreferredencoding @@ -28,7 +29,7 @@ from babel.messages.catalog import Catalog from babel.messages.extract import DEFAULT_KEYWORDS, DEFAULT_MAPPING, check_and_call_extract_file, extract_from_dir from babel.messages.mofile import write_mo from babel.messages.pofile import read_po, write_po -from babel.util import LOCALTZ, odict +from babel.util import LOCALTZ from distutils import log as distutils_log from distutils.cmd import Command as _Command from distutils.errors import DistutilsOptionError, DistutilsSetupError @@ -965,7 +966,7 @@ def parse_mapping(fileobj, filename=None): options_map = {} parser = RawConfigParser() - parser._sections = odict(parser._sections) # We need ordered sections + parser._sections = OrderedDict(parser._sections) # We need ordered sections if PY2: parser.readfp(fileobj, filename) diff --git a/babel/util.py b/babel/util.py index fb93f16..c443b69 100644 --- a/babel/util.py +++ b/babel/util.py @@ -10,6 +10,7 @@ """ import codecs +import collections from datetime import timedelta, tzinfo import os import re @@ -220,77 +221,8 @@ def wraptext(text, width=70, initial_indent='', subsequent_indent=''): return wrapper.wrap(text) -class odict(dict): - """Ordered dict implementation. - - :see: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/107747 - """ - - def __init__(self, data=None): - dict.__init__(self, data or {}) - self._keys = list(dict.keys(self)) - - def __delitem__(self, key): - dict.__delitem__(self, key) - self._keys.remove(key) - - def __setitem__(self, key, item): - new_key = key not in self - dict.__setitem__(self, key, item) - if new_key: - self._keys.append(key) - - def __iter__(self): - return iter(self._keys) - iterkeys = __iter__ - - def clear(self): - dict.clear(self) - self._keys = [] - - def copy(self): - d = odict() - d.update(self) - return d - - def items(self): - return zip(self._keys, self.values()) - - def iteritems(self): - return izip(self._keys, self.itervalues()) - - def keys(self): - return self._keys[:] - - def pop(self, key, default=missing): - try: - value = dict.pop(self, key) - self._keys.remove(key) - return value - except KeyError as e: - if default == missing: - raise e - else: - return default - - def popitem(self, key): - self._keys.remove(key) - return dict.popitem(key) - - def setdefault(self, key, failobj=None): - dict.setdefault(self, key, failobj) - if key not in self._keys: - self._keys.append(key) - - def update(self, dict): - for (key, val) in dict.items(): - self[key] = val - - def values(self): - return map(self.get, self._keys) - - def itervalues(self): - return imap(self.get, self._keys) +# TODO (Babel 3.x): Remove this re-export +odict = collections.OrderedDict class FixedOffsetTimezone(tzinfo): diff --git a/tests/test_util.py b/tests/test_util.py index ef59110..0fc59e5 100644 --- a/tests/test_util.py +++ b/tests/test_util.py @@ -38,20 +38,6 @@ def test_pathmatch(): assert not util.pathmatch('./foo/**.py', 'blah/foo/bar/baz.py') -def test_odict_pop(): - odict = util.odict() - odict[0] = 1 - value = odict.pop(0) - assert 1 == value - assert [] == list(odict.items()) - assert odict.pop(2, None) is None - try: - odict.pop(2) - assert False - except KeyError: - assert True - - class FixedOffsetTimezoneTestCase(unittest.TestCase): def test_zone_negative_offset(self): -- cgit v1.2.1