Skip to content

Commit

Permalink
Drop support for Python 2.7 up to 3.6.
Browse files Browse the repository at this point in the history
  • Loading branch information
Michael Howitz committed Jan 6, 2023
1 parent c96fab6 commit 61c56d9
Show file tree
Hide file tree
Showing 30 changed files with 438 additions and 497 deletions.
2 changes: 2 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

- Drop support for Python 2.7, 3.5, 3.6.

- Drop deprecated support for running the tests using ``python setup.py test``.


4.9.0 (2021-12-09)
==================
Expand Down
18 changes: 0 additions & 18 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,22 +29,6 @@ def read(*rnames):
return f.read()


def alltests():
import sys
import unittest

# use the zope.testrunner machinery to find all the
# test suites we've put under ourselves
import zope.testrunner.find
import zope.testrunner.options
here = os.path.abspath(os.path.join(os.path.dirname(__file__), 'src'))
args = sys.argv[:]
defaults = ["--test-path", here]
options = zope.testrunner.options.get_options(args, defaults)
suites = list(zope.testrunner.find.find_suites(options))
return unittest.TestSuite(suites)


COMPILE_REQUIRES = [
# python-gettext used to be here, but it's now
# a fixed requirement. Keep the extra to avoid
Expand Down Expand Up @@ -118,8 +102,6 @@ def alltests():
'repoze.sphinx.autointerface',
],
},
tests_require=TESTS_REQUIRE,
test_suite='__main__.alltests',
include_package_data=True,
zip_safe=False,
)
9 changes: 4 additions & 5 deletions src/zope/i18n/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
from zope.i18nmessageid import Message
from zope.i18nmessageid import MessageFactory # noqa

from zope.i18n._compat import text_type
from zope.i18n.config import ALLOWED_LANGUAGES
from zope.i18n.interfaces import IFallbackTranslationDomainFactory
from zope.i18n.interfaces import INegotiator
Expand All @@ -37,7 +36,7 @@
% ({'n': NAME_RE}))


class _FallbackNegotiator(object):
class _FallbackNegotiator:

def getLanguage(self, _allowed, _context):
return None
Expand Down Expand Up @@ -171,9 +170,9 @@ def translate(msgid, domain=None, mapping=None, context=None,
number = msgid.number

if default is None:
default = text_type(msgid)
default = str(msgid)
if msgid_plural is not None and default_plural is None:
default_plural = text_type(msgid_plural)
default_plural = str(msgid_plural)

if domain:
util = queryUtility(ITranslationDomain, domain)
Expand Down Expand Up @@ -239,7 +238,7 @@ def replace(match):
value = mapping.get(param1 or param2, whole)
if isinstance(value, Message):
value = interpolate(value, value.mapping)
return text_type(value)
return str(value)

if not text or not mapping:
return text
Expand Down
8 changes: 0 additions & 8 deletions src/zope/i18n/_compat.py

This file was deleted.

9 changes: 3 additions & 6 deletions src/zope/i18n/compile.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
def _safe_mtime(path):
try:
return os.path.getmtime(path)
except (IOError, OSError):
except OSError:
return None


Expand All @@ -37,10 +37,7 @@ def compile_mo_file(domain, lc_messages_path):

if po_mtime > mo_mtime:
try:
# Msgfmt.getAsFile returns io.BytesIO on Python 3,
# and cStringIO.StringIO on Python 2;
# sadly StringIO isn't a proper context manager, so we have to
# wrap it with `closing`. Also, Msgfmt doesn't properly close a
# Msgfmt doesn't properly close a
# file it opens for reading if you pass the path,
# but it does if you pass the file.
with open(pofile, 'rb') as pofd:
Expand All @@ -50,5 +47,5 @@ def compile_mo_file(domain, lc_messages_path):
except PoSyntaxError as err:
logger.warning(
'Syntax error while compiling %s (%s).', pofile, err.msg)
except (IOError, OSError) as err:
except OSError as err:
logger.warning('Error while compiling %s (%s).', pofile, err)
74 changes: 31 additions & 43 deletions src/zope/i18n/format.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,10 @@
import pytz.reference
from zope.interface import implementer

from zope.i18n._compat import text_type
from zope.i18n.interfaces import IDateTimeFormat
from zope.i18n.interfaces import INumberFormat


NATIVE_NUMBER_TYPES = (int, float)
try:
NATIVE_NUMBER_TYPES += (long,)
except NameError:
pass # Py3


def roundHalfUp(n):
"""Works like round() in python2.x
Expand All @@ -57,7 +49,7 @@ class DateTimeParseError(Exception):


@implementer(IDateTimeFormat)
class DateTimeFormat(object):
class DateTimeFormat:
__doc__ = IDateTimeFormat.__doc__

_DATETIMECHARS = "aGyMdEDFwWhHmsSkKz"
Expand Down Expand Up @@ -214,7 +206,7 @@ def format(self, obj, pattern=None):
else:
bin_pattern = self._bin_pattern

text = u""
text = ""
info = buildDateTimeInfo(obj, self.calendar, bin_pattern)
for elem in bin_pattern:
text += info.get(elem, elem)
Expand All @@ -228,7 +220,7 @@ class NumberParseError(Exception):


@implementer(INumberFormat)
class NumberFormat(object):
class NumberFormat:
__doc__ = INumberFormat.__doc__

type = None
Expand All @@ -238,18 +230,18 @@ class NumberFormat(object):
def __init__(self, pattern=None, symbols=()):
# setup default symbols
self.symbols = {
u"decimal": u".",
u"group": u",",
u"list": u";",
u"percentSign": u"%",
u"nativeZeroDigit": u"0",
u"patternDigit": u"#",
u"plusSign": u"+",
u"minusSign": u"-",
u"exponential": u"E",
u"perMille": u"\xe2\x88\x9e",
u"infinity": u"\xef\xbf\xbd",
u"nan": u''
"decimal": ".",
"group": ",",
"list": ";",
"percentSign": "%",
"nativeZeroDigit": "0",
"patternDigit": "#",
"plusSign": "+",
"minusSign": "-",
"exponential": "E",
"perMille": "\xe2\x88\x9e",
"infinity": "\xef\xbf\xbd",
"nan": ''
}
self.symbols.update(symbols)
if pattern is not None:
Expand Down Expand Up @@ -413,12 +405,7 @@ def format(self, obj, pattern=None, rounding=True):
else:
bin_pattern = bin_pattern[1]

if isinstance(obj, NATIVE_NUMBER_TYPES):
# repr() handles high-precision numbers correctly in
# Python 2 and 3. str() is only correct in Python 3.
strobj = repr(obj)
else:
strobj = str(obj)
strobj = str(obj)
if 'e' in strobj:
# Str(obj) # returned scientific representation of a number (e.g.
# 1e-7). We can't rely on str() to format fraction.
Expand All @@ -434,7 +421,7 @@ def format(self, obj, pattern=None, rounding=True):
# The exponential might have a mandatory sign; remove it from the
# bin_pattern and remember the setting
exp_bin_pattern = bin_pattern[EXPONENTIAL]
plus_sign = u""
plus_sign = ""
if exp_bin_pattern.startswith('+'):
plus_sign = self.symbols['plusSign']
exp_bin_pattern = exp_bin_pattern[1:]
Expand Down Expand Up @@ -512,8 +499,8 @@ def format(self, obj, pattern=None, rounding=True):
if bin_pattern[PADDING4] is not None and post_padding > 0:
text += bin_pattern[PADDING4] * post_padding

# TODO: Need to make sure unicode is everywhere
return text_type(text)
# TODO: Need to make sure str is everywhere
return str(text)


DEFAULT = 0
Expand Down Expand Up @@ -624,12 +611,13 @@ def buildDateTimeParseInfo(calendar, pattern):

# am/pm marker (Text)
for entry in _findFormattingCharacterInPattern('a', pattern):
info[entry] = r'(%s|%s)' % (calendar.am, calendar.pm)
info[entry] = r'({}|{})'.format(calendar.am, calendar.pm)

# era designator (Text)
# TODO: works for gregorian only right now
for entry in _findFormattingCharacterInPattern('G', pattern):
info[entry] = r'(%s|%s)' % (calendar.eras[1][1], calendar.eras[2][1])
info[entry] = r'({}|{})'.format(
calendar.eras[1][1], calendar.eras[2][1])

# time zone (Text)
for entry in _findFormattingCharacterInPattern('z', pattern):
Expand Down Expand Up @@ -705,8 +693,8 @@ def buildDateTimeInfo(dt, calendar, pattern):
tz_fullname = getattr(tzinfo, 'zone', None) or tz_name

info = {
('y', 2): text_type(dt.year)[2:],
('y', 4): text_type(dt.year),
('y', 2): str(dt.year)[2:],
('y', 4): str(dt.year),
}

# Generic Numbers
Expand All @@ -717,7 +705,7 @@ def buildDateTimeInfo(dt, calendar, pattern):
('S', dt.microsecond), ('w', int(dt.strftime('%W'))),
('W', week_in_month)):
for entry in _findFormattingCharacterInPattern(field, pattern):
info[entry] = (u"%%.%ii" % entry[1]) % value
info[entry] = ("%%.%ii" % entry[1]) % value

# am/pm marker (Text)
for entry in _findFormattingCharacterInPattern('a', pattern):
Expand All @@ -731,9 +719,9 @@ def buildDateTimeInfo(dt, calendar, pattern):
# time zone (Text)
for entry in _findFormattingCharacterInPattern('z', pattern):
if entry[1] == 1:
info[entry] = u"%s%i%.2i" % (tz_sign, tz_hours, tz_mins)
info[entry] = "%s%i%.2i" % (tz_sign, tz_hours, tz_mins)
elif entry[1] == 2:
info[entry] = u"%s%.2i:%.2i" % (tz_sign, tz_hours, tz_mins)
info[entry] = "%s%.2i:%.2i" % (tz_sign, tz_hours, tz_mins)
elif entry[1] == 3:
info[entry] = tz_name
else:
Expand All @@ -742,9 +730,9 @@ def buildDateTimeInfo(dt, calendar, pattern):
# month in year (Text and Number)
for entry in _findFormattingCharacterInPattern('M', pattern):
if entry[1] == 1:
info[entry] = u"%i" % dt.month
info[entry] = "%i" % dt.month
elif entry[1] == 2:
info[entry] = u"%.2i" % dt.month
info[entry] = "%.2i" % dt.month
elif entry[1] == 3:
info[entry] = calendar.months[dt.month][1]
else:
Expand All @@ -753,9 +741,9 @@ def buildDateTimeInfo(dt, calendar, pattern):
# day in week (Text and Number)
for entry in _findFormattingCharacterInPattern('E', pattern):
if entry[1] == 1:
info[entry] = u"%i" % weekday
info[entry] = "%i" % weekday
elif entry[1] == 2:
info[entry] = u"%.2i" % weekday
info[entry] = "%.2i" % weekday
elif entry[1] == 3:
info[entry] = calendar.days[dt.weekday() + 1][1]
else:
Expand Down
4 changes: 2 additions & 2 deletions src/zope/i18n/gettextmessagecatalog.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from zope.i18n.interfaces import IGlobalMessageCatalog


class _KeyErrorRaisingFallback(object):
class _KeyErrorRaisingFallback:
def ugettext(self, message):
raise KeyError(message)

Expand Down Expand Up @@ -53,7 +53,7 @@ def pformat(catalog, singular, plural, n, *args, **kwargs):


@implementer(IGlobalMessageCatalog)
class GettextMessageCatalog(object):
class GettextMessageCatalog:
"""A message catalog based on GNU gettext and Python's gettext module."""

_catalog = None
Expand Down
36 changes: 18 additions & 18 deletions src/zope/i18n/interfaces/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,13 +89,13 @@ def queryPluralMessage(singular, plural, n, dft1=None, dft2=None):
"""

language = TextLine(
title=u"Language",
description=u"The language the catalog translates to.",
title="Language",
description="The language the catalog translates to.",
required=True)

domain = TextLine(
title=u"Domain",
description=u"The domain the catalog is registered for.",
title="Domain",
description="The domain the catalog is registered for.",
required=True)

def getIdentifier():
Expand Down Expand Up @@ -153,8 +153,8 @@ class ITranslationDomain(Interface):
"""

domain = TextLine(
title=u"Domain Name",
description=u"The name of the domain this object represents.",
title="Domain Name",
description="The name of the domain this object represents.",
required=True)

def translate(msgid, mapping=None, context=None, target_language=None,
Expand All @@ -181,7 +181,7 @@ class IFallbackTranslationDomainFactory(Interface):
debugging i18n.
"""

def __call__(domain_id=u""):
def __call__(domain_id=""):
"""Return a fallback translation domain for the given domain id.
"""

Expand Down Expand Up @@ -383,22 +383,22 @@ class INumberFormat(IFormat):
"""

type = Field(
title=u"Type",
description=((u"The type into which a string is parsed. If ``None``, "
u"then ``int`` will be used for whole numbers and "
u"``float`` for decimals.")),
title="Type",
description=("The type into which a string is parsed. If ``None``, "
"then ``int`` will be used for whole numbers and "
"``float`` for decimals."),
default=None,
required=False)

symbols = Dict(
title=u"Number Symbols",
title="Number Symbols",
key_type=Choice(
title=u"Dictionary Class",
values=(u"decimal", u"group", u"list", u"percentSign",
u"nativeZeroDigit", u"patternDigit", u"plusSign",
u"minusSign", u"exponential", u"perMille",
u"infinity", u"nan")),
value_type=TextLine(title=u"Symbol"))
title="Dictionary Class",
values=("decimal", "group", "list", "percentSign",
"nativeZeroDigit", "patternDigit", "plusSign",
"minusSign", "exponential", "perMille",
"infinity", "nan")),
value_type=TextLine(title="Symbol"))


class IDateTimeFormat(IFormat):
Expand Down

0 comments on commit 61c56d9

Please sign in to comment.