amsdal_cli 0.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- amsdal_cli/Third-Party Materials - AMSDAL Dependencies - License Notices.md +1099 -0
- amsdal_cli/__about__.py +4 -0
- amsdal_cli/__init__.py +0 -0
- amsdal_cli/app.py +8 -0
- amsdal_cli/commands/__init__.py +0 -0
- amsdal_cli/commands/build/__init__.py +0 -0
- amsdal_cli/commands/build/command.py +27 -0
- amsdal_cli/commands/build/constants.py +1 -0
- amsdal_cli/commands/build/utils/__init__.py +0 -0
- amsdal_cli/commands/build/utils/build_app.py +46 -0
- amsdal_cli/commands/build/utils/build_config_file.py +36 -0
- amsdal_cli/commands/callbacks.py +47 -0
- amsdal_cli/commands/generate/__init__.py +0 -0
- amsdal_cli/commands/generate/app.py +5 -0
- amsdal_cli/commands/generate/command.py +5 -0
- amsdal_cli/commands/generate/enums.py +52 -0
- amsdal_cli/commands/generate/sub_commands/__init__.py +13 -0
- amsdal_cli/commands/generate/sub_commands/generate_hook.py +35 -0
- amsdal_cli/commands/generate/sub_commands/generate_model.py +94 -0
- amsdal_cli/commands/generate/sub_commands/generate_modifier.py +32 -0
- amsdal_cli/commands/generate/sub_commands/generate_property.py +38 -0
- amsdal_cli/commands/generate/sub_commands/generate_transaction.py +38 -0
- amsdal_cli/commands/generate/templates/hook.pyt +3 -0
- amsdal_cli/commands/generate/templates/modifier/constructor.pyt +10 -0
- amsdal_cli/commands/generate/templates/modifier/display_name.pyt +4 -0
- amsdal_cli/commands/generate/templates/modifier/version_name.pyt +4 -0
- amsdal_cli/commands/generate/templates/property.pyt +4 -0
- amsdal_cli/commands/generate/templates/transaction.pyt +7 -0
- amsdal_cli/commands/generate/utils/__init__.py +0 -0
- amsdal_cli/commands/generate/utils/build_base_path.py +22 -0
- amsdal_cli/commands/generate/utils/cast_to_attribute_type.py +19 -0
- amsdal_cli/commands/generate/utils/model_attributes.py +131 -0
- amsdal_cli/commands/new/__init__.py +0 -0
- amsdal_cli/commands/new/command.py +54 -0
- amsdal_cli/commands/new/templates/.amsdal-cli +6 -0
- amsdal_cli/commands/new/templates/.gitignore +4 -0
- amsdal_cli/commands/new/templates/README.md +646 -0
- amsdal_cli/commands/new/templates/config.yml +19 -0
- amsdal_cli/commands/serve/__init__.py +0 -0
- amsdal_cli/commands/serve/command.py +38 -0
- amsdal_cli/commands/serve/filters/__init__.py +0 -0
- amsdal_cli/commands/serve/filters/models_watch_filter.py +6 -0
- amsdal_cli/commands/serve/filters/static_files_watch_filter.py +21 -0
- amsdal_cli/commands/serve/services/__init__.py +0 -0
- amsdal_cli/commands/serve/services/supervisor.py +373 -0
- amsdal_cli/commands/serve/utils.py +16 -0
- amsdal_cli/commands/verify/__init__.py +0 -0
- amsdal_cli/commands/verify/command.py +74 -0
- amsdal_cli/commands/verify/models.py +10 -0
- amsdal_cli/commands/verify/utils/__init__.py +0 -0
- amsdal_cli/commands/verify/utils/verify_json_model.py +31 -0
- amsdal_cli/commands/verify/utils/verify_python_file.py +21 -0
- amsdal_cli/config/__init__.py +0 -0
- amsdal_cli/config/main.py +38 -0
- amsdal_cli/main.py +7 -0
- amsdal_cli/py.typed +0 -0
- amsdal_cli/utils/__init__.py +0 -0
- amsdal_cli/utils/cli_config.py +27 -0
- amsdal_cli/utils/copier.py +103 -0
- amsdal_cli/utils/render_template.py +12 -0
- amsdal_cli-0.0.1.dist-info/METADATA +353 -0
- amsdal_cli-0.0.1.dist-info/RECORD +65 -0
- amsdal_cli-0.0.1.dist-info/WHEEL +4 -0
- amsdal_cli-0.0.1.dist-info/entry_points.txt +2 -0
- amsdal_cli-0.0.1.dist-info/licenses/LICENSE.txt +107 -0
amsdal_cli/__about__.py
ADDED
amsdal_cli/__init__.py
ADDED
|
File without changes
|
amsdal_cli/app.py
ADDED
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
import typer
|
|
4
|
+
|
|
5
|
+
from amsdal_cli.app import app
|
|
6
|
+
from amsdal_cli.commands.build.utils.build_app import build_app
|
|
7
|
+
from amsdal_cli.commands.generate.enums import SOURCES_DIR
|
|
8
|
+
from amsdal_cli.utils.cli_config import CliConfig
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@app.command(name='build')
|
|
12
|
+
def build_command(
|
|
13
|
+
ctx: typer.Context,
|
|
14
|
+
output: Path = typer.Argument('.', help='Path to output directory'), # noqa: B008
|
|
15
|
+
config: Path = typer.Option(None, help='Path to custom config.yml file'), # noqa: B008
|
|
16
|
+
) -> None:
|
|
17
|
+
"""
|
|
18
|
+
Build the app and generate the models and other files.
|
|
19
|
+
"""
|
|
20
|
+
cli_config: CliConfig = ctx.meta['config']
|
|
21
|
+
app_source_path = cli_config.app_directory / SOURCES_DIR
|
|
22
|
+
|
|
23
|
+
build_app(
|
|
24
|
+
app_source_path=app_source_path,
|
|
25
|
+
config_path=config or cli_config.config_path,
|
|
26
|
+
output=output,
|
|
27
|
+
)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
TRANSACTION_FILE_NAME = 'transactions.py'
|
|
File without changes
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
from amsdal_framework.configs.main import settings
|
|
4
|
+
from amsdal_framework.manager import AmsdalManager
|
|
5
|
+
from amsdal_utils.config.manager import AmsdalConfigManager
|
|
6
|
+
from rich import print
|
|
7
|
+
|
|
8
|
+
from amsdal_cli.commands.build.utils.build_config_file import build_config_file
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def build_app(
|
|
12
|
+
app_source_path: Path,
|
|
13
|
+
config_path: Path,
|
|
14
|
+
output: Path = Path('.'),
|
|
15
|
+
) -> None:
|
|
16
|
+
settings.override(APP_PATH=output)
|
|
17
|
+
config_manager = AmsdalConfigManager()
|
|
18
|
+
config_manager.load_config(config_path)
|
|
19
|
+
amsdal_manager = AmsdalManager()
|
|
20
|
+
amsdal_manager.pre_setup()
|
|
21
|
+
|
|
22
|
+
print('[blue]Building models...[/blue]', end=' ')
|
|
23
|
+
amsdal_manager.build_models(app_source_path / 'models')
|
|
24
|
+
print('[green]OK![/green]')
|
|
25
|
+
|
|
26
|
+
if output == Path('.'):
|
|
27
|
+
print('[yellow]No output directory specified, skipping config.yml generation[/yellow]')
|
|
28
|
+
else:
|
|
29
|
+
# build config file
|
|
30
|
+
build_config_file(
|
|
31
|
+
output_path=output,
|
|
32
|
+
config_path=config_path,
|
|
33
|
+
no_input=True,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
print('[blue]Building transactions...[/blue]', end=' ')
|
|
37
|
+
amsdal_manager.build_transactions(app_source_path)
|
|
38
|
+
print('[green]OK![/green]')
|
|
39
|
+
|
|
40
|
+
print('[blue]Building static files...[/blue]', end=' ')
|
|
41
|
+
amsdal_manager.build_static_files(app_source_path)
|
|
42
|
+
print('[green]OK![/green]')
|
|
43
|
+
|
|
44
|
+
print('[blue]Building fixtures...[/blue]', end=' ')
|
|
45
|
+
amsdal_manager.build_fixtures(app_source_path / 'models')
|
|
46
|
+
print('[green]OK![/green]')
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
import typer
|
|
4
|
+
from rich import print
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def build_config_file(
|
|
8
|
+
output_path: Path,
|
|
9
|
+
config_path: Path,
|
|
10
|
+
*,
|
|
11
|
+
no_input: bool,
|
|
12
|
+
) -> None:
|
|
13
|
+
print('[blue]Building config.yml file...[/blue]', end=' ')
|
|
14
|
+
|
|
15
|
+
if not config_path.exists() or not config_path.name.endswith('.yml'):
|
|
16
|
+
print(f'\n[red]Config file "{config_path.resolve()}" does not exist or has wrong extension.[/red]')
|
|
17
|
+
raise typer.Exit(1)
|
|
18
|
+
|
|
19
|
+
config_destination = output_path / 'config.yml'
|
|
20
|
+
|
|
21
|
+
if (
|
|
22
|
+
no_input
|
|
23
|
+
or not config_destination.exists()
|
|
24
|
+
or (
|
|
25
|
+
typer.confirm(
|
|
26
|
+
f'\nThe config file "{config_destination.resolve()}" already exists. Would you like to overwrite it?',
|
|
27
|
+
)
|
|
28
|
+
)
|
|
29
|
+
):
|
|
30
|
+
config_destination.parent.mkdir(parents=True, exist_ok=True)
|
|
31
|
+
config_destination.touch(exist_ok=True)
|
|
32
|
+
|
|
33
|
+
with config_path.open('rt') as _file:
|
|
34
|
+
config_destination.write_text(_file.read())
|
|
35
|
+
|
|
36
|
+
print('[green]OK![/green]')
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
from json import JSONDecodeError
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
import typer
|
|
7
|
+
from rich import print
|
|
8
|
+
|
|
9
|
+
from amsdal_cli.utils.cli_config import CliConfig
|
|
10
|
+
|
|
11
|
+
COMMANDS_DO_NOT_REQUIRE_APP_PATH = ('new', 'migrate', 'write_logs')
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def init_app_context(ctx: typer.Context) -> None:
|
|
15
|
+
"""
|
|
16
|
+
AMSDAL CLI - a tool that provides the ability to create a new app,
|
|
17
|
+
generate models, transactions, build, serve, and other useful features
|
|
18
|
+
for the efficient building of new apps using AMSDAL Framework.
|
|
19
|
+
"""
|
|
20
|
+
if not ctx.invoked_subcommand:
|
|
21
|
+
return
|
|
22
|
+
|
|
23
|
+
templates_path = Path(__file__).parent / ctx.invoked_subcommand / 'templates'
|
|
24
|
+
|
|
25
|
+
if ctx.invoked_subcommand in COMMANDS_DO_NOT_REQUIRE_APP_PATH:
|
|
26
|
+
ctx.meta['config'] = CliConfig(templates_path=templates_path)
|
|
27
|
+
|
|
28
|
+
return
|
|
29
|
+
|
|
30
|
+
app_path = Path(os.getcwd())
|
|
31
|
+
cli_config = app_path / '.amsdal-cli'
|
|
32
|
+
|
|
33
|
+
if not cli_config.exists():
|
|
34
|
+
print(f'[red]The directory "{app_path.resolve()}" does not contain AMSDAL application.[/red]')
|
|
35
|
+
print('Use the "amsdal new --help" command to see details about how to create an application.')
|
|
36
|
+
raise typer.Exit(1)
|
|
37
|
+
|
|
38
|
+
with cli_config.open('rt') as config_file:
|
|
39
|
+
try:
|
|
40
|
+
ctx.meta['config'] = CliConfig(
|
|
41
|
+
app_directory=app_path,
|
|
42
|
+
templates_path=templates_path,
|
|
43
|
+
**json.loads(config_file.read()),
|
|
44
|
+
)
|
|
45
|
+
except JSONDecodeError as err:
|
|
46
|
+
print(f'[red]The config file "{cli_config.resolve()}" is corrupted.[/red]')
|
|
47
|
+
raise typer.Exit(1) from err
|
|
File without changes
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
|
|
3
|
+
SOURCES_DIR = 'src'
|
|
4
|
+
MODEL_JSON_FILE = 'model.json'
|
|
5
|
+
MODEL_PY_FILE = 'model.py'
|
|
6
|
+
FIXTURES_JSON_FILE = 'fixtures.json'
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class HookName(str, Enum):
|
|
10
|
+
PRE_INIT = 'pre_init'
|
|
11
|
+
POST_INIT = 'post_init'
|
|
12
|
+
PRE_CREATE = 'pre_create'
|
|
13
|
+
POST_CREATE = 'post_create'
|
|
14
|
+
PRE_UPDATE = 'pre_update'
|
|
15
|
+
POST_UPDATE = 'post_update'
|
|
16
|
+
PRE_DELETE = 'pre_delete'
|
|
17
|
+
POST_DELETE = 'post_delete'
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class ModifierName(str, Enum):
|
|
21
|
+
CONSTRUCTOR = 'constructor'
|
|
22
|
+
DISPLAY_NAME = 'display_name'
|
|
23
|
+
VERSION_NAME = 'version_name'
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class ModelFormat(str, Enum):
|
|
27
|
+
JSON = 'json'
|
|
28
|
+
PY = 'py'
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class AttributeType(str, Enum):
|
|
32
|
+
STRING = 'string'
|
|
33
|
+
NUMBER = 'number'
|
|
34
|
+
BOOLEAN = 'boolean'
|
|
35
|
+
BELONGS_TO = 'belongs-to'
|
|
36
|
+
HAS_MANY = 'has-many'
|
|
37
|
+
DICT = 'dict'
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class JsonType(str, Enum):
|
|
41
|
+
STRING = 'string'
|
|
42
|
+
NUMBER = 'number'
|
|
43
|
+
BOOLEAN = 'boolean'
|
|
44
|
+
ARRAY = 'array'
|
|
45
|
+
DICT = 'dictionary'
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class OptionName(str, Enum):
|
|
49
|
+
INDEX = 'index'
|
|
50
|
+
DEFAULT = 'default'
|
|
51
|
+
REQUIRED = 'required'
|
|
52
|
+
UNIQUE = 'unique'
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from amsdal_cli.commands.generate.sub_commands.generate_hook import generate_hook
|
|
2
|
+
from amsdal_cli.commands.generate.sub_commands.generate_model import generate_model
|
|
3
|
+
from amsdal_cli.commands.generate.sub_commands.generate_modifier import generate_modifier
|
|
4
|
+
from amsdal_cli.commands.generate.sub_commands.generate_property import generate_property
|
|
5
|
+
from amsdal_cli.commands.generate.sub_commands.generate_transaction import generate_transaction
|
|
6
|
+
|
|
7
|
+
__all__ = [
|
|
8
|
+
'generate_model',
|
|
9
|
+
'generate_property',
|
|
10
|
+
'generate_hook',
|
|
11
|
+
'generate_modifier',
|
|
12
|
+
'generate_transaction',
|
|
13
|
+
]
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import typer
|
|
2
|
+
|
|
3
|
+
from amsdal_cli.commands.generate.app import sub_app
|
|
4
|
+
from amsdal_cli.commands.generate.enums import HookName
|
|
5
|
+
from amsdal_cli.commands.generate.utils.build_base_path import build_model_base_path
|
|
6
|
+
from amsdal_cli.utils.cli_config import CliConfig
|
|
7
|
+
from amsdal_cli.utils.copier import copy_blueprint
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@sub_app.command(name='hook')
|
|
11
|
+
def generate_hook(
|
|
12
|
+
ctx: typer.Context,
|
|
13
|
+
hook_name: HookName = typer.Argument( # noqa: B008
|
|
14
|
+
...,
|
|
15
|
+
help='The hook name.',
|
|
16
|
+
),
|
|
17
|
+
model: str = typer.Option(..., help='The model name. It should be provided in PascalCase.'),
|
|
18
|
+
) -> None:
|
|
19
|
+
"""
|
|
20
|
+
Generates hook file for specified model.
|
|
21
|
+
"""
|
|
22
|
+
cli_config: CliConfig = ctx.meta['config']
|
|
23
|
+
base_path = build_model_base_path(ctx, model)
|
|
24
|
+
output_path = base_path / 'hooks'
|
|
25
|
+
|
|
26
|
+
copy_blueprint(
|
|
27
|
+
source_file_path=cli_config.templates_path / 'hook.pyt',
|
|
28
|
+
destination_path=output_path,
|
|
29
|
+
destination_name=f'{hook_name.value}.py',
|
|
30
|
+
context={
|
|
31
|
+
'hook_name': hook_name.value,
|
|
32
|
+
'is_init': hook_name in (HookName.PRE_INIT, HookName.POST_INIT),
|
|
33
|
+
},
|
|
34
|
+
confirm_overwriting=True,
|
|
35
|
+
)
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
import typer
|
|
5
|
+
from amsdal_utils.utils.text import classify
|
|
6
|
+
from amsdal_utils.utils.text import to_snake_case
|
|
7
|
+
from rich import print
|
|
8
|
+
|
|
9
|
+
from amsdal_cli.commands.generate.app import sub_app
|
|
10
|
+
from amsdal_cli.commands.generate.enums import MODEL_JSON_FILE
|
|
11
|
+
from amsdal_cli.commands.generate.enums import SOURCES_DIR
|
|
12
|
+
from amsdal_cli.commands.generate.enums import ModelFormat
|
|
13
|
+
from amsdal_cli.commands.generate.utils.model_attributes import parse_attributes
|
|
14
|
+
from amsdal_cli.utils.cli_config import CliConfig
|
|
15
|
+
from amsdal_cli.utils.copier import write_file
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@sub_app.command(name='model')
|
|
19
|
+
def generate_model(
|
|
20
|
+
ctx: typer.Context,
|
|
21
|
+
model_name: str = typer.Argument(
|
|
22
|
+
...,
|
|
23
|
+
help='The model name. It should be provided in PascalCase.',
|
|
24
|
+
),
|
|
25
|
+
model_format: ModelFormat = typer.Option(ModelFormat.JSON.value, '--format'), # noqa: B008
|
|
26
|
+
attrs: list[str] = typer.Option( # noqa: B008
|
|
27
|
+
(None,),
|
|
28
|
+
'--attributes',
|
|
29
|
+
'-attrs',
|
|
30
|
+
),
|
|
31
|
+
unique: list[str] = typer.Option( # noqa: B008
|
|
32
|
+
(None,),
|
|
33
|
+
'--unique',
|
|
34
|
+
'-u',
|
|
35
|
+
),
|
|
36
|
+
) -> None:
|
|
37
|
+
"""
|
|
38
|
+
Generates model file.
|
|
39
|
+
|
|
40
|
+
Example of usage:
|
|
41
|
+
|
|
42
|
+
>>> bin/cli --app-path ./apps/my_app/ generate model UserProfile --format json -attrs "name:string \
|
|
43
|
+
email:string:index age:number:default=18"
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
if model_format == ModelFormat.PY:
|
|
47
|
+
print('[red]The PY format is not supported for now.[/red]')
|
|
48
|
+
raise typer.Exit
|
|
49
|
+
|
|
50
|
+
cli_config: CliConfig = ctx.meta['config']
|
|
51
|
+
model_name = classify(model_name)
|
|
52
|
+
name = to_snake_case(model_name)
|
|
53
|
+
|
|
54
|
+
output_path = cli_config.app_directory / SOURCES_DIR / 'models' / name
|
|
55
|
+
parsed_attrs = parse_attributes(attrs)
|
|
56
|
+
|
|
57
|
+
schema: dict[str, Any] = {
|
|
58
|
+
'title': model_name,
|
|
59
|
+
'type': 'object',
|
|
60
|
+
'properties': {},
|
|
61
|
+
'required': [attr.name for attr in parsed_attrs if attr.required],
|
|
62
|
+
'indexed': [attr.name for attr in parsed_attrs if attr.index],
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
unique_attrs: list[str | tuple[str, ...]] = [attr.name for attr in parsed_attrs if attr.unique]
|
|
66
|
+
|
|
67
|
+
for _unique in filter(None, unique):
|
|
68
|
+
_unique_attrs = tuple(map(str.strip, _unique.split(',')))
|
|
69
|
+
|
|
70
|
+
if _unique_attrs not in unique_attrs:
|
|
71
|
+
unique_attrs.append(_unique_attrs)
|
|
72
|
+
|
|
73
|
+
if unique_attrs:
|
|
74
|
+
schema['unique_properties'] = unique_attrs
|
|
75
|
+
|
|
76
|
+
for attr in parsed_attrs:
|
|
77
|
+
property_info: dict[str, Any] = {
|
|
78
|
+
'title': attr.name,
|
|
79
|
+
'type': attr.json_type,
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if attr.has_items:
|
|
83
|
+
property_info['items'] = attr.json_items
|
|
84
|
+
|
|
85
|
+
if attr.default != attr.NotSet:
|
|
86
|
+
property_info['default'] = attr.default
|
|
87
|
+
|
|
88
|
+
schema['properties'][attr.name] = property_info
|
|
89
|
+
|
|
90
|
+
write_file(
|
|
91
|
+
json.dumps(schema, indent=cli_config.json_indent),
|
|
92
|
+
destination_file_path=output_path / MODEL_JSON_FILE,
|
|
93
|
+
confirm_overwriting=True,
|
|
94
|
+
)
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import typer
|
|
2
|
+
|
|
3
|
+
from amsdal_cli.commands.generate.app import sub_app
|
|
4
|
+
from amsdal_cli.commands.generate.enums import ModifierName
|
|
5
|
+
from amsdal_cli.commands.generate.utils.build_base_path import build_model_base_path
|
|
6
|
+
from amsdal_cli.utils.cli_config import CliConfig
|
|
7
|
+
from amsdal_cli.utils.copier import copy_blueprint
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@sub_app.command(name='modifier')
|
|
11
|
+
def generate_modifier(
|
|
12
|
+
ctx: typer.Context,
|
|
13
|
+
modifier_name: ModifierName = typer.Argument( # noqa: B008
|
|
14
|
+
...,
|
|
15
|
+
help='The modifier name.',
|
|
16
|
+
),
|
|
17
|
+
model: str = typer.Option(..., help='The model name. It should be provided in PascalCase.'),
|
|
18
|
+
) -> None:
|
|
19
|
+
"""
|
|
20
|
+
Generates modifier file for specified model.
|
|
21
|
+
"""
|
|
22
|
+
cli_config: CliConfig = ctx.meta['config']
|
|
23
|
+
base_path = build_model_base_path(ctx, model)
|
|
24
|
+
modifier_path = base_path / 'modifiers'
|
|
25
|
+
|
|
26
|
+
copy_blueprint(
|
|
27
|
+
source_file_path=cli_config.templates_path / 'modifier' / f'{modifier_name.value}.pyt',
|
|
28
|
+
destination_path=modifier_path,
|
|
29
|
+
destination_name=f'{modifier_name.value}.py',
|
|
30
|
+
context={},
|
|
31
|
+
confirm_overwriting=True,
|
|
32
|
+
)
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import typer
|
|
2
|
+
from amsdal_utils.utils.text import to_snake_case
|
|
3
|
+
|
|
4
|
+
from amsdal_cli.commands.generate.app import sub_app
|
|
5
|
+
from amsdal_cli.commands.generate.utils.build_base_path import build_model_base_path
|
|
6
|
+
from amsdal_cli.utils.cli_config import CliConfig
|
|
7
|
+
from amsdal_cli.utils.copier import copy_blueprint
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@sub_app.command(name='property')
|
|
11
|
+
def generate_property(
|
|
12
|
+
ctx: typer.Context,
|
|
13
|
+
property_name: str = typer.Argument(
|
|
14
|
+
...,
|
|
15
|
+
help=(
|
|
16
|
+
'The property name. Note, it will always transform the provided name to camel_case. Enter the name in '
|
|
17
|
+
'camel_case in order to avoid any issues.'
|
|
18
|
+
),
|
|
19
|
+
),
|
|
20
|
+
model: str = typer.Option(..., help='The model name. It should be provided in PascalCase.'),
|
|
21
|
+
) -> None:
|
|
22
|
+
"""
|
|
23
|
+
Generates property file for specified model.
|
|
24
|
+
"""
|
|
25
|
+
cli_config: CliConfig = ctx.meta['config']
|
|
26
|
+
base_path = build_model_base_path(ctx, model)
|
|
27
|
+
name = to_snake_case(property_name)
|
|
28
|
+
output_path = base_path / 'properties'
|
|
29
|
+
|
|
30
|
+
copy_blueprint(
|
|
31
|
+
source_file_path=cli_config.templates_path / 'property.pyt',
|
|
32
|
+
destination_path=output_path,
|
|
33
|
+
destination_name=f'{name}.py',
|
|
34
|
+
context={
|
|
35
|
+
'property_name': name,
|
|
36
|
+
},
|
|
37
|
+
confirm_overwriting=True,
|
|
38
|
+
)
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import typer
|
|
2
|
+
from amsdal_utils.utils.text import classify
|
|
3
|
+
from amsdal_utils.utils.text import to_snake_case
|
|
4
|
+
|
|
5
|
+
from amsdal_cli.commands.generate.app import sub_app
|
|
6
|
+
from amsdal_cli.commands.generate.enums import SOURCES_DIR
|
|
7
|
+
from amsdal_cli.utils.cli_config import CliConfig
|
|
8
|
+
from amsdal_cli.utils.copier import copy_blueprint
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@sub_app.command(name='transaction')
|
|
12
|
+
def generate_transaction(
|
|
13
|
+
ctx: typer.Context,
|
|
14
|
+
transaction_name: str = typer.Argument(
|
|
15
|
+
...,
|
|
16
|
+
help=(
|
|
17
|
+
'The transaction name. Note, it will always transform the provided name to camel_case. Enter the name in '
|
|
18
|
+
'camel_case in order to avoid any issues.'
|
|
19
|
+
),
|
|
20
|
+
),
|
|
21
|
+
) -> None:
|
|
22
|
+
"""
|
|
23
|
+
Generates transaction file for specified model.
|
|
24
|
+
"""
|
|
25
|
+
cli_config: CliConfig = ctx.meta['config']
|
|
26
|
+
name = to_snake_case(transaction_name)
|
|
27
|
+
output_path = cli_config.app_directory / SOURCES_DIR / 'transactions'
|
|
28
|
+
|
|
29
|
+
copy_blueprint(
|
|
30
|
+
source_file_path=cli_config.templates_path / 'transaction.pyt',
|
|
31
|
+
destination_path=output_path,
|
|
32
|
+
destination_name=f'{name}.py',
|
|
33
|
+
context={
|
|
34
|
+
'transaction_method_name': name,
|
|
35
|
+
'transaction_class_name': classify(transaction_name),
|
|
36
|
+
},
|
|
37
|
+
confirm_overwriting=True,
|
|
38
|
+
)
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
def __init__(self, **kwargs):
|
|
2
|
+
# Add implementation here
|
|
3
|
+
# Note, **kwargs contain raw data, which is not validated yet.
|
|
4
|
+
|
|
5
|
+
super().__init__(**kwargs)
|
|
6
|
+
|
|
7
|
+
# Or add implementation here
|
|
8
|
+
# Note, **kwargs were validated, converted to the correct types and
|
|
9
|
+
# assigned to the corresponding fields.
|
|
10
|
+
# So you safely can use them here via self.
|
|
File without changes
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
import typer
|
|
4
|
+
from amsdal_utils.utils.text import to_snake_case
|
|
5
|
+
from rich import print
|
|
6
|
+
|
|
7
|
+
from amsdal_cli.commands.generate.enums import SOURCES_DIR
|
|
8
|
+
from amsdal_cli.utils.cli_config import CliConfig
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def build_model_base_path(ctx: typer.Context, model_name: str) -> Path:
|
|
12
|
+
cli_config: CliConfig = ctx.meta['config']
|
|
13
|
+
model = to_snake_case(model_name)
|
|
14
|
+
model_path = cli_config.app_directory / SOURCES_DIR / 'models' / model
|
|
15
|
+
|
|
16
|
+
if cli_config.check_model_exists and not (
|
|
17
|
+
(model_path / 'model.json').exists() or (model_path / 'model.py').exists()
|
|
18
|
+
):
|
|
19
|
+
print(f'[red]The model "{model_name}" does not exist.[/red]')
|
|
20
|
+
raise typer.Exit
|
|
21
|
+
|
|
22
|
+
return model_path
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
from amsdal_cli.commands.generate.enums import AttributeType
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def cast_to_attribute_type(
|
|
7
|
+
attr_type: AttributeType,
|
|
8
|
+
value: str,
|
|
9
|
+
) -> Any:
|
|
10
|
+
if value.lower() == 'null':
|
|
11
|
+
return None
|
|
12
|
+
|
|
13
|
+
match attr_type:
|
|
14
|
+
case AttributeType.NUMBER:
|
|
15
|
+
return float(value)
|
|
16
|
+
case AttributeType.BOOLEAN:
|
|
17
|
+
return value.lower() == 'true'
|
|
18
|
+
case _:
|
|
19
|
+
return value
|