Skip to content

Commit

Permalink
[cdd/__main__.py] Add --extra-module option; [cdd/compound/{exmod,e…
Browse files Browse the repository at this point in the history
…xmod_utils}.py] Implement `--extra-module` functionality and automatically add SQLalchemy mod if generated by `exmod` ; [README.md] Update `--help` text to match current cmd
  • Loading branch information
SamuelMarks committed Feb 8, 2024
1 parent aac5d7c commit 9246385
Show file tree
Hide file tree
Showing 28 changed files with 564 additions and 213 deletions.
33 changes: 21 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -482,9 +482,9 @@ class Config(Base):

$ python -m cdd --help
usage: python -m cdd [-h] [--version]
{sync_properties,sync,gen,gen_routes,openapi,doctrans,exmod}
...
{sync_properties,sync,gen,gen_routes,openapi,doctrans,exmod}
...

Open API to/fro routes, models, and tests. Convert between docstrings,
classes, methods, argparse, pydantic, and SQLalchemy.

Expand Down Expand Up @@ -575,7 +575,7 @@ class Config(Base):
[--parse {argparse,class,function,json_schema,pydantic,sqlalchemy,sqlalchemy_hybrid,sqlalchemy_table,infer}]
--emit
{argparse,class,function,json_schema,pydantic,sqlalchemy,sqlalchemy_hybrid,sqlalchemy_table}
--output-filename OUTPUT_FILENAME [--emit-call]
-o OUTPUT_FILENAME [--emit-call]
[--emit-and-infer-imports] [--no-word-wrap]
[--decorator DECORATOR_LIST] [--phase PHASE]

Expand All @@ -593,7 +593,7 @@ class Config(Base):
What type the input is.
--emit {argparse,class,function,json_schema,pydantic,sqlalchemy,sqlalchemy_hybrid,sqlalchemy_table}
Which type to generate.
--output-filename OUTPUT_FILENAME, -o OUTPUT_FILENAME
-o OUTPUT_FILENAME, --output-filename OUTPUT_FILENAME
Output file to write to.
--emit-call Whether to place all the previous body into a new
`__call__` internal function
Expand Down Expand Up @@ -678,20 +678,27 @@ PS: If you're outputting JSON-schema and want a file per schema then:
### `exmod`

$ python -m cdd exmod --help
usage: python -m cdd exmod [-h] --module MODULE --emit
usage: python -m cdd exmod [-h] -m MODULE --emit
{argparse,class,function,json_schema,pydantic,sqlalchemy,sqlalchemy_hybrid,sqlalchemy_table}
[--no-word-wrap] [--blacklist BLACKLIST]
[--whitelist WHITELIST] --output-directory
[--emit-sqlalchemy-submodule]
[--extra-module [EXTRA_MODULES]] [--no-word-wrap]
[--blacklist BLACKLIST] [--whitelist WHITELIST] -o
OUTPUT_DIRECTORY
[--target-module-name TARGET_MODULE_NAME]
[--target-module-name TARGET_MODULE_NAME] [-r]
[--dry-run]

options:
-h, --help show this help message and exit
--module MODULE, -m MODULE
-m MODULE, --module MODULE
The module or fully-qualified name (FQN) to expose.
--emit {argparse,class,function,json_schema,pydantic,sqlalchemy,sqlalchemy_hybrid,sqlalchemy_table}
Which type to generate.
--emit-sqlalchemy-submodule
Whether to; for sqlalchemy*; emit submodule "sqlalchem
y_mod/{__init__,connection,create_tables}.py"
--extra-module [EXTRA_MODULES]
Additional module(s) to expose; specifiable multiple
times. Added to symbol auto-import resolver.
--no-word-wrap Whether word-wrap is disabled (on emission). None
enables word-wrap. Defaults to None.
--blacklist BLACKLIST
Expand All @@ -700,11 +707,13 @@ PS: If you're outputting JSON-schema and want a file per schema then:
--whitelist WHITELIST
Modules/FQN to emit. If unspecified will emit all
(minus blacklist).
--output-directory OUTPUT_DIRECTORY, -o OUTPUT_DIRECTORY
-o OUTPUT_DIRECTORY, --output-directory OUTPUT_DIRECTORY
Where to place the generated exposed interfaces to the
given `--module`.
--target-module-name TARGET_MODULE_NAME
Target module name. Defaults to `${module}.gold`.
Target module name. Defaults to `${module}___gold`.
-r, --recursive Recursively traverse module hierarchy and recreate
hierarchy with exposed interfaces
--dry-run Show what would be created; don't actually write to
the filesystem.

Expand Down
2 changes: 1 addition & 1 deletion cdd/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from logging import getLogger as get_logger

__author__ = "Samuel Marks" # type: str
__version__ = "0.0.99rc24" # type: str
__version__ = "0.0.99rc25" # type: str
__description__ = (
"Open API to/fro routes, models, and tests. "
"Convert between docstrings, classes, methods, argparse, pydantic, and SQLalchemy."
Expand Down
12 changes: 9 additions & 3 deletions cdd/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -401,11 +401,17 @@ def _build_parser():
action="append",
)
exmod_parser.add_argument(
"--emit-base-engine-metadata",
help="[sqlalchemy specific] Whether to produce a file with `Base`, `engine`, and `metadata`."
"`None` is `False`. Defaults to None.",
"--emit-sqlalchemy-submodule",
help='Whether to; for sqlalchemy*; emit submodule "sqlalchemy_mod/{__init__,connection,create_tables}.py"',
action="store_true",
)
exmod_parser.add_argument(
"--extra-module",
help="Additional module(s) to expose; specifiable multiple times. Added to symbol auto-import resolver.",
action="append",
nargs="?",
dest="extra_modules",
)
exmod_parser.add_argument(
"--no-word-wrap",
help="Whether word-wrap is disabled (on emission). None enables word-wrap. Defaults to None.",
Expand Down
29 changes: 14 additions & 15 deletions cdd/argparse_function/emit.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,8 @@
from itertools import chain
from typing import Optional

import cdd.shared.ast_utils
from cdd.docstring.emit import docstring
from cdd.shared.ast_utils import (
get_value,
maybe_type_comment,
param2argparse_param,
set_arg,
set_value,
)
from cdd.shared.emit.utils.emitter_utils import get_internal_body
from cdd.shared.pure_utils import code_quoted, fill, identity, none_types
from cdd.shared.types import Internal
Expand Down Expand Up @@ -87,7 +81,7 @@ def argparse_function(

return FunctionDef(
args=arguments(
args=[set_arg("argument_parser")],
args=[cdd.shared.ast_utils.set_arg("argument_parser")],
# None if function_type in frozenset((None, "static"))
# else set_arg(function_type),
defaults=[],
Expand All @@ -104,7 +98,7 @@ def argparse_function(
iter(
(
Expr(
set_value(
cdd.shared.ast_utils.set_value(
docstring(
{
"doc": "Set CLI arguments",
Expand Down Expand Up @@ -200,14 +194,14 @@ def argparse_function(
col_offset=None,
)
],
value=set_value(
value=cdd.shared.ast_utils.set_value(
(fill if wrap_description else identity)(
intermediate_repr["doc"]
)
),
lineno=None,
expr=None,
**maybe_type_comment
**cdd.shared.ast_utils.maybe_type_comment
),
)
),
Expand All @@ -218,7 +212,7 @@ def argparse_function(
(
map(
partial(
param2argparse_param,
cdd.shared.ast_utils.param2argparse_param,
word_wrap=word_wrap,
emit_default_doc=emit_default_doc,
),
Expand All @@ -241,7 +235,12 @@ def argparse_function(
]
if internal_body
and isinstance(internal_body[0], Expr)
and isinstance(get_value(internal_body[0].value), str)
and isinstance(
cdd.shared.ast_utils.get_value(
internal_body[0].value
),
str,
)
else internal_body
),
(
Expand All @@ -260,7 +259,7 @@ def argparse_function(
col_offset=None,
),
(
set_value(
cdd.shared.ast_utils.set_value(
intermediate_repr["returns"][
"return_type"
]["default"]
Expand Down Expand Up @@ -314,7 +313,7 @@ def argparse_function(
arguments_args=None,
identifier_name=None,
stmt=None,
**maybe_type_comment
**cdd.shared.ast_utils.maybe_type_comment
)


Expand Down
8 changes: 5 additions & 3 deletions cdd/class_/emit.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@
from itertools import chain
from typing import Optional

import cdd.shared.ast_utils
from cdd.class_.utils.emit_utils import RewriteName
from cdd.docstring.emit import docstring
from cdd.function.utils.emit_utils import _make_call_meth
from cdd.shared.ast_utils import param2ast, set_value
from cdd.shared.pure_utils import PY_GTE_3_8, PY_GTE_3_9, rpartial

if PY_GTE_3_9:
Expand Down Expand Up @@ -140,7 +140,9 @@ def class_(
None
if ds is None
else Expr(
set_value(ds), lineno=None, col_offset=None
cdd.shared.ast_utils.set_value(ds),
lineno=None,
col_offset=None,
)
)
)(
Expand All @@ -157,7 +159,7 @@ def class_(
),
),
map(
param2ast,
cdd.shared.ast_utils.param2ast,
(intermediate_repr.get("params") or OrderedDict()).items(),
),
iter(
Expand Down
31 changes: 20 additions & 11 deletions cdd/class_/parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@

import cdd.docstring.parse
import cdd.function.parse
import cdd.shared.ast_utils
import cdd.shared.docstring_parsers
import cdd.shared.parse.utils.parser_utils
import cdd.shared.source_transformer
from cdd.class_.utils.parse_utils import get_source
from cdd.shared.ast_utils import NoneStr, find_ast_type, get_value, parse_to_scalar
from cdd.shared.pure_utils import rpartial, simple_types
from cdd.shared.source_transformer import to_code
from cdd.shared.types import IntermediateRepr


Expand Down Expand Up @@ -89,7 +89,9 @@ def class_(
), "Expected 'Union[Module, ClassDef]' got `{node_name!r}`".format(
node_name=type(class_def).__name__
)
class_def: ClassDef = cast(ClassDef, find_ast_type(class_def, class_name))
class_def: ClassDef = cast(
ClassDef, cdd.shared.ast_utils.find_ast_type(class_def, class_name)
)
doc_str: Optional[str] = get_docstring(class_def, clean=parse_original_whitespace)
intermediate_repr: IntermediateRepr = (
{
Expand All @@ -115,11 +117,11 @@ def class_(
body: ClassDef.body = class_def.body if doc_str is None else class_def.body[1:]
for e in body:
if isinstance(e, AnnAssign):
typ: str = to_code(e.annotation).rstrip("\n")
typ: str = cdd.shared.source_transformer.to_code(e.annotation).rstrip("\n")
val = (
(
lambda v: (
{"default": NoneStr}
{"default": cdd.shared.ast_utils.NoneStr}
if v is None
else {
"default": (
Expand All @@ -130,12 +132,15 @@ def class_(
"{}": {} if isinstance(v, Dict) else set(),
"[]": [],
"()": (),
}.get(value, parse_to_scalar(value))
)(to_code(v).rstrip("\n"))
}.get(
value,
cdd.shared.ast_utils.parse_to_scalar(value),
)
)(cdd.shared.source_transformer.to_code(v).rstrip("\n"))
)
}
)
)(get_value(get_value(e)))
)(cdd.shared.ast_utils.get_value(cdd.shared.ast_utils.get_value(e)))
if hasattr(e, "value") and e.value is not None
else {}
)
Expand All @@ -159,10 +164,10 @@ def class_(
intermediate_repr[k] = OrderedDict()
intermediate_repr[k][target_id] = typ_default
elif isinstance(e, Assign):
val = get_value(e)
val = cdd.shared.ast_utils.get_value(e)

if val is not None:
val = get_value(val)
val = cdd.shared.ast_utils.get_value(val)
deque(
map(
lambda target: setitem(
Expand All @@ -181,7 +186,11 @@ def class_(
(
_target_id
if isinstance(target, Name)
else get_value(get_value(target))
else cdd.shared.ast_utils.get_value(
cdd.shared.ast_utils.get_value(
target
)
)
),
{"default": val},
)
Expand Down
Loading

0 comments on commit 9246385

Please sign in to comment.