From e13def38c3dc0c7e498d9bf0b88156504ce13304 Mon Sep 17 00:00:00 2001 From: Samuel Marks <807580+SamuelMarks@users.noreply.github.com> Date: Sun, 17 Sep 2023 22:50:31 -0400 Subject: [PATCH] [cdd/tests/mocks/sqlalchemy.py] Add mock for `create_from_attr` ; [cdd/tests/test_sqlalchemy/test_emit_sqlalchemy_utils.py] Add `test_generate_create_from_attr_staticmethod` --- cdd/compound/openapi/utils/emit_utils.py | 1 + cdd/tests/mocks/sqlalchemy.py | 94 +++++++++++++++++++ cdd/tests/test_emit/test_emitters.py | 5 +- cdd/tests/test_parse/test_parsers.py | 5 +- .../test_emit_sqlalchemy_utils.py | 20 ++++ 5 files changed, 123 insertions(+), 2 deletions(-) diff --git a/cdd/compound/openapi/utils/emit_utils.py b/cdd/compound/openapi/utils/emit_utils.py index 904ec494..934d7bbf 100644 --- a/cdd/compound/openapi/utils/emit_utils.py +++ b/cdd/compound/openapi/utils/emit_utils.py @@ -903,6 +903,7 @@ def sqlalchemy_table_to_class(table_expr_ass): __all__ = [ "ensure_has_primary_key", + "generate_create_from_attr_staticmethod", "generate_repr_method", "param_to_sqlalchemy_column_call", "sqlalchemy_class_to_table", diff --git a/cdd/tests/mocks/sqlalchemy.py b/cdd/tests/mocks/sqlalchemy.py index 86467684..3fd935e0 100644 --- a/cdd/tests/mocks/sqlalchemy.py +++ b/cdd/tests/mocks/sqlalchemy.py @@ -7,17 +7,23 @@ Attribute, Call, ClassDef, + Compare, + DictComp, Expr, FunctionDef, + IsNot, Load, Module, Name, Return, Store, + Tuple, arguments, + comprehension, keyword, ) from copy import deepcopy +from functools import partial from itertools import chain, islice from textwrap import indent @@ -610,6 +616,93 @@ def __repr__(self): type_ignores=[], ) +create_from_attr_mock = FunctionDef( + name="create_from_attr", + args=arguments( + posonlyargs=[], + args=[set_arg("record")], + kwonlyargs=[], + kw_defaults=[], + defaults=[], + ), + body=[ + Expr( + value=set_value( + "\n".join( + map( + partial(indent, prefix=tab * 2), + ( + "", + "Construct an instance from an object with identical columns (as attributes) as this `class`/`Table`", + tab * 2, + ":return: A new instance made from the input object's attributes", + ":rtype: ```foo```", + tab * 2, + ), + ) + ) + ) + ), + Return( + value=Call( + func=Name(id="foo", ctx=Load()), + args=[], + keywords=[ + keyword( + value=DictComp( + key=Name(id="attr", ctx=Load()), + value=Call( + func=Name(id="getattr", ctx=Load()), + args=[ + Name(id="node", ctx=Load()), + Name(id="attr", ctx=Load()), + ], + keywords=[], + ), + generators=[ + comprehension( + target=Name(id="attr", ctx=Store()), + iter=Tuple( + elts=[ + set_value("id"), + set_value("not_pk_id"), + ], + ctx=Load(), + ), + ifs=[ + Compare( + left=Call( + func=Name(id="getattr", ctx=Load()), + args=[ + Name( + id="node", + ctx=Load(), + ), + Name( + id="attr", + ctx=Load(), + ), + set_value(None), + ], + keywords=[], + ), + ops=[IsNot()], + comparators=[set_value(None)], + ) + ], + is_async=0, + ) + ], + ) + ) + ], + ) + ), + ], + lineno=None, + decorator_list=[Name(id="staticmethod", ctx=Load())], +) + __all__ = [ "config_decl_base_ast", "config_decl_base_str", @@ -617,6 +710,7 @@ def __repr__(self): "config_tbl_with_comments_ast", "config_tbl_with_comments_ast", "config_tbl_with_comments_str", + "create_from_attr_mock", "dataset_primary_key_column_assign", "element_pk_fk_ass", "empty_with_inferred_pk_column_assign", diff --git a/cdd/tests/test_emit/test_emitters.py b/cdd/tests/test_emit/test_emitters.py index 80deb1f7..0cfedce3 100644 --- a/cdd/tests/test_emit/test_emitters.py +++ b/cdd/tests/test_emit/test_emitters.py @@ -21,7 +21,10 @@ def test_emitters_root(self) -> None: EMITTERS, all_dunder_for_module( path.dirname(path.dirname(path.dirname(__file__))), - ("sqlalchemy_table",), + ( + "sqlalchemy_hybrid", + "sqlalchemy_table", + ), ), ) diff --git a/cdd/tests/test_parse/test_parsers.py b/cdd/tests/test_parse/test_parsers.py index 23ea1b6f..8822046c 100644 --- a/cdd/tests/test_parse/test_parsers.py +++ b/cdd/tests/test_parse/test_parsers.py @@ -21,7 +21,10 @@ def test_parsers_root(self) -> None: PARSERS, all_dunder_for_module( path.dirname(path.dirname(path.dirname(__file__))), - ("sqlalchemy_table",), + ( + "sqlalchemy_hybrid", + "sqlalchemy_table", + ), ), ) diff --git a/cdd/tests/test_sqlalchemy/test_emit_sqlalchemy_utils.py b/cdd/tests/test_sqlalchemy/test_emit_sqlalchemy_utils.py index e5cfc8ba..18a201da 100644 --- a/cdd/tests/test_sqlalchemy/test_emit_sqlalchemy_utils.py +++ b/cdd/tests/test_sqlalchemy/test_emit_sqlalchemy_utils.py @@ -23,6 +23,7 @@ from cdd.compound.openapi.utils.emit_utils import ( ensure_has_primary_key, + generate_create_from_attr_staticmethod, param_to_sqlalchemy_column_call, sqlalchemy_class_to_table, sqlalchemy_table_to_class, @@ -42,6 +43,7 @@ from cdd.tests.mocks.sqlalchemy import ( config_hybrid_ast, config_tbl_with_comments_ast, + create_from_attr_mock, element_pk_fk_ass, node_fk_call, node_pk_tbl_ass, @@ -107,6 +109,24 @@ def test_ensure_has_primary_key_from_id(self) -> None: ir["params"]["id"]["doc"] = "[PK] {}".format(ir["params"]["id"]["doc"]) self.assertDictEqual(res, ir) + def test_generate_create_from_attr_staticmethod(self): + """Tests that `generate_create_from_attr` staticmethod is correctly constructed""" + run_ast_test( + self, + generate_create_from_attr_staticmethod( + OrderedDict( + ( + ("id", {"doc": "My doc", "typ": "str"}), + ("not_pk_id", {"doc": "", "typ": "str"}), + ) + ), + cls_name="foo", + docstring_format="rest", + ), + create_from_attr_mock, + skip_black=True, + ) + def test_param_to_sqlalchemy_column_call_when_sql_constraints(self) -> None: """Tests that with SQL constraints the SQLalchemy column is correctly generated""" run_ast_test(