Coverage for opt/mealie/lib/python3.12/site-packages/mealie/alembic/env.py: 52%

34 statements  

« prev     ^ index     » next       coverage.py v7.10.6, created at 2025-11-25 17:29 +0000

1from typing import Any 1a

2 

3import sqlalchemy as sa 1a

4from alembic import context 1a

5 

6import mealie.db.models._all_models # noqa: F401 1a

7from mealie.core.config import get_app_settings 1a

8from mealie.db.models._model_base import SqlAlchemyBase 1a

9 

10# this is the Alembic Config object, which provides 

11# access to the values within the .ini file in use. 

12config = context.config 1a

13 

14# add your model's MetaData object here 

15# for 'autogenerate' support 

16# from myapp import mymodel 

17# target_metadata = mymodel.Base.metadata 

18target_metadata = SqlAlchemyBase.metadata 1a

19 

20# other values from the config, defined by the needs of env.py, 

21# can be acquired: 

22# my_important_option = config.get_main_option("my_important_option") 

23# ... etc. 

24 

25# Set DB url from config 

26settings = get_app_settings() 1a

27 

28if not settings.DB_URL: 28 ↛ 29line 28 didn't jump to line 29 because the condition on line 28 was never true1a

29 raise Exception("DB URL not set in config") 

30 

31config.set_main_option("sqlalchemy.url", settings.DB_URL.replace("%", "%%")) 1a

32 

33 

34def include_object(object: Any, name: str, type_: str, reflected: bool, compare_to: Any): 1a

35 # skip dropping food/unit unique constraints; they are defined manually so alembic doesn't see them 

36 # see: revision dded3119c1fe 

37 if type_ == "unique_constraint" and name == "ingredient_foods_name_group_id_key" and compare_to is None: 

38 return False 

39 if type_ == "unique_constraint" and name == "ingredient_units_name_group_id_key" and compare_to is None: 

40 return False 

41 

42 # skip changing the quantity column in recipes_ingredients; it's a float on postgres, but an integer on sqlite 

43 # see: revision 263dd6707191 

44 if ( 

45 type_ == "column" 

46 and name == "quantity" 

47 and object.table.name == "recipes_ingredients" 

48 and hasattr(compare_to, "type") 

49 and isinstance(compare_to.type, sa.Integer) 

50 ): 

51 return False 

52 

53 return True 

54 

55 

56def run_migrations_offline(): 1a

57 """Run migrations in 'offline' mode. 

58 

59 This configures the context with just a URL 

60 and not an Engine, though an Engine is acceptable 

61 here as well. By skipping the Engine creation 

62 we don't even need a DBAPI to be available. 

63 

64 Calls to context.execute() here emit the given string to the 

65 script output. 

66 

67 """ 

68 url = config.get_main_option("sqlalchemy.url") 

69 context.configure( 

70 url=url, 

71 target_metadata=target_metadata, 

72 literal_binds=True, 

73 dialect_opts={"paramstyle": "named"}, 

74 ) 

75 

76 with context.begin_transaction(): 

77 context.run_migrations() 

78 

79 

80def run_migrations_online(): 1a

81 """Run migrations in 'online' mode. 

82 

83 In this scenario we need to create an Engine 

84 and associate a connection with the context. 

85 

86 """ 

87 connectable = sa.engine_from_config( 1a

88 config.get_section(config.config_ini_section), 

89 prefix="sqlalchemy.", 

90 poolclass=sa.pool.NullPool, 

91 ) 

92 

93 with connectable.connect() as connection: 1a

94 context.configure( 1a

95 connection=connection, 

96 target_metadata=target_metadata, 

97 user_module_prefix="mealie.db.migration_types.", 

98 render_as_batch=True, 

99 include_object=include_object, 

100 ) 

101 

102 with context.begin_transaction(): 1a

103 context.run_migrations() 1a

104 

105 

106if context.is_offline_mode(): 106 ↛ 107line 106 didn't jump to line 107 because the condition on line 106 was never true1a

107 run_migrations_offline() 

108else: 

109 run_migrations_online() 1a