configglue team mailing list archive
-
configglue team
-
Mailing list archive
-
Message #00437
[Merge] lp:~ricardokirkner/configglue/py3k into lp:configglue
Ricardo Kirkner has proposed merging lp:~ricardokirkner/configglue/py3k into lp:configglue.
Commit message:
made code Python 3.x compatible
Requested reviews:
Configglue developers (configglue)
For more details, see:
https://code.launchpad.net/~ricardokirkner/configglue/py3k/+merge/165793
This branch adds compatibility for Python 2.6, 2.7, 3.2 and 3.3
There is one backwards incompatible change, which is that the source file is expected to be read as a unicode string, which means it cannot contain strings using multiple encodings, but all strings within the config file have to be expressed in the same encoding.
--
https://code.launchpad.net/~ricardokirkner/configglue/py3k/+merge/165793
Your team Configglue developers is requested to review the proposed merge of lp:~ricardokirkner/configglue/py3k into lp:configglue.
=== modified file 'configglue/__init__.py'
--- configglue/__init__.py 2012-05-04 19:22:39 +0000
+++ configglue/__init__.py 2013-05-27 01:13:29 +0000
@@ -14,4 +14,4 @@
#
###############################################################################
-__version__ = '1.0.3'
+__version__ = '1.1.0'
=== added file 'configglue/_compat.py'
--- configglue/_compat.py 1970-01-01 00:00:00 +0000
+++ configglue/_compat.py 2013-05-27 01:13:29 +0000
@@ -0,0 +1,15 @@
+import sys
+
+
+PY2 = sys.version_info[0] == 2
+
+if not PY2:
+ text_type = str
+ string_types = (str,)
+ import builtins
+ iteritems = lambda d: iter(d.items())
+else:
+ text_type = unicode
+ string_types = (str, unicode)
+ import __builtin__ as builtins
+ iteritems = lambda d: d.iteritems()
=== modified file 'configglue/glue.py'
--- configglue/glue.py 2011-07-29 22:16:30 +0000
+++ configglue/glue.py 2013-05-27 01:13:29 +0000
@@ -16,7 +16,7 @@
import os
import sys
-from ConfigParser import (
+from configparser import (
NoOptionError,
NoSectionError,
)
=== modified file 'configglue/inischema/attributed.py'
--- configglue/inischema/attributed.py 2011-07-17 22:32:16 +0000
+++ configglue/inischema/attributed.py 2013-05-27 01:13:29 +0000
@@ -18,7 +18,7 @@
AttributtedConfigParser lives here.
"""
import re
-from ConfigParser import RawConfigParser
+from configparser import RawConfigParser
marker = object()
=== modified file 'configglue/inischema/glue.py'
--- configglue/inischema/glue.py 2011-07-17 22:32:16 +0000
+++ configglue/inischema/glue.py 2013-05-27 01:13:29 +0000
@@ -18,9 +18,9 @@
"""
from __future__ import absolute_import
-import __builtin__
from collections import namedtuple
+from configglue._compat import builtins
from configglue.inischema import parsers
from configglue.inischema.attributed import AttributedConfigParser
from configglue.glue import schemaconfigglue
@@ -78,7 +78,7 @@
parser_args = option.attrs.pop('parser.args', '').split()
parser_fun = getattr(parsers, parser, None)
if parser_fun is None:
- parser_fun = getattr(__builtin__, parser, None)
+ parser_fun = getattr(builtins, parser, None)
if parser_fun is None:
parser_fun = lambda x: x
=== modified file 'configglue/inischema/typed.py'
--- configglue/inischema/typed.py 2011-07-17 22:32:16 +0000
+++ configglue/inischema/typed.py 2013-05-27 01:13:29 +0000
@@ -15,10 +15,11 @@
###############################################################################
""" TypedConfigParser lives here """
-from __future__ import absolute_import
+from __future__ import absolute_import, unicode_literals
import os
+from configglue._compat import text_type
from . import parsers
from .attributed import AttributedConfigParser
@@ -34,7 +35,7 @@
'float': float,
'int': int,
'lines': parsers.lines,
- 'unicode': unicode,
+ 'unicode': text_type,
'getenv': os.getenv,
None: lambda x: x}
=== modified file 'configglue/parser.py'
--- configglue/parser.py 2013-05-08 15:20:47 +0000
+++ configglue/parser.py 2013-05-27 01:13:29 +0000
@@ -20,15 +20,18 @@
import logging
import os
import re
-import string
+from io import TextIOWrapper
-from ConfigParser import (
+from configparser import (
DEFAULTSECT,
SafeConfigParser as BaseConfigParser,
InterpolationMissingOptionError,
NoOptionError,
NoSectionError,
)
+from functools import reduce
+
+from configglue._compat import text_type, string_types
__all__ = [
@@ -75,6 +78,8 @@
self._basedir = ''
self._dirty = collections.defaultdict(
lambda: collections.defaultdict(dict))
+ # map to location in configparser
+ self._KEYCRE = self._interpolation._KEYCRE
def is_valid(self, report=False):
"""Return if the state of the parser is valid.
@@ -155,8 +160,8 @@
# structure validates, validate content
self.parse_all()
- except Exception, e:
- errors.append(str(e))
+ except Exception as e:
+ errors.append(text_type(e))
valid = False
if report:
@@ -201,7 +206,7 @@
for option in options:
try:
value = self._interpolate(section, option, d[option], d)
- except InterpolationMissingOptionError, e:
+ except InterpolationMissingOptionError as e:
# interpolation failed, because key was not found in
# section. try other sections before bailing out
value = self._interpolate_value(section, option)
@@ -243,7 +248,7 @@
"""Like ConfigParser.read, but consider files we've already read."""
if already_read is None:
already_read = set()
- if isinstance(filenames, basestring):
+ if isinstance(filenames, string_types):
filenames = [filenames]
read_ok = []
for filename in filenames:
@@ -280,7 +285,7 @@
old_basedir, self._basedir = self._basedir, os.path.dirname(
fpname)
includes = self.get('__main__', 'includes')
- filenames = map(string.strip, includes)
+ filenames = list(map(text_type.strip, includes))
self.read(filenames, already_read=already_read)
self._basedir = old_basedir
@@ -300,7 +305,7 @@
def _update_location(self, old_sections, filename):
# keep list of valid options to include locations for
- option_names = map(lambda x: x.name, self.schema.options())
+ option_names = list(map(lambda x: x.name, self.schema.options()))
# new values
sections = self._sections
@@ -348,7 +353,7 @@
try:
value = option_obj.parse(value, **kwargs)
- except ValueError, e:
+ except ValueError as e:
raise ValueError("Invalid value '%s' for %s '%s' in"
" section '%s'. Original exception was: %s" %
(value, option_obj.__class__.__name__, option,
@@ -379,7 +384,7 @@
def _extract_interpolation_keys(self, item):
if isinstance(item, (list, tuple)):
- keys = map(self._extract_interpolation_keys, item)
+ keys = list(map(self._extract_interpolation_keys, item))
keys = reduce(set.union, keys, set())
else:
keys = set(self._KEYCRE.findall(item))
@@ -390,7 +395,7 @@
def _get_interpolation_keys(self, section, option):
- rawval = super(SchemaConfigParser, self).get(section, option, True)
+ rawval = super(SchemaConfigParser, self).get(section, option, raw=True)
try:
opt = self.schema.section(section).option(option)
value = opt.parse(rawval, raw=True)
@@ -400,6 +405,10 @@
keys = self._extract_interpolation_keys(value)
return rawval, keys
+ def _interpolate(self, *args, **kwargs):
+ """Helper method for transition to configparser."""
+ return self._interpolation.before_get(self, *args, **kwargs)
+
def _interpolate_value(self, section, option):
rawval, keys = self._get_interpolation_keys(section, option)
if not keys:
@@ -429,7 +438,7 @@
# replace holders with values
result = rawval % values
- assert isinstance(result, basestring)
+ assert isinstance(result, string_types)
return result
def interpolate_environment(self, rawval, raw=False):
@@ -508,20 +517,20 @@
pass
# value is defined entirely in current section
value = super(SchemaConfigParser, self).get(section, option,
- raw, vars)
- except InterpolationMissingOptionError, e:
+ raw=raw, vars=vars)
+ except InterpolationMissingOptionError as e:
# interpolation key not in same section
value = self._interpolate_value(section, option)
if value is None:
# this should be a string, so None indicates an error
raise e
- except (NoSectionError, NoOptionError), e:
+ except (NoSectionError, NoOptionError) as e:
# option not found in config, try to get its default value from
# schema
value = self._get_default(section, option)
# interpolate environment variables
- if isinstance(value, basestring):
+ if isinstance(value, string_types):
try:
value = self.interpolate_environment(value, raw=raw)
if parse:
@@ -582,11 +591,12 @@
"""
if fp is not None:
- if isinstance(fp, basestring):
+ if isinstance(fp, string_types):
fp = open(fp, 'w')
- # write to a specific file
- encoded_fp = codecs.getwriter(CONFIG_FILE_ENCODING)(fp)
- self.write(encoded_fp)
+ if not isinstance(fp, TextIOWrapper):
+ # write to a specific file
+ fp = codecs.getwriter(CONFIG_FILE_ENCODING)(fp)
+ self.write(fp)
else:
# write to the original files
for filename, sections in self._dirty.items():
=== modified file 'configglue/schema.py'
--- configglue/schema.py 2011-09-30 19:30:46 +0000
+++ configglue/schema.py 2013-05-27 01:13:29 +0000
@@ -13,15 +13,18 @@
# For bug reports, support, and new releases: http://launchpad.net/configglue
#
###############################################################################
+from __future__ import unicode_literals
import json
-from ConfigParser import (
+from configparser import (
NoSectionError,
NoOptionError,
)
from copy import deepcopy
from inspect import getmembers
+from configglue._compat import text_type, string_types
+
__all__ = [
'BoolOption',
@@ -156,6 +159,9 @@
def __ne__(self, other):
return not self.__eq__(other)
+ def __hash__(self):
+ return id(self)
+
def is_valid(self):
"""Return whether the schema has a valid structure."""
explicit_default_section = isinstance(getattr(self, '__main__', None),
@@ -186,7 +192,7 @@
To get options from the default section, specify section='__main__'
"""
- if isinstance(section, basestring):
+ if isinstance(section, string_types):
section = self.section(section)
if section is None:
options = []
@@ -222,6 +228,9 @@
def __ne__(self, other):
return not self.__eq__(other)
+ def __hash__(self):
+ return id(self)
+
def __repr__(self):
if self.name:
name = " %s" % self.name
@@ -316,6 +325,9 @@
def __ne__(self, other):
return not self.__eq__(other)
+ def __hash__(self):
+ return id(self)
+
def __repr__(self):
extra = ' raw' if self.raw else ''
extra += ' fatal' if self.fatal else ''
@@ -341,7 +353,7 @@
def to_string(self, value):
"""Return a string representation of the value."""
- return str(value)
+ return text_type(value)
class BoolOption(Option):
@@ -432,6 +444,9 @@
return equal
+ def __hash__(self):
+ return id(self)
+
def _get_default(self):
return []
@@ -501,6 +516,9 @@
return equal
+ def __hash__(self):
+ return id(self)
+
def _get_default(self):
return '' if not self.null else None
@@ -514,7 +532,7 @@
result = value
elif self.null:
result = None if value in (None, 'None') else value
- elif isinstance(value, basestring):
+ elif isinstance(value, string_types):
result = value
else:
result = repr(value)
@@ -526,7 +544,7 @@
return value
def validate(self, value):
- return (self.null and value is None) or isinstance(value, basestring)
+ return (self.null and value is None) or isinstance(value, string_types)
class TupleOption(Option):
@@ -552,6 +570,9 @@
return equal
+ def __hash__(self):
+ return id(self)
+
def _get_default(self):
return ()
@@ -620,6 +641,9 @@
return equal
+ def __hash__(self):
+ return id(self)
+
def _get_default(self):
default = {}
for key, value in self.spec.items():
@@ -683,7 +707,7 @@
if not raw:
value = option.default
else:
- value = unicode(option.default)
+ value = text_type(option.default)
result[key] = value
return result
=== modified file 'configglue/tests/app/test_base.py'
--- configglue/tests/app/test_base.py 2011-07-23 20:26:54 +0000
+++ configglue/tests/app/test_base.py 2013-05-27 01:13:29 +0000
@@ -14,7 +14,6 @@
#
###############################################################################
import os
-import user
from optparse import OptionParser
from unittest import TestCase
@@ -68,8 +67,8 @@
class ConfigTestCase(TestCase):
def get_xdg_config_dirs(self):
xdg_config_home = os.environ.get('XDG_CONFIG_HOME',
- os.path.join(user.home, '.config'))
- xdg_config_dirs = ([xdg_config_home] +
+ os.path.join(os.path.expanduser('~'), '.config'))
+ xdg_config_dirs = ([xdg_config_home] +
os.environ.get('XDG_CONFIG_DIRS', '/etc/xdg').split(':'))
return xdg_config_dirs
=== modified file 'configglue/tests/inischema/test_attributed.py'
--- configglue/tests/inischema/test_attributed.py 2011-07-17 22:32:16 +0000
+++ configglue/tests/inischema/test_attributed.py 2013-05-27 01:13:29 +0000
@@ -13,13 +13,14 @@
# For bug reports, support, and new releases: http://launchpad.net/configglue
#
###############################################################################
+from __future__ import unicode_literals
# in testfiles, putting docstrings on methods messes up with the
# runner's output, so pylint: disable-msg=C0111
import unittest
-from ConfigParser import RawConfigParser
-from StringIO import StringIO
+from configparser import RawConfigParser
+from io import StringIO
from configglue.inischema.attributed import AttributedConfigParser
=== modified file 'configglue/tests/inischema/test_glue.py'
--- configglue/tests/inischema/test_glue.py 2011-07-17 22:32:16 +0000
+++ configglue/tests/inischema/test_glue.py 2013-05-27 01:13:29 +0000
@@ -13,21 +13,25 @@
# For bug reports, support, and new releases: http://launchpad.net/configglue
#
###############################################################################
+from __future__ import unicode_literals
# in testfiles, putting docstrings on methods messes up with the
# runner's output, so pylint: disable-msg=C0111
import sys
import unittest
-from StringIO import StringIO
-
+from io import BytesIO, StringIO, TextIOWrapper
+
+from mock import patch
+
+from configglue._compat import PY2
from configglue.inischema.glue import configglue
class TestBase(unittest.TestCase):
""" Base class to keep common set-up """
def setUp(self):
- self.file = StringIO(self.ini)
+ self.file = TextIOWrapper(BytesIO(self.ini))
self.old_sys_argv = sys.argv
sys.argv = ['']
@@ -36,7 +40,7 @@
class TestGlue(TestBase):
- ini = '''
+ ini = b'''
[blah]
foo.help = yadda yadda yadda
yadda
@@ -60,17 +64,20 @@
{self.opt: '5'})
def test_help_is_displayed(self):
- sys.stdout = StringIO()
- try:
- configglue(self.file, args=['', '--help'])
- except SystemExit:
- output = sys.stdout.getvalue()
- sys.stdout = sys.__stdout__
+ new_callable = StringIO
+ if PY2:
+ new_callable = BytesIO
+
+ with patch('sys.stdout', new_callable=new_callable) as mock_stdout:
+ try:
+ configglue(self.file, args=['', '--help'])
+ except SystemExit:
+ output = mock_stdout.getvalue()
self.assertTrue('yadda yadda yadda yadda' in output)
class TestCrazyGlue(TestGlue):
- ini = '''
+ ini = b'''
[bl-ah]
foo.default = 3
foo.help = yadda yadda yadda
@@ -84,7 +91,7 @@
class TestNoValue(TestGlue):
- ini = '''
+ ini = b'''
[blah]
foo.help = yadda yadda yadda
yadda
@@ -96,7 +103,7 @@
class TestGlue2(TestBase):
- ini = '[__main__]\na=1\n'
+ ini = b'[__main__]\na=1\n'
def test_main(self):
parser, options, args = configglue(self.file)
@@ -104,7 +111,7 @@
class TestGlue3(TestBase):
- ini = '[x]\na.help=hi\n'
+ ini = b'[x]\na.help=hi\n'
def test_empty(self):
parser, options, args = configglue(self.file)
@@ -117,7 +124,7 @@
class TestGlueBool(TestBase):
- ini = '''[__main__]
+ ini = b'''[__main__]
foo.parser=bool
foo.action=store_true
@@ -136,7 +143,7 @@
class TestGlueLines(TestBase):
- ini = '''[__main__]
+ ini = b'''[__main__]
foo.parser = lines
foo.action = append
=== modified file 'configglue/tests/inischema/test_glue2glue.py'
--- configglue/tests/inischema/test_glue2glue.py 2011-07-17 22:32:16 +0000
+++ configglue/tests/inischema/test_glue2glue.py 2013-05-27 01:13:29 +0000
@@ -14,11 +14,12 @@
# For bug reports, support, and new releases: http://launchpad.net/configglue
#
###############################################################################
+from __future__ import unicode_literals
import sys
import textwrap
import unittest
-from StringIO import StringIO
+from io import StringIO
from configglue.inischema.glue import (
configglue,
@@ -67,8 +68,6 @@
s = textwrap.dedent("""
[__main__]
bar = zátrapa
- bar.parser = unicode
- bar.parser.args = utf-8
""")
_, cg, _ = configglue(StringIO(s))
_, sg, _ = schemaconfigglue(ini2schema(StringIO(s)))
=== modified file 'configglue/tests/inischema/test_typed.py'
--- configglue/tests/inischema/test_typed.py 2011-07-17 22:32:16 +0000
+++ configglue/tests/inischema/test_typed.py 2013-05-27 01:13:29 +0000
@@ -1,3 +1,4 @@
+# -*- encoding: utf-8 -*-
###############################################################################
#
# configglue -- glue for your apps' configuration
@@ -13,13 +14,14 @@
# For bug reports, support, and new releases: http://launchpad.net/configglue
#
###############################################################################
+from __future__ import unicode_literals
# in testfiles, putting docstrings on methods messes up with the
# runner's output, so pylint: disable-msg=C0111
import unittest
-from StringIO import StringIO
-from ConfigParser import RawConfigParser
+from io import StringIO
+from configparser import RawConfigParser
from configglue.inischema.typed import TypedConfigParser
@@ -52,14 +54,8 @@
baz2.parser = more.parser
baz2 = -1
-meep = \xe1rbol
+meep = árbol
meep.parser = unicode
-meep.parser.args = latin1
-
-quux = \xe1rbol
-quux.parser = unicode
-quux.parser.args = utf-8
- replace
thud.help = this is the help for thud
@@ -119,9 +115,7 @@
('baz', marker),
('baz2', None),
('foo', 1j),
- ('meep', u'\xe1rbol'),
- ('quux', unicode('\xe1rbol', 'utf-8',
- 'replace')),
+ ('meep', '\xe1rbol'),
('thud', None),
('woof', True),
])])
=== modified file 'configglue/tests/test_parser.py'
--- configglue/tests/test_parser.py 2013-05-08 15:20:47 +0000
+++ configglue/tests/test_parser.py 2013-05-27 01:13:29 +0000
@@ -14,20 +14,22 @@
# For bug reports, support, and new releases: http://launchpad.net/configglue
#
###############################################################################
+from __future__ import unicode_literals
+import codecs
import os
import shutil
import tempfile
import textwrap
import unittest
-from ConfigParser import (
+from configparser import (
DEFAULTSECT,
InterpolationDepthError,
InterpolationMissingOptionError,
InterpolationSyntaxError,
NoSectionError,
)
-from StringIO import StringIO
+from io import BytesIO
from mock import (
MagicMock,
@@ -35,6 +37,7 @@
patch,
)
+from configglue._compat import PY2, iteritems
from configglue.parser import (
CONFIG_FILE_ENCODING,
NoOptionError,
@@ -66,20 +69,22 @@
foo = StringOption()
self.schema = MySchema()
fd, self.name = tempfile.mkstemp(suffix='.cfg')
- os.write(fd, '[__main__]\nfoo=bar\n')
+ os.write(fd, b'[__main__]\nfoo=bar\n')
os.close(fd)
def tearDown(self):
os.remove(self.name)
def test_basic_include(self):
- config = StringIO('[__main__]\nincludes=%s' % self.name)
+ config = '[__main__]\nincludes=%s' % self.name
+ config = BytesIO(config.encode(CONFIG_FILE_ENCODING))
parser = SchemaConfigParser(self.schema)
parser.readfp(config, 'my.cfg')
self.assertEquals({'__main__': {'foo': 'bar'}}, parser.values())
def test_locate(self):
- config = StringIO("[__main__]\nincludes=%s" % self.name)
+ config = "[__main__]\nincludes=%s" % self.name
+ config = BytesIO(config.encode(CONFIG_FILE_ENCODING))
parser = SchemaConfigParser(self.schema)
parser.readfp(config, 'my.cfg')
@@ -122,7 +127,8 @@
f.write("[__main__]\nbaz=3")
f.close()
- config = StringIO("[__main__]\nincludes=%s/first.cfg" % folder)
+ config = "[__main__]\nincludes=%s/first.cfg" % folder
+ config = BytesIO(config.encode(CONFIG_FILE_ENCODING))
return config, folder
class MySchema(Schema):
@@ -159,8 +165,8 @@
f.write("[__main__]\nbaz=3")
f.close()
- config = StringIO(
- "[__main__]\nfoo=4\nincludes=%s/first.cfg" % folder)
+ config = "[__main__]\nfoo=4\nincludes=%s/first.cfg" % folder
+ config = BytesIO(config.encode(CONFIG_FILE_ENCODING))
return config, folder
class MySchema(Schema):
@@ -191,7 +197,7 @@
class MySchema(Schema):
foo = StringOption()
bar = BoolOption()
- config = StringIO('[__main__]\nbar=%(foo)s\nfoo=True')
+ config = BytesIO(b'[__main__]\nbar=%(foo)s\nfoo=True')
parser = SchemaConfigParser(MySchema())
parser.readfp(config, 'my.cfg')
self.assertEquals({'__main__': {'foo': 'True', 'bar': True}},
@@ -248,7 +254,7 @@
class baz(Section):
wham = IntOption()
- config = StringIO("[foo]\nbar=%(wham)s\n[baz]\nwham=42")
+ config = BytesIO(b"[foo]\nbar=%(wham)s\n[baz]\nwham=42")
parser = SchemaConfigParser(MySchema())
parser.readfp(config)
self.assertRaises(InterpolationMissingOptionError,
@@ -263,7 +269,7 @@
class baz(Section):
wham = IntOption()
- config = StringIO("[foo]\nbar=%(wham)s\n[baz]\nwham=42")
+ config = BytesIO(b"[foo]\nbar=%(wham)s\n[baz]\nwham=42")
parser = SchemaConfigParser(MySchema())
parser.readfp(config)
self.assertRaises(InterpolationMissingOptionError, parser.get,
@@ -354,7 +360,7 @@
pythonpath = StringOption()
path = StringOption()
- config = StringIO("[__main__]\npythonpath=${PYTHONPATH}\npath=$PATH")
+ config = BytesIO(b"[__main__]\npythonpath=${PYTHONPATH}\npath=$PATH")
parser = SchemaConfigParser(MySchema())
parser.readfp(config)
self.assertEqual(parser.values('__main__'),
@@ -372,7 +378,7 @@
class MySchema(Schema):
foo = IntOption()
- config = StringIO("[__main__]\nfoo=$FOO")
+ config = BytesIO(b"[__main__]\nfoo=$FOO")
parser = SchemaConfigParser(MySchema())
parser.readfp(config)
self.assertEqual(parser.get('__main__', 'foo'), 42)
@@ -381,7 +387,7 @@
class MySchema(Schema):
foo = IntOption()
- config = StringIO("[__main__]\nfoo=$FOO")
+ config = BytesIO(b"[__main__]\nfoo=$FOO")
parser = SchemaConfigParser(MySchema())
parser.readfp(config)
self.assertEqual(parser.get('__main__', 'foo'), 0)
@@ -390,7 +396,7 @@
"""Test get_interpolation_keys for a string."""
class MySchema(Schema):
foo = StringOption()
- config = StringIO("[__main__]\nfoo=%(bar)s")
+ config = BytesIO(b"[__main__]\nfoo=%(bar)s")
expected = ('%(bar)s', set(['bar']))
parser = SchemaConfigParser(MySchema())
@@ -402,7 +408,7 @@
"""Test get_interpolation_keys for an integer."""
class MySchema(Schema):
foo = IntOption()
- config = StringIO("[__main__]\nfoo=%(bar)s")
+ config = BytesIO(b"[__main__]\nfoo=%(bar)s")
expected = ('%(bar)s', set(['bar']))
parser = SchemaConfigParser(MySchema())
@@ -414,7 +420,7 @@
"""Test get_interpolation_keys for a boolean."""
class MySchema(Schema):
foo = BoolOption()
- config = StringIO("[__main__]\nfoo=%(bar)s")
+ config = BytesIO(b"[__main__]\nfoo=%(bar)s")
expected = ('%(bar)s', set(['bar']))
parser = SchemaConfigParser(MySchema())
@@ -426,7 +432,7 @@
"""Test get_interpolation_keys for a tuple."""
class MySchema(Schema):
foo = TupleOption(2)
- config = StringIO("[__main__]\nfoo=%(bar)s,%(baz)s")
+ config = BytesIO(b"[__main__]\nfoo=%(bar)s,%(baz)s")
expected = ('%(bar)s,%(baz)s', set(['bar', 'baz']))
parser = SchemaConfigParser(MySchema())
@@ -438,7 +444,7 @@
"""Test get_interpolation_keys for a list."""
class MySchema(Schema):
foo = ListOption(item=StringOption())
- config = StringIO("[__main__]\nfoo=%(bar)s\n %(baz)s")
+ config = BytesIO(b"[__main__]\nfoo=%(bar)s\n %(baz)s")
expected = ('%(bar)s\n%(baz)s', set(['bar', 'baz']))
parser = SchemaConfigParser(MySchema())
@@ -450,8 +456,8 @@
"""Test get_interpolation_keys for a list of tuples."""
class MySchema(Schema):
foo = ListOption(item=TupleOption(2))
- config = StringIO(
- "[__main__]\nfoo=%(bar)s,%(bar)s\n %(baz)s,%(baz)s")
+ config = BytesIO(
+ b"[__main__]\nfoo=%(bar)s,%(bar)s\n %(baz)s,%(baz)s")
expected = ('%(bar)s,%(bar)s\n%(baz)s,%(baz)s',
set(['bar', 'baz']))
@@ -464,14 +470,14 @@
"""Test get_interpolation_keys for a dict."""
class MySchema(Schema):
foo = DictOption(spec={'a': IntOption()})
- config = StringIO(textwrap.dedent("""
+ config = BytesIO(textwrap.dedent("""
[__noschema__]
bar=4
[__main__]
foo=mydict
[mydict]
a=%(bar)s
- """))
+ """).encode(CONFIG_FILE_ENCODING))
expected = ('mydict', set([]))
parser = SchemaConfigParser(MySchema())
@@ -483,8 +489,8 @@
"""Test interpolate_value for a duplicate key."""
class MySchema(Schema):
foo = TupleOption(2)
- config = StringIO(
- "[__noschema__]\nbar=4\n[__main__]\nfoo=%(bar)s,%(bar)s")
+ config = BytesIO(
+ b"[__noschema__]\nbar=4\n[__main__]\nfoo=%(bar)s,%(bar)s")
expected_value = '4,4'
parser = SchemaConfigParser(MySchema())
@@ -496,7 +502,7 @@
"""Test interpolate_value with an invalid key."""
class MySchema(Schema):
foo = TupleOption(2)
- config = StringIO("[other]\nbar=4\n[__main__]\nfoo=%(bar)s,%(bar)s")
+ config = BytesIO(b"[other]\nbar=4\n[__main__]\nfoo=%(bar)s,%(bar)s")
expected_value = None
parser = SchemaConfigParser(MySchema())
@@ -508,7 +514,7 @@
"""Test interpolate_value with no keys."""
class MySchema(Schema):
foo = TupleOption(2)
- config = StringIO("[__main__]\nfoo=%(bar)s,%(bar)s")
+ config = BytesIO(b"[__main__]\nfoo=%(bar)s,%(bar)s")
mock_get_interpolation_keys = Mock(return_value=('%(bar)s', None))
@@ -524,7 +530,7 @@
"""Test get using a raw value."""
class MySchema(Schema):
foo = StringOption(raw=True)
- config = StringIO('[__main__]\nfoo=blah%(asd)##$@@dddf2kjhkjs')
+ config = BytesIO(b'[__main__]\nfoo=blah%(asd)##$@@dddf2kjhkjs')
expected_value = 'blah%(asd)##$@@dddf2kjhkjs'
parser = SchemaConfigParser(MySchema())
@@ -536,14 +542,14 @@
"""Test interpolation while parsing a dict."""
class MySchema(Schema):
foo = DictOption(spec={'a': IntOption()})
- config = StringIO(textwrap.dedent("""
+ config = BytesIO(textwrap.dedent("""
[__noschema__]
bar=4
[__main__]
foo=mydict
[mydict]
a=%(bar)s
- """))
+ """).encode(CONFIG_FILE_ENCODING))
expected = {'__main__': {'foo': {'a': 4}}}
parser = SchemaConfigParser(MySchema())
@@ -558,7 +564,7 @@
foo = StringOption()
self.schema = MySchema()
self.parser = SchemaConfigParser(self.schema)
- self.config = StringIO("[__main__]\nfoo = bar")
+ self.config = BytesIO(b"[__main__]\nfoo = bar")
def test_init_no_args(self):
self.assertRaises(TypeError, SchemaConfigParser)
@@ -583,13 +589,13 @@
self.assertRaises(NoSectionError, self.parser.items, '__main__')
def test_items_raw(self):
- config = StringIO('[__main__]\nfoo=%(baz)s')
+ config = BytesIO(b'[__main__]\nfoo=%(baz)s')
self.parser.readfp(config)
items = self.parser.items('__main__', raw=True)
self.assertEqual(set(items), set([('foo', '%(baz)s')]))
def test_items_vars(self):
- config = StringIO('[__main__]\nfoo=%(baz)s')
+ config = BytesIO(b'[__main__]\nfoo=%(baz)s')
self.parser.readfp(config)
items = self.parser.items('__main__', vars={'baz': '42'})
self.assertEqual(set(items), set([('foo', '42'), ('baz', '42')]))
@@ -603,14 +609,14 @@
bar = StringOption()
parser = SchemaConfigParser(MySchema())
- config = StringIO('[__main__]\nfoo=%(bar)s\n[baz]\nbar=42')
+ config = BytesIO(b'[__main__]\nfoo=%(bar)s\n[baz]\nbar=42')
parser.readfp(config)
# test interpolate
items = parser.items('baz')
- self.assertEqual(items, {'bar': '42'}.items())
+ self.assertEqual(items, list(iteritems({'bar': '42'})))
def test_items_interpolate_error(self):
- config = StringIO('[__main__]\nfoo=%(bar)s')
+ config = BytesIO(b'[__main__]\nfoo=%(bar)s')
self.parser.readfp(config)
self.assertRaises(InterpolationMissingOptionError, self.parser.items,
'__main__')
@@ -637,7 +643,7 @@
class baz(Section):
bar = IntOption()
- config = StringIO("[foo]\nbar=3\n[baz]\nbar=4")
+ config = BytesIO(b"[foo]\nbar=3\n[baz]\nbar=4")
expected_values = {'foo': {'bar': 3}, 'baz': {'bar': 4}}
schema = MySchema()
@@ -655,7 +661,7 @@
class bar(Section):
baz = IntOption()
- config = StringIO("[foo]\nbar=3\n[bar]\nbaz=4")
+ config = BytesIO(b"[foo]\nbar=3\n[bar]\nbaz=4")
expected_values = {'foo': {'bar': 3}, 'bar': {'baz': 4}}
schema = MySchema()
@@ -671,7 +677,7 @@
bar = StringOption()
expected_value = 'baz'
- config = StringIO("[foo]\nbar = baz")
+ config = BytesIO(b"[foo]\nbar = baz")
parser = SchemaConfigParser(MyOtherSchema())
parser.readfp(config)
value = parser.get('foo', 'bar')
@@ -691,14 +697,14 @@
bla = StringOption(default='hello')
schema = MySchema()
- config = StringIO("[bar]\nbaz=123")
+ config = BytesIO(b"[bar]\nbaz=123")
expected_values = {'__main__': {'foo': True},
'bar': {'baz': 123, 'bla': 'hello'}}
parser = SchemaConfigParser(schema)
parser.readfp(config)
self.assertEquals(expected_values, parser.values())
- config = StringIO("[bar]\nbla=123")
+ config = BytesIO(b"[bar]\nbla=123")
expected = {
'__main__': {'foo': True},
'bar': {'baz': 0, 'bla': '123'}}
@@ -712,13 +718,13 @@
foo = IntOption(fatal=True)
bar = IntOption()
schema = MySchema()
- config = StringIO("[__main__]\nfoo=123")
+ config = BytesIO(b"[__main__]\nfoo=123")
expected = {'__main__': {'foo': 123, 'bar': 0}}
parser = SchemaConfigParser(schema)
parser.readfp(config)
self.assertEquals(expected, parser.values())
- config = StringIO("[__main__]\nbar=123")
+ config = BytesIO(b"[__main__]\nbar=123")
parser = SchemaConfigParser(schema)
parser.readfp(config)
self.assertRaises(NoOptionError, parser.values)
@@ -728,7 +734,7 @@
class MySchema(Schema):
foo = DictOption(spec={'bar': IntOption()})
- config = StringIO("[__main__]\nfoo=mydict\n[mydict]\nbar=1")
+ config = BytesIO(b"[__main__]\nfoo=mydict\n[mydict]\nbar=1")
parser = SchemaConfigParser(MySchema())
parser.readfp(config)
parser.parse_all()
@@ -754,10 +760,10 @@
class MySchema(Schema):
foo = DictOption()
- config = StringIO(textwrap.dedent("""
+ config = BytesIO(textwrap.dedent("""
[__main__]
foo = dict1
- """))
+ """).encode(CONFIG_FILE_ENCODING))
parser = SchemaConfigParser(MySchema())
parser.readfp(config)
parser.parse_all()
@@ -770,8 +776,8 @@
foo = ListOption(
item=DictOption(spec={'bar': IntOption()}))
- config = StringIO('[__main__]\nfoo=d1\n d2\n d3\n'
- '[d1]\nbar=1\n[d2]\nbar=2\n[d3]\nbar=3')
+ config = BytesIO(b'[__main__]\nfoo=d1\n d2\n d3\n'
+ b'[d1]\nbar=1\n[d2]\nbar=2\n[d3]\nbar=3')
parser = SchemaConfigParser(MySchema())
parser.readfp(config)
parser.parse_all()
@@ -781,14 +787,14 @@
self.assertEqual(expected_sections, extra_sections)
def test_get_default(self):
- config = StringIO("[__main__]\n")
+ config = BytesIO(b"[__main__]\n")
expected = ''
self.parser.readfp(config)
default = self.parser._get_default('__main__', 'foo')
self.assertEqual(default, expected)
def test_get_default_noschema(self):
- config = StringIO("[__noschema__]\nbar=1\n[__main__]\n")
+ config = BytesIO(b"[__noschema__]\nbar=1\n[__main__]\n")
expected = '1'
self.parser.readfp(config)
default = self.parser._get_default('__noschema__', 'bar')
@@ -799,7 +805,7 @@
class MySchema(Schema):
class foo(Section):
bar = IntOption()
- config = StringIO("[__main__]\n")
+ config = BytesIO(b"[__main__]\n")
expected = 0
parser = SchemaConfigParser(MySchema())
@@ -822,8 +828,8 @@
'bar': IntOption(),
'baz': IntOption(),
}, strict=True)
- config1 = StringIO('[__main__]\nfoo=mydict\n[mydict]\nbar=1\nbaz=1')
- config2 = StringIO('[mydict]\nbaz=2')
+ config1 = BytesIO(b'[__main__]\nfoo=mydict\n[mydict]\nbar=1\nbaz=1')
+ config2 = BytesIO(b'[mydict]\nbaz=2')
expected_values = {'__main__': {'foo': {'bar': 1, 'baz': 2}}}
parser = SchemaConfigParser(MySchema())
@@ -840,7 +846,7 @@
'baz': IntOption(),
}, strict=True))
- config1 = StringIO('[__main__]\nfoo=mydict\n[mydict]\nbar=1\nbaz=1')
+ config1 = BytesIO(b'[__main__]\nfoo=mydict\n[mydict]\nbar=1\nbaz=1')
expected_values = {'__main__': {'foo': [{'bar': 1, 'baz': 1}]}}
parser = SchemaConfigParser(MySchema())
@@ -848,19 +854,19 @@
self.assertEqual(parser.values(), expected_values)
# override used dictionaries
- config2 = StringIO('[__main__]\nfoo=otherdict\n[otherdict]\nbar=2')
+ config2 = BytesIO(b'[__main__]\nfoo=otherdict\n[otherdict]\nbar=2')
expected_values = {'__main__': {'foo': [{'bar': 2, 'baz': 0}]}}
parser.readfp(config2)
self.assertEqual(parser.values(), expected_values)
# override existing dictionaries
- config3 = StringIO('[otherdict]\nbaz=3')
+ config3 = BytesIO(b'[otherdict]\nbaz=3')
expected_values = {'__main__': {'foo': [{'bar': 2, 'baz': 3}]}}
parser.readfp(config3)
self.assertEqual(parser.values(), expected_values)
# reuse existing dict
- config4 = StringIO('[__main__]\nfoo=mydict\n otherdict')
+ config4 = BytesIO(b'[__main__]\nfoo=mydict\n otherdict')
expected_values = {'__main__': {'foo': [{'bar': 1, 'baz': 1},
{'bar': 2, 'baz': 3}]}}
parser.readfp(config4)
@@ -896,25 +902,29 @@
fp, filename = tempfile.mkstemp()
try:
- f = open(filename, 'w')
- f.write(u'[__main__]\nfoo=€'.encode(CONFIG_FILE_ENCODING))
+ if PY2:
+ f = open(filename, 'w')
+ f.write('[__main__]\nfoo=€'.encode(CONFIG_FILE_ENCODING))
+ else:
+ f = open(filename, 'w', encoding=CONFIG_FILE_ENCODING)
+ f.write('[__main__]\nfoo=€')
f.close()
self.parser.read(filename)
self.assertEqual(self.parser.values(),
- {'__main__': {'foo': u'€'}})
+ {'__main__': {'foo': '€'}})
finally:
# destroy config file
os.remove(filename)
def test_readfp_with_utf8_encoded_text(self):
- config = StringIO(u'[__main__]\nfoo=€'.encode(CONFIG_FILE_ENCODING))
+ config = BytesIO('[__main__]\nfoo=€'.encode(CONFIG_FILE_ENCODING))
self.parser.readfp(config)
- self.assertEqual(self.parser.values(), {'__main__': {'foo': u'€'}})
+ self.assertEqual(self.parser.values(), {'__main__': {'foo': '€'}})
def test_set(self):
with tempfile.NamedTemporaryFile() as f:
- f.write('[__main__]\nfoo=1')
+ f.write(b'[__main__]\nfoo=1')
f.flush()
self.parser.read(f.name)
@@ -953,9 +963,9 @@
pass
parser = SchemaConfigParser(MySchema())
- expected = u"[{0}]\nbaz = 2\n\n[__main__]\nfoo = bar".format(
+ expected = "[{0}]\nbaz = 2\n\n[__main__]\nfoo = bar".format(
DEFAULTSECT)
- config = StringIO(expected)
+ config = BytesIO(expected.encode(CONFIG_FILE_ENCODING))
parser.readfp(config)
# create config file
@@ -974,7 +984,7 @@
foo = IntOption()
parser = SchemaConfigParser(MySchema())
- expected = u"[__main__]\nfoo = 0"
+ expected = "[__main__]\nfoo = 0"
# create config file
fp, filename = tempfile.mkstemp()
@@ -987,15 +997,15 @@
os.unlink(filename)
def test_save_config(self):
- expected = u'[__main__]\nfoo = 42'
+ expected = '[__main__]\nfoo = 42'
self._check_save_file(expected)
def test_save_config_non_ascii(self):
- expected = u'[__main__]\nfoo = fóobâr'
+ expected = '[__main__]\nfoo = fóobâr'
self._check_save_file(expected)
def _check_save_file(self, expected, read_config=True):
- config = StringIO(expected.encode(CONFIG_FILE_ENCODING))
+ config = BytesIO(expected.encode(CONFIG_FILE_ENCODING))
if read_config:
self.parser.readfp(config)
@@ -1003,19 +1013,21 @@
fp, filename = tempfile.mkstemp()
try:
self.parser.save(open(filename, 'w'))
- result = open(filename, 'r').read().strip()
- self.assertEqual(result.decode(CONFIG_FILE_ENCODING), expected)
+ result = codecs.open(filename, 'r',
+ encoding=CONFIG_FILE_ENCODING).read().strip()
+ self.assertEqual(result, expected)
self.parser.save(filename)
- result = open(filename, 'r').read().strip()
- self.assertEqual(result.decode(CONFIG_FILE_ENCODING), expected)
+ result = codecs.open(filename, 'r',
+ encoding=CONFIG_FILE_ENCODING).read().strip()
+ self.assertEqual(result, expected)
finally:
# remove the file
os.unlink(filename)
def test_save_config_prefill_parser(self):
"""Test parser save config when no config files read."""
- expected = u'[__main__]\nfoo ='
+ expected = '[__main__]\nfoo ='
self._check_save_file(expected, read_config=False)
def test_save_no_config_same_files(self):
@@ -1131,7 +1143,7 @@
foo = StringOption()
self.schema = MySchema()
self.parser = SchemaConfigParser(self.schema)
- self.config = StringIO("[__main__]\nfoo = bar")
+ self.config = BytesIO(b"[__main__]\nfoo = bar")
def test_basic_is_valid(self):
"""Test basic validation without error reporting."""
@@ -1139,7 +1151,7 @@
foo = IntOption()
schema = MySchema()
- config = StringIO("[__main__]\nfoo = 5")
+ config = BytesIO(b"[__main__]\nfoo = 5")
parser = SchemaConfigParser(schema)
parser.readfp(config)
@@ -1150,7 +1162,7 @@
class MySchema(Schema):
foo = IntOption()
- config = StringIO("[__main__]\nfoo=5")
+ config = BytesIO(b"[__main__]\nfoo=5")
expected = (True, [])
parser = SchemaConfigParser(MySchema())
parser.readfp(config)
@@ -1163,7 +1175,7 @@
foo = IntOption()
schema = MySchema()
- config = StringIO("[__main__]\nfoo = 5\nbar = 6")
+ config = BytesIO(b"[__main__]\nfoo = 5\nbar = 6")
parser = SchemaConfigParser(schema)
parser.readfp(config)
@@ -1174,7 +1186,7 @@
class MySchema(Schema):
foo = IntOption()
- config = StringIO("[__main__]\nfoo=5\nbar=6")
+ config = BytesIO(b"[__main__]\nfoo=5\nbar=6")
errors = ["Configuration includes invalid options for "
"section '__main__': bar"]
expected = (False, errors)
@@ -1193,7 +1205,7 @@
assert False
schema = MySchema()
- config = StringIO("[__main__]\nfoo = 5")
+ config = BytesIO(b"[__main__]\nfoo = 5")
parser = SchemaConfigParser(schema)
parser.parse_all = mock_parse_all
parser.readfp(config)
@@ -1201,22 +1213,22 @@
self.assertFalse(parser.is_valid())
def test_parse_invalid_section(self):
- config = StringIO("[bar]\nbaz=foo")
+ config = BytesIO(b"[bar]\nbaz=foo")
self.parser.readfp(config)
self.assertFalse(self.parser.is_valid())
def test_parse_invalid_section_with_report(self):
- config = StringIO("[bar]\nbaz=foo")
+ config = BytesIO(b"[bar]\nbaz=foo")
self.parser.readfp(config)
valid, errors = self.parser.is_valid(report=True)
self.assertFalse(valid)
self.assertEqual(errors[0],
- u'Sections in configuration are missing from schema: bar')
+ 'Sections in configuration are missing from schema: bar')
def test_different_sections(self):
- config = StringIO("[__main__]\nfoo=1\n[bar]\nbaz=2")
+ config = BytesIO(b"[__main__]\nfoo=1\n[bar]\nbaz=2")
self.parser.readfp(config)
self.assertFalse(self.parser.is_valid())
@@ -1227,7 +1239,7 @@
foo = IntOption()
bar = IntOption(fatal=True)
- config = StringIO("[__main__]\nfoo=1")
+ config = BytesIO(b"[__main__]\nfoo=1")
parser = SchemaConfigParser(MySchema())
parser.readfp(config)
@@ -1239,7 +1251,7 @@
foo = IntOption()
bar = IntOption(fatal=True)
- config = StringIO("[__main__]\nbar=2")
+ config = BytesIO(b"[__main__]\nbar=2")
parser = SchemaConfigParser(MySchema())
parser.readfp(config)
@@ -1250,7 +1262,7 @@
class MySchema(Schema):
foo = DictOption(spec={'bar': IntOption()})
- config = StringIO("[__main__]\nfoo=mydict\n[mydict]\nbar=1")
+ config = BytesIO(b"[__main__]\nfoo=mydict\n[mydict]\nbar=1")
parser = SchemaConfigParser(MySchema())
parser.readfp(config)
parser.parse_all()
@@ -1262,7 +1274,7 @@
class MySchema(Schema):
foo = DictOption(item=DictOption())
- config = StringIO("""
+ config = BytesIO(b"""
[__main__]
foo=dict1
[dict1]
@@ -1283,7 +1295,7 @@
class MySchema(Schema):
foo = DictOption(spec={'bar': DictOption()}, strict=True)
- config = StringIO("""
+ config = BytesIO(b"""
[__main__]
foo=dict1
[dict1]
@@ -1305,7 +1317,7 @@
foo = ListOption(
item=DictOption(item=DictOption()))
- config = StringIO("""
+ config = BytesIO(b"""
[__main__]
foo = dict1
dict2
@@ -1334,7 +1346,7 @@
foo = DictOption(
item=ListOption(item=DictOption()))
- config = StringIO("""
+ config = BytesIO(b"""
[__main__]
foo = dict1
[dict1]
@@ -1360,7 +1372,7 @@
item=DictOption(
item=ListOption(item=DictOption())))
- config = StringIO("""
+ config = BytesIO(b"""
[__main__]
foo = dict1
dict2
@@ -1394,10 +1406,10 @@
class MySchema(Schema):
foo = DictOption()
- config = StringIO(textwrap.dedent("""
+ config = BytesIO(textwrap.dedent("""
[__main__]
foo = dict1
- """))
+ """).encode(CONFIG_FILE_ENCODING))
parser = SchemaConfigParser(MySchema())
parser.readfp(config)
parser.parse_all()
@@ -1412,8 +1424,8 @@
foo = ListOption(
item=DictOption(spec={'bar': IntOption()}))
- config = StringIO('[__main__]\nfoo=d1\n d2\n d3\n'
- '[d1]\nbar=1\n[d2]\nbar=2\n[d3]\nbar=3')
+ config = BytesIO(b'[__main__]\nfoo=d1\n d2\n d3\n'
+ b'[d1]\nbar=1\n[d2]\nbar=2\n[d3]\nbar=3')
parser = SchemaConfigParser(MySchema())
parser.readfp(config)
parser.parse_all()
@@ -1421,8 +1433,8 @@
self.assertTrue(parser.is_valid())
def test_noschema_section(self):
- config = StringIO(
- "[__main__]\nfoo=%(bar)s\n[__noschema__]\nbar=hello")
+ config = BytesIO(
+ b"[__main__]\nfoo=%(bar)s\n[__noschema__]\nbar=hello")
parser = SchemaConfigParser(self.schema)
parser.readfp(config)
parser.parse_all()
@@ -1437,10 +1449,10 @@
class bar(Section):
baz = BoolOption()
- config = StringIO(textwrap.dedent("""
+ config = BytesIO(textwrap.dedent("""
[foo]
bar = 3
- """))
+ """).encode(CONFIG_FILE_ENCODING))
parser = SchemaConfigParser(MySchema())
parser.readfp(config)
parser.parse_all()
=== modified file 'configglue/tests/test_schema.py'
--- configglue/tests/test_schema.py 2011-09-30 19:30:46 +0000
+++ configglue/tests/test_schema.py 2013-05-27 01:13:29 +0000
@@ -14,15 +14,17 @@
# For bug reports, support, and new releases: http://launchpad.net/configglue
#
###############################################################################
+from __future__ import unicode_literals
import textwrap
import unittest
-from ConfigParser import (
+from configparser import (
NoOptionError,
NoSectionError,
)
-from StringIO import StringIO
+from io import BytesIO
+from configglue._compat import text_type
from configglue.parser import (
SchemaConfigParser,
SchemaValidationError,
@@ -389,19 +391,19 @@
class MySchema(Schema):
foo = self.cls()
- config = StringIO("[__main__]\nfoo = 42")
+ config = BytesIO(b"[__main__]\nfoo = 42")
expected_values = {'__main__': {'foo': 42}}
schema = MySchema()
parser = SchemaConfigParser(schema)
parser.readfp(config)
self.assertEqual(parser.values(), expected_values)
- config = StringIO("[__main__]\nfoo =")
+ config = BytesIO(b"[__main__]\nfoo =")
parser = SchemaConfigParser(schema)
parser.readfp(config)
self.assertRaises(ValueError, parser.values)
- config = StringIO("[__main__]\nfoo = bla")
+ config = BytesIO(b"[__main__]\nfoo = bla")
parser = SchemaConfigParser(schema)
parser.readfp(config)
self.assertRaises(ValueError, parser.values)
@@ -435,24 +437,24 @@
class MySchema(Schema):
foo = self.cls()
- config = StringIO("[__main__]\nfoo = Yes")
+ config = BytesIO(b"[__main__]\nfoo = Yes")
expected_values = {'__main__': {'foo': True}}
schema = MySchema()
parser = SchemaConfigParser(schema)
parser.readfp(config)
self.assertEqual(parser.values(), expected_values)
- config = StringIO("[__main__]\nfoo = tRuE")
+ config = BytesIO(b"[__main__]\nfoo = tRuE")
parser = SchemaConfigParser(schema)
parser.readfp(config)
self.assertEqual(parser.values(), expected_values)
- config = StringIO("[__main__]\nfoo =")
+ config = BytesIO(b"[__main__]\nfoo =")
parser = SchemaConfigParser(schema)
parser.readfp(config)
self.assertRaises(ValueError, parser.values)
- config = StringIO("[__main__]\nfoo = bla")
+ config = BytesIO(b"[__main__]\nfoo = bla")
parser = SchemaConfigParser(schema)
parser.readfp(config)
self.assertRaises(ValueError, parser.values)
@@ -486,7 +488,7 @@
class MySchema(Schema):
foo = self.cls(item=IntOption())
- config = StringIO("[__main__]\nfoo = 42\n 43\n 44")
+ config = BytesIO(b"[__main__]\nfoo = 42\n 43\n 44")
expected_values = {'__main__': {'foo': [42, 43, 44]}}
schema = MySchema()
parser = SchemaConfigParser(schema)
@@ -497,7 +499,7 @@
class MySchema(Schema):
foo = self.cls(item=IntOption(), parse_json=False)
- config = StringIO("[__main__]\nfoo = 42\n 43\n 44")
+ config = BytesIO(b"[__main__]\nfoo = 42\n 43\n 44")
expected_values = {'__main__': {'foo': [42, 43, 44]}}
schema = MySchema()
parser = SchemaConfigParser(schema)
@@ -508,7 +510,7 @@
class MySchema(Schema):
foo = self.cls(item=IntOption(), parse_json=False)
- config = StringIO("[__main__]\nfoo = [42, 43, 44]")
+ config = BytesIO(b"[__main__]\nfoo = [42, 43, 44]")
schema = MySchema()
parser = SchemaConfigParser(schema)
parser.readfp(config)
@@ -518,7 +520,7 @@
class MySchema(Schema):
foo = self.cls(item=IntOption())
- config = StringIO("[__main__]\nfoo = [42, 43, 44]")
+ config = BytesIO(b"[__main__]\nfoo = [42, 43, 44]")
expected_values = {'__main__': {'foo': [42, 43, 44]}}
schema = MySchema()
parser = SchemaConfigParser(schema)
@@ -529,7 +531,7 @@
class MySchema(Schema):
foo = self.cls(item=IntOption())
- config = StringIO('[__main__]\nfoo = 1, 2, 3')
+ config = BytesIO(b'[__main__]\nfoo = 1, 2, 3')
schema = MySchema()
parser = SchemaConfigParser(schema)
parser.readfp(config)
@@ -539,7 +541,7 @@
class MySchema(Schema):
foo = self.cls(item=IntOption())
- config = StringIO('[__main__]\nfoo = {"foo": "bar"}')
+ config = BytesIO(b'[__main__]\nfoo = {"foo": "bar"}')
schema = MySchema()
parser = SchemaConfigParser(schema)
parser.readfp(config)
@@ -551,7 +553,7 @@
foo = self.cls(item=BoolOption())
schema = MySchema()
- config = StringIO("[__main__]\nfoo = tRuE\n No\n 0\n 1")
+ config = BytesIO(b"[__main__]\nfoo = tRuE\n No\n 0\n 1")
expected_values = {'__main__': {'foo': [True, False, False, True]}}
parser = SchemaConfigParser(schema)
parser.readfp(config)
@@ -563,7 +565,7 @@
foo = self.cls(item=BoolOption())
schema = MySchema()
- config = StringIO("[__main__]\nfoo =")
+ config = BytesIO(b"[__main__]\nfoo =")
parser = SchemaConfigParser(schema)
parser.readfp(config)
expected_values = {'__main__': {'foo': []}}
@@ -575,12 +577,12 @@
foo = self.cls(item=BoolOption())
schema = MySchema()
- config = StringIO("[__main__]\nfoo = bla")
+ config = BytesIO(b"[__main__]\nfoo = bla")
parser = SchemaConfigParser(schema)
parser.readfp(config)
self.assertRaises(ValueError, parser.values)
- config = StringIO("[__main__]\nfoo = True\n bla")
+ config = BytesIO(b"[__main__]\nfoo = True\n bla")
parser = SchemaConfigParser(schema)
parser.readfp(config)
self.assertRaises(ValueError, parser.values)
@@ -596,7 +598,7 @@
foo = self.cls(item=StringOption(), remove_duplicates=True)
schema = MySchema()
- config = StringIO("[__main__]\nfoo = bla\n blah\n bla")
+ config = BytesIO(b"[__main__]\nfoo = bla\n blah\n bla")
parser = SchemaConfigParser(schema)
parser.readfp(config)
self.assertEquals({'__main__': {'foo': ['bla', 'blah']}},
@@ -608,7 +610,7 @@
foo = self.cls(item=DictOption(), remove_duplicates=True)
schema = MyOtherSchema()
- config = StringIO("[__main__]\nfoo = bla\n bla\n[bla]\nbar = baz")
+ config = BytesIO(b"[__main__]\nfoo = bla\n bla\n[bla]\nbar = baz")
parser = SchemaConfigParser(schema)
parser.readfp(config)
self.assertEquals({'__main__': {'foo': [{'bar': 'baz'}]}},
@@ -661,7 +663,8 @@
def test_to_string_when_no_json(self):
option = ListOption(parse_json=False)
result = option.to_string(['1', '2', '3'])
- self.assertEqual(result, "['1', '2', '3']")
+ expected = list(map(text_type, [1, 2, 3]))
+ self.assertEqual(result, text_type(expected))
class TestTupleOption(unittest.TestCase):
@@ -683,7 +686,7 @@
class MySchema(Schema):
foo = self.cls()
- config = StringIO('[__main__]\nfoo=1,2,3,4')
+ config = BytesIO(b'[__main__]\nfoo=1,2,3,4')
expected_values = {'__main__': {'foo': ('1', '2', '3', '4')}}
parser = SchemaConfigParser(MySchema())
parser.readfp(config)
@@ -694,19 +697,19 @@
class MySchema(Schema):
foo = self.cls(length=4)
- config = StringIO('[__main__]\nfoo = 1, 2, 3, 4')
+ config = BytesIO(b'[__main__]\nfoo = 1, 2, 3, 4')
expected_values = {'__main__': {'foo': ('1', '2', '3', '4')}}
schema = MySchema()
parser = SchemaConfigParser(schema)
parser.readfp(config)
self.assertEqual(parser.values(), expected_values)
- config = StringIO('[__main__]\nfoo = 1, 2, 3')
+ config = BytesIO(b'[__main__]\nfoo = 1, 2, 3')
parser = SchemaConfigParser(schema)
parser.readfp(config)
self.assertRaises(ValueError, parser.values)
- config = StringIO('[__main__]\nfoo = ')
+ config = BytesIO(b'[__main__]\nfoo = ')
parser = SchemaConfigParser(schema)
parser.readfp(config)
self.assertRaises(ValueError, parser.values)
@@ -763,7 +766,7 @@
class MySchema(Schema):
foo = self.cls(item=self.cls())
- config = StringIO("""
+ config = BytesIO(b"""
[__main__]
foo=dict1
[dict1]
@@ -788,7 +791,7 @@
'bla': BoolOption(),
})
- config = StringIO("""[__main__]
+ config = BytesIO(b"""[__main__]
foo = mydict
[mydict]
bar=baz
@@ -813,7 +816,7 @@
'bla': BoolOption(),
}, parse_json=False)
- config = StringIO("""[__main__]
+ config = BytesIO(b"""[__main__]
foo = mydict
[mydict]
bar=baz
@@ -838,13 +841,13 @@
'bla': BoolOption(),
})
- config = StringIO(textwrap.dedent("""
+ config = BytesIO(textwrap.dedent("""
[__main__]
foo = {
"bar": "baz",
"baz": "42",
"bla": "Yes"}
- """))
+ """).encode('utf-8'))
expected_values = {
'__main__': {
'foo': {'bar': 'baz', 'baz': 42, 'bla': True}}}
@@ -863,10 +866,10 @@
'bla': BoolOption(),
})
- config = StringIO(textwrap.dedent("""
+ config = BytesIO(textwrap.dedent("""
[__main__]
foo = {'bar': 23}
- """))
+ """).encode('utf-8'))
schema = MySchema()
parser = SchemaConfigParser(schema)
@@ -882,10 +885,10 @@
'bla': BoolOption(),
})
- config = StringIO(textwrap.dedent("""
+ config = BytesIO(textwrap.dedent("""
[__main__]
foo = [1, 2, 3]
- """))
+ """).encode('utf-8'))
schema = MySchema()
parser = SchemaConfigParser(schema)
@@ -901,13 +904,13 @@
'bla': BoolOption(),
}, parse_json=False)
- config = StringIO(textwrap.dedent("""
+ config = BytesIO(textwrap.dedent("""
[__main__]
foo = {
"bar": "baz",
"baz": "42",
"bla": "Yes"}
- """))
+ """).encode('utf-8'))
schema = MySchema()
parser = SchemaConfigParser(schema)
@@ -923,7 +926,7 @@
'bla': BoolOption(),
})
- config = StringIO("""[__main__]
+ config = BytesIO(b"""[__main__]
foo = mydict
[mydict]
baz=42
@@ -942,10 +945,10 @@
class logging(Section):
formatters = self.cls(raw=True, item=self.cls())
- config = StringIO(textwrap.dedent("""
+ config = BytesIO(textwrap.dedent("""
[logging]
formatters = {"sample": {"format": "%(name)s"}}
- """))
+ """).encode('utf-8'))
expected = {'sample': {'format': '%(name)s'}}
schema = MySchema()
@@ -960,7 +963,7 @@
class logging(Section):
formatters = self.cls(raw=True, item=self.cls())
- config = StringIO(textwrap.dedent("""
+ config = BytesIO(textwrap.dedent("""
[logging]
formatters = logging_formatters
@@ -969,7 +972,7 @@
[sample_formatter]
format = %%(name)s
- """))
+ """).encode('utf-8'))
expected = {'sample': {'format': '%(name)s'}}
schema = MySchema()
@@ -983,7 +986,7 @@
class MySchema(Schema):
foo = self.cls(spec={'bar': IntOption()})
- config = StringIO("[__main__]\nfoo=mydict\n[mydict]\nbaz=2")
+ config = BytesIO(b"[__main__]\nfoo=mydict\n[mydict]\nbaz=2")
expected_values = {'__main__': {'foo': {'bar': 0, 'baz': '2'}}}
parser = SchemaConfigParser(MySchema())
parser.readfp(config)
@@ -996,7 +999,7 @@
'bar': IntOption(),
'baz': IntOption(fatal=True)})
- config = StringIO("[__main__]\nfoo=mydict\n[mydict]\nbar=2")
+ config = BytesIO(b"[__main__]\nfoo=mydict\n[mydict]\nbar=2")
parser = SchemaConfigParser(MySchema())
parser.readfp(config)
self.assertRaises(ValueError, parser.parse_all)
@@ -1010,7 +1013,7 @@
class MySchema(Schema):
foo = self.cls(spec={'bar': IntOption()})
- config = StringIO("[__main__]\nfoo=mydict\n[mydict]")
+ config = BytesIO(b"[__main__]\nfoo=mydict\n[mydict]")
expected_values = {'__main__': {'foo': {'bar': 0}}}
parser = SchemaConfigParser(MySchema())
parser.readfp(config)
@@ -1020,7 +1023,7 @@
class MySchema(Schema):
foo = self.cls()
- config = StringIO("[__main__]\nfoo=mydict\n[mydict]\nbar=2")
+ config = BytesIO(b"[__main__]\nfoo=mydict\n[mydict]\nbar=2")
expected_values = {'__main__': {'foo': {'bar': '2'}}}
parser = SchemaConfigParser(MySchema())
parser.readfp(config)
@@ -1032,7 +1035,7 @@
foo = self.cls(
item=self.cls(
item=IntOption()))
- config = StringIO("""
+ config = BytesIO(b"""
[__main__]
foo = mydict
[mydict]
@@ -1051,7 +1054,7 @@
spec = {'bar': IntOption()}
foo = self.cls(spec=spec, strict=True)
- config = StringIO("[__main__]\nfoo=mydict\n[mydict]\nbar=2")
+ config = BytesIO(b"[__main__]\nfoo=mydict\n[mydict]\nbar=2")
expected_values = {'__main__': {'foo': {'bar': 2}}}
parser = SchemaConfigParser(MySchema())
parser.readfp(config)
@@ -1064,7 +1067,7 @@
'baz': IntOption()}
foo = self.cls(spec=spec, strict=True)
- config = StringIO("[__main__]\nfoo=mydict\n[mydict]\nbar=2")
+ config = BytesIO(b"[__main__]\nfoo=mydict\n[mydict]\nbar=2")
expected_values = {'__main__': {'foo': {'bar': 2, 'baz': 0}}}
parser = SchemaConfigParser(MySchema())
parser.readfp(config)
@@ -1076,7 +1079,7 @@
spec = {'bar': IntOption()}
foo = self.cls(spec=spec, strict=True)
- config = StringIO("[__main__]\nfoo=mydict\n[mydict]\nbar=2\nbaz=3")
+ config = BytesIO(b"[__main__]\nfoo=mydict\n[mydict]\nbar=2\nbaz=3")
parser = SchemaConfigParser(MySchema())
parser.readfp(config)
self.assertRaises(ValueError, parser.parse_all)
@@ -1116,7 +1119,7 @@
def test_to_string_when_no_json(self):
option = DictOption(parse_json=False)
result = option.to_string({'foo': '1'})
- self.assertEqual(result, str({'foo': '1'}))
+ self.assertEqual(result, text_type({'foo': '1'}))
class TestListOfDictOption(unittest.TestCase):
@@ -1130,7 +1133,7 @@
'bla': BoolOption(),
}))
- config = StringIO("""[__main__]
+ config = BytesIO(b"""[__main__]
foo = mylist0
mylist1
[mylist0]
@@ -1167,7 +1170,7 @@
class MySchema(Schema):
foo = DictOption(spec=spec)
- config = StringIO("""[__main__]
+ config = BytesIO(b"""[__main__]
foo = outerdict
[outerdict]
options = innerdict
@@ -1194,19 +1197,19 @@
self.parser = SchemaConfigParser(schema)
def test_parse_list_of_tuples(self):
- config = StringIO('[__main__]\nfoo = a, b, c\n d, e, f')
+ config = BytesIO(b'[__main__]\nfoo = a, b, c\n d, e, f')
expected_values = {
'__main__': {'foo': [('a', 'b', 'c'), ('d', 'e', 'f')]}}
self.parser.readfp(config)
self.assertEqual(self.parser.values(), expected_values)
def test_parse_wrong_tuple_size(self):
- config = StringIO('[__main__]\nfoo = a, b, c\n d, e')
+ config = BytesIO(b'[__main__]\nfoo = a, b, c\n d, e')
self.parser.readfp(config)
self.assertRaises(ValueError, self.parser.values)
def test_parse_empty_tuple(self):
- config = StringIO('[__main__]\nfoo=()')
+ config = BytesIO(b'[__main__]\nfoo=()')
expected_values = {'__main__': {'foo': [()]}}
self.parser.readfp(config)
self.assertEqual(self.parser.values(), expected_values)
@@ -1331,6 +1334,6 @@
try:
merge(SchemaA, SchemaB)
self.fail('SchemaValidationError not raised.')
- except SchemaValidationError, e:
- self.assertEqual(str(e),
+ except SchemaValidationError as e:
+ self.assertEqual(text_type(e),
"Conflicting option '__main__.foo' while merging schemas.")
=== modified file 'configglue/tests/test_schemaconfig.py'
--- configglue/tests/test_schemaconfig.py 2011-07-29 22:16:30 +0000
+++ configglue/tests/test_schemaconfig.py 2013-05-27 01:13:29 +0000
@@ -14,11 +14,12 @@
# For bug reports, support, and new releases: http://launchpad.net/configglue
#
###############################################################################
+from __future__ import unicode_literals
import unittest
import os
import sys
-from StringIO import StringIO
+from io import BytesIO, StringIO
from optparse import (
OptionConflictError,
OptionParser,
@@ -29,6 +30,7 @@
patch,
)
+from configglue._compat import PY2
from configglue.glue import (
configglue,
schemaconfigglue,
@@ -146,7 +148,7 @@
def test_glue_no_op(self):
"""Test schemaconfigglue with the default OptionParser value."""
- config = StringIO("[__main__]\nbaz=1")
+ config = BytesIO(b"[__main__]\nbaz=1")
self.parser.readfp(config)
self.assertEqual(self.parser.values(),
{'foo': {'bar': 0}, '__main__': {'baz': 1}})
@@ -157,7 +159,7 @@
def test_glue_no_argv(self):
"""Test schemaconfigglue with the default argv value."""
- config = StringIO("[__main__]\nbaz=1")
+ config = BytesIO(b"[__main__]\nbaz=1")
self.parser.readfp(config)
self.assertEqual(self.parser.values(),
{'foo': {'bar': 0}, '__main__': {'baz': 1}})
@@ -172,7 +174,7 @@
def test_glue_section_option(self):
"""Test schemaconfigglue overriding one option."""
- config = StringIO("[foo]\nbar=1")
+ config = BytesIO(b"[foo]\nbar=1")
self.parser.readfp(config)
self.assertEqual(self.parser.values(),
{'foo': {'bar': 1}, '__main__': {'baz': 0}})
@@ -187,7 +189,7 @@
class MySchema(Schema):
foo = DictOption()
- config = StringIO("[__main__]\nfoo = bar")
+ config = BytesIO(b"[__main__]\nfoo = bar")
parser = SchemaConfigParser(MySchema())
parser.readfp(config)
@@ -216,7 +218,7 @@
@patch('configglue.glue.os')
def test_glue_environ(self, mock_os):
mock_os.environ = {'CONFIGGLUE_FOO_BAR': '42', 'CONFIGGLUE_BAZ': 3}
- config = StringIO("[foo]\nbar=1")
+ config = BytesIO(b"[foo]\nbar=1")
self.parser.readfp(config)
_argv, sys.argv = sys.argv, ['prognam']
@@ -230,7 +232,7 @@
@patch('configglue.glue.os')
def test_glue_environ_bad_name(self, mock_os):
mock_os.environ = {'FOO_BAR': 2, 'BAZ': 3}
- config = StringIO("[foo]\nbar=1")
+ config = BytesIO(b"[foo]\nbar=1")
self.parser.readfp(config)
_argv, sys.argv = sys.argv, ['prognam']
@@ -245,7 +247,7 @@
with patch.object(os, 'environ',
{'CONFIGGLUE_FOO_BAR': '42', 'BAR': '1'}):
- config = StringIO("[foo]\nbar=$BAR")
+ config = BytesIO(b"[foo]\nbar=$BAR")
self.parser.readfp(config)
_argv, sys.argv = sys.argv, ['prognam']
@@ -306,7 +308,7 @@
class bar(Section):
baz = IntOption()
- config = StringIO("[foo]\nbaz=1")
+ config = BytesIO(b"[foo]\nbaz=1")
parser = SchemaConfigParser(MySchema())
parser.readfp(config)
self.assertEqual(parser.values('foo'), {'baz': 1})
@@ -319,24 +321,22 @@
def test_help(self):
"""Test schemaconfigglue with --help."""
- config = StringIO("[foo]\nbar=1")
+ config = BytesIO(b"[foo]\nbar=1")
self.parser.readfp(config)
self.assertEqual(self.parser.values(),
{'foo': {'bar': 1}, '__main__': {'baz': 0}})
# replace stdout to capture its value
- stdout = StringIO()
- _stdout = sys.stdout
- sys.stdout = stdout
- # call the method and assert its value
- self.assertRaises(SystemExit, schemaconfigglue, self.parser,
- argv=['--help'])
- # replace stdout again to cleanup
- sys.stdout = _stdout
+ new_callable = StringIO
+ if PY2:
+ new_callable = BytesIO
+ with patch('sys.stdout', new_callable=new_callable) as mock_stdout:
+ # call the method and assert its value
+ self.assertRaises(SystemExit, schemaconfigglue, self.parser,
+ argv=['--help'])
# assert the value of stdout is correct
- stdout.seek(0)
- output = stdout.read()
+ output = mock_stdout.getvalue()
self.assertTrue(output.startswith('Usage:'))
def test_help_with_fatal(self):
@@ -347,18 +347,16 @@
self.parser = SchemaConfigParser(MySchema())
# replace stdout to capture its value
- stdout = StringIO()
- _stdout = sys.stdout
- sys.stdout = stdout
- # call the method and assert its value
- self.assertRaises(SystemExit, schemaconfigglue, self.parser,
- argv=['--help'])
- # replace stdout again to cleanup
- sys.stdout = _stdout
+ new_callable = StringIO
+ if PY2:
+ new_callable = BytesIO
+ with patch('sys.stdout', new_callable=new_callable) as mock_stdout:
+ # call the method and assert its value
+ self.assertRaises(SystemExit, schemaconfigglue, self.parser,
+ argv=['--help'])
# assert the value of stdout is correct
- stdout.seek(0)
- output = stdout.read()
+ output = mock_stdout.getvalue()
self.assertTrue(output.startswith('Usage:'))
def test_parser_set_with_encoding(self):
@@ -410,7 +408,7 @@
class MySchema(Schema):
foo = IntOption(fatal=True)
- config = StringIO("[__main__]\nfoo=1")
+ config = BytesIO(b"[__main__]\nfoo=1")
parser = SchemaConfigParser(MySchema())
parser.readfp(config)
=== modified file 'setup.py'
--- setup.py 2011-07-22 15:44:24 +0000
+++ setup.py 2013-05-27 01:13:29 +0000
@@ -21,6 +21,12 @@
)
import configglue
+from configglue._compat import PY2
+
+
+install_requires = ['pyxdg']
+if PY2:
+ install_requires.extend(['configparser'])
setup(name='configglue',
@@ -36,12 +42,18 @@
'License :: OSI Approved :: BSD License',
'Topic :: Software Development :: Libraries :: Python Modules',
'Programming Language :: Python',
+ 'Programming Language :: Python :: 2',
+ 'Programming Language :: Python :: 2.6',
+ 'Programming Language :: Python :: 2.7',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.2',
+ 'Programming Language :: Python :: 3.3',
],
author='John R. Lenton, Ricardo Kirkner',
author_email='john.lenton@xxxxxxxxxxxxx, ricardo.kirkner@xxxxxxxxxxxxx',
url='https://launchpad.net/configglue',
license='BSD License',
- install_requires=['pyxdg'],
+ install_requires=install_requires,
dependency_links=['http://www.freedesktop.org/wiki/Software/pyxdg'],
packages=find_packages(),
include_package_data=True,
=== modified file 'tox.ini'
--- tox.ini 2011-06-30 02:12:02 +0000
+++ tox.ini 2013-05-27 01:13:29 +0000
@@ -1,12 +1,23 @@
[tox]
-envlist = py26,py27,docs
+envlist = py26,py27,py32,py33,docs
[testenv]
deps =
mock
+ pyxdg
commands =
python setup.py test
+[testenv:py26]
+deps =
+ {[testenv]deps}
+ configparser
+
+[testenv:py27]
+deps =
+ {[testenv]deps}
+ configparser
+
[testenv:docs]
changedir = doc
deps =
Follow ups