rsonlite -- rson的极轻量级版本
项目描述
版本 0.1
版权 (c) 2012, Patrick Maupin
摘要
rsonlite 是在Python中创建自定义缩进数据文件格式的最简单方法。它是一个可以与您的应用程序一起分发的单个小型模块,也可以轻松安装或从PyPI安装。
背景
rson项目 包含一个解析器,允许对可读文件格式的变体进行实验,并定义了一个基RSON配置文件,它是JSON的严格超集(正确地子类化,RSON解析器通过了Python simplejson测试套件,它本身是JSON的超集)。
RSON是在对当时可用的纯Python YAML解析器的大小和速度感到沮丧后诞生的,并且与YAML有着非常相似的目标 - 这些格式的一个关键特点是使用缩进来作为语法,尽可能去除不必要的语法元素,如引号,以及添加注释和使用JSON作为有效输入的能力。
基本RSON格式定义是为了便于从任何语言中进行解析而设计的,但Python解析器本身既灵活又快速,使得可以轻松设计并测试变体格式。其中一种格式是能够轻松与XML双向转换的格式,另一种格式允许宏和包含处理。
但这种灵活性是有代价的。代码更多,所有选项的学习曲线都比如果解析器不那么灵活时要陡峭,而文档——嗯,要正确地记录所有选项需要很长时间,所以还没有完成。
rsonlite是rson的简化版本,主要处理缩进语义,允许客户端代码进行高级解析。与区分“true”、“false”、“null”、字符串和数字的JSON或基本RSON不同,或者simplejson添加了“Nan”和“Infinity”,rsonlite将世界划分为容器节点和叶节点,每个叶节点都是一个字符串。
介绍
rsonlite是一个Python库,它使得使用缩进来构建声明性分层数据结构的文件解析器变得容易。(仅考虑空格——制表符不被视为缩进。)
语法
唯一的特殊字符是#、=和缩进
- 缩进
缩进表示键/值关系。值从键缩进。
- =
表示自由格式字符串的开始。这些字符串可以包含“=”和“#”字符,甚至可以多行,但字符串中的每一行都必须比初始等号缩进。
注意,对于多行字符串,缩进被保留并规范化,使得至少有一行从左侧列开始。这允许reStructuredText或Python代码,甚至额外的rsonlite在多行字符串中解析。
- #
表示行注释的开始,当不在自由格式字符串内时。
对象
使用rsonlite.loads()解析文件产生的唯一Python对象是
- 字符串
自由格式字符串(如上所述)可以包含任何字符,但字符串前后可能被删除空格。
常规字符串必须在一行上,且不能包含“=”或“#”字符。
常规字符串可以用作键/值对的键,但自由格式字符串不能。
- 元组
键/值对是一个二元组。键始终是字符串。值始终是列表。(判断始终使值保持列表的连贯性比让值有时是单个字符串的快捷方式更有用。)
- 列表
顶级是列表,每个键/值对元组的值元素也是列表。列表可以包含字符串和键/值对元组。
rsonlite.simpleparse()利用rsonlite.loads返回一个具有字典的数据结构。如果可用,则使用有序字典,否则使用标准字典。
当字典不适用或会丢失信息时,返回列表。
异常
就rsonlite而言,大部分输入数据都是好的。让它不高兴的主要是缩进错误,如果它遇到无效的缩进,它将抛出Python IndentationError异常。
示例
我从JSON示例页面那里无耻地借鉴了这些示例的大部分,因为JSON是对比和对比rsonlite的绝佳事物。
示例1
>>> import rsonlite
>>> jsonstr1 = '''
... {
... "glossary": {
... "title": "example glossary",
... "GlossDiv": {
... "title": "S",
... "GlossList": {
... "GlossEntry": {
... "ID": "SGML",
... "SortAs": "SGML",
... "GlossTerm": "Standard Generalized Markup Language",
... "Acronym": "SGML",
... "Abbrev": "ISO 8879:1986",
... "GlossDef": {
... "para": "A meta-markup language",
... "GlossSeeAlso": ["GML", "XML"]
... },
... "GlossSee": "markup"
... }
... }
... }
... }
... }
... '''
>>>
>>> rsonstr1 = '''
... glossary
... title = example glossary
... GlossDiv
... title = S
... GlossList
... GlossEntry
... ID = SGML
... SortAs = SGML
... GlossTerm = Standard Generalized Markup Language
... Acronym = SGML
... Abbrev = ISO 8879:1986
... GlossDef
... para = A meta-markup language
... GlossSeeAlso = [GML, XML]
... GlossSee = markup
... '''
>>>
>>> jsondata1 = eval(jsonstr1)
>>> rsondata1 = rsonlite.simpleparse(rsonstr1)
>>> jsondata1 == rsondata1
True
示例2
>>> jsonstr2 = '''
... {"menu": {
... "id": "file",
... "value": "File",
... "popup": {
... "menuitem": [
... {"value": "New", "onclick": "CreateNewDoc()"},
... {"value": "Open", "onclick": "OpenDoc()"},
... {"value": "Close", "onclick": "CloseDoc()"}
... ]
... }
... }}
... '''
>>>
>>> rsonstr2 = '''
... menu
... id = file
... value = File
... popup
... menuitem
... value = New
... onclick = CreateNewDoc()
... value = Open
... onclick = OpenDoc()
... value = Close
... onclick = CloseDoc()
... '''
>>>
>>> jsondata2 = eval(jsonstr2)
>>> rsondata2 = rsonlite.simpleparse(rsonstr2)
>>> jsondata2 == rsondata2
True
API
rsonlite.loads(source)
这是主要接口。它返回一个元组、字符串和列表的列表,如引言中定义的。
rsonlite.dumps(data, indent=’ ‘, initial_indent=’’)
此函数接受从loads()返回的数据,并将其重新输出为字符串。例如
>>> rsondata1 = rsonlite.loads(rsonstr1) >>> roundtrip = rsonlite.dumps(rsondata1, initial_indent=' ') >>> roundtrip == rsonstr1[1:] # Get past initial \n True >>> rsondata2 = rsonlite.loads(rsonstr2) >>> roundtrip = rsonlite.dumps(rsondata2, initial_indent=' ') >>> roundtrip == rsonstr2[1:] # Get past initial \n True
rsonlite.pretty(data, indent=’ ‘)
此功能以美观的方式打印出由loads()创建的数据结构,以供调试使用。结构准确,但易于阅读
>>> data = rsonlite.loads(rsonstr2)
>>> pretty = rsonlite.pretty(data)
>>> print pretty,
[
('menu', [
('id', ['file']),
('value', ['File']),
('popup', [
('menuitem', [
('value', ['New']),
('onclick', ['CreateNewDoc()']),
('value', ['Open']),
('onclick', ['OpenDoc()']),
('value', ['Close']),
('onclick', ['CloseDoc()']),
])
])
])
]
>>> eval(pretty) == data
True
>>>
rsonlite.simpleparse(source, stringparse=stringparse, stddict=stddict)
这是对loads的简单数据结构的便利包装,并提供loads的示例客户端。这是上面JSON示例部分中使用的接口。参数
- source
source可以是传递给loads的字符串,也可以是列表,假设它是将字符串传递给loads后的结果。
- stringparse
stringparse是一个接受(非键)字符串并返回字符串解析值的函数。rsonlite中的默认stringparse示例将处理JSON关键字true、false和null,还将翻译如上[GML, XML]示例中所示的超简单字符串数组。
- stddict
stddict默认为collections.OrderedDict(如果可用),否则为普通dict。如果您希望,可以替换第三方OrderedDict。
测试
空输入
>>> rsonlite.loads('') == rsonlite.loads(' \n \n \n') == []
True
错误的缩进
>>> rsonlite.loads('a\n b\n c')
Traceback (most recent call last):
File "<doctest README.txt[22]>", line 1, in <module>
rsonlite.loads('a\n b\n c')
File "/home/pat/projects/opensource/rson/lite/rsonlite.py", line 179, in loads
raise err
IndentationError: unindent does not match any outer indentation level (<rsonlite>, line 3)
多行数据,包含特殊字符
>>> teststr = '''
... My key =
... This is indented #=
... This should be at the left edge ===#
... This is indented differently
... '''
>>> test2 = '\n'.join(x[6:] for x in teststr.splitlines()[2:])
>>> rsonlite.loads(teststr) == [('My key', [test2])]
True
>>> teststr = '''
... My key = Something on the first line is at the left edge
... This is indented
... This should be at the left edge
... This is indented differently
... '''
>>> test2 = teststr.split('=', 1)[1].strip().splitlines()
>>> for i in range(1, len(test2)):
... test2[i] = test2[i][6:]
>>> test2 = '\n'.join(test2)
>>> rsonlite.loads(teststr) == [('My key', [test2])]
True
注释和特殊字符串内容
>>> test1 = ''' ... a ... b = 1 ... This is part of b's string ... c ... d = 2 ... ''' >>> test2 = ''' ... # Comments can start anywhere outside a string ... a # Like here (but not below) ... b = 1 ... This is part of b's string ... # This isn't in the string because it's far enough left ... # Any non-key string can start with '=' ... = c ... # This isn't in the string because it's far enough left ... d = 2 ... ''' >>> rsonlite.loads(test1) == rsonlite.loads(test2) True
项目详情
rsonlite-0.1.0.tar.gz的哈希值
| 算法 | 哈希摘要 | |
|---|---|---|
| SHA256 | 90b1ac46bef278f718e2767157a63191e2eb5560d918e3f12779ec4937e386c9 |
|
| MD5 | 4a761a43710d1c0a0cf633dcf18be94d |
|
| BLAKE2b-256 | 160e9a4cb86dd5ec7ac103721ef5701a8d7a02c722d7325a4bf11185a81920af |