Skip to content

Commit

Permalink
Add support for Python 3.7
Browse files Browse the repository at this point in the history
Fix the DeprecationWarnings it spewed, which is mostly
TestCase.assertRaisesRegexp.
  • Loading branch information
jamadden committed Oct 4, 2018
1 parent 734037a commit 0fdefe7
Show file tree
Hide file tree
Showing 14 changed files with 199 additions and 208 deletions.
5 changes: 5 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ python:
- 3.6
- pypy
- pypy3
matrix:
include:
- python: "3.7"
dist: xenial
sudo: true
install:
- pip install -U pip setuptools
- pip install -U coverage coveralls
Expand Down
6 changes: 4 additions & 2 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,17 @@ Change History for ZConfig
3.3.0 (unreleased)
------------------

- Drop support for Python 3.3.

- Add support for Python 3.7.

- Drop support for 'python setup.py test'. See `issue 38
<https://github.com/zopefoundation/ZConfig/issues/38>`_.

- Add support for ``example`` in ``section`` and ``multisection``, and
include those examples in generated documentation. See
https://github.com/zopefoundation/ZConfig/pull/5.

- Drop support for Python 3.3.

- Fix configuration loaders to decode byte data using UTF-8 instead of
the default encoding (usually ASCII). See `issue 37
<https://github.com/zopefoundation/ZConfig/issues/37>`_.
Expand Down
37 changes: 20 additions & 17 deletions ZConfig/components/logger/tests/test_logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@
from ZConfig._compat import NStringIO as StringIO
from ZConfig._compat import maxsize

from ZConfig.tests.support import TestHelper


class CustomFormatter(logging.Formatter):
def formatException(self, ei):
"""Format and return the exception information as a string.
Expand All @@ -47,7 +50,7 @@ def read_file(filename):
return f.read()


class LoggingTestHelper:
class LoggingTestHelper(TestHelper):

# Not derived from unittest.TestCase; some test runners seem to
# think that means this class contains tests.
Expand Down Expand Up @@ -229,7 +232,7 @@ def test_with_timed_rotating_logfile_and_size_should_fail(self):
"</eventlog>" % fn)

# Mising old-files
self.assertRaisesRegexp(
self.assertRaisesRegex(
ValueError,
"old-files must be set",
self.check_simple_logger,
Expand All @@ -242,7 +245,7 @@ def test_with_timed_rotating_logfile_and_size_should_fail(self):
" </logfile>\n"
"</eventlog>" % fn)

self.assertRaisesRegexp(
self.assertRaisesRegex(
ValueError,
"max-bytes or when must be set",
self.check_simple_logger,
Expand Down Expand Up @@ -683,13 +686,13 @@ def test_filehandler_reopen_thread_safety(self):

self.assertEqual(calls, ["acquire", "release"])

class TestFunctions(unittest.TestCase):
class TestFunctions(TestHelper, unittest.TestCase):

def test_log_format_bad(self):
self.assertRaisesRegexp(ValueError,
"Invalid log format string",
handlers.log_format,
"%{no-such-key}s")
self.assertRaisesRegex(ValueError,
"Invalid log format string",
handlers.log_format,
"%{no-such-key}s")

def test_resolve_deep(self):
old_mod = None
Expand All @@ -708,15 +711,15 @@ def test_resolve_deep(self):
sys.modules['logging.handlers'] = old_mod

def test_http_handler_url(self):
self.assertRaisesRegexp(ValueError,
'must be an http',
handlers.http_handler_url, 'file://foo/baz')
self.assertRaisesRegexp(ValueError,
'must specify a location',
handlers.http_handler_url, 'http://')
self.assertRaisesRegexp(ValueError,
'must specify a path',
handlers.http_handler_url, 'http://server')
self.assertRaisesRegex(ValueError,
'must be an http',
handlers.http_handler_url, 'file://foo/baz')
self.assertRaisesRegex(ValueError,
'must specify a location',
handlers.http_handler_url, 'http://')
self.assertRaisesRegex(ValueError,
'must specify a path',
handlers.http_handler_url, 'http://server')

v = handlers.http_handler_url("http://server/path;param?q=v#fragment")
self.assertEqual(v, ('server', '/path;param?q=v#fragment'))
Expand Down
8 changes: 6 additions & 2 deletions ZConfig/schema2html.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@

import argparse
from contextlib import contextmanager
import cgi
try:
import html
except ImportError:
# Py2
import cgi as html
import sys

from ZConfig._schema_utils import AbstractSchemaPrinter
Expand All @@ -27,7 +31,7 @@
class HtmlSchemaFormatter(AbstractSchemaFormatter):

def esc(self, x):
return cgi.escape(str(x))
return html.escape(str(x))

@contextmanager
def _simple_tag(self, tag):
Expand Down
3 changes: 3 additions & 0 deletions ZConfig/tests/support.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import contextlib
import os
import sys
from unittest import TestCase

import ZConfig

Expand Down Expand Up @@ -59,6 +60,8 @@ class TestHelper(object):
# Not derived from unittest.TestCase; some test runners seem to
# think that means this class contains tests.

assertRaisesRegex = getattr(TestCase, 'assertRaisesRegex', TestCase.assertRaisesRegexp)

def load_both(self, schema_url, conf_url):
schema = self.load_schema(schema_url)
conf = self.load_config(schema, conf_url)
Expand Down
47 changes: 20 additions & 27 deletions ZConfig/tests/test_cmdline.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,20 +91,20 @@ def test_named_sections(self):
# Ignore foo for now; it's not really important *when* it fails.

# ValueErrors are converted into ConfigurationSyntaxErrors
self.assertRaisesRegexp(ZConfig.ConfigurationSyntaxError,
"could not convert",
foo.basic_key,
'invalid name', ('<place>', 1,))
self.assertRaisesRegex(ZConfig.ConfigurationSyntaxError,
"could not convert",
foo.basic_key,
'invalid name', ('<place>', 1,))

# missing keys return empty lists
self.assertEqual(foo.get_key('no such key'), [])

# VE for matchers do the same conversion
matcher = loader.createSchemaMatcher()
self.assertRaisesRegexp(ZConfig.DataConversionError,
"value did not match",
matcher.addValue,
'invalid name', 'value', (1, 1, '<place>'))
self.assertRaisesRegex(ZConfig.DataConversionError,
"value did not match",
matcher.addValue,
'invalid name', 'value', (1, 1, '<place>'))


simple_schema = None
Expand Down Expand Up @@ -193,28 +193,21 @@ def test_section_contents(self):
self.assertEqual(conf.s2.k3, ["value1", "value2", "value3", "value4"])

self.clopts = [("path/that/dne=foo",)]
self.assertRaisesRegexp(ZConfig.ConfigurationError,
"not all command line options were consumed",
self.load_config_text,
schema, "<st s1/>")
self.assertRaisesRegex(ZConfig.ConfigurationError,
"not all command line options were consumed",
self.load_config_text,
schema, "<st s1/>")

def test_bad_overrides(self):
schema = self.get_simple_schema()
self.clopts = [('',)]
self.assertRaisesRegexp(ZConfig.ConfigurationSyntaxError,
"invalid configuration specifier",
self.create_config_loader,
schema)
self.assertRaisesRegex(ZConfig.ConfigurationSyntaxError,
"invalid configuration specifier",
self.create_config_loader,
schema)

self.clopts = [('double//slashes=value',)]
self.assertRaisesRegexp(ZConfig.ConfigurationSyntaxError,
"not allowed in an option path",
self.create_config_loader,
schema)


def test_suite():
return unittest.defaultTestLoader.loadTestsFromName(__name__)

if __name__ == '__main__':
unittest.main(defaultTest='test_suite')
self.assertRaisesRegex(ZConfig.ConfigurationSyntaxError,
"not allowed in an option path",
self.create_config_loader,
schema)
65 changes: 33 additions & 32 deletions ZConfig/tests/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@
import ZConfig

from ZConfig.tests.support import CONFIG_BASE
from ZConfig.tests.support import TestHelper

from ZConfig._compat import NStringIO as StringIO

class ConfigurationTestCase(unittest.TestCase):
class ConfigurationTestCase(TestHelper, unittest.TestCase):

schema = None

Expand Down Expand Up @@ -171,51 +172,51 @@ def test_define_errors(self):
self.assertNotIn('line', str(exc))

def test_bad_directive(self):
self.assertRaisesRegexp(ZConfig.ConfigurationSyntaxError,
'unknown directive',
self.loadtext, '%not a directive')
self.assertRaisesRegex(ZConfig.ConfigurationSyntaxError,
'unknown directive',
self.loadtext, '%not a directive')

self.assertRaisesRegexp(ZConfig.ConfigurationSyntaxError,
'missing or unrecognized',
self.loadtext, '%')
self.assertRaisesRegex(ZConfig.ConfigurationSyntaxError,
'missing or unrecognized',
self.loadtext, '%')

def test_bad_key(self):
self.assertRaisesRegexp(ZConfig.ConfigurationSyntaxError,
'malformed configuration data',
self.loadtext, '(int-var')
self.assertRaisesRegex(ZConfig.ConfigurationSyntaxError,
'malformed configuration data',
self.loadtext, '(int-var')

def test_bad_section(self):
self.schema = ZConfig.loadSchema(CONFIG_BASE + "simplesections.xml")
self.assertRaisesRegexp(ZConfig.ConfigurationSyntaxError,
'unexpected section end',
self.loadtext, '</close>')
self.assertRaisesRegex(ZConfig.ConfigurationSyntaxError,
'unexpected section end',
self.loadtext, '</close>')

self.assertRaisesRegexp(ZConfig.ConfigurationSyntaxError,
'unbalanced section end',
self.loadtext, '<section>\n</close>')
self.assertRaisesRegex(ZConfig.ConfigurationSyntaxError,
'unbalanced section end',
self.loadtext, '<section>\n</close>')

self.assertRaisesRegexp(ZConfig.ConfigurationSyntaxError,
'unclosed sections not allowed',
self.loadtext, '<section>\n')
self.assertRaisesRegex(ZConfig.ConfigurationSyntaxError,
'unclosed sections not allowed',
self.loadtext, '<section>\n')

self.assertRaisesRegexp(ZConfig.ConfigurationSyntaxError,
'malformed section header',
self.loadtext, '<section()>\n</close>')
self.assertRaisesRegex(ZConfig.ConfigurationSyntaxError,
'malformed section header',
self.loadtext, '<section()>\n</close>')

self.assertRaisesRegexp(ZConfig.ConfigurationSyntaxError,
'malformed section end',
self.loadtext, '<section>\n</section')
self.assertRaisesRegex(ZConfig.ConfigurationSyntaxError,
'malformed section end',
self.loadtext, '<section>\n</section')

self.assertRaisesRegexp(ZConfig.ConfigurationSyntaxError,
'malformed section start',
self.loadtext, '<section')
self.assertRaisesRegex(ZConfig.ConfigurationSyntaxError,
'malformed section start',
self.loadtext, '<section')

# ConfigLoader.endSection raises this and it is recaught and changed to a
# SyntaxError
self.assertRaisesRegexp(ZConfig.ConfigurationSyntaxError,
"no values for",
self.loadtext,
"<hasmin foo>\n</hasmin>")
self.assertRaisesRegex(ZConfig.ConfigurationSyntaxError,
"no values for",
self.loadtext,
"<hasmin foo>\n</hasmin>")

def test_configuration_error_str(self):

Expand Down
35 changes: 15 additions & 20 deletions ZConfig/tests/test_datatypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@

import ZConfig.datatypes

from ZConfig.tests.support import TestHelper

here = os.path.abspath(__file__)

try:
Expand Down Expand Up @@ -383,7 +385,7 @@ def test_timedelta(self):

raises(TypeError, convert, '1y')

class RegistryTestCase(unittest.TestCase):
class RegistryTestCase(TestHelper, unittest.TestCase):

def test_registry_does_not_mask_toplevel_imports(self):
old_sys_path = sys.path[:]
Expand All @@ -406,35 +408,28 @@ def test_registry_does_not_mask_toplevel_imports(self):

def test_register_shadow(self):
reg = ZConfig.datatypes.Registry()
self.assertRaisesRegexp(ValueError,
"conflicts with built-in type",
reg.register,
'integer', None)
self.assertRaisesRegex(ValueError,
"conflicts with built-in type",
reg.register,
'integer', None)

reg.register("foobar", None)
self.assertRaisesRegexp(ValueError,
"already registered",
reg.register,
'foobar', None)
self.assertRaisesRegex(ValueError,
"already registered",
reg.register,
'foobar', None)

def test_get_fallback_basic_key(self):
reg = ZConfig.datatypes.Registry({})
self.assertIsNone(reg._basic_key)
self.assertRaisesRegexp(ValueError,
"unloadable datatype name",
reg.get,
'integer')
self.assertRaisesRegex(ValueError,
"unloadable datatype name",
reg.get,
'integer')
self.assertIsNotNone(reg._basic_key)

TEST_DATATYPE_SOURCE = """
# sample datatypes file
my_sample_datatype = 42
"""


def test_suite():
return unittest.defaultTestLoader.loadTestsFromName(__name__)

if __name__ == '__main__':
unittest.main(defaultTest='test_suite')
Loading

0 comments on commit 0fdefe7

Please sign in to comment.