python-oracle-apex 0.0.1__tar.gz → 0.0.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {python_oracle_apex-0.0.1 → python_oracle_apex-0.0.2}/PKG-INFO +23 -1
- python_oracle_apex-0.0.2/README.md +38 -0
- {python_oracle_apex-0.0.1 → python_oracle_apex-0.0.2}/pyproject.toml +6 -2
- {python_oracle_apex-0.0.1 → python_oracle_apex-0.0.2}/pyproject.toml.orig +3 -1
- python_oracle_apex-0.0.2/src/python_oracle_apex/__init__.py +4 -0
- {python_oracle_apex-0.0.1 → python_oracle_apex-0.0.2}/src/python_oracle_apex/apexlang-26.1.peg +35 -4
- {python_oracle_apex-0.0.1 → python_oracle_apex-0.0.2}/src/python_oracle_apex/objects.py +80 -0
- python_oracle_apex-0.0.2/src/python_oracle_apex/parser.py +47 -0
- python_oracle_apex-0.0.1/src/python_oracle_apex/grammar.py → python_oracle_apex-0.0.2/src/python_oracle_apex/visitor.py +107 -45
- python_oracle_apex-0.0.1/README.md +0 -16
- python_oracle_apex-0.0.1/src/python_oracle_apex/__init__.py +0 -6
- {python_oracle_apex-0.0.1 → python_oracle_apex-0.0.2}/src/python_oracle_apex/reader.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: python-oracle-apex
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.2
|
|
4
4
|
Summary: Parsing files exported from Oracle APEX
|
|
5
5
|
Author: Maurice Koster
|
|
6
6
|
Author-email: Maurice Koster <maurice@mauricekoster.com>
|
|
@@ -20,6 +20,28 @@ Parsing an APEX lang export file into Objects
|
|
|
20
20
|
page = parse_apex("examples/login.apx")
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
+
Better:
|
|
24
|
+
```python
|
|
25
|
+
parser = ApexParser()
|
|
26
|
+
page = parser.parse_file("examples/login.apx")
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Or from a string:
|
|
31
|
+
```python
|
|
32
|
+
parser = ApexParser()
|
|
33
|
+
content = """page A (
|
|
34
|
+
page: 1000
|
|
35
|
+
name: Hello
|
|
36
|
+
alias: HOME
|
|
37
|
+
title: How the West was won
|
|
38
|
+
)
|
|
39
|
+
"""
|
|
40
|
+
page = parser.parse(content)
|
|
41
|
+
assert page.name == "Hello"
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
|
|
23
45
|
## Reading yaml files, pre APEX 26.1
|
|
24
46
|
|
|
25
47
|
```python
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# python-oracle-apex
|
|
2
|
+
Parsing an APEX lang export file into Objects
|
|
3
|
+
|
|
4
|
+
## Oracle APEX
|
|
5
|
+
|
|
6
|
+
## APEXLang - reading .apx files
|
|
7
|
+
|
|
8
|
+
```python
|
|
9
|
+
page = parse_apex("examples/login.apx")
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Better:
|
|
13
|
+
```python
|
|
14
|
+
parser = ApexParser()
|
|
15
|
+
page = parser.parse_file("examples/login.apx")
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Or from a string:
|
|
20
|
+
```python
|
|
21
|
+
parser = ApexParser()
|
|
22
|
+
content = """page A (
|
|
23
|
+
page: 1000
|
|
24
|
+
name: Hello
|
|
25
|
+
alias: HOME
|
|
26
|
+
title: How the West was won
|
|
27
|
+
)
|
|
28
|
+
"""
|
|
29
|
+
page = parser.parse(content)
|
|
30
|
+
assert page.name == "Hello"
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Reading yaml files, pre APEX 26.1
|
|
35
|
+
|
|
36
|
+
```python
|
|
37
|
+
page = parse_yaml("examples/login.yaml")
|
|
38
|
+
```
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "python-oracle-apex"
|
|
3
|
-
version = "0.0.
|
|
3
|
+
version = "0.0.2"
|
|
4
4
|
description = "Parsing files exported from Oracle APEX"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.13"
|
|
@@ -21,4 +21,8 @@ requires = ["uv_build>=0.12.7,<0.13.0"]
|
|
|
21
21
|
build-backend = "uv_build"
|
|
22
22
|
|
|
23
23
|
[dependency-groups]
|
|
24
|
-
dev = [
|
|
24
|
+
dev = [
|
|
25
|
+
"coverage>=7.16.0",
|
|
26
|
+
"pytest>=9.1.1",
|
|
27
|
+
"pytest-cov>=7.1.0",
|
|
28
|
+
]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "python-oracle-apex"
|
|
3
|
-
version = "0.0.
|
|
3
|
+
version = "0.0.2"
|
|
4
4
|
description = "Parsing files exported from Oracle APEX"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
authors = [
|
|
@@ -21,5 +21,7 @@ build-backend = "uv_build"
|
|
|
21
21
|
|
|
22
22
|
[dependency-groups]
|
|
23
23
|
dev = [
|
|
24
|
+
"coverage>=7.16.0",
|
|
24
25
|
"pytest>=9.1.1",
|
|
26
|
+
"pytest-cov>=7.1.0",
|
|
25
27
|
]
|
{python_oracle_apex-0.0.1 → python_oracle_apex-0.0.2}/src/python_oracle_apex/apexlang-26.1.peg
RENAMED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
component = page_object blank_lines
|
|
2
|
+
/ region blank_lines
|
|
3
|
+
/ process blank_lines
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
1
7
|
page_object = indent "page" (required_ws component_id)? ws "(" page_body_line* indent ")" line_end
|
|
2
8
|
page_body_line = page_direct_property_line
|
|
3
9
|
/ page_group_block
|
|
@@ -15,6 +21,7 @@ page_group_block = page_appearance
|
|
|
15
21
|
/ page_css
|
|
16
22
|
/ page_security
|
|
17
23
|
/ page_advanced
|
|
24
|
+
/ page_help
|
|
18
25
|
|
|
19
26
|
page_appearance = indent "appearance" ws "{" line_end page_appearance_property_line* indent "}" line_end
|
|
20
27
|
page_appearance_property_line = indent page_appearance_property line_end
|
|
@@ -53,6 +60,12 @@ page_advanced_property = "enableMetaTags" ":" ws boolean
|
|
|
53
60
|
/ "duplicateSubmissionUrl" ":" ws string_like_value
|
|
54
61
|
|
|
55
62
|
|
|
63
|
+
page_help = indent "help" ws "{" line_end page_help_property_line* indent "}" line_end
|
|
64
|
+
page_help_property_line = indent page_help_property line_end
|
|
65
|
+
page_help_property = "helpText" ":" ws code_block
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
|
|
56
69
|
page_child_component = region
|
|
57
70
|
/ page_item
|
|
58
71
|
/ button
|
|
@@ -270,9 +283,27 @@ process_group_block = process_execution
|
|
|
270
283
|
/ process_source
|
|
271
284
|
/ process_advanced
|
|
272
285
|
|
|
273
|
-
process_source = "
|
|
274
|
-
|
|
275
|
-
|
|
286
|
+
process_source = indent "source" ws "{" line_end process_source_property_line* indent "}" line_end
|
|
287
|
+
process_source_property_line = indent process_source_property line_end
|
|
288
|
+
process_source_property = "location" ":" ws ( "localDatabase" / "restEnabledSql" )
|
|
289
|
+
/ "language" ":" ws ( "plsql" / "javaScript-mle" )
|
|
290
|
+
/ "plsqlCode" ":" ws code_block
|
|
291
|
+
/ "javaScriptCode" ":" ws code_block
|
|
292
|
+
/ "remoteServer" ":" ws reference
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
process_execution = indent "execution" ws "{" line_end process_execution_property_line* indent "}" line_end
|
|
296
|
+
process_execution_property_line = indent process_execution_property line_end
|
|
297
|
+
process_execution_property = "sequence" ":" ws number
|
|
298
|
+
/ "point" ":" ws string_like_value
|
|
299
|
+
/ "runProcess" ":" ws ( "oncePerSessionOrWhenReset" / "oncePerPageVisitDefault" )
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
process_advanced = indent "advanced" ws "{" line_end process_advanced_property_line* indent "}" line_end
|
|
303
|
+
process_advanced_property_line = indent process_advanced_property line_end
|
|
304
|
+
process_advanced_property = "staticId" ":" ws string_like_value
|
|
305
|
+
/ "executionMappingIdentifier" ":" ws string_like_value
|
|
306
|
+
|
|
276
307
|
|
|
277
308
|
|
|
278
309
|
dynamic_action = indent "dynamicAction" (required_ws component_id)? ws "(" line_end dynamic_action_body_line* indent ")" line_end
|
|
@@ -361,7 +392,7 @@ action_c_execution_property = "sequence" ":" ws number
|
|
|
361
392
|
|
|
362
393
|
reference = "@" reference_character*
|
|
363
394
|
component_id = string / identifier / number
|
|
364
|
-
code_block = multiline_string
|
|
395
|
+
code_block = nl? ws multiline_string
|
|
365
396
|
/ string_like_value
|
|
366
397
|
multiline_string = "```" ( any_character / nl )* "```"
|
|
367
398
|
blank_lines = (ws nl)*
|
|
@@ -227,10 +227,90 @@ class ActionExecution(ApexGroup):
|
|
|
227
227
|
class Action(ApexObject):
|
|
228
228
|
pass
|
|
229
229
|
|
|
230
|
+
|
|
231
|
+
class ProcessExecution(ApexGroup):
|
|
232
|
+
@property
|
|
233
|
+
def sequence(self):
|
|
234
|
+
return self['sequence']
|
|
235
|
+
|
|
236
|
+
@property
|
|
237
|
+
def point(self):
|
|
238
|
+
return self['point']
|
|
239
|
+
|
|
240
|
+
@property
|
|
241
|
+
def runProcess(self):
|
|
242
|
+
return self['runProcess']
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
class ProcessAdvanced(ApexGroup):
|
|
246
|
+
@property
|
|
247
|
+
def staticId(self):
|
|
248
|
+
return self['staticId']
|
|
249
|
+
|
|
250
|
+
@property
|
|
251
|
+
def executionMappingIdentifier(self):
|
|
252
|
+
return self['executionMappingIdentifier']
|
|
253
|
+
|
|
254
|
+
class ProcessSource(ApexGroup):
|
|
255
|
+
@property
|
|
256
|
+
def location(self):
|
|
257
|
+
return self['location']
|
|
258
|
+
|
|
259
|
+
@property
|
|
260
|
+
def language(self):
|
|
261
|
+
return self['language']
|
|
262
|
+
|
|
263
|
+
@property
|
|
264
|
+
def remoteServer(self):
|
|
265
|
+
return self['remoteServer']
|
|
266
|
+
|
|
267
|
+
@property
|
|
268
|
+
def plsqlCode(self):
|
|
269
|
+
return self['plsqlCode']
|
|
270
|
+
|
|
230
271
|
class Process(ApexObject):
|
|
231
272
|
def __init__(self, component_id=None, initial_data={}):
|
|
232
273
|
super().__init__(component_id, initial_data)
|
|
233
274
|
|
|
275
|
+
@property
|
|
276
|
+
def name(self):
|
|
277
|
+
return self['name']
|
|
278
|
+
|
|
279
|
+
@property
|
|
280
|
+
def type(self):
|
|
281
|
+
return self['type']
|
|
282
|
+
|
|
283
|
+
@property
|
|
284
|
+
def source(self) -> ProcessSource:
|
|
285
|
+
return self['source']
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
@property
|
|
289
|
+
def execution(self):
|
|
290
|
+
return self['execution']
|
|
291
|
+
|
|
292
|
+
@property
|
|
293
|
+
def advanced(self):
|
|
294
|
+
return self['advanced']
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
class PageAppearance(ApexGroup):
|
|
298
|
+
pass
|
|
299
|
+
|
|
300
|
+
class PageNavigation(ApexGroup):
|
|
301
|
+
pass
|
|
302
|
+
|
|
303
|
+
class PageCss(ApexGroup):
|
|
304
|
+
pass
|
|
305
|
+
|
|
306
|
+
class PageSecurity(ApexGroup):
|
|
307
|
+
pass
|
|
308
|
+
|
|
309
|
+
class PageAdvanced(ApexGroup):
|
|
310
|
+
pass
|
|
311
|
+
|
|
312
|
+
class PageHelp(ApexGroup):
|
|
313
|
+
pass
|
|
234
314
|
|
|
235
315
|
class Page(ApexObject):
|
|
236
316
|
def __init__(self, component_id=None, initial_data={}):
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
from parsimonious import Grammar
|
|
2
|
+
from python_oracle_apex.objects import *
|
|
3
|
+
from importlib import resources as impresources
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
import python_oracle_apex
|
|
8
|
+
from .visitor import ApxNodeVisitor
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class ApexParser:
|
|
12
|
+
def __init__(self, apex_version : str ="26.1"):
|
|
13
|
+
inp_file = impresources.files(python_oracle_apex) / f'apexlang-{apex_version}.peg'
|
|
14
|
+
with inp_file.open("rt") as f:
|
|
15
|
+
template = f.read()
|
|
16
|
+
|
|
17
|
+
self.grammar = Grammar(template)
|
|
18
|
+
self.visitor = ApxNodeVisitor()
|
|
19
|
+
|
|
20
|
+
def parse(self, data):
|
|
21
|
+
nodes = self.grammar.parse(data)
|
|
22
|
+
output = self.visitor.visit(nodes)
|
|
23
|
+
return output
|
|
24
|
+
|
|
25
|
+
def parse_file(self, apex_file: str | Path):
|
|
26
|
+
if type(apex_file) is str:
|
|
27
|
+
fn = Path(apex_file)
|
|
28
|
+
else:
|
|
29
|
+
fn = apex_file
|
|
30
|
+
with fn.open('r') as f:
|
|
31
|
+
data = f.read()
|
|
32
|
+
|
|
33
|
+
return self.parse(data)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def parse_apex_file(apex_file: str | Path, apex_version : str = "26.1") -> ApexObject:
|
|
37
|
+
return ApexParser(apex_version).parse_file(apex_file)
|
|
38
|
+
|
|
39
|
+
def parse_apex(data: str, apex_version : str = "26.1") -> ApexObject:
|
|
40
|
+
return ApexParser(apex_version).parse(data)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
if __name__ == '__main__': # pragma: no cover
|
|
45
|
+
apex_object = parse_apex_file("examples/test.apx")
|
|
46
|
+
|
|
47
|
+
print(apex_object)
|
|
@@ -9,6 +9,10 @@ class RuleNotImplemented(BaseException):
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class ApxNodeVisitor(NodeVisitor):
|
|
12
|
+
|
|
13
|
+
def visit_component(self, node, visited_children):
|
|
14
|
+
return visited_children[0][0]
|
|
15
|
+
|
|
12
16
|
def visit_page_object(self, node, visited_children):
|
|
13
17
|
""" Gets the section name. """
|
|
14
18
|
component_id = visited_children[2]
|
|
@@ -23,6 +27,8 @@ class ApxNodeVisitor(NodeVisitor):
|
|
|
23
27
|
if type(item) is tuple:
|
|
24
28
|
if type(item[1]) is dict:
|
|
25
29
|
page.add_group(item[0], item[1])
|
|
30
|
+
elif isinstance(item[1], ApexGroup):
|
|
31
|
+
page.add_group(item[0], item[1])
|
|
26
32
|
else:
|
|
27
33
|
page.add_property(item[0], item[1])
|
|
28
34
|
elif isinstance(item, ApexObject):
|
|
@@ -63,7 +69,7 @@ class ApxNodeVisitor(NodeVisitor):
|
|
|
63
69
|
d[item[0]] = item[1]
|
|
64
70
|
else:
|
|
65
71
|
raise RuleNotImplemented()
|
|
66
|
-
return ('appearance', d)
|
|
72
|
+
return ('appearance', PageAppearance(d))
|
|
67
73
|
|
|
68
74
|
def visit_page_appearance_property_line(self, node, visited_children):
|
|
69
75
|
return visited_children[1]
|
|
@@ -81,7 +87,7 @@ class ApxNodeVisitor(NodeVisitor):
|
|
|
81
87
|
d[item[0]] = item[1]
|
|
82
88
|
else:
|
|
83
89
|
raise RuleNotImplemented()
|
|
84
|
-
return ('navigation', d)
|
|
90
|
+
return ('navigation', PageNavigation(d))
|
|
85
91
|
|
|
86
92
|
def visit_page_navigation_property_line(self, node, visited_children):
|
|
87
93
|
return visited_children[1]
|
|
@@ -103,7 +109,7 @@ class ApxNodeVisitor(NodeVisitor):
|
|
|
103
109
|
d[item[0]] = item[1]
|
|
104
110
|
else:
|
|
105
111
|
raise RuleNotImplemented()
|
|
106
|
-
return ('css', d)
|
|
112
|
+
return ('css', PageCss(d))
|
|
107
113
|
|
|
108
114
|
def visit_page_css_property_line(self, node, visited_children):
|
|
109
115
|
return visited_children[1]
|
|
@@ -125,7 +131,7 @@ class ApxNodeVisitor(NodeVisitor):
|
|
|
125
131
|
d[item[0]] = item[1]
|
|
126
132
|
else:
|
|
127
133
|
raise RuleNotImplemented()
|
|
128
|
-
return ('security', d)
|
|
134
|
+
return ('security', PageSecurity(d))
|
|
129
135
|
|
|
130
136
|
def visit_page_security_property_line(self, node, visited_children):
|
|
131
137
|
return visited_children[1]
|
|
@@ -149,7 +155,7 @@ class ApxNodeVisitor(NodeVisitor):
|
|
|
149
155
|
d[item[0]] = item[1]
|
|
150
156
|
else:
|
|
151
157
|
raise RuleNotImplemented()
|
|
152
|
-
return ('advanced', d)
|
|
158
|
+
return ('advanced', PageAdvanced(d))
|
|
153
159
|
|
|
154
160
|
def visit_page_advanced_property_line(self, node, visited_children):
|
|
155
161
|
return visited_children[1]
|
|
@@ -165,6 +171,23 @@ class ApxNodeVisitor(NodeVisitor):
|
|
|
165
171
|
case _:
|
|
166
172
|
raise RuleNotImplemented()
|
|
167
173
|
|
|
174
|
+
def visit_page_help(self, node, visited_children):
|
|
175
|
+
parts = visited_children[5]
|
|
176
|
+
d = {}
|
|
177
|
+
for item in parts:
|
|
178
|
+
if type(item) is tuple:
|
|
179
|
+
d[item[0]] = item[1]
|
|
180
|
+
else:
|
|
181
|
+
raise RuleNotImplemented()
|
|
182
|
+
return ('help', PageHelp(d))
|
|
183
|
+
|
|
184
|
+
def visit_page_help_property_line(self, node, visited_children):
|
|
185
|
+
return visited_children[1]
|
|
186
|
+
|
|
187
|
+
def visit_page_help_property(self, node, visited_children):
|
|
188
|
+
v = visited_children[0]
|
|
189
|
+
return (v.text, visited_children[3])
|
|
190
|
+
|
|
168
191
|
|
|
169
192
|
def visit_region(self, node, visited_children):
|
|
170
193
|
component_id = visited_children[2]
|
|
@@ -881,12 +904,89 @@ class ApxNodeVisitor(NodeVisitor):
|
|
|
881
904
|
return visited_children[0]
|
|
882
905
|
|
|
883
906
|
|
|
907
|
+
def visit_process_source(self, node, visited_children):
|
|
908
|
+
parts = visited_children[5]
|
|
909
|
+
d = {}
|
|
910
|
+
for item in parts:
|
|
911
|
+
if type(item) is tuple:
|
|
912
|
+
d[item[0]] = item[1]
|
|
913
|
+
else:
|
|
914
|
+
raise RuleNotImplemented()
|
|
915
|
+
return ('source', ProcessSource(d) )
|
|
916
|
+
|
|
917
|
+
def visit_process_source_property_line(self, node, visited_children):
|
|
918
|
+
return visited_children[1]
|
|
919
|
+
|
|
920
|
+
def visit_process_source_property(self, node, visited_children):
|
|
921
|
+
v = visited_children[0]
|
|
922
|
+
|
|
923
|
+
title, _, _, value = v
|
|
924
|
+
match title.text:
|
|
925
|
+
case 'location' | 'language':
|
|
926
|
+
value = value[0].text
|
|
927
|
+
return (title.text, value)
|
|
928
|
+
|
|
929
|
+
|
|
930
|
+
|
|
931
|
+
def visit_process_execution(self, node, visited_children):
|
|
932
|
+
parts = visited_children[5]
|
|
933
|
+
d = {}
|
|
934
|
+
for item in parts:
|
|
935
|
+
if type(item) is tuple:
|
|
936
|
+
d[item[0]] = item[1]
|
|
937
|
+
else:
|
|
938
|
+
raise RuleNotImplemented()
|
|
939
|
+
return ('execution', ProcessExecution(d) )
|
|
940
|
+
|
|
941
|
+
def visit_process_execution_property_line(self, node, visited_children):
|
|
942
|
+
return visited_children[1]
|
|
943
|
+
|
|
944
|
+
def visit_process_execution_property(self, node, visited_children):
|
|
945
|
+
v = visited_children[0]
|
|
946
|
+
|
|
947
|
+
title, _, _, value = v
|
|
948
|
+
if title.text == 'runProcess':
|
|
949
|
+
value = value[0].text
|
|
950
|
+
return (title.text, value)
|
|
951
|
+
|
|
952
|
+
|
|
953
|
+
def visit_process_advanced(self, node, visited_children):
|
|
954
|
+
parts = visited_children[5]
|
|
955
|
+
d = {}
|
|
956
|
+
for item in parts:
|
|
957
|
+
if type(item) is tuple:
|
|
958
|
+
d[item[0]] = item[1]
|
|
959
|
+
else:
|
|
960
|
+
raise RuleNotImplemented()
|
|
961
|
+
return ('advanced', ProcessAdvanced(d) )
|
|
962
|
+
|
|
963
|
+
def visit_process_advanced_property_line(self, node, visited_children):
|
|
964
|
+
return visited_children[1]
|
|
965
|
+
|
|
966
|
+
def visit_process_advanced_property(self, node, visited_children):
|
|
967
|
+
v = visited_children[0]
|
|
968
|
+
|
|
969
|
+
title, _, _, value = v
|
|
970
|
+
return (title.text, value)
|
|
971
|
+
|
|
972
|
+
|
|
973
|
+
|
|
884
974
|
def visit_reference(self, node, visited_children):
|
|
885
975
|
return node.text
|
|
886
976
|
|
|
887
977
|
|
|
888
978
|
def visit_code_block(self, node, visited_children):
|
|
889
|
-
|
|
979
|
+
if type(visited_children[0]) is str:
|
|
980
|
+
return visited_children[0]
|
|
981
|
+
|
|
982
|
+
indent_len = len(visited_children[0][1])
|
|
983
|
+
lines = visited_children[0][2].split("\n")
|
|
984
|
+
if indent_len == 0:
|
|
985
|
+
indent_len = lines[-1].find('```')
|
|
986
|
+
code = [lines[0]]
|
|
987
|
+
for line in lines[1:]:
|
|
988
|
+
code.append(line[indent_len:])
|
|
989
|
+
return "\n".join(code)
|
|
890
990
|
|
|
891
991
|
def visit_multiline_string(self, node, visited_children):
|
|
892
992
|
return node.text
|
|
@@ -925,7 +1025,7 @@ class ApxNodeVisitor(NodeVisitor):
|
|
|
925
1025
|
return None
|
|
926
1026
|
|
|
927
1027
|
def visit_ws(self, node, visited_children):
|
|
928
|
-
return
|
|
1028
|
+
return node.text
|
|
929
1029
|
|
|
930
1030
|
def visit_blank_lines(self, node, visited_children):
|
|
931
1031
|
return None
|
|
@@ -934,41 +1034,3 @@ class ApxNodeVisitor(NodeVisitor):
|
|
|
934
1034
|
def generic_visit(self, node, visited_children):
|
|
935
1035
|
""" The generic visit method. """
|
|
936
1036
|
return visited_children or node
|
|
937
|
-
|
|
938
|
-
def parse_apex_file(apex_file: str | Path, apex_version : str = "26.1") -> ApexObject:
|
|
939
|
-
if type(apex_file) is str:
|
|
940
|
-
fn = Path(apex_file)
|
|
941
|
-
else:
|
|
942
|
-
fn = apex_file
|
|
943
|
-
with fn.open('r') as f:
|
|
944
|
-
data = f.read()
|
|
945
|
-
|
|
946
|
-
return parse_apex(data, apex_version)
|
|
947
|
-
|
|
948
|
-
def parse_apex(data: str, apex_version : str = "26.1") -> ApexObject:
|
|
949
|
-
inp_file = impresources.files(python_oracle_apex) / f'apexlang-{apex_version}.peg'
|
|
950
|
-
with inp_file.open("rt") as f:
|
|
951
|
-
template = f.read()
|
|
952
|
-
|
|
953
|
-
grammar = Grammar(template)
|
|
954
|
-
|
|
955
|
-
nodes = grammar.parse(data)
|
|
956
|
-
|
|
957
|
-
visitor = ApxNodeVisitor()
|
|
958
|
-
output = visitor.visit(nodes)
|
|
959
|
-
return output
|
|
960
|
-
|
|
961
|
-
if __name__ == '__main__': # pragma: no cover
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
page = parse_apex(
|
|
966
|
-
"""page A (
|
|
967
|
-
)
|
|
968
|
-
""")
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
print(page)
|
|
973
|
-
|
|
974
|
-
print(page.appearance)
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
# python-oracle-apex
|
|
2
|
-
Parsing an APEX lang export file into Objects
|
|
3
|
-
|
|
4
|
-
## Oracle APEX
|
|
5
|
-
|
|
6
|
-
## APEXLang - reading .apx files
|
|
7
|
-
|
|
8
|
-
```python
|
|
9
|
-
page = parse_apex("examples/login.apx")
|
|
10
|
-
```
|
|
11
|
-
|
|
12
|
-
## Reading yaml files, pre APEX 26.1
|
|
13
|
-
|
|
14
|
-
```python
|
|
15
|
-
page = parse_yaml("examples/login.yaml")
|
|
16
|
-
```
|
|
File without changes
|