Skip to content

Commit 1b91f7c

Browse files
authored
Merge pull request #1 from xpodev/dev/poc
Dev/poc
2 parents 5ccc02e + 1e40d75 commit 1b91f7c

File tree

11 files changed

+706
-0
lines changed

11 files changed

+706
-0
lines changed

README.md

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
# Python RSON
2+
3+
4+
RSON is a superset of the JSON format. It extends JSON with the primary goal of allowing
5+
references in the JSON itself.
6+
7+
In addition to that, RSON also allows:
8+
- [x] Line comments
9+
- [x] Block comments
10+
- [x] Trailing commas
11+
12+
> These are just some nicities are not the primary goal of the RSON format.
13+
14+
15+
## Usage
16+
17+
The RSON format allows references by adding 2 types of tokens:
18+
1. DEF node - defines a `ref-name` for the value
19+
2. REF node - references the given `ref-name`
20+
21+
The `DEF` node can be used on any JSON value. This node defines a name for the value which can then used
22+
to refer to the same value.
23+
The `REF` node can only appear as an *object value* or an *array member*, and is used to refer to a
24+
defined name.
25+
26+
Here is an example of how this would work:
27+
```json
28+
// team.rson
29+
30+
[
31+
{
32+
"members": [
33+
{
34+
"name": "Alice",
35+
"role": $ROLE_DEVELOPER
36+
},
37+
{
38+
"name": "Bob",
39+
"role": $ROLE_MANAGER
40+
},
41+
{
42+
"name": "Charlie",
43+
"role": $ROLE_DESIGNER
44+
}
45+
],
46+
"roles": [
47+
{
48+
"name": "Developer"
49+
}(ROLE_DEVELOPER),
50+
{
51+
"name": "Designer"
52+
}(ROLE_DESIGNER),
53+
{
54+
"name": "Manager"
55+
}(ROLE_MANAGER)
56+
]
57+
}
58+
]
59+
```
60+
61+
We can load the `teams.rson` file with the following code:
62+
```py
63+
from rson import load
64+
65+
with open("teams.rson") as f:
66+
team = load(f)[0]
67+
68+
target_role_name = input("Which role to look for? ")
69+
70+
for role in team["roles"]:
71+
if role["name"].lower() == target_role_name.lower():
72+
target_role = role
73+
break
74+
else:
75+
print("Could not find role " + target_role_name)
76+
exit()
77+
78+
members_with_role = [
79+
member for member in team["members"]
80+
if member["role"] is target_role # <- note the identity check here
81+
]
82+
83+
print(f"Found {len(members_with_role)} members with role {role['name']}:")
84+
for i, member in enumerate(members_with_role):
85+
print(f"\t{i}. {member['name']}")
86+
87+
```
88+
89+
and a sample execution:
90+
```
91+
Which role to look for? developer
92+
Found 2 members with role Developer:
93+
0. Alice
94+
1. David
95+
```
96+
97+
## Specification
98+
99+
The `ref-name` must conform to the following regex:
100+
```re
101+
[A-Za-z_][A-Za-z_0-9]*
102+
```
103+
104+
Or, in plain english:
105+
> The first character must be a valid english letter or an underscore, and the
106+
> following letters must be either an english letter, an underscore or a digit.
107+
> A `ref-name` must have at least 1 character (the first character).
108+
109+
110+
A `DEF` node can be used for every JSON value, so this makes the following
111+
valid as well:
112+
```json
113+
{
114+
"organization": {
115+
"name": "Xpo Development"(ORG_NAME)
116+
},
117+
"title": $ORG_NAME
118+
}
119+
```
120+
121+
122+
## Contributing
123+
124+
Feel free to open an issue or a PR.
125+
126+
## ToDo
127+
128+
- [x] Implement the `load` function
129+
- [x] Implement the `loads` function
130+
- [ ] Implement the `dump` function
131+
- [ ] Implement the `dumps` function

examples/teams.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
from pathlib import Path
2+
3+
from rson import load
4+
5+
6+
HERE = Path(__file__).parent.resolve()
7+
8+
9+
with open(f"{HERE}/teams.rson") as f:
10+
team = load(f)[0]
11+
12+
target_role_name = input("Which role to look for? ")
13+
14+
for role in team["roles"]:
15+
if role["name"].lower() == target_role_name.lower():
16+
target_role = role
17+
break
18+
else:
19+
print("Could not find role " + target_role_name)
20+
exit()
21+
22+
members_with_role = [
23+
member for member in team["members"]
24+
if member["role"] is target_role # <- note the identity check here
25+
]
26+
27+
print(f"Found {len(members_with_role)} members with role {role['name']}:")
28+
for i, member in enumerate(members_with_role):
29+
print(f"\t{i}. {member['name']}")

examples/teams.rson

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
[
2+
{
3+
"members": [
4+
{
5+
"name": "Alice",
6+
"role": $ROLE_DEVELOPER
7+
},
8+
{
9+
"name": "Bob",
10+
"role": $ROLE_MANAGER
11+
},
12+
{
13+
"name": "Charlie",
14+
"role": $ROLE_DESIGNER
15+
},
16+
{
17+
"name": "David",
18+
"role": $ROLE_DEVELOPER
19+
}
20+
],
21+
"roles": [
22+
{
23+
"name": "Developer"
24+
}(ROLE_DEVELOPER),
25+
{
26+
"name": "Designer"
27+
}(ROLE_DESIGNER),
28+
{
29+
"name": "Manager"
30+
}(ROLE_MANAGER)
31+
]
32+
}
33+
]

pyproject.toml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
[project]
2+
name = "python-rson"
3+
authors = [
4+
{ name="Xpo Development", email="[email protected]" },
5+
]
6+
description = "Python implementation of RSON (Reference JSON)"
7+
readme = "README.md"
8+
requires-python = ">=3.8"
9+
classifiers = [
10+
"Programming Language :: Python :: 3",
11+
"License :: OSI Approved :: MIT License",
12+
"Operating System :: OS Independent",
13+
]
14+
dynamic = ["version"]
15+
16+
[project.urls]
17+
Homepage = "https://github.com/xpodev/python-rson"
18+
Issues = "https://github.com/xpodev/python-rson/issues"
19+
20+
[build-system]
21+
requires = ["setuptools", "wheel"]
22+
build-backend = "setuptools.build_meta"
23+
24+
[tool.setuptools]
25+
package-dir = {"" = "src"}
26+
27+
[tool.setuptools.dynamic]
28+
version = {attr="rson.__version__"}

src/rson/__init__.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
from .rson import load
2+
3+
4+
__version__ = "0.1.0"
5+
__author__ = "Xpo Development <[email protected]>"
6+
7+
8+
__all__ = [
9+
"load",
10+
"__version__",
11+
"__author__",
12+
]

0 commit comments

Comments
 (0)