Skip to content

Commit de2e547

Browse files
authored
Merge pull request #2 from xnuinside/v0.3.0_release
V0.3.0 release
2 parents 01ba4e0 + b15edf8 commit de2e547

File tree

11 files changed

+609
-43
lines changed

11 files changed

+609
-43
lines changed

CHANGELOG.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
**v0.3.0**
2+
1. Added cli - `pmp` command with args -d, --dump
3+
2. Added support for simple Django ORM models
4+
3. Added base support for pure Python Classes
5+
16
**v0.2.0**
27
1. Added support for Dataclasses
38
2. Added parse_from_file method

README.md

Lines changed: 49 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,19 @@
44

55

66
It's as second Parser that done by me, first is a https://github.com/xnuinside/simple-ddl-parser for SQL DDL with different dialects.
7-
Py-Models-Parser supports now ORM Sqlalchemy, Gino, Tortoise; Pydantic, Python Enum models, Dataclasses & in nearest feature I plan to add pure pyton classes. And next will be added other ORMs models.
7+
8+
Py-Models-Parser can parse & extract information from models:
9+
10+
- Sqlalchemy ORM,
11+
- Gino ORM,
12+
- Tortoise ORM,
13+
- Django ORM Model,
14+
- Pydantic,
15+
- Python Enum,
16+
- Python Dataclasses
17+
- pure Python Classes
18+
19+
Number of supported models will be increased, check 'TODO' section.
820

921
Py-Models-Parser written with PEG parser and it's python implementation - parsimonious. It's pretty new and I did not cover all possible test cases, so if you will have an issue - please just open an issue in this case with example, I will fix it as soon as possible.
1022

@@ -51,7 +63,7 @@ NOTE: it's is a text parser, so it don't import or load your code, parser work w
5163

5264
Library detect automaticaly that type of models you tries to parse. You can check a lot of examples in test/ folder on the GitHub
5365

54-
You can parse models from python string:
66+
1. You can parse models from python string:
5567

5668
```python
5769

@@ -75,7 +87,7 @@ result = parse(models_str)
7587

7688
```
7789

78-
or just provide the path to file:
90+
2. Parse models from file:
7991

8092
```python
8193

@@ -87,7 +99,31 @@ or just provide the path to file:
8799
result = parse_from_file(file_path)
88100
```
89101

90-
It will produce the result:
102+
3. Parse models from file with command line
103+
104+
```bash
105+
106+
pmp path_to_models.py
107+
108+
# for example: pmp tests/data/dataclass_defaults.py
109+
110+
```
111+
112+
Output from cli can be dumped in 'output_models.json' file - use flag '-d' '--dump' if you want to change target file name, provide it after argument like '-d target_file.json'
113+
114+
```bash
115+
116+
# example how to dump output from cli
117+
118+
pmp path_to_models.py -d target_file.json
119+
120+
```
121+
122+
### Output example
123+
124+
You can find a lot of output examples in tests - https://github.com/xnuinside/py-models-parser/tree/main/tests
125+
126+
For model from point 1 (above) library will produce the result:
91127

92128
```python
93129

@@ -132,16 +168,19 @@ It will produce the result:
132168
]
133169
```
134170

135-
136171
## TODO: in next Release
137172

138-
1. Parse from file method
139-
2. Add cli
140-
3. Add more tests for supported models (and fix existed not covered cases): Pydantic, Enums, Dataclasses, SQLAlchemy Models, GinoORM models, TortoiseORM models
141-
4. Add support for pure Python classes
142-
5. Add support for pure SQLAlchemy Core Tables
173+
1. Add more tests for supported models (and fix existed not covered cases): Django ORM, Pydantic, Enums, Dataclasses, SQLAlchemy Models, GinoORM models, TortoiseORM models
174+
2. Add support for SQLAlchemy Core Tables
175+
3. Add support for Pony ORM models
176+
4. Add support for Piccolo ORM models
143177

144178
## Changelog
179+
**v0.3.0**
180+
1. Added cli - `pmp` command with args -d, --dump
181+
2. Added support for simple Django ORM models
182+
3. Added base support for pure Python Classes
183+
145184
**v0.2.0**
146185
1. Added support for Dataclasses
147186
2. Added parse_from_file method

docs/README.rst

Lines changed: 54 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,20 @@ Py-Models-Parser
2121

2222

2323
It's as second Parser that done by me, first is a https://github.com/xnuinside/simple-ddl-parser for SQL DDL with different dialects.
24-
Py-Models-Parser supports now ORM Sqlalchemy, Gino, Tortoise; Pydantic, Python Enum models, Dataclasses & in nearest feature I plan to add pure pyton classes. And next will be added other ORMs models.
24+
25+
Py-Models-Parser can parse & extract information from models:
26+
27+
28+
* Sqlalchemy ORM,
29+
* Gino ORM,
30+
* Tortoise ORM,
31+
* Django ORM Model,
32+
* Pydantic,
33+
* Python Enum,
34+
* Python Dataclasses
35+
* pure Python Classes
36+
37+
Number of supported models will be increased, check 'TODO' section.
2538

2639
Py-Models-Parser written with PEG parser and it's python implementation - parsimonious. It's pretty new and I did not cover all possible test cases, so if you will have an issue - please just open an issue in this case with example, I will fix it as soon as possible.
2740

@@ -69,7 +82,8 @@ How to use
6982

7083
Library detect automaticaly that type of models you tries to parse. You can check a lot of examples in test/ folder on the GitHub
7184

72-
You can parse models from python string:
85+
86+
#. You can parse models from python string:
7387

7488
.. code-block:: python
7589
@@ -92,7 +106,8 @@ You can parse models from python string:
92106
"""
93107
result = parse(models_str)
94108
95-
or just provide the path to file:
109+
110+
#. Parse models from file:
96111

97112
.. code-block:: python
98113
@@ -104,7 +119,31 @@ or just provide the path to file:
104119
# for example: tests/data/dataclass_defaults.py
105120
result = parse_from_file(file_path)
106121
107-
It will produce the result:
122+
123+
#. Parse models from file with command line
124+
125+
.. code-block:: bash
126+
127+
128+
pmp path_to_models.py
129+
130+
# for example: pmp tests/data/dataclass_defaults.py
131+
132+
Output from cli can be dumped in 'output_models.json' file - use flag '-d' '--dump' if you want to change target file name, provide it after argument like '-d target_file.json'
133+
134+
.. code-block:: bash
135+
136+
137+
# example how to dump output from cli
138+
139+
pmp path_to_models.py -d target_file.json
140+
141+
Output example
142+
^^^^^^^^^^^^^^
143+
144+
You can find a lot of output examples in tests - https://github.com/xnuinside/py-models-parser/tree/main/tests
145+
146+
For model from point 1 (above) library will produce the result:
108147

109148
.. code-block:: python
110149
@@ -153,15 +192,21 @@ TODO: in next Release
153192
---------------------
154193

155194

156-
#. Parse from file method
157-
#. Add cli
158-
#. Add more tests for supported models (and fix existed not covered cases): Pydantic, Enums, Dataclasses, SQLAlchemy Models, GinoORM models, TortoiseORM models
159-
#. Add support for pure Python classes
160-
#. Add support for pure SQLAlchemy Core Tables
195+
#. Add more tests for supported models (and fix existed not covered cases): Django ORM, Pydantic, Enums, Dataclasses, SQLAlchemy Models, GinoORM models, TortoiseORM models
196+
#. Add support for SQLAlchemy Core Tables
197+
#. Add support for Pony ORM models
198+
#. Add support for Piccolo ORM models
161199

162200
Changelog
163201
---------
164202

203+
**v0.3.0**
204+
205+
206+
#. Added cli - ``pmp`` command with args -d, --dump
207+
#. Added support for simple Django ORM models
208+
#. Added base support for pure Python Classes
209+
165210
**v0.2.0**
166211

167212

py_models_parser/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
from py_models_parser.core import parse, parse_from_file
1+
from py_models_parser.core import dump_result, parse, parse_from_file
22

3-
__all__ = ["parse", "parse_from_file"]
3+
__all__ = ["parse", "parse_from_file", "dump_result"]

py_models_parser/cli.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import argparse
2+
import os
3+
import pprint
4+
import sys
5+
6+
from py_models_parser import dump_result, parse_from_file
7+
8+
9+
def version(**kwargs):
10+
return "0.2.0"
11+
12+
13+
def cli():
14+
pmp_cli = argparse.ArgumentParser(description="Python Models Parser")
15+
16+
pmp_cli.add_argument(
17+
"file_path", type=str, help="The path to .py file with models to parse"
18+
)
19+
20+
pmp_cli.add_argument(
21+
"-d",
22+
"--dump",
23+
nargs="?",
24+
type=str,
25+
const="output_models.json",
26+
help="Target path to save parse results in .json files",
27+
)
28+
29+
return pmp_cli
30+
31+
32+
def run_for_file(args):
33+
print(f"Start parsing file {args.file_path} \n")
34+
result = parse_from_file(args.file_path)
35+
if args.dump:
36+
dump_result(result, args.dump)
37+
print(f"File with result was saved to >> {args.dump} file")
38+
if not args.dump:
39+
pprint.pprint(result)
40+
41+
42+
def correct_extension(file_name: str) -> bool:
43+
ext = ["ddl", "sql", "hql", ""]
44+
split_name = file_name.split(".")
45+
if len(split_name) >= 2:
46+
ext_file = split_name[1]
47+
if ext_file in ext:
48+
return True
49+
return False
50+
51+
52+
def main():
53+
sdb_cli = cli()
54+
args = sdb_cli.parse_args()
55+
if not os.path.exists(args.file_path):
56+
print("The file path specified does not exist")
57+
sys.exit()
58+
if os.path.isfile(args.file_path):
59+
run_for_file(args)
60+
else:
61+
files = [
62+
os.path.join(args.ddl_file_path, file_name)
63+
for file_name in os.listdir(args.ddl_file_path)
64+
if correct_extension(file_name)
65+
]
66+
for file_path in files:
67+
args.ddl_file_path = file_path
68+
run_for_file(args)

py_models_parser/core.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import json
12
import os
23
from typing import Dict, List
34

@@ -76,3 +77,8 @@ def parse_from_file(file_path: str) -> List[Dict]:
7677
with open(file_path, "r") as f:
7778
models = f.read()
7879
return parse(models)
80+
81+
82+
def dump_result(output: str, file_path: str) -> None:
83+
with open(file_path, "w+") as f:
84+
json.dump(output, f, indent=1)

py_models_parser/grammar.py

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,24 @@
22

33
grammar = Grammar(
44
r"""
5-
expr = (class / call_result / attr_def / emptyline)*
6-
class = class_def attr_def* ws?
5+
expr = (class / call_result / attr_def / emptyline / funct_def)*
6+
class = class_def attr_def* funct_def* ws?
77
class_def = intend? class_name args? ":"* ws?
8-
attr_def = intend? id ("=" right_part)* ws?
9-
right_part = args / call_result / id / string / text
8+
attr_def = intend? id type? ("=" (right_part))* ws?
9+
right_part = (id args_in_brackets) / string / args / call_result / args_in_brackets / id / text
10+
type = ":" ( (id args_in_brackets) / id)
1011
string = one_quote_str / double_quotes_str
11-
one_quote_str = ~"\'[^\']+\'"
12-
double_quotes_str = ~'"[^\"]+"'
12+
one_quote_str = ~"\'[^\']+\'"i
13+
double_quotes_str = ~'"[^\"]+"'i
14+
funct_def = intend? "def" id args? ":"* ws?
15+
args_in_brackets = "[" ((id/string)* ","* )* "]"
1316
args = "(" (( call_result / args / attr_def / id )* ","* )* ")"
1417
call_result = id args ws?
1518
class_name = "class" id
16-
id = (((dot_id / text)+ ","*) * / dot_id / text) ws?
19+
id = (((dot_id / text)+ ) * / dot_id / text) ws?
1720
dot_id = (text".")*text
18-
intend = " " / "\t"
19-
text = !class ~"['\_A-Z 0-9\{\}\[\]_\"\-\/\$:<%>\w]*"i
21+
intend = " " / "\t" / "\n"
22+
text = !class ~"['\_A-Z 0-9\{\}_\"\-\/\$<%>\+\-\w]*"i
2023
ws = ~"\s*"
2124
emptyline = ws+
2225
"""

0 commit comments

Comments
 (0)