ApiLogicServer 15.0.46__py3-none-any.whl → 15.0.52__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 (103) hide show
  1. api_logic_server_cli/api_logic_server.py +26 -5
  2. api_logic_server_cli/api_logic_server_info.yaml +3 -3
  3. api_logic_server_cli/cli.py +20 -16
  4. api_logic_server_cli/create_from_model/api_logic_server_utils.py +6 -3
  5. api_logic_server_cli/manager.py +24 -13
  6. api_logic_server_cli/prototypes/base/config/config.py +15 -0
  7. api_logic_server_cli/prototypes/base/venv_setup/requirements-no-cli.txt +5 -4
  8. api_logic_server_cli/prototypes/manager/.vscode/settings.json +1 -1
  9. api_logic_server_cli/prototypes/manager/{run_sample.sh → samples/docker_samples/run_sample_docker.sh} +4 -4
  10. api_logic_server_cli/prototypes/manager/samples/docker_samples/run_web_genai.sh +5 -0
  11. api_logic_server_cli/prototypes/manager/samples/readme_samples.md +22 -10
  12. api_logic_server_cli/prototypes/manager/system/app_model_editor/venv_setup/requirements-no-cli.txt +5 -4
  13. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/venv_setup/requirements-no-cli.txt +5 -4
  14. api_logic_server_cli/prototypes/manager/system/install-ApiLogicServer-dev/install-ApiLogicServer-dev.ps1 +7 -3
  15. api_logic_server_cli/prototypes/ont_app/ontimize_seed/package.json +2 -2
  16. api_logic_server_cli/sqlacodegen_wrapper/sqlacodegen/sqlacodegen/codegen.py +4 -2
  17. api_logic_server_cli/sqlacodegen_wrapper/sqlacodegen/sqlacodegen/main.py +25 -5
  18. api_logic_server_cli/sqlacodegen_wrapper/sqlacodegen_wrapper.py +25 -8
  19. {apilogicserver-15.0.46.dist-info → apilogicserver-15.0.52.dist-info}/METADATA +6 -5
  20. {apilogicserver-15.0.46.dist-info → apilogicserver-15.0.52.dist-info}/RECORD +24 -102
  21. api_logic_server_cli/create_from_model/__pycache__/__init__.cpython-312.pyc +0 -0
  22. api_logic_server_cli/create_from_model/__pycache__/api_expose_api_models_creator.cpython-312.pyc +0 -0
  23. api_logic_server_cli/create_from_model/__pycache__/api_logic_server_utils.cpython-312.pyc +0 -0
  24. api_logic_server_cli/create_from_model/__pycache__/create_db_from_model.cpython-312.pyc +0 -0
  25. api_logic_server_cli/create_from_model/__pycache__/dbml.cpython-312.pyc +0 -0
  26. api_logic_server_cli/create_from_model/__pycache__/meta_model.cpython-312.pyc +0 -0
  27. api_logic_server_cli/create_from_model/__pycache__/model_creation_services.cpython-312.pyc +0 -0
  28. api_logic_server_cli/create_from_model/__pycache__/ont_build.cpython-312.pyc +0 -0
  29. api_logic_server_cli/create_from_model/__pycache__/ont_create.cpython-312.pyc +0 -0
  30. api_logic_server_cli/create_from_model/__pycache__/ui_admin_creator.cpython-312.pyc +0 -0
  31. api_logic_server_cli/create_from_model/__pycache__/uri_info.cpython-312.pyc +0 -0
  32. api_logic_server_cli/prototypes/manager/run_web_genai.sh +0 -6
  33. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/__pycache__/api_logic_server_run.cpython-312.pyc +0 -0
  34. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/api/__pycache__/__init__.cpython-312.pyc +0 -0
  35. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/api/__pycache__/customize_api.cpython-312.pyc +0 -0
  36. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/api/__pycache__/expose_api_models.cpython-312.pyc +0 -0
  37. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/api/__pycache__/json_encoder.cpython-312.pyc +0 -0
  38. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/api/api_discovery/__pycache__/auto_discovery.cpython-312.pyc +0 -0
  39. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/api/api_discovery/__pycache__/new_service.cpython-312.pyc +0 -0
  40. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/api/api_discovery/__pycache__/newer_service.cpython-312.pyc +0 -0
  41. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/api/api_discovery/__pycache__/ontimize_api.cpython-312.pyc +0 -0
  42. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/api/api_discovery/__pycache__/system.cpython-312.pyc +0 -0
  43. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/api/system/__pycache__/api_utils.cpython-312.pyc +0 -0
  44. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/api/system/__pycache__/custom_endpoint.cpython-312.pyc +0 -0
  45. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/api/system/__pycache__/expression_parser.cpython-312.pyc +0 -0
  46. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/api/system/__pycache__/gen_csv_report.cpython-312.pyc +0 -0
  47. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/api/system/__pycache__/gen_pdf_report.cpython-312.pyc +0 -0
  48. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/api/system/opt_locking/__pycache__/opt_locking.cpython-312.pyc +0 -0
  49. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/config/__pycache__/__init__.cpython-312.pyc +0 -0
  50. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/config/__pycache__/activate_logicbank.cpython-312.pyc +0 -0
  51. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/config/__pycache__/config.cpython-312.pyc +0 -0
  52. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/config/__pycache__/server_setup.cpython-312.pyc +0 -0
  53. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/database/__pycache__/__init__.cpython-312.pyc +0 -0
  54. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/database/__pycache__/bind_dbs.cpython-312.pyc +0 -0
  55. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/database/__pycache__/customize_models.cpython-312.pyc +0 -0
  56. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/database/__pycache__/models.cpython-312.pyc +0 -0
  57. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/database/alembic/__pycache__/env.cpython-312.pyc +0 -0
  58. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/database/database_discovery/__pycache__/authentication_models.cpython-312.pyc +0 -0
  59. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/database/database_discovery/__pycache__/auto_discovery.cpython-312.pyc +0 -0
  60. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/database/db_debug/__pycache__/db_debug.cpython-312.pyc +0 -0
  61. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/database/system/__pycache__/SAFRSBaseX.cpython-312.pyc +0 -0
  62. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/database/test_data/__pycache__/alp_init.cpython-312.pyc +0 -0
  63. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/database/test_data/__pycache__/response2code.cpython-312.pyc +0 -0
  64. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/database/test_data/__pycache__/test_data_preamble.cpython-312.pyc +0 -0
  65. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/devops/keycloak/unused/__pycache__/auth_provider.cpython-312.pyc +0 -0
  66. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/devops/python-anywhere/__pycache__/python_anywhere_wsgi.cpython-312.pyc +0 -0
  67. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/integration/kafka/__pycache__/kafka_consumer.cpython-312.pyc +0 -0
  68. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/integration/kafka/__pycache__/kafka_producer.cpython-312.pyc +0 -0
  69. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/integration/n8n/__pycache__/n8n_producer.cpython-312.pyc +0 -0
  70. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/integration/system/__pycache__/FlaskKafka.cpython-312.pyc +0 -0
  71. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/integration/system/__pycache__/RowDictMapper.cpython-312.pyc +0 -0
  72. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/logic/__pycache__/declare_logic.cpython-312.pyc +0 -0
  73. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/logic/__pycache__/load_verify_rules.cpython-312.pyc +0 -0
  74. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/logic/logic_discovery/__pycache__/auto_discovery.cpython-312.pyc +0 -0
  75. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/security/__pycache__/__init__.cpython-312.pyc +0 -0
  76. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/security/__pycache__/declare_security.cpython-312.pyc +0 -0
  77. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/security/authentication_provider/__pycache__/__init__.cpython-312.pyc +0 -0
  78. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/security/authentication_provider/__pycache__/abstract_authentication_provider.cpython-312.pyc +0 -0
  79. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/security/authentication_provider/keycloak/__pycache__/auth_provider.cpython-312.pyc +0 -0
  80. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/security/authentication_provider/memory/__pycache__/auth_provider.cpython-312.pyc +0 -0
  81. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/security/authentication_provider/memory/__pycache__/auth_provider_no_swagger.cpython-312.pyc +0 -0
  82. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/security/authentication_provider/sql/__pycache__/auth_provider.cpython-312.pyc +0 -0
  83. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/security/system/__pycache__/authentication.cpython-312.pyc +0 -0
  84. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/security/system/__pycache__/authorization.cpython-312.pyc +0 -0
  85. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/test/__pycache__/__init__.cpython-312.pyc +0 -0
  86. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/test/api_logic_server_behave/__pycache__/__init__.cpython-312.pyc +0 -0
  87. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/test/api_logic_server_behave/__pycache__/behave_logic_report.cpython-312.pyc +0 -0
  88. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/test/api_logic_server_behave/__pycache__/behave_run.cpython-312.pyc +0 -0
  89. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/test/api_logic_server_behave/features/steps/__pycache__/about.cpython-312.pyc +0 -0
  90. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/test/api_logic_server_behave/features/steps/__pycache__/test_utils.cpython-312.pyc +0 -0
  91. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/test/basic/__pycache__/server_test.cpython-312.pyc +0 -0
  92. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/ui/__pycache__/__init__.cpython-312.pyc +0 -0
  93. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/ui/admin/__pycache__/admin_loader.cpython-312.pyc +0 -0
  94. api_logic_server_cli/prototypes/manager/system/genai/examples/genai_demo/genai_demo_docs_logic/venv_setup/__pycache__/py.cpython-312.pyc +0 -0
  95. api_logic_server_cli/sqlacodegen_wrapper/__pycache__/__init__.cpython-312.pyc +0 -0
  96. api_logic_server_cli/sqlacodegen_wrapper/__pycache__/sqlacodegen_wrapper.cpython-312.pyc +0 -0
  97. api_logic_server_cli/sqlacodegen_wrapper/sqlacodegen/__pycache__/__init__.cpython-312.pyc +0 -0
  98. api_logic_server_cli/sqlacodegen_wrapper/sqlacodegen/sqlacodegen/__pycache__/__init__.cpython-312.pyc +0 -0
  99. api_logic_server_cli/sqlacodegen_wrapper/sqlacodegen/sqlacodegen/__pycache__/codegen.cpython-312.pyc +0 -0
  100. {apilogicserver-15.0.46.dist-info → apilogicserver-15.0.52.dist-info}/WHEEL +0 -0
  101. {apilogicserver-15.0.46.dist-info → apilogicserver-15.0.52.dist-info}/entry_points.txt +0 -0
  102. {apilogicserver-15.0.46.dist-info → apilogicserver-15.0.52.dist-info}/licenses/LICENSE +0 -0
  103. {apilogicserver-15.0.46.dist-info → apilogicserver-15.0.52.dist-info}/top_level.txt +0 -0
@@ -12,10 +12,11 @@ ApiLogicServer CLI: given a database url, create [and run] customizable ApiLogic
12
12
  Called from api_logic_server_cli.py, by instantiating the ProjectRun object.
13
13
  '''
14
14
 
15
- __version__ = "15.00.46" # last public release: 15.00.41 (15.00.12)
15
+ __version__ = "15.00.52" # last public release: 15.00.47 (15.00.12)
16
16
  recent_changes = \
17
17
  f'\n\nRecent Changes:\n' +\
18
- "\t07/14/2024 - 15.00.46: venv fix, copilot vibe tweaks - creation, mcp logic, basic_demo autonums \n"\
18
+ "\t07/20/2024 - 15.00.52: Python 3.13 compatibility fixes - psycopg2→psycopg3, SQLAlchemy 2.0+, pkg_resources→importlib.metadata. mgr dbs \n"\
19
+ "\t07/17/2024 - 15.00.49: venv fix+, ext bldr * fix, copilot vibe tweaks - creation, mcp logic, basic_demo autonums \n"\
19
20
  "\t07/10/2024 - 15.00.41: copilot vibe support for logic, UI, MCP, bug[98] \n"\
20
21
  "\t06/30/2024 - 15.00.33: Tech Preview: genai-logic genai-add-app --vibe, bug [96, 97] \n"\
21
22
  "\t06/10/2024 - 15.00.12: MCP Security, win fixes for readme, graphics quotes \n"\
@@ -463,6 +464,13 @@ def create_project_and_overlay_prototypes(project: 'ProjectRun', msg: str) -> st
463
464
  copy_sqlite = True
464
465
  if copy_sqlite == False or "sqlite" not in project.abs_db_url:
465
466
  db_uri = get_windows_path_with_slashes(project.abs_db_url)
467
+
468
+ # Convert PostgreSQL URL for Python 3.13+ compatibility
469
+ import sys
470
+ if sys.version_info >= (3, 13) and db_uri.startswith('postgresql://'):
471
+ db_uri = db_uri.replace('postgresql://', 'postgresql+psycopg://')
472
+ log.debug(f'.. ..Converted PostgreSQL URL for Python 3.13+: {db_uri}')
473
+
466
474
  create_utils.replace_string_in_file(search_for="replace_db_url",
467
475
  replace_with=db_uri,
468
476
  in_file=f'{project.project_directory}/config/config.py')
@@ -744,7 +752,14 @@ fi
744
752
  env_file_path = project.project_directory_path.joinpath('.env')
745
753
  venv_dir = str(Path(defaultInterpreterPath_str).parent.parent) # Get the venv directory
746
754
 
747
- env_content = f"""# Virtual Environment Configuration
755
+ # Platform-specific .env file content
756
+ if os.name == "nt": # Windows
757
+ env_content = f"""# Virtual Environment Configuration
758
+ VIRTUAL_ENV={venv_dir}
759
+ PYTHONPATH={venv_site_packages}
760
+ """
761
+ else: # Unix/Linux/macOS
762
+ env_content = f"""# Virtual Environment Configuration
748
763
  VIRTUAL_ENV={venv_dir}
749
764
  PATH={Path(defaultInterpreterPath_str).parent}:$PATH
750
765
  PYTHONPATH={venv_site_packages}
@@ -778,7 +793,7 @@ def update_api_logic_server_run(project):
778
793
  """
779
794
  api_logic_server_run_py = f'{project.project_directory}/api_logic_server_run.py'
780
795
  config_py = f'{project.project_directory}/config/config.py'
781
- create_utils.replace_string_in_file(search_for="\"api_logic_server_project_name\"", # fix logic_bank_utils.add_python_path
796
+ create_utils.replace_string_in_file(search_for="api_logic_server_project_name", # fix logic_bank_utils.add_python_path
782
797
  replace_with='"' + os.path.basename(project.project_name) + '"',
783
798
  in_file=api_logic_server_run_py)
784
799
  create_utils.replace_string_in_file(search_for="ApiLogicServer hello",
@@ -908,7 +923,10 @@ def start_open_with(project: Project):
908
923
 
909
924
  def invoke_extended_builder(builder_path, db_url, project_directory, model_creation_services):
910
925
  # spec = importlib.util.spec_from_file_location("module.name", "/path/to/file.py")
911
- spec = importlib.util.spec_from_file_location("module.name", builder_path)
926
+ use_builder_path = builder_path
927
+ if builder_path == '*':
928
+ use_builder_path = Path('extended_builder.py')
929
+ spec = importlib.util.spec_from_file_location("module.name", use_builder_path)
912
930
  extended_builder = importlib.util.module_from_spec(spec)
913
931
  spec.loader.exec_module(extended_builder) # runs "bare" module code (e.g., initialization)
914
932
  extended_builder.extended_builder(db_url, project_directory, model_creation_services) # extended_builder.MyClass()
@@ -1186,6 +1204,9 @@ class ProjectRun(Project):
1186
1204
  """
1187
1205
  log.debug(f'.. .. ..Copying sqlite database to: database/{self.bind_key}_db.sqlite')
1188
1206
  db_loc = self.abs_db_url.replace("sqlite:///", "")
1207
+ if os.name == "nt":
1208
+ if db_loc.startswith(r"C:\C:"): # windows
1209
+ db_loc = db_loc.replace(r"C:\C:", "C:") # remove unk junk
1189
1210
  target_db_loc_actual = str(self.project_directory_path.joinpath(f'database/{self.bind_key}_db.sqlite'))
1190
1211
  # target: /Users/val/dev/ApiLogicServer/ApiLogicServer-dev/org_git/servers/NW_NoCust/database/Todo_db.sqlite
1191
1212
  # e.g., /Users/val/dev/ApiLogicServer/ApiLogicServer-dev/servers/NW_NoCust/database
@@ -1,3 +1,3 @@
1
- last_created_date: July 14, 2025 19:56:50
2
- last_created_project_name: ApiLogicProject
3
- last_created_version: 15.00.46
1
+ last_created_date: July 20, 2025 08:02:02
2
+ last_created_project_name: samples/nw_sample_nocust
3
+ last_created_version: 15.00.52
@@ -188,14 +188,16 @@ def main(ctx):
188
188
  Creation is from your database (--db-url identifies a SQLAlchemy database)
189
189
 
190
190
  \b
191
- Doc: https://apilogicserver.github.io/Docs
191
+ Synonym to genai-logic: gail | gal
192
+ \b
193
+ Doc: https://apilogicserver.github.io/Docs/Doc-Home/
192
194
  And: https://apilogicserver.github.io/Docs/Database-Connectivity/
193
195
  \b
194
196
  Suggestions:
195
197
 
196
198
  \b
197
- ApiLogicServer start # create and manage projects
198
- ApiLogicServer create --db-url= --project-name= # defaults to Northwind sample
199
+ genai-logic start # create and manage projects
200
+ genai-logic create --db-url= --project-name= # defaults to Northwind sample
199
201
  """
200
202
  pass # all commands come through here
201
203
 
@@ -1083,13 +1085,13 @@ def genai_iterate(ctx, project_name: str, using: str):
1083
1085
  help="your_code.py for additional build automation")
1084
1086
  @click.option('--include_tables',
1085
1087
  default=f'',
1086
- help="yml for include: exclude:")
1088
+ help="yml for include, exclude")
1087
1089
  @click.option('--include-tables', 'include_tables',
1088
1090
  default=f'',
1089
- help="yml for include: exclude:")
1091
+ help="yml for include, exclude")
1090
1092
  @click.option('--infer_primary_key/--no_infer_primary_key',
1091
1093
  default=False, is_flag=True,
1092
- help="xInfer primary_key for unique cols")
1094
+ help="Infer primary_key for unique cols")
1093
1095
  @click.option('--infer-primary-key/--no-infer-primary-key', 'infer_primary_key',
1094
1096
  default=False, is_flag=True,
1095
1097
  help="Infer primary-key for unique cols")
@@ -1250,22 +1252,22 @@ def create(ctx, project_name: str, db_url: str, not_exposed: str, api_name: str,
1250
1252
  help="Swagger hostname (default is localhost)")
1251
1253
  @click.option('--extended_builder',
1252
1254
  default=f'',
1253
- help="your_code.py for additional build automation")
1255
+ help="your python for additional build automation")
1254
1256
  @click.option('--extended-builder', 'extended_builder',
1255
1257
  default=f'',
1256
- help="your_code.py for additional build automation")
1258
+ help="your python for additional build automation")
1257
1259
  @click.option('--include_tables',
1258
1260
  default=f'',
1259
- help="yml for include: exclude:")
1261
+ help="yml for include / exclude")
1260
1262
  @click.option('--include-tables', 'include_tables',
1261
1263
  default=f'',
1262
- help="yml for include: exclude:")
1264
+ help="yml for include / exclude")
1263
1265
  @click.option('--infer_primary_key/--no_infer_primary_key',
1264
1266
  default=False, is_flag=True,
1265
- help="Infer primary-key for unique cols")
1267
+ help="Infer primary key for unique cols")
1266
1268
  @click.option('--infer-primary-key/--no-infer-primary-key', 'infer_primary_key',
1267
1269
  default=False, is_flag=True,
1268
- help="Infer primary-key for unique cols")
1270
+ help="Unique cols infer primary key")
1269
1271
  @click.pass_context
1270
1272
  def create_and_run(ctx, project_name: str, db_url: str, not_exposed: str, api_name: str,
1271
1273
  from_git: str,
@@ -1280,11 +1282,13 @@ def create_and_run(ctx, project_name: str, db_url: str, not_exposed: str, api_na
1280
1282
  host: str,
1281
1283
  port: str,
1282
1284
  swagger_host: str,
1283
- favorites: str, non_favorites: str,
1285
+ favorites: str,
1286
+ non_favorites: str,
1284
1287
  extended_builder: str,
1285
1288
  include_tables: str,
1286
1289
  multi_api: click.BOOL,
1287
- opt_locking: str, opt_locking_attr: str,
1290
+ opt_locking: str,
1291
+ opt_locking_attr: str,
1288
1292
  id_column_alias: str,
1289
1293
  infer_primary_key: click.BOOL):
1290
1294
  """
@@ -2122,7 +2126,7 @@ if __name__ == '__main__': # debugger & python command line start here
2122
2126
  "show-args" in api_logic_server_info_file_dict:
2123
2127
  print_args(commands, f'\nCommand Line Arguments:')
2124
2128
  python_version = sys.version_info
2125
- assert python_version[0] >= 3 and python_version[1] in [10,11,12], \
2126
- "... Requires Python >=3.10, !=3.11.0, !=3.11.1, 3.12"
2129
+ assert python_version[0] >= 3 and python_version[1] in [10,11,12, 13], \
2130
+ "... Requires Python >=3.10, !=3.11.0, !=3.11.1, 3.12, 3.13"
2127
2131
  main()
2128
2132
 
@@ -293,10 +293,13 @@ def get_abs_db_url(msg, project: Project, is_auth: bool = False):
293
293
  else:
294
294
  rtn_abs_db_url = f'sqlite:///{str(project.api_logic_server_dir_path.joinpath("prototypes/sample_ai/database/chatgpt/sample_ai_items.sqlite"))}'
295
295
  # log.info('.. using installed nw sample database')
296
- else:
296
+ else: # for win, might be: sqlite:////C:\\Users\\val\\dev\\ApiLogicServer\\ApiLogicServer-dev\\org_git\\ApiLogicServer-src\\api_logic_server_cli\\database\\mcp.sqlite
297
297
  url = url_to_process[10: len(url_to_process)]
298
+ if url_to_process.startswith('sqlite:////c:'):
299
+ url = url_to_process[11: len(url_to_process)]
298
300
  rtn_abs_db_url = abspath(url)
299
301
  rtn_abs_db_url = 'sqlite:///' + rtn_abs_db_url
302
+ pass
300
303
  elif url_to_process == 'sqlsvr-sample': # work-around - VSCode run config arg parsing
301
304
  rtn_abs_db_url = 'mssql+pyodbc://sa:Posey3861@localhost:1433/SampleDB?driver=ODBC+Driver+18+for+SQL+Server&trusted_connection=no&Encrypt=no'
302
305
  elif url_to_process == 'sqlsvr-nwlogic': # work-around - VSCode run config arg parsing
@@ -405,10 +408,10 @@ def does_file_contain(search_for: str, in_file: str) -> bool:
405
408
  return found
406
409
 
407
410
  def replace_string_in_file(search_for: str, replace_with: str, in_file: str):
408
- with open(Path(in_file), 'r') as file:
411
+ with open(Path(in_file), 'r', encoding="utf-8") as file:
409
412
  file_data = file.read()
410
413
  file_data = file_data.replace(search_for, replace_with)
411
- with open(in_file, 'w') as file:
414
+ with open(in_file, 'w', encoding="utf-8") as file:
412
415
  file.write(file_data)
413
416
 
414
417
  def assign_value_to_key_in_file(key: str, value: any, in_file: str):
@@ -36,9 +36,9 @@ def create_manager(clean: bool, open_with: str, api_logic_server_path: Path,
36
36
  samples (bool, optional): Whether to create large samples (prevent win max file length)
37
37
  """
38
38
 
39
- def create_sym_links(cli_path: Path, mgr_path: Path):
39
+ def copy_sqlite_dbs(cli_path: Path, mgr_path: Path):
40
40
  """
41
- Creates symbolic links to sample dbs and prompts (clearer than db abbreviations).
41
+ Copy sample sqlite databases to mgr/samples/dbs (clearer than db abbreviations).
42
42
 
43
43
  Args:
44
44
  cli_path (Path): loc of cli.py in the manager's venv
@@ -48,16 +48,27 @@ def create_manager(clean: bool, open_with: str, api_logic_server_path: Path,
48
48
  Creates a symbolic link from 'cli_path/database/basic_demo.sqlite' to 'mgr_path/samples/dbs/basic_demo'.
49
49
 
50
50
  """
51
-
52
- # create symbolic link - thanks https://www.geeksforgeeks.org/python/python-os-symlink-method/
53
- try:
54
- os.symlink(cli_path.parent / 'database/basic_demo.sqlite', mgr_path / 'samples/dbs/basic_demo.sqlite')
55
- os.symlink(cli_path.parent / 'database/nw-gold.sqlite', mgr_path / 'samples/dbs/nw.sqlite')
56
- os.symlink(cli_path.parent / 'database/Chinook_Sqlite.sqlite', mgr_path / 'samples/dbs/chinook.sqlite')
57
- os.symlink(cli_path.parent / 'database/classicmodels.sqlite', mgr_path / 'samples/dbs/classicmodels.sqlite')
58
- log.debug("✅ Manager Creation - SymLink created: samples/dbs/")
59
- except Exception as e:
60
- log.debug(f"❌ Manager Creation - SymLink creation failed: {str(e)}")
51
+ if use_syn_link := False:
52
+ # could create symbolic link - thanks https://www.geeksforgeeks.org/python/python-os-symlink-method/
53
+ # but this fails on windows due to permissions
54
+ try:
55
+ os.symlink(cli_path.parent / 'database/basic_demo.sqlite', mgr_path / 'samples/dbs/basic_demo.sqlite')
56
+ os.symlink(cli_path.parent / 'database/nw-gold.sqlite', mgr_path / 'samples/dbs/nw.sqlite')
57
+ os.symlink(cli_path.parent / 'database/Chinook_Sqlite.sqlite', mgr_path / 'samples/dbs/chinook.sqlite')
58
+ os.symlink(cli_path.parent / 'database/classicmodels.sqlite', mgr_path / 'samples/dbs/classicmodels.sqlite')
59
+ log.debug("✅ Manager Creation - SymLink created: samples/dbs/")
60
+ except Exception as e:
61
+ log.debug(f"❌ Manager Creation - Copy samples/dbs SymLink creation failed: {str(e)}")
62
+ else:
63
+ try:
64
+ copyfile(cli_path.parent / 'database/basic_demo.sqlite', mgr_path / 'samples/dbs/basic_demo.sqlite')
65
+ copyfile(cli_path.parent / 'database/nw-gold.sqlite', mgr_path / 'samples/dbs/nw.sqlite')
66
+ copyfile(cli_path.parent / 'database/Chinook_Sqlite.sqlite', mgr_path / 'samples/dbs/chinook.sqlite')
67
+ copyfile(cli_path.parent / 'database/classicmodels.sqlite', mgr_path / 'samples/dbs/classicmodels.sqlite')
68
+ copyfile(cli_path.parent / 'database/todos.sqlite', mgr_path / 'samples/dbs/todos.sqlite')
69
+ log.debug("✅ Manager Creation - Created: samples/dbs/")
70
+ except Exception as e:
71
+ log.debug(f"❌ Manager Creation - Copy samples/dbs creation failed: {str(e)}")
61
72
 
62
73
 
63
74
  log = logging.getLogger(__name__)
@@ -218,7 +229,7 @@ def create_manager(clean: bool, open_with: str, api_logic_server_path: Path,
218
229
  create_utils.replace_string_in_file(search_for = 'cli_path',
219
230
  replace_with=str(cli_str),
220
231
  in_file=vscode_launch_path)
221
- create_sym_links(cli_path=cli_path, mgr_path=to_dir)
232
+ copy_sqlite_dbs(cli_path=cli_path, mgr_path=to_dir)
222
233
 
223
234
  if env_path.exists():
224
235
  create_utils.replace_string_in_file(search_for = 'APILOGICSERVER_AUTO_OPEN=code',
@@ -133,6 +133,12 @@ class Config:
133
133
  SQLALCHEMY_DATABASE_URI : typing.Optional[str] = f"replace_db_url"
134
134
  # override SQLALCHEMY_DATABASE_URI here as required
135
135
 
136
+ # Python 3.13+ compatibility: Convert PostgreSQL URLs to use psycopg3
137
+ import sys
138
+ if sys.version_info >= (3, 13) and SQLALCHEMY_DATABASE_URI.startswith('postgresql://'):
139
+ SQLALCHEMY_DATABASE_URI = SQLALCHEMY_DATABASE_URI.replace('postgresql://', 'postgresql+psycopg://')
140
+ app_logger.debug(f'config.py - converted PostgreSQL URL for Python 3.13+: {SQLALCHEMY_DATABASE_URI}')
141
+
136
142
  BACKTIC_AS_QUOTE = False # use backtic as quote for table names for API Bridge
137
143
  if SQLALCHEMY_DATABASE_URI.startswith("mysql") or SQLALCHEMY_DATABASE_URI.startswith("mariadb"):
138
144
  BACKTIC_AS_QUOTE = True
@@ -145,6 +151,11 @@ class Config:
145
151
  if os.getenv('SQLALCHEMY_DATABASE_URI'): # e.g. export SECURITY_ENABLED=true
146
152
  SQLALCHEMY_DATABASE_URI = os.getenv('SQLALCHEMY_DATABASE_URI')
147
153
  app_logger.debug(f'.. overridden from env variable: {SQLALCHEMY_DATABASE_URI}')
154
+
155
+ # Python 3.13+ compatibility: Convert PostgreSQL URLs to use psycopg3 (for env override)
156
+ if sys.version_info >= (3, 13) and SQLALCHEMY_DATABASE_URI.startswith('postgresql://'):
157
+ SQLALCHEMY_DATABASE_URI = SQLALCHEMY_DATABASE_URI.replace('postgresql://', 'postgresql+psycopg://')
158
+ app_logger.debug(f'config.py - converted PostgreSQL URL for Python 3.13+: {SQLALCHEMY_DATABASE_URI}')
148
159
 
149
160
 
150
161
  # KEYCLOAK Args
@@ -178,6 +189,10 @@ class Config:
178
189
  # Begin Multi-Database URLs (from ApiLogicServer add-db...)
179
190
  auth_db_path = str(project_path.joinpath('database/authentication_db.sqlite'))
180
191
  SQLALCHEMY_DATABASE_URI_AUTHENTICATION = f'sqlite:///{auth_db_path}'
192
+ # Python 3.13+ compatibility: Convert PostgreSQL URLs to use psycopg3 (for env override)
193
+ if sys.version_info >= (3, 13) and SQLALCHEMY_DATABASE_URI_AUTHENTICATION.startswith('postgresql://'):
194
+ SQLALCHEMY_DATABASE_URI_AUTHENTICATION = SQLALCHEMY_DATABASE_URI_AUTHENTICATION.replace('postgresql://', 'postgresql+psycopg://')
195
+ app_logger.debug(f'config.py - converted PostgreSQL URL for Python 3.13+: {SQLALCHEMY_DATABASE_URI_AUTHENTICATION}')
181
196
  app_logger.info(f'config.py - SQLALCHEMY_DATABASE_URI_AUTHENTICATION: {SQLALCHEMY_DATABASE_URI_AUTHENTICATION}\n')
182
197
 
183
198
  # as desired, use env variable: export SQLALCHEMY_DATABASE_URI='sqlite:////Users/val/dev/servers/docker_api_logic_project/database/db.sqliteXX'
@@ -1,9 +1,9 @@
1
1
  PyJWT==2.6.0
2
2
  python-dateutil==2.8.2
3
3
  six==1.16.0
4
- SQLAlchemy==1.4.29
5
- Flask-SQLAlchemy==2.5.1
6
- SQLAlchemy-Utils==0.38.2
4
+ SQLAlchemy>=2.0.0
5
+ Flask-SQLAlchemy>=3.0.0
6
+ SQLAlchemy-Utils>=0.38.2
7
7
  Werkzeug==2.2.3
8
8
  logicbankutils==0.6.0
9
9
  inflect==5.0.2
@@ -25,7 +25,8 @@ PyMySQL==1.0.2
25
25
  cryptography==36.0.1
26
26
  requests==2.27.1
27
27
  gunicorn==20.1.0
28
- psycopg2-binary==2.9.5
28
+ psycopg2-binary>=2.9.5; python_version < '3.13'
29
+ psycopg[binary]>=3.1.0; python_version >= '3.13'
29
30
  DotMap==1.3.25
30
31
  WTForms==2.3.3
31
32
  behave==1.2.6
@@ -20,5 +20,5 @@
20
20
  "workbench.editorAssociations": {
21
21
  "*.md": "vscode.markdown.preview.editor"
22
22
  },
23
- "workbench.colorTheme": "Visual Studio Light"
23
+ "workbench.colorTheme": "Arduino Light"
24
24
  }
@@ -14,8 +14,8 @@ if [ $# -eq 0 ]
14
14
  # echo "shell: $SHELL"
15
15
  echo " eg:"
16
16
  echo " "
17
- echo " > cd webgenai # or ApiLogicServer"
18
- echo " > sh run_sample.sh nw_sample_nocust"
17
+ echo " > cd ApiLogicServer # ONLY if already running under docker"
18
+ echo " > sh samples/docker_samples/run_sample_docker.sh nw_sample_nocust"
19
19
  echo " "
20
20
  exit 0
21
21
  fi
@@ -26,5 +26,5 @@ if [ "$1" = "$" ]
26
26
  sample="nw_sample"
27
27
  fi
28
28
 
29
- cd samples/$sample
30
- docker run -it --rm --name api_logic_project -p 5656:5656 --env-file ./devops/docker-standard-image/env.list -v ./:/app apilogicserver/web_genai python3 /app/api_logic_server_run.py
29
+ pushd samples/$sample
30
+ docker run -it --rm --name api_logic_project_${sample}_$(date +%s) -p 5656:5656 --env-file ./devops/docker-standard-image/env.list -v ./:/app apilogicserver/web_genai python3 /app/api_logic_server_run.py
@@ -0,0 +1,5 @@
1
+ # Run WebGenAI docker container
2
+
3
+ # sh samples/docker_samples/run_web_genai.sh
4
+
5
+ docker compose -f webgenai/docker-compose.yml up
@@ -6,7 +6,7 @@ The created `samples/nw_sample` illustrates important customization sample code
6
6
 
7
7
  ## Sqlite Sample Databases
8
8
 
9
- The `samples/db` files are symbolic links to pre-installed sqlite databases. These allow you to explore creating projects from existing databases.
9
+ The `samples/db` files are pre-installed sqlite databases. These allow you to explore creating projects from existing databases.
10
10
 
11
11
  For example, create Northwind like this:
12
12
 
@@ -14,24 +14,36 @@ For example, create Northwind like this:
14
14
  genai-logic create --project_name=nw --db_url=sqlite:///samples/dbs/nw.sqlite
15
15
  ```
16
16
 
17
- > Note: If the symbolic links are missing, it is probably due to permission issues, e.g., on windows you must run the Shell with Admin privileges. You can continue using the abbeviations instead of a standard SQLAlchemy database uri.
18
-
19
17
  ## Database Connectivity
20
18
 
21
19
  Sample project creation commands:
22
20
 
23
21
  ```bash
24
- genai-logic create
25
- genai-logic create-and-run
26
- genai-logic create --db_url=sqlite:////Users/val/dev/todo_example/todos.db --project_name=todo
22
+ # local sqlite
27
23
  genai-logic create --db_url=sqlite:///c:\genai-logic\nw.sqlite --project_name=nw
28
- genai-logic create --db_url=sqlite:///ai.sqlite --project_name=ai --open_with=code
29
- genai-logic create --db_url=mysql+pymysql://root:p@mysql-container:3306/classicmodels --project_name=/localhost/docker_db_project
30
- genai-logic create --db_url='mssql+pyodbc://sa:Posey3861@localhost:1433/NORTHWND?driver=ODBC+Driver+18+for+SQL+Server&trusted_connection=no&Encrypt=no'
24
+ genai-logic create --db_url=sqlite:///samples/dbs/todos.sqlite --project_name=todo
25
+ genai-logic create --db_url=sqlite:////Users/val/dev/ApiLogicServer/ApiLogicServer-dev/clean/ApiLogicServer/samples/dbs/todos.sqlite --project_name=todo
26
+
27
+ # from localhost to mysql container
28
+ genai-logic create --db_url=mysql+pymysql://root:p@localhost:3306/classicmodels --project_name=docker_classicmodels
29
+ genai-logic create --db_url=mysql+pymysql://root:p@localhost:3306/Chinook --project_name=docker_chinook
30
+
31
+ # from container to mysql container replace localhost with....
32
+ genai-logic create --db_url=mysql+pymysql://root:p@mysql-container:3306/Chinook --project_name=/localhost/docker_chinook
33
+
34
+ # microsoft sql server (setup: https://apilogicserver.github.io/Docs/Install-pyodbc/)
35
+ genai-logic create --db_url='mssql+pyodbc://sa:Posey3861@localhost:1433/NORTHWND?driver=ODBC+Driver+18+for+SQL+Server&trusted_connection=no&Encrypt=no' --project-name=NORTHWND
36
+
37
+ # oracle
31
38
  genai-logic create --project_name=oracle_hr --db_url='oracle+oracledb://hr:tiger@localhost:1521/?service_name=ORCL'
39
+
40
+ # postgres
41
+ genai-logic create --db_url=postgresql://postgres:p@localhost/northwind --project-name=nw-postgres
32
42
  genai-logic create --db_url=postgresql://postgres:p@10.0.0.234/postgres
33
43
  genai-logic create --project_name=my_schema --db_url=postgresql://postgres:p@localhost/my_schema
34
- genai-logic create --db_url=postgresql+psycopg2://postgres:password@localhost:5432/postgres?options=-csearch_path%3Dmy_db_schema
44
+ genai-logic create --db_url=postgresql://postgres:password@localhost:5432/postgres?options=-csearch_path%3Dmy_db_schema
45
+
46
+ # pythonanywhere
35
47
  genai-logic create --project_name=Chinook \
36
48
  --host=ApiLogicServer.pythonanywhere.com --port= \
37
49
  --db_url=mysql+pymysql://ApiLogicServer:@ApiLogicServer.mysql.pythonanywhere-services.com/ApiLogicServer\$Chinook
@@ -1,9 +1,9 @@
1
1
  PyJWT==2.6.0
2
2
  python-dateutil==2.8.2
3
3
  six==1.16.0
4
- SQLAlchemy==1.4.29
5
- Flask-SQLAlchemy==2.5.1
6
- SQLAlchemy-Utils==0.38.2
4
+ SQLAlchemy>=2.0.0
5
+ Flask-SQLAlchemy>=3.0.0
6
+ SQLAlchemy-Utils>=0.38.2
7
7
  Werkzeug==2.2.3
8
8
  logicbankutils==0.6.0
9
9
  inflect==5.0.2
@@ -25,7 +25,8 @@ PyMySQL==1.0.2
25
25
  cryptography==36.0.1
26
26
  requests==2.27.1
27
27
  gunicorn==20.1.0
28
- psycopg2-binary==2.9.5
28
+ psycopg2-binary>=2.9.5; python_version < '3.13'
29
+ psycopg[binary]>=3.1.0; python_version >= '3.13'
29
30
  DotMap==1.3.25
30
31
  WTForms==2.3.3
31
32
  behave==1.2.6
@@ -1,9 +1,9 @@
1
1
  PyJWT==2.6.0
2
2
  python-dateutil==2.8.2
3
3
  six==1.16.0
4
- SQLAlchemy==1.4.29
5
- Flask-SQLAlchemy==2.5.1
6
- SQLAlchemy-Utils==0.38.2
4
+ SQLAlchemy>=2.0.0
5
+ Flask-SQLAlchemy>=3.0.0
6
+ SQLAlchemy-Utils>=0.38.2
7
7
  Werkzeug==2.2.3
8
8
  logicbankutils==0.6.0
9
9
  inflect==5.0.2
@@ -25,7 +25,8 @@ PyMySQL==1.0.2
25
25
  cryptography==36.0.1
26
26
  requests==2.27.1
27
27
  gunicorn==20.1.0
28
- psycopg2-binary==2.9.5
28
+ psycopg2-binary>=2.9.5; python_version < '3.13'
29
+ psycopg[binary]>=3.1.0; python_version >= '3.13'
29
30
  DotMap==1.3.25
30
31
  WTForms==2.3.3
31
32
  behave==1.2.6
@@ -4,7 +4,10 @@ param(
4
4
  [String]$IDE
5
5
  )
6
6
 
7
- SRA="venv/lib/python3.12/site-packages/api_logic_server_cli/create_from_model/safrs-react-admin-npm-build"
7
+ # $SRA="venv/lib/python3.12/site-packages/api_logic_server_cli/create_from_model/safrs-react-admin-npm-build"
8
+
9
+ $venvPath = "venv\Lib\site-packages"
10
+ $SRA = Join-Path $venvPath "api_logic_server_cli\create_from_model\safrs-react-admin-npm-build"
8
11
 
9
12
  if (Test-Path -Path $SRA) {
10
13
  Write-Output " "
@@ -12,7 +15,7 @@ if (Test-Path -Path $SRA) {
12
15
  Write-Output " "
13
16
  } else {
14
17
  Write-Output " "
15
- Write-Output "Safrs React Admin (SRA) not found - please fix line above"
18
+ Write-Output "Safrs React Admin (SRA) not found - please fix line above for $SRA"
16
19
  Write-Output " "
17
20
  Exit 1
18
21
  }
@@ -28,8 +31,9 @@ if($IDE -eq "") {
28
31
  Write-Output " "
29
32
  Write-Output " IMPORTANT - create a folder, then install:"
30
33
  Write-Output " > mkdir ApiLogicServer"
34
+ Write-Output " > pip install ApiLogicServer"
31
35
  Write-Output " "
32
- Write-Output " > .\Install-ApiLogicServer-Dev [ vscode | charm | x ]"
36
+ Write-Output " > .\system\install-ApiLogicServer-dev\install-ApiLogicServer-dev.ps1 vscode"
33
37
  Write-Output " "
34
38
  Exit
35
39
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ontimize-app",
3
- "version": "15.6.0-NEXT-2",
3
+ "version": "15.6.0-NEXT-7",
4
4
  "scripts": {
5
5
  "ng": "ng",
6
6
  "start": "ng serve --port 4299",
@@ -30,7 +30,7 @@
30
30
  "@angular/router": "^15.2.10",
31
31
  "@angular/service-worker": "^15.2.10",
32
32
  "@angular/upgrade": "^15.2.10",
33
- "ontimize-web-ngx": "15.6.0-next.4",
33
+ "ontimize-web-ngx": "15.6.0-next.7",
34
34
  "ontimize-web-ngx-charts": "15.2.0-next.3",
35
35
  "ontimize-web-ngx-filemanager": "^15.1.0-next.0",
36
36
  "ontimize-web-ngx-map": "15.0.0",
@@ -8,6 +8,7 @@ from collections import defaultdict
8
8
  from importlib import import_module
9
9
  from inspect import FullArgSpec # val-311
10
10
  from keyword import iskeyword
11
+ from typing import TYPE_CHECKING
11
12
 
12
13
  import sqlalchemy
13
14
  import sqlalchemy.exc
@@ -22,7 +23,8 @@ import yaml
22
23
  import datetime
23
24
 
24
25
  # The generic ARRAY type was introduced in SQLAlchemy 1.1
25
- from api_logic_server_cli.create_from_model.model_creation_services import ModelCreationServices
26
+ if TYPE_CHECKING:
27
+ from api_logic_server_cli.create_from_model.model_creation_services import ModelCreationServices
26
28
  from api_logic_server_cli.create_from_model.meta_model import Resource, ResourceRelationship, ResourceAttribute
27
29
 
28
30
  log = logging.getLogger(__name__)
@@ -818,7 +820,7 @@ class CodeGenerator(object):
818
820
  """ not used by API Logic Server """
819
821
  self.noinflect = noinflect
820
822
  self.noclasses = noclasses
821
- self.model_creation_services = model_creation_services # type: ModelCreationServices
823
+ self.model_creation_services = model_creation_services # type: "ModelCreationServices"
822
824
  self.generate_relationships_on = "parent" # "child"
823
825
  """ FORMERLY, relns were genned ONLY on parent (== 'parent') """
824
826
  self.indentation = indentation
@@ -4,11 +4,23 @@ import argparse
4
4
  import io
5
5
  import sys
6
6
 
7
- import pkg_resources
7
+ try:
8
+ from importlib import metadata
9
+ except ImportError:
10
+ # Python < 3.8
11
+ import pkg_resources as metadata_fallback
12
+
13
+ class MetadataWrapper:
14
+ @staticmethod
15
+ def version(name):
16
+ return metadata_fallback.get_distribution(name).version
17
+
18
+ metadata = MetadataWrapper()
19
+
8
20
  from sqlalchemy.engine import create_engine
9
21
  from sqlalchemy.schema import MetaData
10
22
 
11
- from sqlacodegen_wrapper.sqlacodegen_wrapper import CodeGenerator
23
+ from .codegen import CodeGenerator
12
24
 
13
25
 
14
26
  def main(calling_args=None):
@@ -30,8 +42,11 @@ def main(calling_args=None):
30
42
  args = parser.parse_args()
31
43
 
32
44
  if args.version:
33
- version = pkg_resources.get_distribution('sqlacodegen').parsed_version
34
- print(version.public)
45
+ try:
46
+ version = metadata.version('sqlacodegen')
47
+ print(version)
48
+ except Exception:
49
+ print("sqlacodegen version unknown")
35
50
  return
36
51
  if not args.url:
37
52
  print('You must supply a url\n', file=sys.stderr)
@@ -39,7 +54,12 @@ def main(calling_args=None):
39
54
  return
40
55
 
41
56
  # Use reflection to fill in the metadata
42
- engine = create_engine(args.url)
57
+ # For Python 3.13+, force PostgreSQL URLs to use psycopg3 dialect
58
+ engine_url = args.url
59
+ if sys.version_info >= (3, 13) and engine_url.startswith('postgresql://'):
60
+ engine_url = engine_url.replace('postgresql://', 'postgresql+psycopg://', 1)
61
+
62
+ engine = create_engine(engine_url)
43
63
  try:
44
64
  # dirty hack for sqlite TODO review ApiLogicServer
45
65
  engine.execute("""PRAGMA journal_mode = OFF""")