Skip to content

Commit

Permalink
Fix errors
Browse files Browse the repository at this point in the history
  • Loading branch information
klen committed Dec 28, 2012
1 parent ee6dd41 commit 1b2974a
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 20 deletions.
1 change: 0 additions & 1 deletion MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
recursive-include inirama *
exclude *.pyc *.orig
64 changes: 50 additions & 14 deletions inirama.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,53 +103,79 @@ class INIScanner(Scanner):
ignore = ['IGNORE']

def pre_scan(self):
self.source = re.sub(r'\\\n\s*', '', self.source)
escape_re = re.compile(r'\\\n[\t ]+')
self.source = escape_re.sub('', self.source)


undefined = object()
var_re = re.compile('{([^}]+)}')


class Section(dict):

@property
def context(self):
return dict(iter(self))
return self

def __init__(self, namespace, *args, **kwargs):
super(Section, self).__init__(*args, **kwargs)
self.namespace = namespace

def __setitem__(self, name, value):
super(Section, self).__setitem__(name, str(value))

def __iter__(self):
for key in super(Section, self).keys():
yield key, self[key]


class InterpolationSection(Section):

var_re = re.compile('{([^}]+)}')

@property
def context(self):
return dict(iter(self))

def get(self, name, default=None):
if name in self:
return self[name]
return default

def __interpolate__(self, math):
try:
return self[math.group(1)]
# return self[math.group(1)]
key = math.group(1)
return self.namespace.default.get(key) or self[key]
except KeyError:
return ''

def __getitem__(self, name):
value = super(Section, self).__getitem__(name)
value = super(InterpolationSection, self).__getitem__(name)
sample = undefined
while sample != value:
try:
sample, value = value, var_re.sub(self.__interpolate__, value)
sample, value = value, self.var_re.sub(self.__interpolate__, value)
except RuntimeError:
raise ValueError("Interpolation failed: {0}".format(name))
return value

def __iter__(self):
for key in super(Section, self).keys():
yield key, self[key]


class Namespace:
class Namespace(object):

default_section = 'default'
default_section = 'DEFAULT'
silent_read = True
section_type = Section

def __init__(self, **default_items):
self.sections = OrderedDict()
if default_items:
self[self.default_section] = self.section_type(**default_items)
self[self.default_section] = self.section_type(self, **default_items)

@property
def default(self):
""" Return default section or empty dict.
"""
return self.sections.get(self.default_section, dict())

def read(self, *files):
""" Read and parse INI files.
Expand All @@ -163,6 +189,11 @@ def read(self, *files):
raise

def write(self, f):
"""
Write self as INI file.
:param f: File object or path to file.
"""
if isinstance(f, str):
f = io.open(f, 'w', encoding='utf-8')

Expand Down Expand Up @@ -196,8 +227,13 @@ def __getitem__(self, name):
""" Look name in self sections.
"""
if not name in self.sections:
self.sections[name] = self.section_type()
self.sections[name] = self.section_type(self)
return self.sections[name]

def __repr__(self):
return "<Namespace: {0}>".format(self.sections)


class InterpolationNamespace(Namespace):

section_type = InterpolationSection
12 changes: 7 additions & 5 deletions tests/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from unittest import TestCase

from inirama import Namespace
from inirama import Namespace, InterpolationNamespace


class MainTest(TestCase):
Expand All @@ -13,29 +13,31 @@ def test_parse(self):
self.assertTrue(parser['main'])
self.assertTrue(parser['main']['key'])
self.assertTrue(parser['main']['additional'])
self.assertEqual(parser['default']['defkey'], 'defvalue')
self.assertEqual(parser['DEFAULT']['defkey'], 'defvalue')
self.assertEqual(parser['other']['foo'], 'bar/zeta')
self.assertEqual(parser['other']['long'], 'long value')
self.assertEqual(parser['other']['safe_value'], 'c:\\\\test\\')
self.assertEqual(parser['other']['b'], '[test]')

parser['main']['test'] = 123
self.assertEqual(parser['main']['test'], '123')

def test_interpolation(self):
parser = Namespace()
parser = InterpolationNamespace()
parser.default_section = 'main'
parser.read('tests/vars.ini')
self.assertEqual(parser['main']['var_test'], 'Hello world!')

parser['main']['foo'] = 'bar {var_test}'
self.assertEqual(parser['main']['foo'], 'bar Hello world!')

self.assertEqual(parser['main'].context, {'foo': 'bar Hello world!', 'test': 'world', 'var_test': 'Hello world!'})

parser['main']['test'] = '{foo}'
with self.assertRaises(ValueError):
self.assertEqual(parser['main']['foo'], 'bar Hello world!')

parser['main']['test'] = 'parse {unknown}done'
self.assertEqual(parser['main']['test'], 'parse done')
self.assertEqual(parser['other']['b'], 'Hello parse done! start')

def test_write(self):
from tempfile import mkstemp
Expand Down
2 changes: 2 additions & 0 deletions tests/test.ini
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ key = value
; Other comment
foo:bar/zeta
alpha = beta 28 54
b = [test]
long = long \
value
safe_value = c:\\test\

[empty]
5 changes: 5 additions & 0 deletions tests/vars.ini
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
[main]
test = world
var_test = Hello {test}!
c = start

[other]
a = {var_test}
b = {a} {c}

0 comments on commit 1b2974a

Please sign in to comment.