Coverage for src/pydal2sql/core.py: 100%
30 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-07-20 15:20 +0200
« prev ^ index » next coverage.py v7.2.7, created at 2023-07-20 15:20 +0200
1"""
2Main functionality.
3"""
5import typing
7import pydal
8from pydal.adapters import MySQL, Postgre, SQLAdapter, SQLite
9from pydal.migrator import Migrator
10from pydal.objects import Table
12from .helpers import TempdirOrExistingDir, get_typing_args
13from .types import SUPPORTED_DATABASE_TYPES, SUPPORTED_DATABASE_TYPES_WITH_ALIASES
16def _build_dummy_migrator(_driver_name: SUPPORTED_DATABASE_TYPES_WITH_ALIASES, /, db_folder: str) -> Migrator:
17 """
18 Create a Migrator specific to the sql dialect of _driver_name.
19 """
20 db = pydal.DAL(None, migrate=False, folder=db_folder)
22 aliases = {
23 "postgresql": "psycopg2",
24 "postgres": "psycopg2",
25 "psql": "psycopg2",
26 "sqlite": "sqlite3",
27 "mysql": "pymysql",
28 }
30 driver_name = _driver_name.lower()
31 driver_name = aliases.get(driver_name, driver_name)
33 if driver_name not in get_typing_args(SUPPORTED_DATABASE_TYPES):
34 raise ValueError(
35 f"Unsupported database type {driver_name}. "
36 f"Choose one of {get_typing_args(SUPPORTED_DATABASE_TYPES_WITH_ALIASES)}"
37 )
39 adapters_per_database: dict[str, typing.Type[SQLAdapter]] = {
40 "psycopg2": Postgre,
41 "sqlite3": SQLite,
42 "pymysql": MySQL,
43 }
45 adapter = adapters_per_database[driver_name]
47 installed_driver = db._drivers_available.get(driver_name)
49 if not installed_driver: # pragma: no cover
50 raise ValueError(f"Please install the correct driver for database type {driver_name}")
52 class DummyAdaptor(SQLAdapter): # type: ignore
53 types = adapter.types
54 driver = installed_driver
55 dbengine = adapter.dbengine
57 adapter = DummyAdaptor(db, "", adapter_args={"driver": installed_driver})
58 return Migrator(adapter)
61def generate_sql(
62 define_table: Table, db_type: SUPPORTED_DATABASE_TYPES_WITH_ALIASES = None, *, db_folder: str = None
63) -> str:
64 """
65 Given a Table object (result of `db.define_table('mytable')` or simply db.mytable) \
66 and a db type (e.g. postgres, sqlite, mysql), generate the `CREATE TABLE` SQL for that dialect.
68 If no db_type is supplied, the type is guessed from the specified table.
69 However, your db_type can differ from the current database used.
70 You can even use a dummy database to generate SQL code with:
71 `db = pydal.DAL(None, migrate=False)`
73 db_folder is the database folder where migration (`.table`) files are stored.
74 By default, a random temporary dir is created.
75 """
76 if db_type is None:
77 db_type = define_table._db._dbname
79 with TempdirOrExistingDir(db_folder) as db_folder:
80 migrator = _build_dummy_migrator(db_type, db_folder=db_folder)
82 sql: str = migrator.create_table(
83 define_table,
84 migrate=True,
85 fake_migrate=True,
86 )
87 return sql