class API:
@staticmethod
def from_json_file(path: Path) -> API:
with path.open(encoding="utf-8") as api_file:
api_json = json.load(api_file)
return API.from_dict(api_json)
@staticmethod
def from_dict(d: dict[str, Any]) -> API:
result = API(d["distribution"], d["package"], d["version"])
for module_json in d.get("modules", []):
result.add_module(Module.from_dict(module_json))
for class_json in d.get("classes", []):
result.add_class(Class.from_dict(class_json))
for function_json in d.get("functions", []):
result.add_function(Function.from_dict(function_json))
return result
def __init__(self, distribution: str, package: str, version: str) -> None:
self.distribution: str = distribution
self.package: str = package
self.version: str = version
self.modules: dict[str, Module] = {}
self.classes: dict[str, Class] = {}
self.functions: dict[str, Function] = {}
self.attributes_: dict[str, Attribute] | None = None
self.parameters_: dict[str, Parameter] | None = None
self.results_: dict[str, Result] | None = None
def add_module(self, module: Module) -> None:
self.modules[module.id] = module
def add_class(self, class_: Class) -> None:
self.classes[class_.id] = class_
def add_function(self, function: Function) -> None:
self.functions[function.id] = function
def is_public_class(self, class_id: str) -> bool:
return class_id in self.classes and self.classes[class_id].is_public
def is_public_function(self, function_id: str) -> bool:
return function_id in self.functions and self.functions[function_id].is_public
def class_count(self) -> int:
return len(self.classes)
def public_class_count(self) -> int:
return len([it for it in self.classes.values() if it.is_public])
def function_count(self) -> int:
return len(self.functions)
def public_function_count(self) -> int:
return len([it for it in self.functions.values() if it.is_public])
def parameter_count(self) -> int:
return len(self.parameters())
def public_parameter_count(self) -> int:
return len([it for it in self.parameters().values() if it.is_public])
def parameters(self) -> dict[str, Parameter]:
if self.parameters_ is not None:
return self.parameters_
parameters_: dict[str, Parameter] = {}
for function in self.functions.values():
for parameter in function.parameters:
parameter_id = f"{function.id}/{parameter.name}"
parameters_[parameter_id] = parameter
self.parameters_ = parameters_
return parameters_
def attributes(self) -> dict[str, Attribute]:
if self.attributes_ is not None:
return self.attributes_
attributes_: dict[str, Attribute] = {}
for class_ in self.classes.values():
for attribute in class_.instance_attributes:
attribute_id = f"{class_.id}/{attribute.name}"
attributes_[attribute_id] = attribute
self.attributes_ = attributes_
return attributes_
def results(self) -> dict[str, Result]:
if self.results_ is not None:
return self.results_
results_: dict[str, Result] = {}
for function in self.functions.values():
for result in function.results:
result_id = f"{function.id}/{result.name}"
results_[result_id] = result
self.results_ = results_
return results_
def get_default_value(self, parameter_id: str) -> str | None:
function_id = parent_id(parameter_id)
if function_id not in self.functions:
return None
for parameter in self.functions[function_id].parameters:
if parameter.id == parameter_id:
return parameter.default_value
return None
def get_public_api(self) -> API:
result = API(self.distribution, self.package, self.version)
for module in self.modules.values():
result.add_module(module)
for class_ in self.classes.values():
if class_.is_public:
copy = Class(
id=class_.id,
qname=class_.qname,
decorators=class_.decorators,
superclasses=class_.superclasses,
is_public=class_.is_public,
reexported_by=class_.reexported_by,
docstring=class_.docstring,
code=class_.code,
instance_attributes=class_.instance_attributes,
)
for method in class_.methods:
if self.is_public_function(method):
copy.add_method(method)
result.add_class(copy)
for function in self.functions.values():
if function.is_public:
result.add_function(function)
return result
def to_json_file(self, path: Path) -> None:
ensure_file_exists(path)
with path.open("w", encoding="utf-8") as f:
json.dump(self.to_dict(), f, indent=2)
def to_dict(self) -> dict[str, Any]:
return {
"schemaVersion": API_SCHEMA_VERSION,
"distribution": self.distribution,
"package": self.package,
"version": self.version,
"modules": [module.to_dict() for module in sorted(self.modules.values(), key=lambda it: it.id)],
"classes": [class_.to_dict() for class_ in sorted(self.classes.values(), key=lambda it: it.id)],
"functions": [function.to_dict() for function in sorted(self.functions.values(), key=lambda it: it.id)],
}