diff --git a/analysis.py b/analysis.py new file mode 100644 index 0000000..df04339 --- /dev/null +++ b/analysis.py @@ -0,0 +1,92 @@ +import ast +import shutil +from typing import List, Tuple +from pprint import pprint +from enum import Enum + + +''' +AST analyzer +''' +class Analyzer(ast.NodeVisitor): + def __init__(self) -> None: + self.stats = { + 'for': 0, + 'import': [], + } + + def visit_For(self, node): + for alias in node.names: + self.stats['for'].append(alias.name) + self.generic_visit(node) + + def visit_Import(self, node): + for alias in node.names: + self.stats["import"].append(alias.name) + self.generic_visit(node) + + def report(self): + pprint(self.stats) + + +''' +Notation format enum +''' +class NotationFormat(Enum): + + BIG_O : str = 'BIG O' + BIG_OMEGA : str = 'BIG Ω (OMEGA)' + BIG_THETA : str = 'BIG Θ (THETA)' + + def __str__(self) -> str: + return str(self.value) + + +''' +Class that contains and represents analysis data +''' +class AnalysisFormatter: + + def __init__( + self, + notation_format: NotationFormat, + func_name: str = 'No name', + func_attrs: List[Tuple[str, str]] | None = None, + complexity: str = '1', + memory: str = '1', + ) -> None: + + self.notation_format = notation_format + self.func_name = func_name + self.func_attrs = func_attrs + self.complexity = complexity + self.memory = memory + + def report(self, full=True): + + print() + + if full: + print('Function name:', self.func_name) + + if self.func_attrs: + print('Function attributes:', ', '.join([f'{attr_name}: {attr_type}' for attr_name, attr_type in self.func_attrs])) + + terminal_width = shutil.get_terminal_size().columns + indent = max((terminal_width - len(self.notation_format.__str__()) - 2)//2, 0) + print('-' * indent + f' {self.notation_format.__str__()} ' + '-' * indent) + + if self.notation_format == NotationFormat.BIG_O: + print('Сomplexity of algorithm: O({})'.format(self.complexity)) + print('Memory of algorithm: O({})'.format(self.memory)) + + if self.notation_format == NotationFormat.BIG_OMEGA: + print('Сomplexity of algorithm: Ω({})'.format(self.complexity)) + print('Memory of algorithm: Ω({})'.format(self.memory)) + + if self.notation_format == NotationFormat.BIG_THETA: + print('Сomplexity of algorithm: Θ({})'.format(self.complexity)) + print('Memory of algorithm: Θ({})'.format(self.memory)) + + print() + \ No newline at end of file diff --git a/notations.py b/notations.py new file mode 100644 index 0000000..05bfa36 --- /dev/null +++ b/notations.py @@ -0,0 +1,109 @@ +import ast +import inspect +from typing import List, Tuple + +<<<<<<<< HEAD:pycomplexity/notations.py +from pycomplexity.analysis import Analyzer, AnalysisFormatter, NotationFormat +======== +from analysis import Analyzer, AnalysisFormatter, NotationFormat +>>>>>>>> b9371afd8058da6c402979f1d0bf20215ea8fbc7:notations.py + + +''' +Base class of asymptotic notation +''' +class AsymptoticNotation: + + def __init__(self, full_report: bool = True) -> None: + self.full_report = full_report + + def _code_to_string(self, func) -> str: + code = inspect.getsource(func) + code_lines = code.split('\n')[1:] + modified_code = '\n'.join(code_lines) + return modified_code + + def _get_ast(self, func) -> ast.Module: + code_str = self._code_to_string(func) + return ast.parse(code_str) + + def analyze(self, func): + analyzer = Analyzer() + tree = self._get_ast(func) + # print(ast.dump(tree, indent=4)) + + for node in ast.walk(tree): + # print(node) + if isinstance(node, ast.FunctionDef): + func_name = node.name + + if isinstance(node, ast.For): + print(node, node.body, node.iter) + + # analyzer.visit(tree) + # analyzer.report() + + return func_name or 'No name', ... + + def report(func): + def wrapper(self, *args, **kwargs): + analysis_formatter: AnalysisFormatter = func(self, *args, **kwargs) + return analysis_formatter.report(full=self.full_report) + return wrapper + + +''' +Implementation of Big O notation +''' +class BigO(AsymptoticNotation): + + def __init__(self) -> None: + super().__init__() + + @AsymptoticNotation.report + def complexity(self, func) -> AnalysisFormatter: + + func_name, _ = self.analyze(func) + + return AnalysisFormatter( + func_name=func_name, + notation_format=NotationFormat.BIG_O, + ) + + +''' +Implementation of Big Omega notation +''' +class BigOmega(AsymptoticNotation): + + def __init__(self) -> None: + super().__init__() + + @AsymptoticNotation.report + def complexity(self, func) -> AnalysisFormatter: + + func_name, _ = self.analyze(func) + + return AnalysisFormatter( + func_name=func_name, + notation_format=NotationFormat.BIG_OMEGA, + ) + + +''' +Implementation of Big Theta notation +''' +class BigTheta(AsymptoticNotation): + + def __init__(self) -> None: + super().__init__() + + @AsymptoticNotation.report + def complexity(self, func) -> AnalysisFormatter: + + func_name, _ = self.analyze(func) + + return AnalysisFormatter( + func_name=func_name, + notation_format=NotationFormat.BIG_THETA, + ) \ No newline at end of file diff --git a/pycomplexity/notations.py b/pycomplexity/notations.py index 2ba38d2..05bfa36 100644 --- a/pycomplexity/notations.py +++ b/pycomplexity/notations.py @@ -2,7 +2,11 @@ import inspect from typing import List, Tuple +<<<<<<<< HEAD:pycomplexity/notations.py from pycomplexity.analysis import Analyzer, AnalysisFormatter, NotationFormat +======== +from analysis import Analyzer, AnalysisFormatter, NotationFormat +>>>>>>>> b9371afd8058da6c402979f1d0bf20215ea8fbc7:notations.py '''