Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat chaotic: allow object in root of file #779

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 40 additions & 2 deletions chaotic/chaotic/front/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import contextlib
import dataclasses
import os
import re
from typing import Dict
from typing import Generator
from typing import List
Expand All @@ -13,6 +14,27 @@
from chaotic.front import types


@dataclasses.dataclass(init=False)
class NameMapItem:
pattern: re.Pattern
dest: str # string for str.format()

def __init__(self, data: str):
groups = data.split('=')
if len(groups) != 2:
raise Exception(f'-n arg must contain "=" ({data})')

pattern, dest = groups
self.pattern = re.compile(pattern)
self.dest = dest

def match(self, data: str) -> Optional[str]:
match = self.pattern.fullmatch(data) # pylint: disable=no-member
if match:
return self.dest.format(*match.groups())
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

давай тут добавим возможность задавать stem (filename without ext), это будет чище и будет расширять возможности уже существующего -n

return None


@dataclasses.dataclass(frozen=True)
class ParserConfig:
erase_prefix: str
Expand All @@ -33,14 +55,17 @@ class ParserError(error.BaseError):

class SchemaParser:
def __init__(
self, *, config: ParserConfig, full_filepath: str, full_vfilepath: str,
self, *, config: ParserConfig,
full_filepath: str, full_vfilepath: str,
plain_object_path_map: List[NameMapItem] = None,
) -> None:
self._config = config
# Full filepath on real filesystem
self.full_filepath: str = full_filepath
# Full filepath on virtual filesystem, used by $ref
self.full_vfilepath: str = full_vfilepath
self._state = ParserState(infile_path='', schemas=dict())
self._plain_object_path_map = plain_object_path_map

def parse_schema(self, infile_path: str, input__: dict) -> None:
self._state.infile_path = ''
Expand Down Expand Up @@ -312,7 +337,20 @@ def _make_abs_ref(self, ref: str) -> str:
return self.full_vfilepath + ref
else:
my_ref = '/'.join(self.full_vfilepath.split('/')[:-1])
file, infile = ref.split('#')
if '#' in ref:
file, infile = ref.split('#')
else:
file = ref
if file.startswith('./'):
file = file[2:]

for item in self._plain_object_path_map:
infile = item.match(ref)
if infile is not None:
infile = infile.rstrip('/')
break
if infile is None:
self._raise(f'Invalid ref without in-file path')
out_file = os.path.join(my_ref, file)
# print(f'ref: {out_file} # {infile}')
return out_file + '#' + infile
Expand Down
50 changes: 24 additions & 26 deletions chaotic/chaotic/main.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
import argparse
import dataclasses
import os
import pathlib
import re
import sys
from typing import Any
from typing import Callable
from typing import Dict
from typing import List
from typing import Optional

import yaml

Expand All @@ -17,27 +14,7 @@
from chaotic.front import parser as front_parser
from chaotic.front import ref_resolver
from chaotic.front import types


@dataclasses.dataclass(init=False)
class NameMapItem:
pattern: re.Pattern
dest: str # string for str.format()

def __init__(self, data: str):
groups = data.split('=')
if len(groups) != 2:
raise Exception(f'-n arg must contain "=" ({data})')

pattern, dest = groups
self.pattern = re.compile(pattern)
self.dest = dest

def match(self, data: str) -> Optional[str]:
match = self.pattern.fullmatch(data) # pylint: disable=no-member
if match:
return self.dest.format(*match.groups())
return None
from chaotic.front.parser import NameMapItem


def parse_args() -> argparse.Namespace:
Expand All @@ -60,6 +37,13 @@ def parse_args() -> argparse.Namespace:
help='full filepath to virtual filepath mapping',
)

parser.add_argument(
'--plain-object-path-map',
type=NameMapItem,
action='append',
help='plain object filepath to in-file path',
)

parser.add_argument(
'-u',
'--userver',
Expand Down Expand Up @@ -174,9 +158,17 @@ def traverse_dfs(path: str, data: Any):

def extract_schemas_to_scan(
inp: dict, name_map: List[NameMapItem],
fname: str, plain_object_path_map: List[NameMapItem],
) -> Dict[str, Any]:
schemas = []

if plain_object_path_map is not None and ('type' in inp) and inp['type'] == 'object':
for item in plain_object_path_map:
path = item.match(fname)
if path is not None:
schemas.append((path, inp))
return dict(schemas)

gen = traverse_dfs('/', inp)
ok_ = None
while True:
Expand All @@ -201,6 +193,7 @@ def read_schemas(
name_map,
file_map,
dependencies: List[types.ResolvedSchemas] = [],
plain_object_path_map: List[NameMapItem] = None,
) -> types.ResolvedSchemas:
config = front_parser.ParserConfig(erase_prefix=erase_path_prefix)
rr = ref_resolver.RefResolver()
Expand All @@ -210,11 +203,12 @@ def read_schemas(
with open(fname) as ifile:
data = yaml.load(ifile, Loader=yaml.CLoader)

scan_objects = extract_schemas_to_scan(data, name_map)
scan_objects = extract_schemas_to_scan(data, name_map, fname, plain_object_path_map)

vfilepath = vfilepath_from_filepath(fname, file_map)
parser = front_parser.SchemaParser(
config=config, full_filepath=fname, full_vfilepath=vfilepath,
plain_object_path_map=plain_object_path_map,
)
for path, obj in rr.sort_json_types(
scan_objects, erase_path_prefix,
Expand Down Expand Up @@ -246,7 +240,11 @@ def main() -> None:
args = parse_args()

schemas = read_schemas(
args.erase_path_prefix, args.file, args.name_map, args.file_map,
erase_path_prefix=args.erase_path_prefix,
filepaths=args.file,
name_map=args.name_map,
file_map=args.file_map,
plain_object_path_map=args.plain_object_path_map,
)
cpp_name_func = generate_cpp_name_func(
args.name_map, args.erase_path_prefix,
Expand Down
Loading