2018年7月28日土曜日

開発環境

load関数の引数がファイル名だと、手元のファイルの読み込みは簡単だけど、データのやり取りでバイナリモードのファイルの読み込みが出来なくて、urllib.responeモジュールのurlopenとかで使えないから変更。

コード(Emacs)

sion.py

# Created by kamimura on 2018/07/21.
# Copyright © 2018 kamimura. All rights reserved.
import sys
import datetime
from antlr4 import *
from SIONLexer import SIONLexer
from SIONParser import SIONParser
from SIONVisitor import SIONVisitor


def load(file, encoding: str='utf-8', errors: str='strict') -> object:
    data = file.read()
    if type(data) == bytes:
        data = data.decode(encoding, errors)
    stream = InputStream(data)
    lexer = SIONLexer(stream)
    tokens = CommonTokenStream(lexer)
    parser = SIONParser(tokens)
    tree = parser.si_self()
    visitor = SIONVisitor()
    return visitor.visit(tree)


def str_esc(s):
    for o, n in [('"', '\\"'), ('\n', '\\n'), ('\r', '\\r'), ('\\', '\\\\')]:
        s = s.replace(o, n)
    return s


def dump(obj, file):
    t = type(obj)
    if obj is None:
        print('nil', file=file, end='')
    elif t == bool:
        if obj:
            print('ture', file=file, end='')
        else:
            print('false', file=file, end='')
    elif t in {int, float}:
        print(obj, file=file, end='')
    elif t == str:
        print(f'"{str_esc(obj)}"', file=file, end='')
    elif t == bytes:
        print(f'.Data("{str(obj)[2:-1]}")', file=file, end='')
    elif t == datetime.datetime:
        print(f'.Date({t.timestamp(obj)})', file=file, end='')
    elif t in {list, tuple}:
        print(f'[', file=file, end='')
        if len(obj) > 0:
            for o in obj[:-1]:
                dump(o, file)
                print(',', file=file, end='')
            dump(obj[-1], file)
        print(']', file=file, end='')
    elif t == dict:
        print('[', file=file, end='')
        ks = list(obj.keys())
        if len(ks) == 0:
            print(':', file=file, end='')
        elif len(ks) == 1:
            dump(ks[0], file)
            print(':', file=file, end='')
            dump(obj[ks[0]], file)
        else:
            for k in ks[:-1]:
                dump(k, file)
                print(':', file=file, end='')
                dump(obj[k], file)
                print(',', file=file, end='')
            dump(ks[-1], file)
            print(':', file=file, end='')
            dump(obj[ks[-1]], file)
        print(']', file=file, end='')
    else:
        raise TypeError(
            f"Object of type '{obj.__class__.__name__}' is not SION serializable")


if __name__ == '__main__':
    if len(sys.argv) > 1:
        filename = sys.argv[1]
    else:
        filename = '../test/t.sion'
    with open(filename) as f:
        obj = load(f)
    print(obj)
    with open('../test/output.sion', 'w') as f:
        dump(obj, f)

バイナリファイルの読み込みが出来る事を確認。

Python 3

#!/usr/bin/env python3
import pprint
from urllib.request import urlopen
import sion

url = 'https://raw.githubusercontent.com/kamimura/py-sion/master/test/t.sion'

with urlopen(url) as res:
    pprint.pprint(sion.load(res))

with open('sample.sion') as f:
    pprint.pprint(sion.load(f))

入出力結果(Terminal, Jupyter(IPython))

$ cat sample.sion 
[
    "array" : [
        nil,
        true,
        1,    // Int in decimal
        1.0,  // Double in decimal
        "one",
        [1],
        ["one" : 1.0]
    ],
    "bool" : true,
    "data" : .Data("R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"),
    "date" : .Date(0x0p+0),
    "dictionary" : [
        "array" : [],
        "bool" : false,
        "double" : 0x0p+0,
        "int" : 0,
        "nil" : nil,
        "object" : [:],
        "string" : ""
    ],
    "double" : 0x1.518f5c28f5c29p+5, // Double in hexadecimal
    "int" : -0x2a, // Int in hexadecimal
    "nil" : nil,
   "string" : "漢字、カタカナ、ひらがなの入ったstring😇",
    "url" : "https://github.com/dankogai/",
    nil   : "Unlike JSON and Property Lists,",
    true  : "Yes, SION",
    1     : "does accept",
    1.0   : "non-String keys.",
    []    : "like",
    [:]   : "Map of ECMAScript."
]$ ./sample3.py
{None: 'Unlike JSON and Property Lists,',
 True: 'non-String keys.',
 '[]': 'like',
 'array': [None, True, 1, 1.0, 'one', [1], {'one': 1.0}],
 'bool': True,
 'data': b'R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7',
 'date': datetime.datetime(1970, 1, 1, 9, 0),
 'dictionary': {'array': [],
                'bool': False,
                'double': 0.0,
                'int': 0,
                'nil': None,
                'object': {},
                'string': ''},
 'double': 42.195,
 'int': -42,
 'nil': None,
 'string': '漢字、カタカナ、ひらがなの入ったstring😇',
 'url': 'https://github.com/dankogai/',
 '{}': 'Map of ECMAScript.'}
{None: 'Unlike JSON and Property Lists,',
 True: 'non-String keys.',
 '[]': 'like',
 'array': [None, True, 1, 1.0, 'one', [1], {'one': 1.0}],
 'bool': True,
 'data': b'R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7',
 'date': datetime.datetime(1970, 1, 1, 9, 0),
 'dictionary': {'array': [],
                'bool': False,
                'double': 0.0,
                'int': 0,
                'nil': None,
                'object': {},
                'string': ''},
 'double': 42.195,
 'int': -42,
 'nil': None,
 'string': '漢字、カタカナ、ひらがなの入ったstring😇',
 'url': 'https://github.com/dankogai/',
 '{}': 'Map of ECMAScript.'}
$ 

0 コメント:

コメントを投稿