def get_models_from_pysa_file()

in scripts/compare_pysa_models_to_json.py [0:0]


def get_models_from_pysa_file(path: str) -> Dict[str, TargetModel]:
    """
    Process a .pysa file with models in the form of:
        def foo.bar(x: TaintSource[A], b) -> TaintSink[B]: ...
    and return a dictionary of callables and their models in the form:
        {
            'parameters': {'x': {'sources': {'A', ...}, 'sinks': ... }, ...},
            'return_model': {'sources': {}, 'sinks': {'B'}, 'tito': {}}
        }
    IMPORTANT: Note that this only works on .pysa files where:
        1. All the models are self-contained on a single line.
        2. Models do not contain ViaTag[...], AppliesTo[...] syntax

    This script was originally intended to compare models that were generated
    by the existing Python model generators, so it should be noted that
    this will likely not work with most user-defined .pysa files.
    """
    pysa_models: Dict[str, TargetModel] = defaultdict(make_default_target_model)
    skipped = 0
    with Path(path).open() as pysa_file:
        for line in pysa_file:
            # This is a quick hack/heuristic to skip lines with no models in them
            # since regex matching can be more costly.
            if "[" not in line:
                skipped += 1
                continue

            if "def " in line:
                result = get_callable_model_from_line(line)
            else:
                result = get_attribute_model_from_line(line)

            if result:
                name, model = result
                for parameter in model["parameters"]:
                    for model_type in model["parameters"][parameter]:
                        # pyre-fixme[26]: TypedDict key must be a string literal.
                        pysa_models[name]["parameters"][parameter][model_type].update(
                            # pyre-fixme[26]: TypedDict key must be a string literal.
                            model["parameters"][parameter][model_type]
                        )
                pysa_models[name]["parameters"].update(model["parameters"])
                for model_type in model["return_model"]:
                    # pyre-fixme[26]: TypedDict key must be a string literal.
                    pysa_models[name]["return_model"][model_type].update(
                        # pyre-fixme[26]: TypedDict key must be a string literal.
                        model["return_model"][model_type]
                    )
            else:
                skipped += 1

    LOG.warning(f"Skipped {skipped} lines in .pysa (no models found or were invalid).")
    return pysa_models