diff --git a/stone/cli.py b/stone/cli.py index 887bb819..aace9bfb 100644 --- a/stone/cli.py +++ b/stone/cli.py @@ -90,6 +90,11 @@ type=str, help='JSON file containing the exact relative output paths Stone must produce.', ) +_cmdline_parser.add_argument( + '--recursive', + action='store_true', + help='Recursively expand directory specification arguments into .stone files.', +) _cmdline_parser.add_argument( '--clean-build', action='store_true', @@ -145,6 +150,16 @@ help='If set, backends will not see any routes for the specified namespaces.', ) +def _recursive_stone_specs(spec_root): + # type: (str) -> typing.List[str] + spec_paths = [] + for root, _, file_names in os.walk(spec_root): + for file_name in file_names: + if file_name.endswith('.stone'): + spec_paths.append(os.path.join(root, file_name)) + return sorted(spec_paths) + + def _actual_outputs(output_root): # type: (str) -> typing.List[str] outputs = [] @@ -224,6 +239,10 @@ def main(): for spec_path in args.spec: if spec_path == '-': read_from_stdin = True + elif os.path.isdir(spec_path) and args.recursive: + for recursive_spec_path in _recursive_stone_specs(spec_path): + with open(recursive_spec_path, encoding='utf-8') as f: + specs.append((recursive_spec_path, f.read())) elif not spec_path.endswith('.stone'): print("error: Specification '%s' must have a .stone extension." % spec_path, diff --git a/test/test_cli.py b/test/test_cli.py index fce1b36a..8f057db8 100755 --- a/test/test_cli.py +++ b/test/test_cli.py @@ -9,6 +9,7 @@ from stone.cli import ( _actual_outputs, _load_expected_output_manifest, + _recursive_stone_specs, _validate_expected_output_manifest, ) from stone.cli_helpers import parse_route_attr_filter @@ -149,6 +150,23 @@ def test_actual_outputs(self): _actual_outputs(output_root), ['Generated.py', 'nested/Generated.swift']) + def test_recursive_stone_specs(self): + with tempfile.TemporaryDirectory() as spec_root: + os.makedirs(os.path.join(spec_root, 'nested')) + with open(os.path.join(spec_root, 'top.stone'), 'w', encoding='utf-8'): + pass + with open(os.path.join(spec_root, 'nested', 'child.stone'), 'w', encoding='utf-8'): + pass + with open(os.path.join(spec_root, 'nested', 'ignored.txt'), 'w', encoding='utf-8'): + pass + + self.assertEqual( + _recursive_stone_specs(spec_root), + [ + os.path.join(spec_root, 'nested', 'child.stone'), + os.path.join(spec_root, 'top.stone'), + ]) + def test_load_expected_output_manifest(self): with tempfile.NamedTemporaryFile(mode='w', encoding='utf-8') as manifest_file: json.dump(['b.py', 'a.py'], manifest_file)