Skip to content

Commit

Permalink
[cdd/tests/test_shared/test_ast_utils.py] Test `construct_module_with…
Browse files Browse the repository at this point in the history
…_symbols` ; [cdd/compound/exmod_utils.py] Remove unused function call ; [cdd/shared/ast_utils.py] Comment out implementation ; [cdd/shared/pure_utils.py] Remove unused function `no_magic_or_builtin_dir2attr` ; [cdd/__init__.py] Bump version
  • Loading branch information
SamuelMarks committed Jul 11, 2023
1 parent c0fb33b commit 10bc935
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 76 deletions.
2 changes: 1 addition & 1 deletion cdd/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from logging import getLogger as get_logger

__author__ = "Samuel Marks"
__version__ = "0.0.99rc6"
__version__ = "0.0.99rc7"
__description__ = (
"Open API to/fro routes, models, and tests. "
"Convert between docstrings, classes, methods, argparse, pydantic, and SQLalchemy."
Expand Down
17 changes: 8 additions & 9 deletions cdd/compound/exmod_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
from cdd.shared.pkg_utils import relative_filename
from cdd.shared.pure_utils import (
INIT_FILENAME,
no_magic_or_builtin_dir2attr,
read_file_to_str,
rpartial,
sanitise_emit_name,
Expand Down Expand Up @@ -59,12 +58,12 @@ def get_module_contents(obj, module_root_dir, current_module=None, _result={}):
module_root_dir_init = path.join(
module_root_dir, "__init__{extsep}py".format(extsep=path.extsep)
)
process_module_contents = partial(
_process_module_contents,
_result=_result,
current_module=current_module,
module_root_dir=module_root_dir,
)
# process_module_contents = partial(
# _process_module_contents,
# _result=_result,
# current_module=current_module,
# module_root_dir=module_root_dir,
# )
if path.isfile(module_root_dir):
with open(module_root_dir, "rt") as f:
mod = ast.parse(f.read())
Expand Down Expand Up @@ -141,8 +140,8 @@ def get_module_contents(obj, module_root_dir, current_module=None, _result={}):
# assert not isinstance(
# obj, (int, float, complex, str, bool, type(None))
# ), "module is unexpected type: {!r}".format(type(obj).__name__)
for name, symbol in no_magic_or_builtin_dir2attr(obj).items():
process_module_contents(name=name, symbol=symbol)
# for name, symbol in no_magic_or_builtin_dir2attr(obj).items():
# process_module_contents(name=name, symbol=symbol)
return _result


Expand Down
82 changes: 41 additions & 41 deletions cdd/shared/ast_utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
ast_utils, bunch of helpers for converting input into ast.* input_str
ast_utils, a bunch of helpers for converting input into ast.* input_str
"""

import ast
Expand Down Expand Up @@ -1668,46 +1668,46 @@ def merge_modules(mod0, mod1, remove_imports_from_second=True, deduplicate_names
if remove_imports_from_second
else deepcopy(mod1_body)
)
if deduplicate_names:

def unique_nodes(node):
"""
:param node: AST node
:type node: ```AST```
:return: node if name is in `seen` set else None; with side-effect of adding to `seen`
:rtype: ```bool```
"""

def side_effect_ret(name):
"""
:param name: Name
:type name: ```str```
:return: node if name is in `seen` set else None; with side-effect of adding to `seen`
:rtype: ```bool```
"""
if name in seen:
return None
else:
seen.add(node.name)
return node

if isinstance(node, (FunctionDef, AsyncFunctionDef, ClassDef)):
return side_effect_ret(node.name)
elif isinstance(node, AnnAssign):
return side_effect_ret(get_value(node.target))
elif isinstance(node, Assign):
return any(
filter(
lambda target: side_effect_ret(get_value(target)), node.targets
)
)
else:
return node

seen = set()
new_mod.body = list(filter(None, map(unique_nodes, new_mod.body)))
# if deduplicate_names:
#
# def unique_nodes(node):
# """
# :param node: AST node
# :type node: ```AST```
#
# :return: node if name is in `seen` set else None; with side-effect of adding to `seen`
# :rtype: ```bool```
# """
#
# def side_effect_ret(name):
# """
# :param name: Name
# :type name: ```str```
#
# :return: node if name is in `seen` set else None; with side-effect of adding to `seen`
# :rtype: ```bool```
# """
# if name in seen:
# return None
# else:
# seen.add(node.name)
# return node
#
# if isinstance(node, (FunctionDef, AsyncFunctionDef, ClassDef)):
# return side_effect_ret(node.name)
# elif isinstance(node, AnnAssign):
# return side_effect_ret(get_value(node.target))
# elif isinstance(node, Assign):
# return any(
# filter(
# lambda target: side_effect_ret(get_value(target)), node.targets
# )
# )
# else:
# return node
#
# seen = set()
# new_mod.body = list(filter(None, map(unique_nodes, new_mod.body)))

return new_mod

Expand Down
23 changes: 0 additions & 23 deletions cdd/shared/pure_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
from sys import stderr, version_info
from textwrap import fill as _fill
from textwrap import indent
from types import BuiltinFunctionType
from typing import Callable, Dict, FrozenSet, Optional, Tuple, Union

pp: Callable[[object], None] = PrettyPrinter(indent=4, width=100, stream=stderr).pprint
Expand Down Expand Up @@ -1120,27 +1119,6 @@ def default(self, obj):
)


def no_magic_or_builtin_dir2attr(p_object):
"""
Dictionary of `dir` without the __ prefix magics (also without _ prefix)
and without builtins
return the names comprising (some of) the attributes
of the given object, and of attributes reachable from it.
:param p_object: Object
:type p_object: ```Any```
:return: Dict of name to attribute value
:rtype: ```dict```
"""
return {
attr: getattr(p_object, attr)
for attr in dir(p_object)
if not attr.startswith("_")
and not isinstance(getattr(p_object, attr), BuiltinFunctionType)
}


def pascal_to_upper_camelcase(s):
"""
Transform pascal input to upper camelcase
Expand Down Expand Up @@ -1261,7 +1239,6 @@ def namespaced_upper_camelcase_to_pascal(s, sep="__"):
"multiline",
"namespaced_pascal_to_upper_camelcase",
"namespaced_upper_camelcase_to_pascal",
"no_magic_or_builtin_dir2attr",
"none_types",
"num_of_nls",
"omit_whitespace",
Expand Down
2 changes: 2 additions & 0 deletions cdd/tests/mocks/methods.py
Original file line number Diff line number Diff line change
Expand Up @@ -659,6 +659,8 @@ def add_6_5(*, a=6, b=5):
arguments_args=None,
identifier_name=None,
stmt=None,
lineno=None,
returns=None,
)

function_default_complex_default_arg_str = (
Expand Down
29 changes: 27 additions & 2 deletions cdd/tests/test_shared/test_ast_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
annotate_ancestry,
ast_type_to_python_type,
cmp_ast,
construct_module_with_symbols,
del_ass_where_name,
emit_ann_assign,
emit_arg,
Expand Down Expand Up @@ -70,13 +71,14 @@
from cdd.shared.pure_utils import PY3_8, PY_GTE_3_8, tab
from cdd.shared.source_transformer import ast_parse
from cdd.tests.mocks.argparse import argparse_add_argument_expr
from cdd.tests.mocks.classes import class_ast, class_str
from cdd.tests.mocks.doctrans import function_type_annotated
from cdd.tests.mocks.classes import class_ast, class_doc_str_expr, class_str
from cdd.tests.mocks.doctrans import ann_assign_with_annotation, function_type_annotated
from cdd.tests.mocks.gen import import_star_from_input_ast
from cdd.tests.mocks.methods import (
class_with_method_and_body_types_ast,
class_with_method_and_body_types_str,
class_with_optional_arg_method_ast,
function_adder_ast,
function_adder_str,
)
from cdd.tests.mocks.sqlalchemy import config_decl_base_ast
Expand Down Expand Up @@ -133,6 +135,29 @@ def test_cmp_ast(self) -> None:
"""Test `cmp_ast` branch that isn't tested anywhere else"""
self.assertFalse(cmp_ast(None, 5))

def test_construct_module_with_symbols(self) -> None:
"""Tests `construct_module_with_symbols` creates a Module with symbols"""
run_ast_test(
self,
gen_ast=construct_module_with_symbols(
Module(
body=[
class_doc_str_expr,
ann_assign_with_annotation,
function_adder_ast,
],
type_ignores=[],
stmt=None,
),
("add_6_5",),
),
gold=Module(
body=[function_adder_ast],
type_ignores=[],
stmt=None,
),
)

def test_emit_ann_assign(self) -> None:
"""Tests that AnnAssign is emitted from `emit_ann_assign`"""
self.assertIsInstance(class_ast.body[1], AnnAssign)
Expand Down

0 comments on commit 10bc935

Please sign in to comment.