Coverage for src/pydal2sql/core.py: 100%

32 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-07-20 17:06 +0200

1""" 

2Main functionality. 

3""" 

4 

5import typing 

6 

7import pydal 

8from pydal.adapters import MySQL, Postgre, SQLAdapter, SQLite 

9from pydal.migrator import Migrator 

10from pydal.objects import Table 

11 

12from .helpers import TempdirOrExistingDir, get_typing_args 

13from .types import SUPPORTED_DATABASE_TYPES, SUPPORTED_DATABASE_TYPES_WITH_ALIASES 

14 

15 

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) 

21 

22 aliases = { 

23 "postgresql": "psycopg2", 

24 "postgres": "psycopg2", 

25 "psql": "psycopg2", 

26 "sqlite": "sqlite3", 

27 "mysql": "pymysql", 

28 } 

29 

30 driver_name = _driver_name.lower() 

31 driver_name = aliases.get(driver_name, driver_name) 

32 

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 ) 

38 

39 adapters_per_database: dict[str, typing.Type[SQLAdapter]] = { 

40 "psycopg2": Postgre, 

41 "sqlite3": SQLite, 

42 "pymysql": MySQL, 

43 } 

44 

45 adapter = adapters_per_database[driver_name] 

46 

47 installed_driver = db._drivers_available.get(driver_name) 

48 

49 if not installed_driver: # pragma: no cover 

50 raise ValueError(f"Please install the correct driver for database type {driver_name}") 

51 

52 class DummyAdaptor(SQLAdapter): # type: ignore 

53 types = adapter.types 

54 driver = installed_driver 

55 dbengine = adapter.dbengine 

56 

57 adapter = DummyAdaptor(db, "", adapter_args={"driver": installed_driver}) 

58 return Migrator(adapter) 

59 

60 

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. 

67 

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)` 

72 

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 = getattr(define_table._db, "_dbname", None) 

78 if db_type is None: 

79 raise ValueError("Please manually define a database type!") 

80 

81 with TempdirOrExistingDir(db_folder) as db_folder: 

82 migrator = _build_dummy_migrator(db_type, db_folder=db_folder) 

83 

84 sql: str = migrator.create_table( 

85 define_table, 

86 migrate=True, 

87 fake_migrate=True, 

88 ) 

89 return sql