Skip to content

Commit edca912

Browse files
committed
Add 'this_dir' argument file token
1 parent 8ce47eb commit edca912

File tree

10 files changed

+106
-43
lines changed

10 files changed

+106
-43
lines changed

docs/argfiles.rst

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
Argument Files
2+
==============
3+
4+
PeakRDL supports reading argument files using the ``-f FILE`` flag.
5+
Argument files can be used to provide source file lists, or to simply reduce the
6+
amount of text provided in the command-line.
7+
8+
Argument files contain additional command-line text, as well as a few other
9+
things described below.
10+
11+
12+
Comments
13+
--------
14+
Anything after a ``#`` character is treated as a comment and is discarded.
15+
16+
17+
Nested -f Flags
18+
---------------
19+
Argument files can include other additional argument files by using the ``-f``
20+
flag.
21+
22+
23+
Environment Variables
24+
---------------------
25+
Argument files can contain references to environment variables. Both
26+
``$VAR_NAME`` and ``${VAR_NAME}`` styles are supported.
27+
28+
29+
Anchor to current directory
30+
---------------------------
31+
If referencing files that are relative to an argument file, the
32+
``${{this_dir}}`` token can be used. This token expands to the directory path
33+
that contains the current agument file.

docs/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ Links
4949

5050
self
5151
gallery
52+
argfiles
5253
processing-input
5354
configuring
5455
licensing

docs/licensing.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ licensed individually.
2525

2626

2727
What is exempt from the LGPL v3 license?
28-
---------------------------------------
28+
----------------------------------------
2929
Don't worry. Not everything that the PeakRDL project touches is considered
3030
LGPL v3 code.
3131

peakrdl-cli/src/peakrdl/argfile.py

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,35 @@
44
import re
55
from typing import List, Optional, Set, Match
66

7-
def expand_tokens(argv: List[str]) -> List[str]:
7+
def expand_tokens(argv: List[str], path) -> List[str]:
88
"""
99
Expand environment variables in args
1010
"""
11-
pattern = re.compile(r"\$(\w+|\{[^}]*\})")
12-
def repl(m: Match) -> str:
13-
k = m.group(1)
14-
if k.startswith("{") and k.endswith("}"):
15-
k = k[1:-1]
11+
token_queries = [
12+
("cwd", r"\$\{\{this_dir\}\}"), # ${{this_dir}}
13+
("env1", r"\$(\w+)"), # $ENV_VAR
14+
("env2", r"\$\{(\w+)\}"), # ${ENV_VAR}
15+
]
16+
token_regex = re.compile(
17+
'|'.join('(?P<%s>%s)' % pair for pair in token_queries)
18+
)
1619

17-
v = os.environ.get(k, m.group(0))
18-
return v
20+
def repl(m: Match) -> str:
21+
if m.lastgroup in {"env1", "env2"}:
22+
k = m.group(m.lastindex + 1)
23+
if k in os.environ:
24+
v = os.environ.get(k)
25+
else:
26+
print(f"warning: environment variable '{k}' is not set", file=sys.stderr)
27+
v = ""
28+
return v
29+
elif m.lastgroup == "cwd":
30+
this_dir = os.path.normpath(os.path.dirname(path))
31+
return this_dir
32+
else:
33+
raise RuntimeError
1934

20-
return [pattern.sub(repl, arg) for arg in argv]
35+
return [token_regex.sub(repl, arg) for arg in argv]
2136

2237

2338
def parse_argfile(path: str) -> List[str]:
@@ -27,7 +42,7 @@ def parse_argfile(path: str) -> List[str]:
2742

2843
with open(path, "r", encoding='utf-8') as f:
2944
args = shlex.split(f.read(), comments=True)
30-
args = expand_tokens(args)
45+
args = expand_tokens(args, path)
3146
return args
3247

3348

test/test_argfile.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import os
2+
from unittest_utils import PeakRDLTestcase
3+
4+
class TestArgfile(PeakRDLTestcase):
5+
def do_argfile_test(self, filename: str):
6+
os.environ["PEAKRDL_TOP_TEST_ENVVAR"] = "nested"
7+
self.run_commandline([
8+
'-f', os.path.join(self.testdata_dir, filename),
9+
])
10+
captured = self.capsys.readouterr()
11+
expected = "\n".join([
12+
"0x00-0x03: nested.rf_inst.r_inst1",
13+
"0x04-0x07: nested.rf_inst.r_inst2",
14+
"0x08-0x0b: nested.r1_inst",
15+
"0x0c-0x0f: nested.r1_inst2",
16+
"",
17+
])
18+
self.assertEqual(captured.out, expected)
19+
20+
def test_env1(self):
21+
self.do_argfile_test("dump_nested_env1.f")
22+
23+
def test_env2(self):
24+
self.do_argfile_test("dump_nested_env2.f")
25+
26+
def test_this_dir(self):
27+
self.do_argfile_test("dump_nested_this_dir.f")
28+
29+
def test_err_dne(self):
30+
self.run_commandline([
31+
'-f', os.path.join(self.testdata_dir, "dne.f"),
32+
], expects_error=True)
33+
34+
def test_err_missing(self):
35+
self.run_commandline([
36+
'-f',
37+
], expects_error=True)
38+
39+
def test_err_circular(self):
40+
self.run_commandline([
41+
'-f', os.path.join(self.testdata_dir, "circular.f"),
42+
], expects_error=True)

test/test_basics.py

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -59,34 +59,3 @@ def test_input_dne(self):
5959
'dump',
6060
os.path.join(self.testdata_dir, "this_file_doesnt_exist.rdl"),
6161
], expects_error=True)
62-
63-
def test_f_argfile(self):
64-
os.environ["PEAKRDL_TOP_TEST_ENVVAR"] = "nested"
65-
self.run_commandline([
66-
'-f', os.path.join(self.testdata_dir, "dump_nested.f"),
67-
])
68-
captured = self.capsys.readouterr()
69-
expected = "\n".join([
70-
"0x00-0x03: nested.rf_inst.r_inst1",
71-
"0x04-0x07: nested.rf_inst.r_inst2",
72-
"0x08-0x0b: nested.r1_inst",
73-
"0x0c-0x0f: nested.r1_inst2",
74-
"",
75-
])
76-
self.assertEqual(captured.out, expected)
77-
78-
def test_f_argfile_errors(self):
79-
with self.subTest("file DNE"):
80-
self.run_commandline([
81-
'-f', os.path.join(self.testdata_dir, "dne.f"),
82-
], expects_error=True)
83-
84-
with self.subTest("file missing"):
85-
self.run_commandline([
86-
'-f',
87-
], expects_error=True)
88-
89-
with self.subTest("circular ref"):
90-
self.run_commandline([
91-
'-f', os.path.join(self.testdata_dir, "circular.f"),
92-
], expects_error=True)

test/testdata/dump_nested.f

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
dump testdata/parameters.rdl --top ${PEAKRDL_TOP_TEST_ENVVAR}
1+
dump testdata/parameters.rdl --top nested

test/testdata/dump_nested_env1.f

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
dump testdata/parameters.rdl --top $PEAKRDL_TOP_TEST_ENVVAR

test/testdata/dump_nested_env2.f

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
dump testdata/parameters.rdl --top ${PEAKRDL_TOP_TEST_ENVVAR}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
dump ${{this_dir}}/parameters.rdl --top nested

0 commit comments

Comments
 (0)