pax_global_header00006660000000000000000000000064125021321730014506gustar00rootroot0000000000000052 comment=ecfe13528771510fdc6d9b190b0c398982143ee2 pytoml-0.1.2/000077500000000000000000000000001250213217300130325ustar00rootroot00000000000000pytoml-0.1.2/LICENSE000066400000000000000000000015611250213217300140420ustar00rootroot00000000000000No-notice MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. pytoml-0.1.2/MANIFEST.in000066400000000000000000000000171250213217300145660ustar00rootroot00000000000000include test/* pytoml-0.1.2/README.md000066400000000000000000000014611250213217300143130ustar00rootroot00000000000000# pytoml This project aims at being a specs-conforming and strict parser and writer for [TOML][1] files. The library currently supports [version 0.4.0][2] of the specs and runs with Python 2.7 and 3.4+. Install: easy_install pytoml The interface is the same as for the standard `json` package. >>> import pytoml as toml >>> toml.loads('a = 1') {'a': 1} >>> with open('file.toml', 'rb') as fin: ... obj = toml.load(fin) >>> obj {'a': 1} The `loads` function accepts either a bytes object (that gets decoded as UTF-8 with no BOM allowed), or a unicode object. Use `dump` or `dumps` to serialize a dict into TOML. >>> print toml.dumps(obj) a = 1 [1]: https://github.com/toml-lang/toml [2]: https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.4.0.md pytoml-0.1.2/pytoml/000077500000000000000000000000001250213217300143565ustar00rootroot00000000000000pytoml-0.1.2/pytoml/__init__.py000066400000000000000000000001341250213217300164650ustar00rootroot00000000000000from .core import TomlError from .parser import load, loads from .writer import dump, dumps pytoml-0.1.2/pytoml/core.py000066400000000000000000000007751250213217300156710ustar00rootroot00000000000000class TomlError(RuntimeError): def __init__(self, message, line, col, filename): RuntimeError.__init__(self, message, line, col, filename) self.message = message self.line = line self.col = col self.filename = filename def __str__(self): return '{}({}, {}): {}'.format(self.filename, self.line, self.col, self.message) def __repr__(self): return 'TomlError({!r}, {!r}, {!r}, {!r})'.format(self.message, self.line, self.col, self.filename) pytoml-0.1.2/pytoml/parser.py000066400000000000000000000336721250213217300162370ustar00rootroot00000000000000import string, re, sys, datetime from .core import TomlError class _CharSource: def __init__(self, s, filename): self._s = s self._index = 0 self._mark = 0 self._line = 1 self._col = 1 self._filename = filename self._update_cur() def __bool__(self): return self.cur is not None def __len__(self): return len(self._s[self._index:]) def __getitem__(self, item): return self._s[self._index:][item] def next(self, l=1): for ch in self[:l]: if ch == '\n': self._line += 1 self._col = 1 else: self._col += 1 self._index += l self._update_cur() def mark(self): self._mark = self._index self._mark_pos = self._line, self._col def rollback(self): self._index = self._mark self._line, self._col = self._mark_pos self._update_cur() def commit(self, type=None, text=None): tok = self._s[self._mark:self._index] pos = (self._mark_pos, (self._line, self._col)) if type is None: type = tok if text is None: text = tok return type, text, pos def error(self, message): raise TomlError(message, self._line, self._col, self._filename) def _update_cur(self): self.tail = self._s[self._index:] if self._index < len(self._s): self.cur = self._s[self._index] else: self.cur = None if sys.version_info[0] == 2: _chr = unichr else: _chr = chr _datetime_re = re.compile(r'(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(\.\d+)?(?:Z|([+-]\d{2}):(\d{2}))') def _lex(s, filename): src = _CharSource(s.replace('\r\n', '\n'), filename) def is_id(ch): return ch is not None and (ch.isalnum() or ch in '-_') def is_ws(ch): return ch is not None and ch in ' \t' def fetch_esc(): escapes = {'b':'\b', 't':'\t', 'n':'\n', 'f':'\f', 'r':'\r', '"':'"', '\\':'\\'} if src.cur == 'u': if len(src) < 5 or any(ch not in string.hexdigits for ch in src[1:5]): src.error('invalid_escape_sequence') res = _chr(int(src[1:5], 16)) src.next(5) elif src.cur == 'U': if len(src) < 9 or any(ch not in string.hexdigits for ch in src[1:9]): src.error('invalid_escape_sequence') res = _chr(int(src[1:9], 16)) src.next(9) elif src.cur == '\n': while src and src.cur in ' \n\t': src.next() res = '' elif src.cur in escapes: res = escapes[src.cur] src.next(1) else: src.error('invalid_escape_sequence') return res def consume_datetime(): m = _datetime_re.match(src.tail) if not m: return False src.next(len(m.group(0))) return True def consume_int(): if not src: src.error('malformed') if src.cur in '+-': src.next() if not src or src.cur not in '0123456789': src.error('malformed') while src and src.cur in '0123456789_': src.next() def consume_float(): consume_int() type = 'int' if src and src.cur == '.': type = 'float' src.next() if not src or src.cur not in '0123456789_': src.error('malformed_float') while src and src.cur in '0123456789_': src.next() if src and src.cur in 'eE': type = 'float' src.next() consume_int() return type while src: src.mark() if src.cur in ' \t': src.next() while src and src.cur in ' \t': src.next() elif src.cur == '#': src.next() while src and src.cur != '\n': src.next() elif src.cur in '0123456789': if consume_datetime(): yield src.commit('datetime') else: src.rollback() type = consume_float() yield src.commit(type) elif src.cur in '+-': type = consume_float() yield src.commit(type) elif is_id(src.cur): while is_id(src.cur): src.next() yield src.commit('id') elif src.cur in '[]{}=.,\n': src.next() yield src.commit() elif src.tail.startswith("'''"): src.next(3) if src.cur == '\n': src.next() end_quote = src.tail.find("'''") if end_quote == -1: src.error('unclosed_multiline_string') text = src[:end_quote] src.next(end_quote+3) yield src.commit('str', text) elif src.cur == "'": src.next() end_quote = src.tail.find("'") if end_quote == -1: src.error('unclosed_string') text = src[:end_quote] src.next(end_quote+1) yield src.commit('str', text) elif src.tail.startswith('"""'): src.next(3) if src.cur == '\n': src.next() res = [] while True: src.mark() end_quote = src.tail.find('"""') if end_quote == -1: src.error('unclosed_multiline_string') esc_pos = src.tail.find('\\') if esc_pos == -1 or esc_pos > end_quote: res.append(src[:end_quote]) src.next(end_quote+3) break res.append(src[:esc_pos]) src.next(esc_pos+1) res.append(fetch_esc()) yield src.commit('str', ''.join(res)) elif src.cur == '"': src.next() res = [] while True: src.mark() end_quote = src.tail.find('"') if end_quote == -1: src.error('unclosed_string') esc_pos = src.tail.find('\\') if esc_pos == -1 or esc_pos > end_quote: res.append(src[:end_quote]) src.next(end_quote+1) break res.append(src[:esc_pos]) src.next(esc_pos+1) res.append(fetch_esc()) yield src.commit('str', ''.join(res)) else: src.error('unexpected_char') src.mark() yield src.commit('\n', '') yield src.commit('eof', '') class _TokSource: def __init__(self, s, filename): self._filename = filename self._lex = iter(_lex(s, filename)) self.pos = None self.next() def next(self): self.prev_pos = self.pos self.tok, self.text, self.pos = next(self._lex) def consume(self, kind): if self.tok == kind: self.next() return True return False def consume_adjacent(self, kind): if self.prev_pos is None or self.prev_pos[1] != self.pos[0]: return False return self.consume(kind) def consume_nls(self): while self.consume('\n'): pass def expect(self, kind, error_text): if not self.consume(kind): self.error(error_text) def error(self, message): raise TomlError(message, self.pos[0][0], self.pos[0][1], self._filename) def _translate_datetime(s): match = _datetime_re.match(s) re.compile(r'(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(\.\d+)?(?:Z|([+-]\d{2}):(\d{2}))') y = int(match.group(1)) m = int(match.group(2)) d = int(match.group(3)) H = int(match.group(4)) M = int(match.group(5)) S = int(match.group(6)) if match.group(7) is not None: micro = float(match.group(7)) else: micro = 0 if match.group(8) is not None: tzh = int(match.group(8)) tzm = int(match.group(9)) if tzh < 0: tzm = -tzm offs = tzh * 60 + tzm else: offs = 0 dt = datetime.datetime(y, m, d, H, M, S, int(micro * 1000000), _TimeZone(datetime.timedelta(0, offs*60))) return dt def _translate_literal(type, text): if type == 'bool': return text == 'true' elif type == 'int': return int(text.replace('_', '')) elif type == 'float': return float(text.replace('_', '')) elif type == 'str': return text elif type == 'datetime': return _translate_datetime(text) def _translate_array(a): return a def load(fin, translate_literal=_translate_literal, translate_array=_translate_array): return loads(fin.read(), translate_literal=translate_literal, translate_array=translate_array, filename=fin.name) def loads(s, translate_literal=_translate_literal, translate_array=_translate_array, filename=''): if isinstance(s, bytes): s = s.decode('utf-8') toks = _TokSource(s, filename) def read_value(): while True: if toks.tok == 'id': if toks.text in ('true', 'false'): value = translate_literal('bool', toks.text) toks.next() return 'bool', value else: toks.error('unexpected_identifier') elif toks.tok in ('int', 'str', 'float', 'datetime'): type = toks.tok value = translate_literal(toks.tok, toks.text) toks.next() return type, value elif toks.consume('['): res = [] toks.consume_nls() if not toks.consume(']'): toks.consume_nls() type, val = read_value() res.append(val) toks.consume_nls() while toks.consume(','): toks.consume_nls() if toks.consume(']'): break cur_type, val = read_value() if type != cur_type: toks.error('heterogenous_array') res.append(val) toks.consume_nls() else: toks.expect(']', 'expected_right_brace') return 'array', translate_array(res) elif toks.consume('{'): res = {} while toks.tok in ('id', 'str'): k = toks.text toks.next() if k in res: toks.error('duplicate_key') toks.expect('=', 'expected_equals') type, v = read_value() res[k] = v if not toks.consume(','): break toks.expect('}', 'expected_closing_brace') return 'table', res else: toks.error('unexpected_token') root = {} tables = {} scope = root while toks.tok != 'eof': if toks.tok in ('id', 'str'): k = toks.text toks.next() toks.expect('=', 'expected_equals') type, v = read_value() if k in scope: toks.error('duplicate_keys') scope[k] = v toks.expect('\n', 'expected_eol') elif toks.consume('\n'): pass elif toks.consume('['): is_table_array = toks.consume_adjacent('[') path = [] if toks.tok not in ('id', 'str'): toks.error('expected_table_name') path.append(toks.text) toks.next() while toks.consume('.'): if toks.tok not in ('id', 'str'): toks.error('expected_table_name') path.append(toks.text) toks.next() if not toks.consume(']') or (is_table_array and not toks.consume_adjacent(']')): toks.error('malformed_table_name') toks.expect('\n', 'expected_eol') cur = tables for name in path[:-1]: if isinstance(cur.get(name), list): d, cur = cur[name][-1] else: d, cur = cur.setdefault(name, (None, {})) scope = {} name = path[-1] if name not in cur: if is_table_array: cur[name] = [(scope, {})] else: cur[name] = (scope, {}) elif isinstance(cur[name], list): if not is_table_array: toks.error('table_type_mismatch') cur[name].append((scope, {})) else: if is_table_array: toks.error('table_type_mismatch') old_scope, next_table = cur[name] if old_scope is not None: toks.error('duplicate_tables') cur[name] = (scope, next_table) else: toks.error('unexpected') def merge_tables(scope, tables): if scope is None: scope = {} for k in tables: if k in scope: toks.error('key_table_conflict') v = tables[k] if isinstance(v, list): scope[k] = [merge_tables(sc, tbl) for sc, tbl in v] else: scope[k] = merge_tables(v[0], v[1]) return scope return merge_tables(root, tables) class _TimeZone(datetime.tzinfo): def __init__(self, offset): self._offset = offset def utcoffset(self, dt): return self._offset def dst(self, dt): return None def tzname(self, dt): m = self._offset.total_seconds() // 60 if m < 0: res = '-' m = -m else: res = '+' h = m // 60 m = m - h * 60 return '{}{:.02}{:.02}'.format(res, h, m) pytoml-0.1.2/pytoml/writer.py000066400000000000000000000053531250213217300162520ustar00rootroot00000000000000from __future__ import unicode_literals import io, datetime, sys if sys.version_info[0] == 3: long = int unicode = str def dumps(obj): fout = io.StringIO() dump(fout, obj) return fout.getvalue() _escapes = { '\n': 'n', '\r': 'r', '\\': '\\', '\t': 't', '\b': 'b', '\f': 'f', '"': '"' } def _escape_string(s): res = [] start = 0 def flush(): if start != i: res.append(s[start:i]) return i + 1 i = 0 while i < len(s): c = s[i] if c in '"\\\n\r\t\b\f': start = flush() res.append('\\' + _escapes[c]) elif ord(c) < 0x20: start = flush() res.append('\\u%04x' % ord(c)) i += 1 flush() return '"' + ''.join(res) + '"' def _escape_id(s): if any(not c.isalnum() and c not in '-_' for c in s): return _escape_string(s) return s def _format_list(v): return '[{}]'.format(', '.join(_format_value(obj) for obj in v)) def _format_value(v): if isinstance(v, bool): return 'true' if v else 'false' if isinstance(v, int) or isinstance(v, long): return unicode(v) if isinstance(v, float): return '{:.17f}'.format(v) elif isinstance(v, unicode) or isinstance(v, bytes): return _escape_string(v) elif isinstance(v, datetime.datetime): offs = v.utcoffset() offs = offs.total_seconds() // 60 if offs is not None else 0 if offs == 0: suffix = 'Z' else: if offs > 0: suffix = '+' else: suffix = '-' offs = -offs suffix = '{}{:.02}{:.02}'.format(suffix, offs // 60, offs % 60) if v.microsecond: return v.strftime('%Y-%m-%dT%H:%M:%S.%f') + suffix else: return v.strftime('%Y-%m-%dT%H:%M:%S') + suffix elif isinstance(v, list): return _format_list(v) else: raise RuntimeError('XXX') def dump(fout, obj): tables = [((), obj, False)] while tables: name, table, is_array = tables.pop() if name: section_name = '.'.join(_escape_id(c) for c in name) if is_array: fout.write('[[{}]]\n'.format(section_name)) else: fout.write('[{}]\n'.format(section_name)) for k in table: v = table[k] if isinstance(v, dict): tables.append((name + (k,), v, False)) elif isinstance(v, list) and v and all(isinstance(o, dict) for o in v): tables.extend((name + (k,), d, True) for d in reversed(v)) else: fout.write('{} = {}\n'.format(_escape_id(k), _format_value(v))) if tables: fout.write('\n') pytoml-0.1.2/setup.py000066400000000000000000000005041250213217300145430ustar00rootroot00000000000000#!/usr/bin/env python # coding: utf-8 from setuptools import setup setup( name='pytoml', version='0.1.2', description='A parser for TOML-0.4.0', author='Martin Vejnár', author_email='avakar@ratatanek.cz', url='https://github.com/avakar/pytoml', license='MIT', packages=['pytoml'], ) pytoml-0.1.2/test/000077500000000000000000000000001250213217300140115ustar00rootroot00000000000000pytoml-0.1.2/test/invalid/000077500000000000000000000000001250213217300154375ustar00rootroot00000000000000pytoml-0.1.2/test/invalid/array-mixed-types-arrays-and-ints.toml000066400000000000000000000000651250213217300247330ustar00rootroot00000000000000arrays-and-ints = [1, ["Arrays are not integers."]] pytoml-0.1.2/test/invalid/array-mixed-types-ints-and-floats.toml000066400000000000000000000000331250213217300247150ustar00rootroot00000000000000ints-and-floats = [1, 1.1] pytoml-0.1.2/test/invalid/array-mixed-types-strings-and-ints.toml000066400000000000000000000000361250213217300251210ustar00rootroot00000000000000strings-and-ints = ["hi", 42] pytoml-0.1.2/test/invalid/datetime-malformed-no-leads.toml000066400000000000000000000000371250213217300235740ustar00rootroot00000000000000no-leads = 1987-7-05T17:45:00Z pytoml-0.1.2/test/invalid/datetime-malformed-no-secs.toml000066400000000000000000000000341250213217300234360ustar00rootroot00000000000000no-secs = 1987-07-05T17:45Z pytoml-0.1.2/test/invalid/datetime-malformed-no-t.toml000066400000000000000000000000331250213217300227430ustar00rootroot00000000000000no-t = 1987-07-0517:45:00Z pytoml-0.1.2/test/invalid/datetime-malformed-no-z.toml000066400000000000000000000000331250213217300227510ustar00rootroot00000000000000no-z = 1987-07-05T17:45:00 pytoml-0.1.2/test/invalid/datetime-malformed-with-milli.toml000066400000000000000000000000441250213217300241470ustar00rootroot00000000000000with-milli = 1987-07-5T17:45:00.12Z pytoml-0.1.2/test/invalid/duplicate-key-table.toml000066400000000000000000000000631250213217300221600ustar00rootroot00000000000000[fruit] type = "apple" [fruit.type] apple = "yes" pytoml-0.1.2/test/invalid/duplicate-keys.toml000066400000000000000000000000311250213217300212510ustar00rootroot00000000000000dupe = false dupe = true pytoml-0.1.2/test/invalid/duplicate-tables.toml000066400000000000000000000000101250213217300215450ustar00rootroot00000000000000[a] [a] pytoml-0.1.2/test/invalid/empty-implicit-table.toml000066400000000000000000000000231250213217300223620ustar00rootroot00000000000000[naughty..naughty] pytoml-0.1.2/test/invalid/empty-table.toml000066400000000000000000000000031250213217300205500ustar00rootroot00000000000000[] pytoml-0.1.2/test/invalid/float-no-leading-zero.toml000066400000000000000000000000441250213217300224270ustar00rootroot00000000000000answer = .12345 neganswer = -.12345 pytoml-0.1.2/test/invalid/float-no-trailing-digits.toml000066400000000000000000000000341250213217300231400ustar00rootroot00000000000000answer = 1. neganswer = -1. pytoml-0.1.2/test/invalid/key-after-table.toml000066400000000000000000000000441250213217300213060ustar00rootroot00000000000000[error] this = "should not be here" pytoml-0.1.2/test/invalid/key-empty.toml000066400000000000000000000000051250213217300202530ustar00rootroot00000000000000 = 1 pytoml-0.1.2/test/invalid/key-hash.toml000066400000000000000000000000071250213217300200420ustar00rootroot00000000000000a# = 1 pytoml-0.1.2/test/invalid/key-newline.toml000066400000000000000000000000061250213217300205570ustar00rootroot00000000000000a = 1 pytoml-0.1.2/test/invalid/key-no-eol.toml000066400000000000000000000000141250213217300203060ustar00rootroot00000000000000a = 1 b = 2 pytoml-0.1.2/test/invalid/key-open-bracket.toml000066400000000000000000000000111250213217300214640ustar00rootroot00000000000000[abc = 1 pytoml-0.1.2/test/invalid/key-single-open-bracket.toml000066400000000000000000000000011250213217300227420ustar00rootroot00000000000000[pytoml-0.1.2/test/invalid/key-space.toml000066400000000000000000000000071250213217300202120ustar00rootroot00000000000000a b = 1pytoml-0.1.2/test/invalid/key-start-bracket.toml000066400000000000000000000000211250213217300216610ustar00rootroot00000000000000[a] [xyz = 5 [b] pytoml-0.1.2/test/invalid/key-two-equals.toml000066400000000000000000000000111250213217300212130ustar00rootroot00000000000000key= = 1 pytoml-0.1.2/test/invalid/llbrace.toml000066400000000000000000000000131250213217300177320ustar00rootroot00000000000000[ [table]] pytoml-0.1.2/test/invalid/rrbrace.toml000066400000000000000000000000131250213217300177460ustar00rootroot00000000000000[[table] ] pytoml-0.1.2/test/invalid/string-bad-byte-escape.toml000066400000000000000000000000211250213217300225560ustar00rootroot00000000000000naughty = "\xAg" pytoml-0.1.2/test/invalid/string-bad-escape.toml000066400000000000000000000000761250213217300216270ustar00rootroot00000000000000invalid-escape = "This string has a bad \a escape character." pytoml-0.1.2/test/invalid/string-byte-escapes.toml000066400000000000000000000000201250213217300222140ustar00rootroot00000000000000answer = "\x33" pytoml-0.1.2/test/invalid/string-no-close.toml000066400000000000000000000000521250213217300213540ustar00rootroot00000000000000no-ending-quote = "One time, at band camp pytoml-0.1.2/test/invalid/table-array-implicit.toml000066400000000000000000000011561250213217300223520ustar00rootroot00000000000000# This test is a bit tricky. It should fail because the first use of # `[[albums.songs]]` without first declaring `albums` implies that `albums` # must be a table. The alternative would be quite weird. Namely, it wouldn't # comply with the TOML spec: "Each double-bracketed sub-table will belong to # the most *recently* defined table element *above* it." # # This is in contrast to the *valid* test, table-array-implicit where # `[[albums.songs]]` works by itself, so long as `[[albums]]` isn't declared # later. (Although, `[albums]` could be.) [[albums.songs]] name = "Glory Days" [[albums]] name = "Born in the USA" pytoml-0.1.2/test/invalid/table-array-malformed-bracket.toml000066400000000000000000000000371250213217300241140ustar00rootroot00000000000000[[albums] name = "Born to Run" pytoml-0.1.2/test/invalid/table-array-malformed-empty.toml000066400000000000000000000000321250213217300236320ustar00rootroot00000000000000[[]] name = "Born to Run" pytoml-0.1.2/test/invalid/table-empty.toml000066400000000000000000000000031250213217300205500ustar00rootroot00000000000000[] pytoml-0.1.2/test/invalid/table-nested-brackets-close.toml000066400000000000000000000000171250213217300236000ustar00rootroot00000000000000[a]b] zyx = 42 pytoml-0.1.2/test/invalid/table-nested-brackets-open.toml000066400000000000000000000000171250213217300234340ustar00rootroot00000000000000[a[b] zyx = 42 pytoml-0.1.2/test/invalid/table-whitespace.toml000066400000000000000000000000151250213217300215510ustar00rootroot00000000000000[invalid key]pytoml-0.1.2/test/invalid/table-with-pound.toml000066400000000000000000000000271250213217300215160ustar00rootroot00000000000000[key#group] answer = 42pytoml-0.1.2/test/invalid/text-after-array-entries.toml000066400000000000000000000001061250213217300231770ustar00rootroot00000000000000array = [ "Is there life after an array separator?", No "Entry" ] pytoml-0.1.2/test/invalid/text-after-integer.toml000066400000000000000000000000411250213217300220450ustar00rootroot00000000000000answer = 42 the ultimate answer? pytoml-0.1.2/test/invalid/text-after-string.toml000066400000000000000000000000541250213217300217220ustar00rootroot00000000000000string = "Is there life after strings?" No. pytoml-0.1.2/test/invalid/text-after-table.toml000066400000000000000000000000371250213217300215040ustar00rootroot00000000000000[error] this shouldn't be here pytoml-0.1.2/test/invalid/text-before-array-separator.toml000066400000000000000000000001071250213217300236700ustar00rootroot00000000000000array = [ "Is there life before an array separator?" No, "Entry" ] pytoml-0.1.2/test/invalid/text-in-array.toml000066400000000000000000000000701250213217300210350ustar00rootroot00000000000000array = [ "Entry 1", I don't belong, "Entry 2", ] pytoml-0.1.2/test/test.py000066400000000000000000000030421250213217300153410ustar00rootroot00000000000000import os, json, sys, io import pytoml as toml def _testbench_literal(type, text): _type_table = {'str': 'string', 'int': 'integer'} return {'type': _type_table.get(type, type), 'value': text} def _testbench_array(values): return {'type': 'array', 'value': values} def _main(): succeeded = [] failed = [] for top, dirnames, fnames in os.walk('.'): for fname in fnames: if not fname.endswith('.toml'): continue try: with open(os.path.join(top, fname), 'rb') as fin: parsed = toml.load(fin) except toml.TomlError: parsed = None else: dumped = toml.dumps(parsed) parsed2 = toml.loads(dumped) if parsed != parsed2: failed.append(fname) continue with open(os.path.join(top, fname), 'rb') as fin: parsed = toml.load(fin, _testbench_literal, _testbench_array) try: with io.open(os.path.join(top, fname[:-5] + '.json'), 'rt', encoding='utf-8') as fin: bench = json.load(fin) except IOError: bench = None if parsed != bench: failed.append(fname) else: succeeded.append(fname) for f in failed: print('failed: {}'.format(f)) print('succeeded: {}'.format(len(succeeded))) return 1 if failed else 0 if __name__ == '__main__': sys.exit(_main()) pytoml-0.1.2/test/valid/000077500000000000000000000000001250213217300151105ustar00rootroot00000000000000pytoml-0.1.2/test/valid/array-empty.json000066400000000000000000000004231250213217300202540ustar00rootroot00000000000000{ "thevoid": { "type": "array", "value": [ {"type": "array", "value": [ {"type": "array", "value": [ {"type": "array", "value": [ {"type": "array", "value": []} ]} ]} ]} ]} } pytoml-0.1.2/test/valid/array-empty.toml000066400000000000000000000000251250213217300202540ustar00rootroot00000000000000thevoid = [[[[[]]]]] pytoml-0.1.2/test/valid/array-nospaces.json000066400000000000000000000003321250213217300207300ustar00rootroot00000000000000{ "ints": { "type": "array", "value": [ {"type": "integer", "value": "1"}, {"type": "integer", "value": "2"}, {"type": "integer", "value": "3"} ] } } pytoml-0.1.2/test/valid/array-nospaces.toml000066400000000000000000000000171250213217300207320ustar00rootroot00000000000000ints = [1,2,3] pytoml-0.1.2/test/valid/arrays-hetergeneous.json000066400000000000000000000010461250213217300220000ustar00rootroot00000000000000{ "mixed": { "type": "array", "value": [ {"type": "array", "value": [ {"type": "integer", "value": "1"}, {"type": "integer", "value": "2"} ]}, {"type": "array", "value": [ {"type": "string", "value": "a"}, {"type": "string", "value": "b"} ]}, {"type": "array", "value": [ {"type": "float", "value": "1.1"}, {"type": "float", "value": "2.1"} ]} ] } } pytoml-0.1.2/test/valid/arrays-hetergeneous.toml000066400000000000000000000000511250213217300217750ustar00rootroot00000000000000mixed = [[1, 2], ["a", "b"], [1.1, 2.1]] pytoml-0.1.2/test/valid/arrays-nested.json000066400000000000000000000004411250213217300205630ustar00rootroot00000000000000{ "nest": { "type": "array", "value": [ {"type": "array", "value": [ {"type": "string", "value": "a"} ]}, {"type": "array", "value": [ {"type": "string", "value": "b"} ]} ] } } pytoml-0.1.2/test/valid/arrays-nested.toml000066400000000000000000000000261250213217300205640ustar00rootroot00000000000000nest = [["a"], ["b"]] pytoml-0.1.2/test/valid/arrays.json000066400000000000000000000016361250213217300173120ustar00rootroot00000000000000{ "ints": { "type": "array", "value": [ {"type": "integer", "value": "1"}, {"type": "integer", "value": "2"}, {"type": "integer", "value": "3"} ] }, "floats": { "type": "array", "value": [ {"type": "float", "value": "1.1"}, {"type": "float", "value": "2.1"}, {"type": "float", "value": "3.1"} ] }, "strings": { "type": "array", "value": [ {"type": "string", "value": "a"}, {"type": "string", "value": "b"}, {"type": "string", "value": "c"} ] }, "dates": { "type": "array", "value": [ {"type": "datetime", "value": "1987-07-05T17:45:00Z"}, {"type": "datetime", "value": "1979-05-27T07:32:00Z"}, {"type": "datetime", "value": "2006-06-01T11:00:00Z"} ] } } pytoml-0.1.2/test/valid/arrays.toml000066400000000000000000000002301250213217300173010ustar00rootroot00000000000000ints = [1, 2, 3] floats = [1.1, 2.1, 3.1] strings = ["a", "b", "c"] dates = [ 1987-07-05T17:45:00Z, 1979-05-27T07:32:00Z, 2006-06-01T11:00:00Z, ] pytoml-0.1.2/test/valid/bool.json000066400000000000000000000001341250213217300167340ustar00rootroot00000000000000{ "f": {"type": "bool", "value": "false"}, "t": {"type": "bool", "value": "true"} } pytoml-0.1.2/test/valid/bool.toml000066400000000000000000000000231250213217300167330ustar00rootroot00000000000000t = true f = false pytoml-0.1.2/test/valid/comments-everywhere.json000066400000000000000000000004241250213217300220130ustar00rootroot00000000000000{ "group": { "answer": {"type": "integer", "value": "42"}, "more": { "type": "array", "value": [ {"type": "integer", "value": "42"}, {"type": "integer", "value": "42"} ] } } } pytoml-0.1.2/test/valid/comments-everywhere.toml000066400000000000000000000007101250213217300220130ustar00rootroot00000000000000# Top comment. # Top comment. # Top comment. # [no-extraneous-groups-please] [group] # Comment answer = 42 # Comment # no-extraneous-keys-please = 999 # Inbetween comment. more = [ # Comment # What about multiple # comments? # Can you handle it? # # Evil. # Evil. 42, 42, # Comments within arrays are fun. # What about multiple # comments? # Can you handle it? # # Evil. # Evil. # ] Did I fool you? ] # Hopefully not. pytoml-0.1.2/test/valid/datetime.json000066400000000000000000000001151250213217300175740ustar00rootroot00000000000000{ "bestdayever": {"type": "datetime", "value": "1987-07-05T17:45:00Z"} } pytoml-0.1.2/test/valid/datetime.toml000066400000000000000000000000431250213217300175760ustar00rootroot00000000000000bestdayever = 1987-07-05T17:45:00Z pytoml-0.1.2/test/valid/empty.json000066400000000000000000000000031250213217300171320ustar00rootroot00000000000000{} pytoml-0.1.2/test/valid/empty.toml000066400000000000000000000000001250213217300171310ustar00rootroot00000000000000pytoml-0.1.2/test/valid/example.json000066400000000000000000000005421250213217300174370ustar00rootroot00000000000000{ "best-day-ever": {"type": "datetime", "value": "1987-07-05T17:45:00Z"}, "numtheory": { "boring": {"type": "bool", "value": "false"}, "perfection": { "type": "array", "value": [ {"type": "integer", "value": "6"}, {"type": "integer", "value": "28"}, {"type": "integer", "value": "496"} ] } } } pytoml-0.1.2/test/valid/example.toml000066400000000000000000000001331250213217300174350ustar00rootroot00000000000000best-day-ever = 1987-07-05T17:45:00Z [numtheory] boring = false perfection = [6, 28, 496] pytoml-0.1.2/test/valid/float.json000066400000000000000000000001431250213217300171060ustar00rootroot00000000000000{ "pi": {"type": "float", "value": "3.14"}, "negpi": {"type": "float", "value": "-3.14"} } pytoml-0.1.2/test/valid/float.toml000066400000000000000000000000301250213217300171030ustar00rootroot00000000000000pi = 3.14 negpi = -3.14 pytoml-0.1.2/test/valid/implicit-and-explicit-after.json000066400000000000000000000003021250213217300232660ustar00rootroot00000000000000{ "a": { "better": {"type": "integer", "value": "43"}, "b": { "c": { "answer": {"type": "integer", "value": "42"} } } } } pytoml-0.1.2/test/valid/implicit-and-explicit-after.toml000066400000000000000000000000451250213217300232740ustar00rootroot00000000000000[a.b.c] answer = 42 [a] better = 43 pytoml-0.1.2/test/valid/implicit-and-explicit-before.json000066400000000000000000000003021250213217300234270ustar00rootroot00000000000000{ "a": { "better": {"type": "integer", "value": "43"}, "b": { "c": { "answer": {"type": "integer", "value": "42"} } } } } pytoml-0.1.2/test/valid/implicit-and-explicit-before.toml000066400000000000000000000000451250213217300234350ustar00rootroot00000000000000[a] better = 43 [a.b.c] answer = 42 pytoml-0.1.2/test/valid/implicit-groups.json000066400000000000000000000002141250213217300211270ustar00rootroot00000000000000{ "a": { "b": { "c": { "answer": {"type": "integer", "value": "42"} } } } } pytoml-0.1.2/test/valid/implicit-groups.toml000066400000000000000000000000241250213217300211300ustar00rootroot00000000000000[a.b.c] answer = 42 pytoml-0.1.2/test/valid/inline-table.json000066400000000000000000000004711250213217300203500ustar00rootroot00000000000000{ "simple": { "a": {"type": "integer", "value": "1"} }, "str-key": { "a": {"type": "integer", "value": "1"} }, "table-array": { "type": "array", "value": [ { "a": {"type": "integer", "value": "1"} }, { "b": {"type": "integer", "value": "2"} } ] } } pytoml-0.1.2/test/valid/inline-table.toml000066400000000000000000000001221250213217300203430ustar00rootroot00000000000000simple = { a = 1 } str-key = { "a" = 1 } table-array = [{ "a" = 1 }, { "b" = 2 }] pytoml-0.1.2/test/valid/integer.json000066400000000000000000000001531250213217300174370ustar00rootroot00000000000000{ "answer": {"type": "integer", "value": "42"}, "neganswer": {"type": "integer", "value": "-42"} } pytoml-0.1.2/test/valid/integer.toml000066400000000000000000000000341250213217300174370ustar00rootroot00000000000000answer = 42 neganswer = -42 pytoml-0.1.2/test/valid/key-equals-nospace.json000066400000000000000000000000651250213217300215120ustar00rootroot00000000000000{ "answer": {"type": "integer", "value": "42"} } pytoml-0.1.2/test/valid/key-equals-nospace.toml000066400000000000000000000000121250213217300215040ustar00rootroot00000000000000answer=42 pytoml-0.1.2/test/valid/key-space.json000066400000000000000000000000611250213217300176610ustar00rootroot00000000000000{ "a b": {"type": "integer", "value": "1"} } pytoml-0.1.2/test/valid/key-space.toml000066400000000000000000000000121250213217300176570ustar00rootroot00000000000000"a b" = 1 pytoml-0.1.2/test/valid/key-special-chars.json000066400000000000000000000001371250213217300213100ustar00rootroot00000000000000{ "~!@$^&*()_+-`1234567890[]|/?><.,;:'": { "type": "integer", "value": "1" } } pytoml-0.1.2/test/valid/key-special-chars.toml000066400000000000000000000000521250213217300213060ustar00rootroot00000000000000"~!@$^&*()_+-`1234567890[]|/?><.,;:'" = 1 pytoml-0.1.2/test/valid/long-float.json000066400000000000000000000002051250213217300200420ustar00rootroot00000000000000{ "longpi": {"type": "float", "value": "3.141592653589793"}, "neglongpi": {"type": "float", "value": "-3.141592653589793"} } pytoml-0.1.2/test/valid/long-float.toml000066400000000000000000000000721250213217300200460ustar00rootroot00000000000000longpi = 3.141592653589793 neglongpi = -3.141592653589793 pytoml-0.1.2/test/valid/long-integer.json000066400000000000000000000002151250213217300203730ustar00rootroot00000000000000{ "answer": {"type": "integer", "value": "9223372036854775807"}, "neganswer": {"type": "integer", "value": "-9223372036854775808"} } pytoml-0.1.2/test/valid/long-integer.toml000066400000000000000000000000761250213217300204020ustar00rootroot00000000000000answer = 9223372036854775807 neganswer = -9223372036854775808 pytoml-0.1.2/test/valid/multiline-string.json000066400000000000000000000012731250213217300213140ustar00rootroot00000000000000{ "multiline_empty_one": { "type": "string", "value": "" }, "multiline_empty_two": { "type": "string", "value": "" }, "multiline_empty_three": { "type": "string", "value": "" }, "multiline_empty_four": { "type": "string", "value": "" }, "equivalent_one": { "type": "string", "value": "The quick brown fox jumps over the lazy dog." }, "equivalent_two": { "type": "string", "value": "The quick brown fox jumps over the lazy dog." }, "equivalent_three": { "type": "string", "value": "The quick brown fox jumps over the lazy dog." } } pytoml-0.1.2/test/valid/multiline-string.toml000066400000000000000000000006121250213217300213120ustar00rootroot00000000000000multiline_empty_one = """""" multiline_empty_two = """ """ multiline_empty_three = """\ """ multiline_empty_four = """\ \ \ """ equivalent_one = "The quick brown fox jumps over the lazy dog." equivalent_two = """ The quick brown \ fox jumps over \ the lazy dog.""" equivalent_three = """\ The quick brown \ fox jumps over \ the lazy dog.\ """ pytoml-0.1.2/test/valid/raw-multiline-string.json000066400000000000000000000005471250213217300221060ustar00rootroot00000000000000{ "oneline": { "type": "string", "value": "This string has a ' quote character." }, "firstnl": { "type": "string", "value": "This string has a ' quote character." }, "multiline": { "type": "string", "value": "This string\nhas ' a quote character\nand more than\none newline\nin it." } } pytoml-0.1.2/test/valid/raw-multiline-string.toml000066400000000000000000000003031250213217300220760ustar00rootroot00000000000000oneline = '''This string has a ' quote character.''' firstnl = ''' This string has a ' quote character.''' multiline = ''' This string has ' a quote character and more than one newline in it.''' pytoml-0.1.2/test/valid/raw-string.json000066400000000000000000000014171250213217300201030ustar00rootroot00000000000000{ "backspace": { "type": "string", "value": "This string has a \\b backspace character." }, "tab": { "type": "string", "value": "This string has a \\t tab character." }, "newline": { "type": "string", "value": "This string has a \\n new line character." }, "formfeed": { "type": "string", "value": "This string has a \\f form feed character." }, "carriage": { "type": "string", "value": "This string has a \\r carriage return character." }, "slash": { "type": "string", "value": "This string has a \\/ slash character." }, "backslash": { "type": "string", "value": "This string has a \\\\ backslash character." } } pytoml-0.1.2/test/valid/raw-string.toml000066400000000000000000000005651250213217300201100ustar00rootroot00000000000000backspace = 'This string has a \b backspace character.' tab = 'This string has a \t tab character.' newline = 'This string has a \n new line character.' formfeed = 'This string has a \f form feed character.' carriage = 'This string has a \r carriage return character.' slash = 'This string has a \/ slash character.' backslash = 'This string has a \\ backslash character.' pytoml-0.1.2/test/valid/string-empty.json000066400000000000000000000001101250213217300204350ustar00rootroot00000000000000{ "answer": { "type": "string", "value": "" } } pytoml-0.1.2/test/valid/string-empty.toml000066400000000000000000000000141250213217300204420ustar00rootroot00000000000000answer = "" pytoml-0.1.2/test/valid/string-escapes.json000066400000000000000000000024241250213217300207340ustar00rootroot00000000000000{ "backspace": { "type": "string", "value": "This string has a \u0008 backspace character." }, "tab": { "type": "string", "value": "This string has a \u0009 tab character." }, "newline": { "type": "string", "value": "This string has a \u000A new line character." }, "formfeed": { "type": "string", "value": "This string has a \u000C form feed character." }, "carriage": { "type": "string", "value": "This string has a \u000D carriage return character." }, "quote": { "type": "string", "value": "This string has a \u0022 quote character." }, "backslash": { "type": "string", "value": "This string has a \u005C backslash character." }, "notunicode1": { "type": "string", "value": "This string does not have a unicode \\u escape." }, "notunicode2": { "type": "string", "value": "This string does not have a unicode \u005Cu escape." }, "notunicode3": { "type": "string", "value": "This string does not have a unicode \\u0075 escape." }, "notunicode4": { "type": "string", "value": "This string does not have a unicode \\\u0075 escape." } } pytoml-0.1.2/test/valid/string-escapes.toml000066400000000000000000000012021250213217300207270ustar00rootroot00000000000000backspace = "This string has a \b backspace character." tab = "This string has a \t tab character." newline = "This string has a \n new line character." formfeed = "This string has a \f form feed character." carriage = "This string has a \r carriage return character." quote = "This string has a \" quote character." backslash = "This string has a \\ backslash character." notunicode1 = "This string does not have a unicode \\u escape." notunicode2 = "This string does not have a unicode \u005Cu escape." notunicode3 = "This string does not have a unicode \\u0075 escape." notunicode4 = "This string does not have a unicode \\\u0075 escape." pytoml-0.1.2/test/valid/string-simple.json000066400000000000000000000001531250213217300205770ustar00rootroot00000000000000{ "answer": { "type": "string", "value": "You are not drinking enough whisky." } } pytoml-0.1.2/test/valid/string-simple.toml000066400000000000000000000000571250213217300206040ustar00rootroot00000000000000answer = "You are not drinking enough whisky." pytoml-0.1.2/test/valid/string-with-pound.json000066400000000000000000000002711250213217300214050ustar00rootroot00000000000000{ "pound": {"type": "string", "value": "We see no # comments here."}, "poundcomment": { "type": "string", "value": "But there are # some comments here." } } pytoml-0.1.2/test/valid/string-with-pound.toml000066400000000000000000000001611250213217300214050ustar00rootroot00000000000000pound = "We see no # comments here." poundcomment = "But there are # some comments here." # Did I # mess you up? pytoml-0.1.2/test/valid/table-array-implicit.json000066400000000000000000000001641250213217300220170ustar00rootroot00000000000000{ "albums": { "songs": [ {"name": {"type": "string", "value": "Glory Days"}} ] } } pytoml-0.1.2/test/valid/table-array-implicit.toml000066400000000000000000000000451250213217300220170ustar00rootroot00000000000000[[albums.songs]] name = "Glory Days" pytoml-0.1.2/test/valid/table-array-many.json000066400000000000000000000007271250213217300211560ustar00rootroot00000000000000{ "people": [ { "first_name": {"type": "string", "value": "Bruce"}, "last_name": {"type": "string", "value": "Springsteen"} }, { "first_name": {"type": "string", "value": "Eric"}, "last_name": {"type": "string", "value": "Clapton"} }, { "first_name": {"type": "string", "value": "Bob"}, "last_name": {"type": "string", "value": "Seger"} } ] } pytoml-0.1.2/test/valid/table-array-many.toml000066400000000000000000000002431250213217300211510ustar00rootroot00000000000000[[people]] first_name = "Bruce" last_name = "Springsteen" [[people]] first_name = "Eric" last_name = "Clapton" [[people]] first_name = "Bob" last_name = "Seger" pytoml-0.1.2/test/valid/table-array-nest.json000066400000000000000000000010721250213217300211550ustar00rootroot00000000000000{ "albums": [ { "name": {"type": "string", "value": "Born to Run"}, "songs": [ {"name": {"type": "string", "value": "Jungleland"}}, {"name": {"type": "string", "value": "Meeting Across the River"}} ] }, { "name": {"type": "string", "value": "Born in the USA"}, "songs": [ {"name": {"type": "string", "value": "Glory Days"}}, {"name": {"type": "string", "value": "Dancing in the Dark"}} ] } ] } pytoml-0.1.2/test/valid/table-array-nest.toml000066400000000000000000000004061250213217300211570ustar00rootroot00000000000000[[albums]] name = "Born to Run" [[albums.songs]] name = "Jungleland" [[albums.songs]] name = "Meeting Across the River" [[albums]] name = "Born in the USA" [[albums.songs]] name = "Glory Days" [[albums.songs]] name = "Dancing in the Dark" pytoml-0.1.2/test/valid/table-array-one.json000066400000000000000000000002621250213217300207650ustar00rootroot00000000000000{ "people": [ { "first_name": {"type": "string", "value": "Bruce"}, "last_name": {"type": "string", "value": "Springsteen"} } ] } pytoml-0.1.2/test/valid/table-array-one.toml000066400000000000000000000000721250213217300207660ustar00rootroot00000000000000[[people]] first_name = "Bruce" last_name = "Springsteen" pytoml-0.1.2/test/valid/table-empty.json000066400000000000000000000000201250213217300202160ustar00rootroot00000000000000{ "a": {} } pytoml-0.1.2/test/valid/table-empty.toml000066400000000000000000000000041250213217300202220ustar00rootroot00000000000000[a] pytoml-0.1.2/test/valid/table-no-eol.json000066400000000000000000000000201250213217300202510ustar00rootroot00000000000000{ "table": {} } pytoml-0.1.2/test/valid/table-no-eol.toml000066400000000000000000000000071250213217300202600ustar00rootroot00000000000000[table]pytoml-0.1.2/test/valid/table-sub-empty.json000066400000000000000000000000311250213217300210070ustar00rootroot00000000000000{ "a": { "b": {} } } pytoml-0.1.2/test/valid/table-sub-empty.toml000066400000000000000000000000121250213217300210100ustar00rootroot00000000000000[a] [a.b] pytoml-0.1.2/test/valid/table-whitespace.json000066400000000000000000000000301250213217300212150ustar00rootroot00000000000000{ "valid key": {} } pytoml-0.1.2/test/valid/table-whitespace.toml000066400000000000000000000000161250213217300212230ustar00rootroot00000000000000["valid key"] pytoml-0.1.2/test/valid/table-with-pound.json000066400000000000000000000001221250213217300211610ustar00rootroot00000000000000{ "key#group": { "answer": {"type": "integer", "value": "42"} } } pytoml-0.1.2/test/valid/table-with-pound.toml000066400000000000000000000000321250213217300211630ustar00rootroot00000000000000["key#group"] answer = 42 pytoml-0.1.2/test/valid/unicode-escape.json000066400000000000000000000001571250213217300206720ustar00rootroot00000000000000{ "answer4": {"type": "string", "value": "\u03B4"}, "answer8": {"type": "string", "value": "\u03B4"} } pytoml-0.1.2/test/valid/unicode-escape.toml000066400000000000000000000000521250213217300206660ustar00rootroot00000000000000answer4 = "\u03B4" answer8 = "\U000003B4" pytoml-0.1.2/test/valid/unicode-literal.json000066400000000000000000000000641250213217300210630ustar00rootroot00000000000000{ "answer": {"type": "string", "value": "δ"} } pytoml-0.1.2/test/valid/unicode-literal.toml000066400000000000000000000000161250213217300210620ustar00rootroot00000000000000answer = "δ"