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.
- jetbase/cli/main.py +146 -4
- jetbase/commands/current.py +20 -0
- jetbase/commands/fix_checksums.py +172 -0
- jetbase/commands/fix_files.py +133 -0
- jetbase/commands/history.py +53 -0
- jetbase/commands/init.py +29 -0
- jetbase/commands/lock_status.py +25 -0
- jetbase/commands/new.py +65 -0
- jetbase/commands/rollback.py +172 -0
- jetbase/commands/status.py +212 -0
- jetbase/commands/unlock.py +29 -0
- jetbase/commands/upgrade.py +248 -0
- jetbase/commands/validators.py +37 -0
- jetbase/config.py +304 -25
- jetbase/constants.py +10 -2
- jetbase/database/connection.py +40 -0
- jetbase/database/queries/base.py +353 -0
- jetbase/database/queries/default_queries.py +215 -0
- jetbase/database/queries/postgres.py +14 -0
- jetbase/database/queries/query_loader.py +87 -0
- jetbase/database/queries/sqlite.py +197 -0
- jetbase/engine/checksum.py +25 -0
- jetbase/engine/dry_run.py +105 -0
- jetbase/engine/file_parser.py +324 -0
- jetbase/engine/formatters.py +61 -0
- jetbase/engine/lock.py +65 -0
- jetbase/engine/repeatable.py +125 -0
- jetbase/engine/validation.py +238 -0
- jetbase/engine/version.py +144 -0
- jetbase/enums.py +37 -1
- jetbase/exceptions.py +87 -0
- jetbase/models.py +45 -0
- jetbase/repositories/lock_repo.py +129 -0
- jetbase/repositories/migrations_repo.py +451 -0
- jetbase-0.12.1.dist-info/METADATA +135 -0
- jetbase-0.12.1.dist-info/RECORD +39 -0
- {jetbase-0.7.0.dist-info → jetbase-0.12.1.dist-info}/WHEEL +1 -1
- jetbase/core/dry_run.py +0 -38
- jetbase/core/file_parser.py +0 -199
- jetbase/core/initialize.py +0 -33
- jetbase/core/repository.py +0 -169
- jetbase/core/rollback.py +0 -67
- jetbase/core/upgrade.py +0 -75
- jetbase/core/version.py +0 -163
- jetbase/queries.py +0 -72
- jetbase-0.7.0.dist-info/METADATA +0 -12
- jetbase-0.7.0.dist-info/RECORD +0 -17
- {jetbase-0.7.0.dist-info → jetbase-0.12.1.dist-info}/entry_points.txt +0 -0
- {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
|
-
""")
|
jetbase-0.7.0.dist-info/METADATA
DELETED
|
@@ -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
|
jetbase-0.7.0.dist-info/RECORD
DELETED
|
@@ -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,,
|
|
File without changes
|
|
File without changes
|