arpakitlib 1.7.103__py3-none-any.whl → 1.7.132__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.
Files changed (64) hide show
  1. arpakitlib/_arpakit_project_template/README.md +1 -3
  2. arpakitlib/_arpakit_project_template/example.env +5 -0
  3. arpakitlib/_arpakit_project_template/manage/docker_run_postgres_for_dev.sh +3 -3
  4. arpakitlib/_arpakit_project_template/manage/docker_start_postgres_for_dev.sh +1 -1
  5. arpakitlib/_arpakit_project_template/manage/docker_stop_postgres_for_dev.sh +1 -1
  6. arpakitlib/_arpakit_project_template/manage/git_set_arpakit_company_origin.sh +2 -2
  7. arpakitlib/_arpakit_project_template/manage/git_set_arpakit_origin.sh +2 -2
  8. arpakitlib/_arpakit_project_template/manage/hello_world.py +2 -2
  9. arpakitlib/_arpakit_project_template/manage/{json_beutify.py → json_beautify.py} +2 -2
  10. arpakitlib/_arpakit_project_template/manage/poetry_config.sh +2 -0
  11. arpakitlib/_arpakit_project_template/manage/poetry_self_add_plugin_export.sh +2 -0
  12. arpakitlib/_arpakit_project_template/manage/poetry_show_arpakitlib.sh +1 -1
  13. arpakitlib/_arpakit_project_template/manage/sandbox/sandbox_1.py +4 -4
  14. arpakitlib/_arpakit_project_template/manage/sandbox/sandbox_2.py +4 -4
  15. arpakitlib/_arpakit_project_template/manage/sandbox/sandbox_3.py +4 -4
  16. arpakitlib/_arpakit_project_template/manage/sandbox/sandbox_4.py +4 -4
  17. arpakitlib/_arpakit_project_template/manage/sandbox/sandbox_5.py +4 -4
  18. arpakitlib/_arpakit_project_template/manage/sandbox/sandbox_6.py +4 -4
  19. arpakitlib/_arpakit_project_template/manage/sandbox/sandbox_7.py +4 -4
  20. arpakitlib/_arpakit_project_template/src/admin1/__init__.py +0 -0
  21. arpakitlib/_arpakit_project_template/src/admin1/add_admin_in_app.py +26 -0
  22. arpakitlib/_arpakit_project_template/src/admin1/admin_auth.py +29 -0
  23. arpakitlib/_arpakit_project_template/src/admin1/model_view.py +19 -0
  24. arpakitlib/_arpakit_project_template/src/api/create_api_app.py +14 -54
  25. arpakitlib/_arpakit_project_template/src/api/event.py +51 -2
  26. arpakitlib/_arpakit_project_template/src/api/start_api_for_dev_with_reload.py +12 -4
  27. arpakitlib/_arpakit_project_template/src/api/{start_api_for_dev.py → start_api_for_dev_without_reload.py} +3 -3
  28. arpakitlib/_arpakit_project_template/src/api/transmitted_api_data.py +4 -0
  29. arpakitlib/_arpakit_project_template/src/business_service/hello_world.py +12 -0
  30. arpakitlib/_arpakit_project_template/{manage/logging_check.py → src/core/check_logging.py} +3 -3
  31. arpakitlib/_arpakit_project_template/{manage/settings_check.py → src/core/check_settings.py} +2 -0
  32. arpakitlib/_arpakit_project_template/src/core/const.py +24 -25
  33. arpakitlib/_arpakit_project_template/src/core/generate_settings_env_example.py +16 -0
  34. arpakitlib/_arpakit_project_template/src/core/settings.py +16 -10
  35. arpakitlib/_arpakit_project_template/{manage/sqlalchemy_db_init.py → src/db/init_sqlalchemy_db.py} +2 -2
  36. arpakitlib/_arpakit_project_template/{manage/sqlalchemy_db_reinit.py → src/db/reinit_sqlalchemy_db.py} +4 -2
  37. arpakitlib/_arpakit_project_template/src/operation_execution/operation_executor.py +6 -4
  38. arpakitlib/_arpakit_project_template/src/operation_execution/scheduled_operations.py +3 -3
  39. arpakitlib/_arpakit_project_template/src/operation_execution/{start_operation_executor_worker_for_dev.py → start_operation_executor_worker.py} +5 -4
  40. arpakitlib/_arpakit_project_template/src/operation_execution/{start_scheduled_operation_creator_worker_for_dev.py → start_scheduled_operation_creator_worker.py} +6 -4
  41. arpakitlib/_arpakit_project_template/src/operation_execution/util.py +0 -21
  42. arpakitlib/_arpakit_project_template/src/tg_bot/__init__.py +0 -0
  43. arpakitlib/_arpakit_project_template/src/tg_bot/router/__init__.py +0 -0
  44. arpakitlib/_arpakit_project_template/src/tg_bot/start_tg_bot.py +0 -0
  45. arpakitlib/ar_arpakit_lib_module_util.py +7 -0
  46. arpakitlib/ar_arpakit_project_template_util.py +3 -3
  47. arpakitlib/ar_fastapi_util.py +0 -42
  48. arpakitlib/ar_settings_util.py +14 -5
  49. arpakitlib/ar_str_util.py +15 -15
  50. arpakitlib/ar_type_util.py +1 -1
  51. {arpakitlib-1.7.103.dist-info → arpakitlib-1.7.132.dist-info}/METADATA +27 -20
  52. {arpakitlib-1.7.103.dist-info → arpakitlib-1.7.132.dist-info}/RECORD +57 -53
  53. {arpakitlib-1.7.103.dist-info → arpakitlib-1.7.132.dist-info}/WHEEL +1 -1
  54. arpakitlib/_arpakit_project_template/AUTHOR.md +0 -4
  55. arpakitlib/_arpakit_project_template/manage/example_nginx_proxy.nginx +0 -14
  56. arpakitlib/_arpakit_project_template/manage/example_poetry_arpakitlib.sh +0 -1
  57. arpakitlib/_arpakit_project_template/manage/example_pyproject.toml +0 -18
  58. arpakitlib/_arpakit_project_template/manage/example_systemd.service +0 -12
  59. arpakitlib/_arpakit_project_template/manage/requirements.txt +0 -209
  60. arpakitlib/_arpakit_project_template/manage/settings_generate_env_example.py +0 -13
  61. /arpakitlib/_arpakit_project_template/{manage/sqlalchemy_db_check_conn.py → src/db/check_conn_sqlalchemy_db.py} +0 -0
  62. {arpakitlib-1.7.103.dist-info → arpakitlib-1.7.132.dist-info}/LICENSE +0 -0
  63. {arpakitlib-1.7.103.dist-info → arpakitlib-1.7.132.dist-info}/NOTICE +0 -0
  64. {arpakitlib-1.7.103.dist-info → arpakitlib-1.7.132.dist-info}/entry_points.txt +0 -0
@@ -2,41 +2,40 @@ import asyncio
2
2
  import os
3
3
  import pathlib
4
4
 
5
- BASE_DIRPATH: str = str(pathlib.Path(__file__).parent.parent.parent)
5
+ from arpakitlib.ar_enumeration_util import Enumeration
6
6
 
7
- ENV_FILENAME: str = ".env"
8
7
 
9
- ENV_FILEPATH: str = os.path.join(BASE_DIRPATH, ENV_FILENAME)
8
+ class ProjectPaths(Enumeration):
9
+ base_dirpath: str = str(pathlib.Path(__file__).parent.parent.parent)
10
10
 
11
- SRC_DIRNAME: str = "src"
11
+ env_filename: str = ".env"
12
+ env_filepath: str = os.path.join(base_dirpath, env_filename)
12
13
 
13
- SRC_DIRPATH: str = os.path.join(BASE_DIRPATH, SRC_DIRNAME)
14
+ src_dirname: str = "src"
15
+ src_dirpath: str = os.path.join(base_dirpath, src_dirname)
14
16
 
15
- MANAGE_DIRNAME: str = "manage"
17
+ manage_dirname: str = "manage"
18
+ manage_dirpath: str = os.path.join(base_dirpath, manage_dirname)
16
19
 
17
- MANAGE_DIRPATH: str = os.path.join(BASE_DIRPATH, MANAGE_DIRNAME)
20
+ resource_dirname: str = "resource"
21
+ resource_dirpath: str = os.path.join(base_dirpath, resource_dirname)
18
22
 
19
- RESOURCE_DIRNAME: str = "resource"
20
-
21
- RESOURCE_DIRPATH: str = os.path.join(BASE_DIRPATH, RESOURCE_DIRNAME)
22
-
23
- STATIC_DIRNAME: str = "static"
24
-
25
- STATIC_DIRPATH: str = os.path.join(RESOURCE_DIRPATH, STATIC_DIRNAME)
23
+ static_dirname: str = "static"
24
+ static_dirpath: str = os.path.join(resource_dirpath, static_dirname)
26
25
 
27
26
 
28
27
  def __example():
29
- print(f"BASE_DIRPATH: {BASE_DIRPATH}")
30
- print(f"ENV_FILENAME: {ENV_FILENAME}")
31
- print(f"ENV_FILEPATH: {ENV_FILEPATH}")
32
- print(f"SRC_DIRNAME: {SRC_DIRNAME}")
33
- print(f"SRC_DIRPATH: {SRC_DIRPATH}")
34
- print(f"MANAGE_DIRNAME: {MANAGE_DIRNAME}")
35
- print(f"MANAGE_DIRPATH: {MANAGE_DIRPATH}")
36
- print(f"RESOURCE_DIRNAME: {RESOURCE_DIRNAME}")
37
- print(f"RESOURCE_DIRPATH: {RESOURCE_DIRPATH}")
38
- print(f"STATIC_DIRNAME: {STATIC_DIRNAME}")
39
- print(f"STATIC_DIRPATH: {STATIC_DIRPATH}")
28
+ print(f"base_dirpath: {ProjectPaths.base_dirpath}")
29
+ print(f"env_filename: {ProjectPaths.env_filename}")
30
+ print(f"env_filepath: {ProjectPaths.env_filepath}")
31
+ print(f"src_dirname: {ProjectPaths.src_dirname}")
32
+ print(f"src_dirpath: {ProjectPaths.src_dirpath}")
33
+ print(f"manage_dirname: {ProjectPaths.manage_dirname}")
34
+ print(f"manage_dirpath: {ProjectPaths.manage_dirpath}")
35
+ print(f"resource_dirname: {ProjectPaths.resource_dirname}")
36
+ print(f"resource_dirpath: {ProjectPaths.resource_dirpath}")
37
+ print(f"static_dirname: {ProjectPaths.static_dirname}")
38
+ print(f"static_dirpath: {ProjectPaths.static_dirpath}")
40
39
 
41
40
 
42
41
  async def __async_example():
@@ -0,0 +1,16 @@
1
+ import os.path
2
+
3
+ from arpakitlib.ar_json_util import safely_transfer_obj_to_json_str
4
+ from src.core.const import ProjectPaths
5
+ from src.core.settings import Settings, get_cached_settings
6
+ from src.core.util import setup_logging
7
+
8
+
9
+ def command():
10
+ setup_logging()
11
+ print(safely_transfer_obj_to_json_str(get_cached_settings().model_dump(mode="json")))
12
+ Settings.save_env_example_to_file(filepath=os.path.join(ProjectPaths.base_dirpath, "example.env"))
13
+
14
+
15
+ if __name__ == '__main__':
16
+ command()
@@ -7,23 +7,25 @@ import pytz
7
7
 
8
8
  from arpakitlib.ar_json_util import safely_transfer_obj_to_json_str
9
9
  from arpakitlib.ar_settings_util import SimpleSettings
10
- from src.core.const import BASE_DIRPATH, ENV_FILEPATH
10
+ from src.core.const import ProjectPaths
11
11
 
12
12
 
13
13
  class Settings(SimpleSettings):
14
- project_name: str = "{PROJECT_NAME}"
14
+ project_name: str = "{{PROJECT_NAME}}"
15
+
16
+ sql_db_port: int | None = int("{{SQL_DB_PORT}}") if "{{SQL_DB_PORT}}".strip().isdigit() else None
15
17
 
16
18
  sql_db_url: str | None = (
17
- "postgresql://{PROJECT_NAME}:{PROJECT_NAME}@127.0.0.1:{SQL_DB_PORT}/{PROJECT_NAME}"
18
- ) if (str("{PROJECT_NAME}") and str("{SQL_DB_PORT}").strip().isdigit()) else None
19
+ f"postgresql://{{PROJECT_NAME}}:{{PROJECT_NAME}}@127.0.0.1:{sql_db_port}/{{PROJECT_NAME}}"
20
+ ) if sql_db_port is not None else None
19
21
 
20
22
  sql_db_echo: bool = False
21
23
 
22
24
  api_init_sql_db_at_start: bool = True
23
25
 
24
- api_title: str = "{PROJECT_NAME}"
26
+ api_title: str = project_name
25
27
 
26
- api_description: str = "{PROJECT_NAME} (arpakitlib)"
28
+ api_description: str = f"{project_name} (arpakitlib)"
27
29
 
28
30
  api_create_story_log_before_response_in_handle_exception: bool = True
29
31
 
@@ -31,15 +33,17 @@ class Settings(SimpleSettings):
31
33
 
32
34
  api_start_scheduled_operation_creator_worker: bool = False
33
35
 
34
- api_port: int | None = int("{API_PORT}") if "{API_PORT}".strip().isdigit() else None
36
+ api_port: int | None = int("{{API_PORT}}") if "{{API_PORT}}".strip().isdigit() else None
35
37
 
36
38
  api_correct_api_key: str | None = "1"
37
39
 
38
40
  api_correct_token: str | None = "1"
39
41
 
42
+ api_enable_admin1: bool = True
43
+
40
44
  var_dirname: str | None = "var"
41
45
 
42
- var_dirpath: str | None = os.path.join(BASE_DIRPATH, var_dirname)
46
+ var_dirpath: str | None = os.path.join(ProjectPaths.base_dirpath, var_dirname)
43
47
 
44
48
  log_filename: str | None = "story.log"
45
49
 
@@ -63,13 +67,15 @@ class Settings(SimpleSettings):
63
67
  def local_timezone_as_pytz(self) -> Any:
64
68
  return pytz.timezone(self.local_timezone)
65
69
 
70
+ admin1_secret_key: str | None = "85a9583cb91c4de7a78d7eb1e5306a04418c9c43014c447ea8ec8dd5deb4cf71"
71
+
66
72
  # ...
67
73
 
68
74
 
69
75
  @lru_cache()
70
76
  def get_cached_settings() -> Settings:
71
- if os.path.exists(ENV_FILEPATH):
72
- return Settings(_env_file=ENV_FILEPATH, _env_file_encoding="utf-8")
77
+ if os.path.exists(ProjectPaths.env_filepath):
78
+ return Settings(_env_file=ProjectPaths.env_filepath, _env_file_encoding="utf-8")
73
79
  return Settings()
74
80
 
75
81
 
@@ -2,10 +2,10 @@ from src.core.util import setup_logging
2
2
  from src.db.util import get_cached_sqlalchemy_db
3
3
 
4
4
 
5
- def command():
5
+ def __init_sqlalchemy_db():
6
6
  setup_logging()
7
7
  get_cached_sqlalchemy_db().init()
8
8
 
9
9
 
10
10
  if __name__ == '__main__':
11
- command()
11
+ __init_sqlalchemy_db()
@@ -1,11 +1,13 @@
1
+ from src.core.settings import get_cached_settings
1
2
  from src.core.util import setup_logging
2
3
  from src.db.util import get_cached_sqlalchemy_db
3
4
 
4
5
 
5
- def command():
6
+ def __reinit_sqlalchemy_db():
6
7
  setup_logging()
8
+ get_cached_settings().raise_if_mode_type_not_prod()
7
9
  get_cached_sqlalchemy_db().reinit()
8
10
 
9
11
 
10
12
  if __name__ == '__main__':
11
- command()
13
+ __reinit_sqlalchemy_db()
@@ -1,14 +1,16 @@
1
+ from sqlalchemy.orm import Session
2
+
1
3
  from arpakitlib.ar_operation_execution_util import BaseOperationExecutor
2
4
  from arpakitlib.ar_sqlalchemy_model_util import OperationDBM
3
5
 
4
6
 
5
7
  class OperationExecutor(BaseOperationExecutor):
6
- def sync_execute_operation(self, operation_dbm: OperationDBM) -> OperationDBM:
8
+ def sync_execute_operation(self, operation_dbm: OperationDBM, session: Session) -> OperationDBM:
7
9
  # ...
8
- operation_dbm = super().sync_execute_operation(operation_dbm=operation_dbm)
10
+ operation_dbm = super().sync_execute_operation(operation_dbm=operation_dbm, session=session)
9
11
  return operation_dbm
10
12
 
11
- async def async_execute_operation(self, operation_dbm: OperationDBM) -> OperationDBM:
13
+ async def async_execute_operation(self, operation_dbm: OperationDBM, session: Session) -> OperationDBM:
12
14
  # ...
13
- operation_dbm = await super().async_execute_operation(operation_dbm=operation_dbm)
15
+ operation_dbm = await super().async_execute_operation(operation_dbm=operation_dbm, session=session)
14
16
  return operation_dbm
@@ -4,14 +4,14 @@ from arpakitlib.ar_operation_execution_util import ScheduledOperation, every_tim
4
4
  between_different_times_is_time_func
5
5
  from arpakitlib.ar_sqlalchemy_model_util import BaseOperationTypes
6
6
 
7
- ALL_SCHEDULED_OPERATIONS = []
7
+ SCHEDULED_OPERATIONS = []
8
8
 
9
9
  healthcheck_1_scheduled_operation = ScheduledOperation(
10
10
  type=BaseOperationTypes.healthcheck_,
11
11
  input_data={"healthcheck_1": "healthcheck_1"},
12
12
  is_time_func=every_timedelta_is_time_func(td=timedelta(seconds=15))
13
13
  )
14
- ALL_SCHEDULED_OPERATIONS.append(healthcheck_1_scheduled_operation)
14
+ SCHEDULED_OPERATIONS.append(healthcheck_1_scheduled_operation)
15
15
 
16
16
  healthcheck_2_scheduled_operation = ScheduledOperation(
17
17
  type=BaseOperationTypes.healthcheck_,
@@ -22,4 +22,4 @@ healthcheck_2_scheduled_operation = ScheduledOperation(
22
22
  ),
23
23
  timeout_after_creation=timedelta(seconds=60)
24
24
  )
25
- ALL_SCHEDULED_OPERATIONS.append(healthcheck_2_scheduled_operation)
25
+ SCHEDULED_OPERATIONS.append(healthcheck_2_scheduled_operation)
@@ -1,18 +1,19 @@
1
1
  from arpakitlib.ar_operation_execution_util import OperationExecutorWorker
2
+ from src.core.settings import get_cached_settings
2
3
  from src.core.util import setup_logging
3
4
  from src.db.util import get_cached_sqlalchemy_db
4
5
  from src.operation_execution.operation_executor import OperationExecutor
5
6
 
6
7
 
7
- def start_operation_executor_worker_for_dev():
8
+ def start_operation_executor_worker():
8
9
  setup_logging()
10
+ get_cached_settings().raise_if_mode_type_prod()
9
11
  worker = OperationExecutorWorker(
10
12
  sqlalchemy_db=get_cached_sqlalchemy_db(),
11
- operation_executor=OperationExecutor(sqlalchemy_db=get_cached_sqlalchemy_db()),
12
- filter_operation_types=None
13
+ operation_executor=OperationExecutor(sqlalchemy_db=get_cached_sqlalchemy_db())
13
14
  )
14
15
  worker.sync_safe_run()
15
16
 
16
17
 
17
18
  if __name__ == '__main__':
18
- start_operation_executor_worker_for_dev()
19
+ start_operation_executor_worker()
@@ -1,17 +1,19 @@
1
1
  from arpakitlib.ar_operation_execution_util import ScheduledOperationCreatorWorker
2
+ from src.core.settings import get_cached_settings
2
3
  from src.core.util import setup_logging
3
4
  from src.db.util import get_cached_sqlalchemy_db
4
- from src.operation_execution.scheduled_operations import ALL_SCHEDULED_OPERATIONS
5
+ from src.operation_execution.scheduled_operations import SCHEDULED_OPERATIONS
5
6
 
6
7
 
7
- def start_create_scheduled_operation_worker_for_dev():
8
+ def start_scheduled_operation_creator_worker():
8
9
  setup_logging()
10
+ get_cached_settings().raise_if_mode_type_prod()
9
11
  worker = ScheduledOperationCreatorWorker(
10
12
  sqlalchemy_db=get_cached_sqlalchemy_db(),
11
- scheduled_operations=ALL_SCHEDULED_OPERATIONS
13
+ scheduled_operations=SCHEDULED_OPERATIONS
12
14
  )
13
15
  worker.sync_safe_run()
14
16
 
15
17
 
16
18
  if __name__ == '__main__':
17
- start_create_scheduled_operation_worker_for_dev()
19
+ start_scheduled_operation_creator_worker()
@@ -1,21 +0,0 @@
1
- from datetime import timedelta
2
- from functools import lru_cache
3
-
4
- from arpakitlib.ar_operation_execution_util import ScheduledOperationCreatorWorker
5
- from src.db.util import get_cached_sqlalchemy_db
6
-
7
-
8
- def create_scheduled_operation_creator_worker() -> ScheduledOperationCreatorWorker:
9
- from src.operation_execution.scheduled_operations import ALL_SCHEDULED_OPERATIONS
10
- scheduled_operation_creator_worker = ScheduledOperationCreatorWorker(
11
- sqlalchemy_db=get_cached_sqlalchemy_db(),
12
- scheduled_operations=ALL_SCHEDULED_OPERATIONS,
13
- timeout_after_run=timedelta(seconds=0.1).total_seconds(),
14
- timeout_after_err_in_run=timedelta(seconds=1).total_seconds()
15
- )
16
- return scheduled_operation_creator_worker
17
-
18
-
19
- @lru_cache()
20
- def get_scheduled_operation_creator_worker() -> ScheduledOperationCreatorWorker:
21
- return create_scheduled_operation_creator_worker()
@@ -79,6 +79,12 @@ class ArpakitLibModules(NamedTuple):
79
79
  if arpakit_lib_module.module_has_error
80
80
  ]
81
81
 
82
+ def have_modules_with_error(self) -> bool:
83
+ for arpakit_lib_module in self.arpakit_lib_modules:
84
+ if arpakit_lib_module.module_has_error:
85
+ return True
86
+ return False
87
+
82
88
  def module_name_to_module_exception(self, *, filter_module_has_error: bool = False) -> dict[str, BaseException]:
83
89
  if filter_module_has_error:
84
90
  return {
@@ -150,6 +156,7 @@ def __example():
150
156
  print(module_name)
151
157
  print(d)
152
158
  print()
159
+ print("have_modules_with_error", get_arpakit_lib_modules().have_modules_with_error())
153
160
 
154
161
 
155
162
  if __name__ == '__main__':
@@ -69,11 +69,11 @@ def init_arpakit_project_template(
69
69
  with open(os.path.join(root, file), "r", encoding="utf-8") as _file:
70
70
  _content = _file.read()
71
71
  if project_name is not None:
72
- _content = _content.replace("{PROJECT_NAME}", project_name)
72
+ _content = _content.replace("{{PROJECT_NAME}}", project_name)
73
73
  if sql_db_port is not None:
74
- _content = _content.replace("{SQL_DB_PORT}", str(sql_db_port))
74
+ _content = _content.replace("{{SQL_DB_PORT}}", str(sql_db_port))
75
75
  if api_port is not None:
76
- _content = _content.replace("{API_PORT}", str(api_port))
76
+ _content = _content.replace("{{API_PORT}}", str(api_port))
77
77
  res[rel_path] = _content
78
78
  return res
79
79
 
@@ -25,10 +25,8 @@ from starlette import status
25
25
  from starlette.middleware.cors import CORSMiddleware
26
26
  from starlette.staticfiles import StaticFiles
27
27
 
28
- from arpakitlib.ar_base_worker_util import BaseWorker, safe_run_worker_in_background
29
28
  from arpakitlib.ar_dict_util import combine_dicts
30
29
  from arpakitlib.ar_enumeration_util import Enumeration
31
- from arpakitlib.ar_file_storage_in_dir_util import FileStorageInDir
32
30
  from arpakitlib.ar_func_util import raise_if_not_async_func, is_async_function, is_async_object
33
31
  from arpakitlib.ar_json_util import safely_transfer_obj_to_json_str_to_json_obj
34
32
  from arpakitlib.ar_logging_util import setup_normal_logging
@@ -431,37 +429,6 @@ class BaseShutdownAPIEvent:
431
429
  self._logger.info("on_shutdown ends")
432
430
 
433
431
 
434
- class InitSqlalchemyDBStartupAPIEvent(BaseStartupAPIEvent):
435
- def __init__(self, sqlalchemy_db: SQLAlchemyDB):
436
- super().__init__()
437
- self.sqlalchemy_db = sqlalchemy_db
438
-
439
- async def async_on_startup(self, *args, **kwargs):
440
- self.sqlalchemy_db.init()
441
-
442
-
443
- class SafeRunWorkerStartupAPIEvent(BaseStartupAPIEvent):
444
- def __init__(self, workers: list[BaseWorker], safe_run_in_background_mode: str):
445
- super().__init__()
446
- self.workers = workers
447
- self.safe_run_in_background_mode = safe_run_in_background_mode
448
-
449
- async def async_on_startup(self, *args, **kwargs):
450
- for worker in self.workers:
451
- _ = safe_run_worker_in_background(worker=worker, mode=self.safe_run_in_background_mode)
452
-
453
-
454
- class InitFileStoragesInDir(BaseStartupAPIEvent):
455
- def __init__(self, file_storages_in_dir: list[FileStorageInDir | None]):
456
- super().__init__()
457
- file_storages_in_dir = [v for v in file_storages_in_dir if v is not None]
458
- self.file_storages_in_dir = file_storages_in_dir
459
-
460
- async def async_on_startup(self, *args, **kwargs):
461
- for file_storage_in_dir in self.file_storages_in_dir:
462
- file_storage_in_dir.init()
463
-
464
-
465
432
  class BaseTransmittedAPIData(BaseModel):
466
433
  model_config = ConfigDict(extra="ignore", arbitrary_types_allowed=True, from_attributes=True)
467
434
 
@@ -693,12 +660,6 @@ def simple_api_router_for_testing():
693
660
  return router
694
661
 
695
662
 
696
- DEFAULT_CONTACT = {
697
- "name": "ARPAKIT Company",
698
- "email": "support@arpakit.com"
699
- }
700
-
701
-
702
663
  def create_fastapi_app(
703
664
  *,
704
665
  title: str = "arpakitlib FastAPI",
@@ -720,9 +681,6 @@ def create_fastapi_app(
720
681
  if handle_exception_ is None:
721
682
  handle_exception_ = create_handle_exception()
722
683
 
723
- if contact is None:
724
- contact = DEFAULT_CONTACT
725
-
726
684
  if not startup_api_events:
727
685
  startup_api_events = [BaseStartupAPIEvent()]
728
686
  startup_api_events = [v for v in startup_api_events if v is not None]
@@ -21,29 +21,38 @@ def generate_env_example(settings_class: Union[BaseSettings, type[BaseSettings]]
21
21
  return res
22
22
 
23
23
 
24
+ class ModeTypes(Enumeration):
25
+ not_prod: str = "not_prod"
26
+ prod: str = "prod"
27
+
28
+
24
29
  class SimpleSettings(BaseSettings):
25
30
  model_config = ConfigDict(extra="ignore")
26
31
 
27
- class ModeTypes(Enumeration):
28
- not_prod: str = "not_prod"
29
- prod: str = "prod"
30
-
31
32
  mode_type: str = ModeTypes.not_prod
32
33
 
33
34
  @field_validator("mode_type")
34
35
  @classmethod
35
36
  def validate_mode_type(cls, v: str):
36
- cls.ModeTypes.parse_and_validate_values(v)
37
+ ModeTypes.parse_and_validate_values(v.lower().strip())
37
38
  return v
38
39
 
39
40
  @property
40
41
  def is_mode_type_not_prod(self) -> bool:
41
42
  return self.mode_type == self.ModeTypes.not_prod
42
43
 
44
+ def raise_if_mode_type_not_prod(self):
45
+ if self.is_mode_type_not_prod:
46
+ raise ValueError(f"mode type = {self.mode_type}")
47
+
43
48
  @property
44
49
  def is_mode_type_prod(self) -> bool:
45
50
  return self.mode_type == self.ModeTypes.prod
46
51
 
52
+ def raise_if_mode_type_prod(self):
53
+ if self.is_mode_type_prod:
54
+ raise ValueError(f"mode type = {self.mode_type}")
55
+
47
56
  @classmethod
48
57
  def generate_env_example(cls) -> str:
49
58
  return generate_env_example(settings_class=cls)
arpakitlib/ar_str_util.py CHANGED
@@ -87,35 +87,35 @@ def raise_if_string_blank(string: str) -> str:
87
87
 
88
88
  def __example():
89
89
  print("str_in:")
90
- print(str_in(string="hello", main_string="hello world")) # True
91
- print(str_in(string="bye", main_string="hello world")) # False
92
- print(str_in(string="hello", main_string="hello world", max_diff=6)) # True
93
- print(str_in(string="hello", main_string="hello world", max_diff=1)) # False
90
+ print(str_in(string="hello", main_string="hello world"))
91
+ print(str_in(string="bye", main_string="hello world"))
92
+ print(str_in(string="hello", main_string="hello world", max_diff=6))
93
+ print(str_in(string="hello", main_string="hello world", max_diff=1))
94
94
 
95
95
  print("\nbidirectional_str_in:")
96
- print(bidirectional_str_in(string1="hello", string2="hello world")) # True
97
- print(bidirectional_str_in(string1="world", string2="hello world")) # True
96
+ print(bidirectional_str_in(string1="hello", string2="hello world"))
97
+ print(bidirectional_str_in(string1="world", string2="hello world"))
98
98
 
99
99
  print("\nstr_startswith:")
100
- print(str_startswith(string="hello", main_string="hello world")) # True
101
- print(str_startswith(string="world", main_string="hello world")) # False
100
+ print(str_startswith(string="hello", main_string="hello world"))
101
+ print(str_startswith(string="world", main_string="hello world"))
102
102
 
103
103
  print("\nbidirectional_str_startswith:")
104
- print(bidirectional_str_startswith(string1="hello", string2="hello world")) # True
105
- print(bidirectional_str_startswith(string1="world", string2="hello world")) # False
104
+ print(bidirectional_str_startswith(string1="hello", string2="hello world"))
105
+ print(bidirectional_str_startswith(string1="world", string2="hello world"))
106
106
 
107
107
  print("\nmake blank_if_none:")
108
- print(make_blank_if_none()) # ""
109
- print(make_blank_if_none(string="test")) # "test"
108
+ print(make_blank_if_none())
109
+ print(make_blank_if_none(string="test"))
110
110
 
111
111
  print("\nremove_html:")
112
- print(remove_html(string="<div>Hello <b>World</b></div>")) # "Hello World"
112
+ print(remove_html(string="<div>Hello <b>World</b></div>"))
113
113
 
114
114
  print("\nremove_tags:")
115
- print(remove_tags(string="<div>Hello <b>World</b></div>")) # "divHello bWorldbdiv"
115
+ print(remove_tags(string="<div>Hello <b>World</b></div>"))
116
116
 
117
117
  print("\nremove_tags_and_html:")
118
- print(remove_tags_and_html("<div>Hello <b>World</b></div>")) # "Hello World"
118
+ print(remove_tags_and_html("<div>Hello <b>World</b></div>"))
119
119
 
120
120
 
121
121
  if __name__ == '__main__':
@@ -134,7 +134,7 @@ def __example():
134
134
  print("\nraise_for_types:")
135
135
  try:
136
136
  raise_for_types(comparable="test", need_types=[str, int]) # pass
137
- raise_for_types(comparable=100.5, need_types=[str, int], comment_for_error="Ooops") # raise
137
+ raise_for_types(comparable=100.5, need_types=[str, int], comment_for_error="ops") # raise
138
138
  except TypeError as e:
139
139
  print(e)
140
140
 
@@ -1,55 +1,55 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.3
2
2
  Name: arpakitlib
3
- Version: 1.7.103
3
+ Version: 1.7.132
4
4
  Summary: arpakitlib
5
- Home-page: https://github.com/ARPAKIT-Company/arpakitlib
6
5
  License: Apache-2.0
7
6
  Keywords: arpakitlib,arpakit,arpakit-company,arpakitcompany,arpakit_company
8
7
  Author: arpakit
9
8
  Author-email: arpakit@gmail.com
10
- Requires-Python: >=3.12,<4.0
9
+ Requires-Python: >=3.12.4,<4.0
11
10
  Classifier: Development Status :: 5 - Production/Stable
12
11
  Classifier: Intended Audience :: Developers
13
12
  Classifier: License :: OSI Approved :: Apache Software License
14
- Classifier: Operating System :: OS Independent
15
13
  Classifier: Programming Language :: Python
16
14
  Classifier: Programming Language :: Python :: 3
17
15
  Classifier: Programming Language :: Python :: 3.12
18
- Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Operating System :: OS Independent
19
17
  Classifier: Topic :: Software Development :: Libraries
20
- Requires-Dist: aiogram (>=3.15.0,<4.0.0)
21
- Requires-Dist: aiohttp-socks (>=0.9.1,<0.10.0)
22
- Requires-Dist: alembic (>=1.14.0,<2.0.0)
18
+ Requires-Dist: aiogram (>=3.17.0,<4.0.0)
19
+ Requires-Dist: aiohttp-socks (>=0.10.1,<0.11.0)
20
+ Requires-Dist: alembic (>=1.14.1,<2.0.0)
23
21
  Requires-Dist: asyncpg (>=0.30.0,<0.31.0)
24
- Requires-Dist: asyncssh (>=2.18.0,<3.0.0)
22
+ Requires-Dist: asyncssh (>=2.19.0,<3.0.0)
25
23
  Requires-Dist: bs4 (>=0.0.2,<0.0.3)
26
- Requires-Dist: cachetools (>=5.5.0,<6.0.0)
24
+ Requires-Dist: cachetools (>=5.5.1,<6.0.0)
27
25
  Requires-Dist: celery (>=5.4.0,<6.0.0)
28
26
  Requires-Dist: cryptography (>=44.0.0,<45.0.0)
29
27
  Requires-Dist: email-validator (>=2.2.0,<3.0.0)
30
- Requires-Dist: emoji (>=2.14.0,<3.0.0)
31
- Requires-Dist: fastapi (>=0.115.5,<0.116.0)
28
+ Requires-Dist: emoji (>=2.14.1,<3.0.0)
29
+ Requires-Dist: fastapi (>=0.115.6,<0.116.0)
32
30
  Requires-Dist: gunicorn (>=23.0.0,<24.0.0)
33
31
  Requires-Dist: itsdangerous (>=2.2.0,<3.0.0)
34
32
  Requires-Dist: jupyter (>=1.1.1,<2.0.0)
35
33
  Requires-Dist: matplotlib (>=3.10.0,<4.0.0)
36
- Requires-Dist: openai (>=1.55.3,<2.0.0)
34
+ Requires-Dist: openai (>=1.59.9,<2.0.0)
37
35
  Requires-Dist: openpyxl (>=3.1.5,<4.0.0)
38
36
  Requires-Dist: pandas (>=2.2.3,<3.0.0)
39
37
  Requires-Dist: paramiko (>=3.5.0,<4.0.0)
40
- Requires-Dist: poetry (>=1.8.5,<2.0.0)
38
+ Requires-Dist: poetry (>=2.0.1,<3.0.0)
41
39
  Requires-Dist: psycopg2-binary (>=2.9.10,<3.0.0)
42
- Requires-Dist: pydantic-settings (>=2.6.1,<3.0.0)
40
+ Requires-Dist: pydantic (>=2.10.5,<3.0.0)
41
+ Requires-Dist: pydantic-settings (>=2.7.1,<3.0.0)
43
42
  Requires-Dist: pyjwt (>=2.10.1,<3.0.0)
44
43
  Requires-Dist: pymongo (>=4.10.1,<5.0.0)
45
44
  Requires-Dist: pytz (>=2024.2,<2025.0)
46
45
  Requires-Dist: pyzabbix (>=1.3.1,<2.0.0)
47
- Requires-Dist: redis (>=5.2.0,<6.0.0)
48
46
  Requires-Dist: requests[socks] (>=2.32.3,<3.0.0)
49
47
  Requires-Dist: sqladmin (>=0.20.1,<0.21.0)
50
- Requires-Dist: sqlalchemy (>=2.0.36,<3.0.0)
51
- Requires-Dist: twine (>=6.0.1,<7.0.0)
52
- Requires-Dist: uvicorn (>=0.32.1,<0.33.0)
48
+ Requires-Dist: sqlalchemy (>=2.0.37,<3.0.0)
49
+ Requires-Dist: twine (>=6.1.0,<7.0.0)
50
+ Requires-Dist: uvicorn (>=0.34.0,<0.35.0)
51
+ Project-URL: Documentation, https://github.com/ARPAKIT-Company/arpakitlib
52
+ Project-URL: Homepage, https://github.com/ARPAKIT-Company/arpakitlib
53
53
  Project-URL: Repository, https://github.com/ARPAKIT-Company/arpakitlib
54
54
  Description-Content-Type: text/markdown
55
55
 
@@ -80,6 +80,13 @@ poetry add arpakitlib
80
80
  pip install arpakitlib
81
81
  ```
82
82
 
83
+ ### Init template
84
+
85
+ ```
86
+ # poetry run arpakitlib -c help
87
+ poetry run arpakitlib -c init_arpakit_project_template -project_dirpath ./ -overwrite_if_exists true -project_name ... -sql_db_port ... (optional) -api_port ... (optional) -ignore_paths_startswith ... (optional) -only_paths_startswith ...(optional)
88
+ ```
89
+
83
90
  ---
84
91
 
85
92
  ### Links