Skip to content

Commit 7ba481f

Browse files
committed
[cdd/tests/test_{compound,json_schema,shared,sqlalchemy}] Increase test coverage ; [cdd/__init__.py] Bump version
1 parent fc4eea2 commit 7ba481f

File tree

11 files changed

+140
-88
lines changed

11 files changed

+140
-88
lines changed

cdd/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from logging import getLogger as get_logger
1010

1111
__author__ = "Samuel Marks" # type: str
12-
__version__ = "0.0.99rc45" # type: str
12+
__version__ = "0.0.99rc46" # type: str
1313
__description__ = (
1414
"Open API to/fro routes, models, and tests. "
1515
"Convert between docstrings, classes, methods, argparse, pydantic, and SQLalchemy."

cdd/compound/gen_utils.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ def gen_module(
251251
:type no_word_wrap: ```Optional[Literal[True]]```
252252
253253
:param imports: Import to preclude in Python file
254-
:type imports: ```str```
254+
:type imports: ```Optional[str]```
255255
256256
:param functions_and_classes: Functions and classes that have been preparsed
257257
:type functions_and_classes: ```Optional[Tuple[AST]]```
@@ -466,8 +466,9 @@ def file_to_input_mapping(filepath, parse_name):
466466

467467
__all__ = [
468468
"file_to_input_mapping",
469-
"get_input_mapping_from_path",
470-
"get_emit_kwarg",
471469
"gen_file",
470+
"gen_module",
471+
"get_emit_kwarg",
472+
"get_input_mapping_from_path",
472473
"get_parser",
473474
]

cdd/json_schema/utils/parse_utils.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ def transform_ref_fk_set(ref, foreign_key):
7777
_param.pop("anyOf"),
7878
)
7979
)
80+
8081
if len(_param["typ"]) > 1 and "string" in _param["typ"]:
8182
del _param["typ"][_param["typ"].index("string")]
8283
_param["typ"] = (

cdd/shared/defaults_utils.py

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -187,31 +187,6 @@ def extract_default(
187187
)
188188

189189

190-
def type_default_from_default(default, typ):
191-
"""
192-
:param default: The default value; potentially `NoneStr`
193-
:type default: ```str```
194-
195-
:param typ: The type of the parameter
196-
:type typ: ```str```
197-
198-
:return: (Optional[typ], None) if default is NoneStr else (typ, default)
199-
:rtype: ```tuple[Optional[str], str]```
200-
"""
201-
return (
202-
(
203-
(
204-
typ
205-
if typ == "None"
206-
else "Optional[{typ}]".format(typ=typ) if typ != "None" else typ
207-
),
208-
None,
209-
)
210-
if default is NoneStr
211-
else (typ, default)
212-
)
213-
214-
215190
def _parse_out_default_and_doc(
216191
_start_idx,
217192
start_rest_offset,

cdd/sqlalchemy/utils/parse_utils.py

Lines changed: 3 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@
22
Utility functions for `cdd.parse.sqlalchemy`
33
"""
44

5-
import ast
6-
from ast import Assign, Call, ClassDef, Constant, Load, Module, Name
7-
from itertools import chain, filterfalse
8-
from operator import attrgetter
5+
from ast import Assign, Call, ClassDef, Constant, Load, Name
6+
from itertools import chain
97

108
import cdd.shared.ast_utils
119
import cdd.shared.source_transformer
@@ -146,9 +144,7 @@ def column_parse_arg(idx_arg):
146144

147145
val = cdd.shared.ast_utils.get_value(arg)
148146
assert val != arg, "Unable to parse {!r}".format(arg)
149-
if idx == 0:
150-
return None # Column name
151-
return None, val
147+
return None if idx == 0 else (None, val)
152148

153149

154150
def column_parse_kwarg(key_word):
@@ -289,48 +285,6 @@ def concat_with_whitespace(a, b):
289285
return indent_all_but_first(res, indent_level=1, sep=tab)
290286

291287

292-
def infer_imports_from_sqlalchemy(sqlalchemy_class_or_assigns):
293-
"""
294-
Infer imports from SQLalchemy ast
295-
296-
:param sqlalchemy_class_or_assigns: SQLalchemy Class or Assign
297-
:type sqlalchemy_class_or_assigns: ```Union[ClassDef, Assign]```
298-
299-
:return: filter of imports (can be considered ```Iterable[str]```)
300-
:rtype: ```filter```
301-
"""
302-
candidates = frozenset(
303-
map(
304-
attrgetter("id"),
305-
filter(
306-
rpartial(isinstance, Name),
307-
ast.walk(
308-
Module(
309-
body=list(
310-
filter(
311-
rpartial(isinstance, Call),
312-
ast.walk(sqlalchemy_class_or_assigns),
313-
)
314-
),
315-
type_ignores=[],
316-
stmt=None,
317-
)
318-
),
319-
),
320-
)
321-
)
322-
323-
candidates_not_in_valid_types = frozenset(
324-
filterfalse(
325-
frozenset(
326-
("list", "string", "int", "float", "complex", "long")
327-
).__contains__,
328-
filterfalse(sqlalchemy_top_level_imports.__contains__, candidates),
329-
)
330-
)
331-
return candidates_not_in_valid_types ^ candidates
332-
333-
334288
def get_pk_and_type(sqlalchemy_class):
335289
"""
336290
Get the primary key and its type from an SQLalchemy class

cdd/tests/test_compound/test_gen.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -340,19 +340,30 @@ def test_gen_json_schema_input_mapping(self) -> None:
340340
with patch(
341341
"cdd.json_schema.emit.json_schema_file", new_callable=MagicMock()
342342
) as json_schema_file_mock, TemporaryDirectory() as tempdir:
343-
json_schema_file = os.path.join(tempdir, "foo.json")
343+
json_schema_file = os.path.join(tempdir, "foo{}json".format(os.path.extsep))
344344
with open(json_schema_file, "wt") as f:
345345
dump(server_error_schema, f)
346+
# file
346347
gen(
347348
"{name}",
348349
input_mapping=json_schema_file,
349350
parse_name="json_schema",
350351
emit_name="json_schema",
351352
output_filename=os.path.join(
352-
tempdir, "foo.gen{}json".format(os.path.extsep)
353+
tempdir, "foo.gen0{}json".format(os.path.extsep)
353354
),
354355
)
355-
self.assertEqual(json_schema_file_mock.call_count, 1)
356+
# directory
357+
gen(
358+
"{name}",
359+
input_mapping=tempdir,
360+
parse_name="json_schema",
361+
emit_name="json_schema",
362+
output_filename=os.path.join(
363+
tempdir, "foo.gen1{}json".format(os.path.extsep)
364+
),
365+
)
366+
self.assertEqual(json_schema_file_mock.call_count, 2)
356367

357368

358369
unittest_main()

cdd/tests/test_compound/test_gen_utils.py

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,18 @@
11
""" Tests for gen_utils """
22

3+
from ast import Assign, List, Load, Module, Name, Store
4+
from os import path
5+
from tempfile import TemporaryDirectory
36
from unittest import TestCase
47

5-
from cdd.compound.gen_utils import get_input_mapping_from_path
6-
from cdd.tests.utils_for_tests import unittest_main
8+
import cdd.shared.source_transformer
9+
from cdd.compound.gen_utils import (
10+
file_to_input_mapping,
11+
gen_module,
12+
get_input_mapping_from_path,
13+
)
14+
from cdd.tests.mocks.classes import class_ast
15+
from cdd.tests.utils_for_tests import run_ast_test, unittest_main
716

817

918
def f(s):
@@ -17,6 +26,17 @@ def f(s):
1726
class TestGenUtils(TestCase):
1827
"""Test class for cdd.gen_utils"""
1928

29+
def test_file_to_input_mapping_else_condition(self) -> None:
30+
"""Test that `file_to_input_mapping` else condition works"""
31+
with TemporaryDirectory() as temp_dir:
32+
filename: str = path.join(temp_dir, "foo{}py".format(path.extsep))
33+
with open(filename, "wt") as f:
34+
f.write(cdd.shared.source_transformer.to_code(class_ast))
35+
input_mapping = file_to_input_mapping(filename, "infer")
36+
self.assertEqual(len(input_mapping.keys()), 1)
37+
self.assertIn(class_ast.name, input_mapping)
38+
run_ast_test(self, input_mapping[class_ast.name], class_ast)
39+
2040
def test_get_input_mapping_from_path(self) -> None:
2141
"""test `get_input_mapping_from_path`"""
2242
self.assertEqual(f(""), "")
@@ -27,5 +47,48 @@ def test_get_input_mapping_from_path(self) -> None:
2747
self.assertIn("f", name_to_node)
2848
self.assertIsInstance(name_to_node["f"], dict)
2949

50+
def test_gen_module_when_emit_and_infer_imports(self) -> None:
51+
"""
52+
Tests that `emit_and_infer_imports` works when `emit_and_infer_imports` is True
53+
"""
54+
run_ast_test(
55+
self,
56+
gen_module(
57+
decorator_list=[],
58+
emit_and_infer_imports=True,
59+
emit_call=False,
60+
emit_default_doc=False,
61+
emit_name="class",
62+
functions_and_classes=None,
63+
imports=None,
64+
input_mapping_it={},
65+
name_tpl="{name}Foo",
66+
no_word_wrap=True,
67+
parse_name="class",
68+
prepend=None,
69+
),
70+
Module(
71+
body=[
72+
Assign(
73+
targets=[
74+
Name(
75+
id="__all__", ctx=Store(), lineno=None, col_offset=None
76+
)
77+
],
78+
value=List(
79+
elts=[],
80+
ctx=Load(),
81+
expr=None,
82+
),
83+
type_comment=None,
84+
expr=None,
85+
lineno=None,
86+
)
87+
],
88+
stmt=None,
89+
type_ignores=[],
90+
),
91+
)
92+
3093

3194
unittest_main()

cdd/tests/test_json_schema/test_parse_json_schema_utils.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,5 +86,11 @@ def test_json_schema_property_to_param_default_none(self) -> None:
8686
self.assertEqual(res[0], mock[0])
8787
self.assertDictEqual(res[1], mock[1])
8888

89+
def test_json_schema_property_to_param_removes_string_from_anyOf(self) -> None:
90+
"""Tests that `json_schema_property_to_param` removes `string` from `anyOf`"""
91+
param = ("foo", {"anyOf": ["string", "can"], "typ": ["string", "can", "haz"]})
92+
cdd.json_schema.utils.parse_utils.json_schema_property_to_param(param, {})
93+
self.assertDictEqual(param[1], {"typ": "Optional[can]"})
94+
8995

9096
unittest_main()

cdd/tests/test_shared/test_pure_utils.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
multiline,
2525
namespaced_pascal_to_upper_camelcase,
2626
namespaced_upper_camelcase_to_pascal,
27+
pairwise,
2728
parse_comment_from_line,
2829
pluralise,
2930
pp,
@@ -185,7 +186,7 @@ def test_multiline(self) -> None:
185186
),
186187
)
187188

188-
def test_(self) -> None:
189+
def test_parse_comment_from_line(self) -> None:
189190
"""Tests that parses the comment out of the line"""
190191
for output_val, input_val in (
191192
("foo", "foo#bar"),
@@ -197,6 +198,7 @@ def test_(self) -> None:
197198
("foo = 'ba#r'", "foo = 'ba#r'"),
198199
("foo =", "foo = #'foo'"),
199200
("source = ndb.TextProperty()", "source = ndb.TextProperty()"),
201+
("bar\\'", "bar" "\\" "'"),
200202
):
201203
self.assertEqual(output_val, parse_comment_from_line(input_val))
202204

@@ -220,17 +222,21 @@ def test_pluralises(self) -> None:
220222

221223
def test_append_to_dict(self) -> None:
222224
"""Tests `append_to_dict`"""
223-
self.assertEqual(
225+
self.assertDictEqual(
224226
append_to_dict({"a": {"b": {}}}, ["a", "b", "c"], "d"),
225227
{"a": {"b": {"c": "d"}}},
226228
)
227-
self.assertEqual(
229+
self.assertDictEqual(
228230
append_to_dict({"a": {"b": 2}}, ["a", "b", "c"], "d"), {"a": {"b": 2}}
229231
)
230-
self.assertEqual(
232+
self.assertDictEqual(
231233
append_to_dict({"a": {"b": {"c": {}}}}, ["a", "b", "c"], "d"),
232234
{"a": {"b": {"c": "d"}}},
233235
)
236+
self.assertDictEqual(
237+
append_to_dict({}, [], None),
238+
{},
239+
)
234240

235241
def test_remove_whitespace_comments(self) -> None:
236242
"""Tests `remove_whitespace_comments` actually removes whitespace and comments from Python source"""
@@ -344,5 +350,12 @@ def test_namespaced_pascal_to_upper_camelcase(self) -> None:
344350
namespaced_pascal_to_upper_camelcase("foo_bar_can"), "FooBarCan"
345351
)
346352

353+
def test_pairwise(self) -> None:
354+
"""Tests that (potentially proxy) `pairwise` implementation works"""
355+
self.assertTupleEqual(
356+
tuple(pairwise("ABCDEFG")),
357+
(("A", "B"), ("B", "C"), ("C", "D"), ("D", "E"), ("E", "F"), ("F", "G")),
358+
)
359+
347360

348361
unittest_main()

cdd/tests/test_sqlalchemy/test_emit_sqlalchemy_utils.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,20 @@ def test_update_args_infer_typ_sqlalchemy_when_simple_array_in_typ(self) -> None
302302
# gold=Name(id="Small", ctx=Load(), lineno=None, col_offset=None),
303303
# )
304304

305+
def test_update_args_infer_typ_sqlalchemy_calls__handle_union_of_length_2(
306+
self,
307+
) -> None:
308+
"""Tests that `update_args_infer_typ_sqlalchemy` calls `_handle_union_of_length_2`"""
309+
args = []
310+
with patch(
311+
"cdd.sqlalchemy.utils.shared_utils._handle_union_of_length_2", lambda _: 5
312+
):
313+
update_args_infer_typ_sqlalchemy(
314+
{"typ": "Union[string, Small]"}, args, "", False, {}
315+
)
316+
self.assertEqual(len(args), 1)
317+
self.assertListEqual(args, [5])
318+
305319
def test_update_args_infer_typ_sqlalchemy_early_exit(self) -> None:
306320
"""Tests that `update_args_infer_typ_sqlalchemy` exits early"""
307321
_update_args_infer_typ_sqlalchemy: Callable[

cdd/tests/test_sqlalchemy/test_parse_sqlalchemy_utils.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Tests for the utils that is used by the SQLalchemy parsers
33
"""
44

5-
from ast import ClassDef, keyword
5+
from ast import Call, ClassDef, Load, Name, keyword
66
from copy import deepcopy
77
from unittest import TestCase
88

@@ -52,6 +52,20 @@ def test_column_call_to_param_pk(self) -> None:
5252
self.assertEqual(gold_name, gen_name)
5353
self.assertDictEqual(gold_param, gen_param)
5454

55+
def test_column_call_name_manipulator_remove_op(self) -> None:
56+
"""
57+
Tests that `column_call_name_manipulator` runs remove op
58+
"""
59+
call: Call = Call(
60+
func=Name(id="Column", ctx=Load(), lineno=None, col_offset=None),
61+
args=[set_value("foo")],
62+
keywords=[],
63+
lineno=None,
64+
col_offset=None,
65+
)
66+
column_call_name_manipulator(call, "remove")
67+
self.assertListEqual(call.args, [])
68+
5569
def test_column_call_to_param_server_default(self) -> None:
5670
"""
5771
Tests that `parse.sqlalchemy.utils.column_call_to_param` works with server_default

0 commit comments

Comments
 (0)