jetbase 0.7.0__py3-none-any.whl → 0.12.1__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 (49) hide show
  1. jetbase/cli/main.py +146 -4
  2. jetbase/commands/current.py +20 -0
  3. jetbase/commands/fix_checksums.py +172 -0
  4. jetbase/commands/fix_files.py +133 -0
  5. jetbase/commands/history.py +53 -0
  6. jetbase/commands/init.py +29 -0
  7. jetbase/commands/lock_status.py +25 -0
  8. jetbase/commands/new.py +65 -0
  9. jetbase/commands/rollback.py +172 -0
  10. jetbase/commands/status.py +212 -0
  11. jetbase/commands/unlock.py +29 -0
  12. jetbase/commands/upgrade.py +248 -0
  13. jetbase/commands/validators.py +37 -0
  14. jetbase/config.py +304 -25
  15. jetbase/constants.py +10 -2
  16. jetbase/database/connection.py +40 -0
  17. jetbase/database/queries/base.py +353 -0
  18. jetbase/database/queries/default_queries.py +215 -0
  19. jetbase/database/queries/postgres.py +14 -0
  20. jetbase/database/queries/query_loader.py +87 -0
  21. jetbase/database/queries/sqlite.py +197 -0
  22. jetbase/engine/checksum.py +25 -0
  23. jetbase/engine/dry_run.py +105 -0
  24. jetbase/engine/file_parser.py +324 -0
  25. jetbase/engine/formatters.py +61 -0
  26. jetbase/engine/lock.py +65 -0
  27. jetbase/engine/repeatable.py +125 -0
  28. jetbase/engine/validation.py +238 -0
  29. jetbase/engine/version.py +144 -0
  30. jetbase/enums.py +37 -1
  31. jetbase/exceptions.py +87 -0
  32. jetbase/models.py +45 -0
  33. jetbase/repositories/lock_repo.py +129 -0
  34. jetbase/repositories/migrations_repo.py +451 -0
  35. jetbase-0.12.1.dist-info/METADATA +135 -0
  36. jetbase-0.12.1.dist-info/RECORD +39 -0
  37. {jetbase-0.7.0.dist-info → jetbase-0.12.1.dist-info}/WHEEL +1 -1
  38. jetbase/core/dry_run.py +0 -38
  39. jetbase/core/file_parser.py +0 -199
  40. jetbase/core/initialize.py +0 -33
  41. jetbase/core/repository.py +0 -169
  42. jetbase/core/rollback.py +0 -67
  43. jetbase/core/upgrade.py +0 -75
  44. jetbase/core/version.py +0 -163
  45. jetbase/queries.py +0 -72
  46. jetbase-0.7.0.dist-info/METADATA +0 -12
  47. jetbase-0.7.0.dist-info/RECORD +0 -17
  48. {jetbase-0.7.0.dist-info → jetbase-0.12.1.dist-info}/entry_points.txt +0 -0
  49. {jetbase-0.7.0.dist-info → jetbase-0.12.1.dist-info}/licenses/LICENSE +0 -0
jetbase/core/upgrade.py DELETED
@@ -1,75 +0,0 @@
1
- import os
2
-
3
- from jetbase.core.dry_run import process_dry_run
4
- from jetbase.core.file_parser import parse_upgrade_statements
5
- from jetbase.core.repository import (
6
- create_migrations_table_if_not_exists,
7
- get_last_updated_version,
8
- run_migration,
9
- )
10
- from jetbase.core.version import get_migration_filepaths_by_version
11
- from jetbase.enums import MigrationOperationType
12
-
13
-
14
- def upgrade_cmd(
15
- count: int | None = None, to_version: str | None = None, dry_run: bool = False
16
- ) -> None:
17
- """
18
- Run database migrations by applying all pending SQL migration files.
19
- Executes migration files in order starting from the last applied version,
20
- updating the migrations tracking table after each successful migration.
21
-
22
- Returns:
23
- None
24
- """
25
-
26
- if count is not None and to_version is not None:
27
- raise ValueError(
28
- "Cannot specify both 'count' and 'to_version' for upgrade. "
29
- "Select only one, or do not specify either to run all pending migrations."
30
- )
31
-
32
- create_migrations_table_if_not_exists()
33
- latest_version: str | None = get_last_updated_version()
34
-
35
- all_versions: dict[str, str] = get_migration_filepaths_by_version(
36
- directory=os.path.join(os.getcwd(), "migrations"),
37
- version_to_start_from=latest_version,
38
- )
39
-
40
- if latest_version:
41
- all_versions = dict(list(all_versions.items())[1:])
42
-
43
- if count:
44
- all_versions = dict(list(all_versions.items())[:count])
45
- elif to_version:
46
- if all_versions.get(to_version) is None:
47
- raise ValueError(
48
- f"The specified to_version '{to_version}' does not exist among pending migrations."
49
- )
50
- all_versions_list = []
51
- for file_version, file_path in all_versions.items():
52
- all_versions_list.append((file_version, file_path))
53
- if file_version == to_version:
54
- break
55
- all_versions = dict(all_versions_list)
56
-
57
- if not dry_run:
58
- for version, file_path in all_versions.items():
59
- sql_statements: list[str] = parse_upgrade_statements(file_path=file_path)
60
- filename: str = os.path.basename(file_path)
61
-
62
- run_migration(
63
- sql_statements=sql_statements,
64
- version=version,
65
- migration_operation=MigrationOperationType.UPGRADE,
66
- filename=filename,
67
- )
68
-
69
- print(f"Migration applied successfully: {filename}")
70
-
71
- else:
72
- process_dry_run(
73
- version_to_filepath=all_versions,
74
- migration_operation=MigrationOperationType.UPGRADE,
75
- )
jetbase/core/version.py DELETED
@@ -1,163 +0,0 @@
1
- import os
2
-
3
- from jetbase.core.file_parser import is_filename_format_valid, is_filename_length_valid
4
-
5
-
6
- def _get_version_key_from_filename(filename: str) -> str:
7
- """
8
- Extract and normalize version key from a filename.
9
-
10
- The function extracts the version part from a filename that follows the format:
11
- 'V{version}__{description}.sql' where version can be like '1', '1_1', or '1.1'.
12
-
13
- Args:
14
- filename (str): The filename to extract version from.
15
- Must follow pattern like 'V1__description.sql' or 'V1_1__description.sql'
16
-
17
- Returns:
18
- str: Normalized version string where underscores are replaced with periods.
19
-
20
- Raises:
21
- ValueError: If the filename doesn't follow the expected format.
22
-
23
- Examples:
24
- >>> _get_version_key_from_filename("V1__my_description.sql")
25
- '1'
26
- >>> _get_version_key_from_filename("V1_1__my_description.sql")
27
- '1.1'
28
- >>> _get_version_key_from_filename("V1.1__my_description.sql")
29
- '1.1'
30
- """
31
- try:
32
- version = filename.split("__")[0][1:]
33
- except Exception:
34
- raise (
35
- ValueError(
36
- "Filename must be in the following format: V1__my_description.sql, V1_1__my_description.sql, V1.1__my_description.sql"
37
- )
38
- )
39
- return version.replace("_", ".")
40
-
41
-
42
- def _convert_version_tuple_to_str(version_tuple: tuple[str, ...]) -> str:
43
- """
44
- Convert a version tuple to a string representation.
45
-
46
- Args:
47
- version_tuple (tuple[str, ...]): A tuple containing version components as strings.
48
-
49
- Returns:
50
- str: A string representation of the version, with components joined by periods.
51
-
52
- Example:
53
- >>> _convert_version_tuple_to_str(('1', '2', '3'))
54
- '1.2.3'
55
- """
56
- return ".".join(version_tuple)
57
-
58
-
59
- def convert_version_to_tuple(version: str) -> tuple[str, ...]:
60
- """
61
- Convert a version string to a tuple of version components.
62
-
63
- Args:
64
- version_str (str): A version string with components separated by periods.
65
-
66
- Returns:
67
- tuple[str, ...]: A tuple containing the version components as strings.
68
-
69
- Example:
70
- >>> convert_version_to_tuple("1.2.3")
71
- ('1', '2', '3')
72
- """
73
- return tuple(version.split("."))
74
-
75
-
76
- def get_migration_filepaths_by_version(
77
- directory: str,
78
- version_to_start_from: str | None = None,
79
- end_version: str | None = None,
80
- ) -> dict[str, str]:
81
- """
82
- Retrieve migration file paths organized by version number.
83
-
84
- Walks through the specified directory to find SQL migration files and creates
85
- a dictionary mapping version strings to their file paths. Files are validated
86
- for proper naming format and length. Results can be filtered by version range.
87
-
88
- Args:
89
- directory (str): The directory path to search for SQL migration files.
90
- version_to_start_from (str | None): Optional minimum version (inclusive).
91
- Only files with versions >= this value are included. Defaults to None.
92
- end_version (str | None): Optional maximum version (exclusive).
93
- Only files with versions < this value are included. Defaults to None.
94
-
95
- Returns:
96
- dict[str, str]: Dictionary mapping version strings to file paths,
97
- sorted in ascending order by version number.
98
-
99
- Raises:
100
- ValueError: If a filename doesn't match the required format or exceeds
101
- the maximum length of 512 characters.
102
-
103
- Example:
104
- >>> get_migration_filepaths_by_version('/path/to/migrations')
105
- {'1.0.0': '/path/to/migrations/V1_0_0__init.sql',
106
- '1.2.0': '/path/to/migrations/V1_2_0__add_users.sql'}
107
- >>> get_migration_filepaths_by_version('/path/to/migrations', version_to_start_from='1.1.0')
108
- {'1.2.0': '/path/to/migrations/V1_2_0__add_users.sql'}
109
- """
110
- version_to_filepath_dict: dict[str, str] = {}
111
-
112
- for root, _, files in os.walk(directory):
113
- for filename in files:
114
- if filename.endswith(".sql") and not is_filename_format_valid(
115
- filename=filename
116
- ):
117
- raise ValueError(
118
- f"Invalid migration filename format: {filename}. "
119
- "Filenames must start with 'V', followed by the version number, "
120
- "two underscores '__', a description, and end with '.sql'. "
121
- "V<version_number>__<my_description>.sql. "
122
- "Examples: 'V1_2_0__add_new_table.sql' or 'V1.2.0__add_new_table.sql'"
123
- )
124
-
125
- if filename.endswith(".sql") and not is_filename_length_valid(
126
- filename=filename
127
- ):
128
- raise ValueError(
129
- f"Migration filename too long: {filename}. "
130
- f"Filename is currently {len(filename)} characters. "
131
- "Filenames must not exceed 512 characters."
132
- )
133
-
134
- if is_filename_format_valid(filename=filename):
135
- file_path: str = os.path.join(root, filename)
136
- version: str = _get_version_key_from_filename(filename=filename)
137
- version_tuple: tuple[str, ...] = convert_version_to_tuple(
138
- version=version
139
- )
140
-
141
- if end_version:
142
- if version_tuple > convert_version_to_tuple(version=end_version):
143
- continue
144
-
145
- if version_to_start_from:
146
- if version_tuple >= convert_version_to_tuple(
147
- version=version_to_start_from
148
- ):
149
- version_to_filepath_dict[
150
- _convert_version_tuple_to_str(version_tuple=version_tuple)
151
- ] = file_path
152
-
153
- else:
154
- version_to_filepath_dict[
155
- _convert_version_tuple_to_str(version_tuple=version_tuple)
156
- ] = file_path
157
-
158
- ordered_version_to_filepath_dict: dict[str, str] = {
159
- version: version_to_filepath_dict[version]
160
- for version in sorted(version_to_filepath_dict.keys())
161
- }
162
-
163
- return ordered_version_to_filepath_dict
jetbase/queries.py DELETED
@@ -1,72 +0,0 @@
1
- from sqlalchemy import TextClause, text
2
-
3
- LATEST_VERSION_QUERY: TextClause = text("""
4
- SELECT
5
- version
6
- FROM
7
- jetbase_migrations
8
- ORDER BY
9
- applied_at DESC
10
- LIMIT 1
11
- """)
12
-
13
- CREATE_MIGRATIONS_TABLE_STMT: TextClause = text("""
14
- CREATE TABLE IF NOT EXISTS jetbase_migrations (
15
- version VARCHAR(255) PRIMARY KEY,
16
- description VARCHAR(500),
17
- filename VARCHAR(512),
18
- order_executed INT GENERATED ALWAYS AS IDENTITY,
19
- applied_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
20
- )
21
- """)
22
-
23
- INSERT_VERSION_STMT: TextClause = text("""
24
- INSERT INTO jetbase_migrations (version, description, filename)
25
- VALUES (:version, :description, :filename)
26
- """)
27
-
28
- DELETE_VERSION_STMT: TextClause = text("""
29
- DELETE FROM jetbase_migrations
30
- WHERE version = :version
31
- """)
32
-
33
- LATEST_VERSIONS_QUERY: TextClause = text("""
34
- SELECT
35
- version
36
- FROM
37
- jetbase_migrations
38
- ORDER BY
39
- applied_at DESC
40
- LIMIT :limit
41
- """)
42
-
43
- LATEST_VERSIONS_BY_STARTING_VERSION_QUERY: TextClause = text("""
44
- SELECT
45
- version
46
- FROM
47
- jetbase_migrations
48
- WHERE applied_at >
49
- (select applied_at from jetbase_migrations
50
- where version = :starting_version)
51
- ORDER BY
52
- applied_at DESC
53
- """)
54
-
55
- CHECK_IF_VERSION_EXISTS_QUERY: TextClause = text("""
56
- SELECT
57
- COUNT(*)
58
- FROM
59
- jetbase_migrations
60
- WHERE
61
- version = :version
62
- """)
63
-
64
-
65
- CHECK_IF_MIGRATIONS_TABLE_EXISTS_QUERY: TextClause = text("""
66
- SELECT EXISTS (
67
- SELECT 1
68
- FROM information_schema.tables
69
- WHERE table_schema = 'public'
70
- AND table_name = 'jetbase_migrations'
71
- )
72
- """)
@@ -1,12 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: jetbase
3
- Version: 0.7.0
4
- Summary: Jetbase is a Python database migration tool
5
- Author-email: jaz <jaz.allibhai@gmail.com>
6
- License-File: LICENSE
7
- Requires-Python: >=3.10
8
- Requires-Dist: sqlalchemy>=2.0.10
9
- Requires-Dist: typer>=0.12.3
10
- Description-Content-Type: text/markdown
11
-
12
- # jetbase
@@ -1,17 +0,0 @@
1
- jetbase/config.py,sha256=-YZgS-fVW8k53azx9Ur0GjJvYCZLwOHkguMr_Ujc-mo,1731
2
- jetbase/constants.py,sha256=X2SYgXRxj77zWB-6N764RQsJmKKUd5Wa7RaQGN6eTiQ,339
3
- jetbase/enums.py,sha256=LFNZnWcBxvF4kIdZYdGKn2Z65ADHJs38MnGAqeEbZ_U,110
4
- jetbase/queries.py,sha256=jZ9ei8V-dEb_8ZAwtSAFqLnIEI5rumm3KvQmw4CiZk4,1619
5
- jetbase/cli/main.py,sha256=I0HIRGC7dmTvEhgdEBksF-p7QPoY4-CfVcm-niVhzck,1504
6
- jetbase/core/dry_run.py,sha256=zIV4NM_OL-aR7UJlEXYysiGairMOgytnT5rg8baFSms,1469
7
- jetbase/core/file_parser.py,sha256=Aau7iFaBoZxOgoxB-4C5XAvE_a9142kv7sJHOAANe2A,6069
8
- jetbase/core/initialize.py,sha256=lm3FWhe1YNKCTmZix465tBGjJsl_YshhRo2ENm7iPFM,955
9
- jetbase/core/repository.py,sha256=JrmqFkIIbICPsxnY7O3ei9kLL-0mXWFefU0QPHppcgw,5586
10
- jetbase/core/rollback.py,sha256=e87xlI3WJaOAQD_4QdmeZIDj9a5CW7wKUxQkgIFXy3c,2385
11
- jetbase/core/upgrade.py,sha256=GowNGAxXRD9dks8FWqSMoQPCMnMh_yP01HNEYB5Py2Q,2603
12
- jetbase/core/version.py,sha256=mPeJEgcqA0hZMb6YMZQcfc-MGcNI2Ls_7hiH6vJnC1k,6136
13
- jetbase-0.7.0.dist-info/METADATA,sha256=6vue-I4pBPIQRmMHY3JrxjU7j81fgL6ITMiWcwnmbOs,306
14
- jetbase-0.7.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
15
- jetbase-0.7.0.dist-info/entry_points.txt,sha256=-Pe7A0r8aGF-6C14hB0Ck8aEuszuH5pdadt5OWSiWwA,50
16
- jetbase-0.7.0.dist-info/licenses/LICENSE,sha256=hyssQNKtnK32aFCk8mVR406ysMtGNP6_dZCig8zBk4Q,1065
17
- jetbase-0.7.0.dist-info/RECORD,,