Skip to content

Commit eff5ae2

Browse files
committed
T910-014: Improve App
- Allow just subclassing App.process_unit, by providing a default main that iterates on units and calls process_unit on each - Allow passing args to python App programmatically
1 parent 039b5aa commit eff5ae2

File tree

10 files changed

+79
-16
lines changed

10 files changed

+79
-16
lines changed

langkit/templates/python_api/module_py.mako

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1873,16 +1873,26 @@ class App(object):
18731873
"""
18741874
return ""
18751875

1876-
def __init__(self):
1876+
def __init__(self, args=None):
18771877
self.parser = argparse.ArgumentParser(description=self.description)
18781878
self.parser.add_argument('files', nargs='+', help='Files')
18791879
self.add_arguments()
1880-
self.args = self.parser.parse_args()
1880+
1881+
# Parse command line arguments
1882+
self.args = self.parser.parse_args(args)
1883+
18811884
self.ctx = AnalysisContext(
18821885
'utf-8', with_trivia=True,
18831886
unit_provider=self.create_unit_provider()
18841887
)
18851888

1889+
# Parse files
1890+
self.units = {}
1891+
for file_name in self.args.files:
1892+
self.u = self.ctx.get_from_file(file_name)
1893+
self.units[file_name] = self.u
1894+
1895+
18861896
def add_arguments(self):
18871897
"""
18881898
Hook for subclasses to add arguments to self.parser. Default
@@ -1897,23 +1907,26 @@ class App(object):
18971907
"""
18981908
return None
18991909

1900-
def process_files(self):
1910+
def main(self):
19011911
"""
1902-
Load units for all source files on the command-line in `self.units`.
1903-
Put the last one in `self.u`.
1912+
Default implementation for App.main: just iterates on every units and
1913+
call ``process_unit`` on it.
19041914
"""
1905-
self.units = {}
1906-
for file_name in self.args.files:
1907-
self.u = self.ctx.get_from_file(file_name)
1908-
self.units[file_name] = self.u
1915+
for u in sorted(self.units.values(), key=lambda u: u.filename):
1916+
self.process_unit(u)
1917+
1918+
def process_unit(self, unit):
1919+
"""
1920+
Abstract method that processes one unit. Needs to be subclassed by
1921+
implementors.
1922+
"""
1923+
raise NotImplementedError()
19091924

19101925
@classmethod
1911-
def run(cls):
1926+
def run(cls, args=None):
19121927
"""
19131928
Instantiate and run this application.
19141929
"""
1915-
instance = cls()
1916-
instance.process_files()
1917-
instance.main()
1930+
cls(args).main()
19181931

19191932
${exts.include_extension(ctx.ext('python_api/app_exts'))}

langkit/templates/python_api/module_pyi.mako

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -417,12 +417,12 @@ class App(object):
417417
@property
418418
def description(self) -> str: ...
419419

420-
def __init__(self) -> None: ...
420+
def __init__(self, args: Opt[List[str]]) -> None: ...
421421
def add_arguments(self) -> None: ...
422422
def create_unit_provider(self) -> Opt[UnitProvider]: ...
423-
def process_files(self) -> None: ...
423+
def process_unit(self, unit: AnalysisUnit) -> None: ...
424424

425425
@classmethod
426-
def run(cls) -> None: ...
426+
def run(cls, args: Opt[List[str]]=None) -> None: ...
427427

428428
${exts.include_extension(ctx.ext('python_api', 'mypy_app_exts'))}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import lexer_example
2+
@with_lexer(foo_lexer)
3+
grammar foo_grammar {
4+
@main_rule main_rule <- Example("example")
5+
6+
}
7+
8+
@abstract class FooNode : Node {
9+
}
10+
11+
class Example : FooNode implements TokenNode {
12+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
example hello1
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
example hello2
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
example hello3
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import libfoolang as lfl
2+
3+
4+
class App(lfl.App):
5+
def process_unit(self, unit):
6+
unit.root.dump()
7+
8+
9+
if __name__ == '__main__':
10+
App.run(['input3', 'input1', 'input2'])
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Example input1:1:1-1:8: example
2+
Example input2:1:1-1:8: example
3+
Example input3:1:1-1:8: example
4+
Done
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
"""
2+
Test python App class.
3+
"""
4+
5+
from langkit.dsl import ASTNode
6+
7+
from utils import build_and_run
8+
9+
10+
class FooNode(ASTNode):
11+
pass
12+
13+
14+
class Example(FooNode):
15+
token_node = True
16+
17+
18+
build_and_run(lkt_file='expected_concrete_syntax.lkt', py_script='main.py',
19+
types_from_lkt=True)
20+
print('Done')
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
driver: python

0 commit comments

Comments
 (0)