half-orm-dev 1.0.0a34__tar.gz → 1.0.0a35__tar.gz

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 (85) hide show
  1. {half_orm_dev-1.0.0a34/half_orm_dev.egg-info → half_orm_dev-1.0.0a35}/PKG-INFO +1 -1
  2. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/file_executor.py +3 -1
  3. half_orm_dev-1.0.0a35/half_orm_dev/migrations/1/0/0/a35/00_drop_stale_release_schemas.py +145 -0
  4. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/repo.py +48 -9
  5. half_orm_dev-1.0.0a35/half_orm_dev/version.txt +1 -0
  6. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35/half_orm_dev.egg-info}/PKG-INFO +1 -1
  7. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev.egg-info/SOURCES.txt +1 -0
  8. half_orm_dev-1.0.0a34/half_orm_dev/version.txt +0 -1
  9. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/AUTHORS +0 -0
  10. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/LICENSE +0 -0
  11. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/README.md +0 -0
  12. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/__init__.py +0 -0
  13. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/_bootstrap_runner.py +0 -0
  14. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/cli/__init__.py +0 -0
  15. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/cli/commands/__init__.py +0 -0
  16. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/cli/commands/apply.py +0 -0
  17. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/cli/commands/check.py +0 -0
  18. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/cli/commands/clone.py +0 -0
  19. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/cli/commands/init.py +0 -0
  20. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/cli/commands/migrate.py +0 -0
  21. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/cli/commands/patch.py +0 -0
  22. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/cli/commands/recover.py +0 -0
  23. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/cli/commands/release.py +0 -0
  24. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/cli/commands/restore.py +0 -0
  25. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/cli/commands/revert_migration.py +0 -0
  26. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/cli/commands/rollback.py +0 -0
  27. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/cli/commands/set_git_origin.py +0 -0
  28. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/cli/commands/sync.py +0 -0
  29. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/cli/commands/todo.py +0 -0
  30. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/cli/commands/undo.py +0 -0
  31. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/cli/commands/upgrade.py +0 -0
  32. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/cli/main.py +0 -0
  33. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/cli_extension.py +0 -0
  34. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/database.py +0 -0
  35. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/decorators.py +0 -0
  36. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/hgit.py +0 -0
  37. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/migration_manager.py +0 -0
  38. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/migrations/0/17/1/00_move_to_hop.py +0 -0
  39. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/migrations/0/17/1/01_txt_to_toml.py +0 -0
  40. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/migrations/0/17/4/00_toml_dict_format.py +0 -0
  41. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/migrations/0/17/4/02_move_patches_to_subdirs.py +0 -0
  42. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/migrations/0/17/5/01_update_pyproject_dependency.py +0 -0
  43. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/migrations/0/18/0/00_add_async_support.py +0 -0
  44. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/migrations/0/18/0/01_update_default_tests.py +0 -0
  45. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/migrations/1/0/0/a20/01_update_gitignore.py +0 -0
  46. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/migrations/1/0/0/a33/00_metadata_to_data_sql.py +0 -0
  47. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/migrations/hop/BREAKING_CHANGES-1.0.0.md +0 -0
  48. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/modules.py +0 -0
  49. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/patch_manager.py +0 -0
  50. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/patch_validator.py +0 -0
  51. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/patches/0/1/0/00_half_orm_meta.database.sql +0 -0
  52. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/patches/0/1/0/01_alter_half_orm_meta.hop_release.sql +0 -0
  53. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/patches/0/1/0/02_half_orm_meta.view.hop_penultimate_release.sql +0 -0
  54. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/patches/log +0 -0
  55. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/patches/sql/half_orm_meta.sql +0 -0
  56. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/py.typed +0 -0
  57. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/release_file.py +0 -0
  58. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/release_manager.py +0 -0
  59. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/scripts/repair-metadata.py +0 -0
  60. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/templates/.gitignore +0 -0
  61. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/templates/MANIFEST.in +0 -0
  62. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/templates/README +0 -0
  63. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/templates/conftest_template +0 -0
  64. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/templates/git-hooks/pre-commit +0 -0
  65. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/templates/git-hooks/pre-push +0 -0
  66. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/templates/git-hooks/prepare-commit-msg +0 -0
  67. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/templates/git-hooks/reference-transaction +0 -0
  68. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/templates/init_module_template +0 -0
  69. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/templates/module_template_1 +0 -0
  70. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/templates/module_template_2 +0 -0
  71. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/templates/module_template_3 +0 -0
  72. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/templates/pyproject.toml +0 -0
  73. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/templates/relation_test +0 -0
  74. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/templates/sql_adapter +0 -0
  75. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/templates/warning +0 -0
  76. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/utils.py +0 -0
  77. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev/venv_setup.py +0 -0
  78. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev.egg-info/dependency_links.txt +0 -0
  79. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev.egg-info/entry_points.txt +0 -0
  80. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev.egg-info/requires.txt +0 -0
  81. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/half_orm_dev.egg-info/top_level.txt +0 -0
  82. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/pyproject.toml +0 -0
  83. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/setup.cfg +0 -0
  84. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/setup.py +0 -0
  85. {half_orm_dev-1.0.0a34 → half_orm_dev-1.0.0a35}/tests/test_bootstrap_runner.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: half_orm_dev
3
- Version: 1.0.0a34
3
+ Version: 1.0.0a35
4
4
  Summary: half_orm development Framework.
5
5
  Author-email: Joël Maïzi <joel.maizi@collorg.org>
6
6
  License-Expression: GPL-3.0-or-later
@@ -61,7 +61,9 @@ def execute_sql_file_psql(file_path: Path, database, database_name: str) -> None
61
61
  try:
62
62
  database.execute_pg_command('psql', '-v', 'ON_ERROR_STOP=1', '-d', database_name, '-f', str(file_path))
63
63
  except Exception as e:
64
- raise FileExecutionError(f"psql execution failed for {file_path.name}: {e}") from e
64
+ stderr = getattr(e, 'stderr', None)
65
+ detail = f"{e}\n{stderr.strip()}" if stderr else str(e)
66
+ raise FileExecutionError(f"psql execution failed for {file_path.name}: {detail}") from e
65
67
 
66
68
 
67
69
  def execute_python_file(
@@ -0,0 +1,145 @@
1
+ """
2
+ Migration 1.0.0a35 — drop stale release-X.Y.Z.sql on active branches
3
+
4
+ Before 1.0.0a33, restore_database_from_schema() rebuilt the database
5
+ from model/schema.sql + model/metadata-{version}.sql, and the latter
6
+ held half_orm_meta bookkeeping *only* - no application data.
7
+ generate_release_schema() then took a full pg_dump of that database, so
8
+ every model/release-{version}.sql produced this way captured the
9
+ structure plus the half_orm_meta rows and nothing else.
10
+
11
+ The a33 migration backfilled model/data-{version}.sql with the real,
12
+ complete snapshot, but left those release files untouched. They are
13
+ still what `patch apply` and `patch merge` restore from whenever a
14
+ release is in flight, so development databases come back up with no
15
+ application data at all - the symptom that motivated this migration
16
+ (a project whose release-0.3.10.sql carried 78 half_orm_meta.hop_release
17
+ rows and zero rows for its 39 other tables, against 2098 rows in
18
+ data-0.3.9.sql).
19
+
20
+ Rather than rebuilding those files here - which would mean restoring a
21
+ database and replaying every staged patch, per branch - this deletes
22
+ them. They are derived artifacts: the fallback already in
23
+ apply_patch_complete_workflow() rebuilds one from
24
+ restore_database_from_schema() (schema + full data) plus the staged
25
+ patches, then calls generate_release_schema() again. Deleting is
26
+ therefore self-healing, and costs one rebuild on the next `patch apply`.
27
+
28
+ A release schema is carried by every active branch: create_release()
29
+ commits it on ho-release/X.Y.Z, patch branches inherit a copy, and .hop/
30
+ syncing propagates it to ho-prod as well. All of them have to be
31
+ cleaned, and ho-prod in particular must not be skipped - syncing copies
32
+ .hop/ with `git checkout <source> -- .hop/`, so a copy left on ho-prod
33
+ would be restored onto every branch this migration just cleaned. For
34
+ the same reason the deletion never propagates on its own: that checkout
35
+ adds and overwrites, but never deletes.
36
+
37
+ Ordering therefore matters. Other branches are handled first, each with
38
+ its own commit, while ho-prod's copy is only staged - the migration
39
+ runner commits it, then pushes ho-prod, and only then syncs .hop/
40
+ outwards.
41
+
42
+ Committing on other branches is covered by the existing safety net:
43
+ capture_branches_snapshot() records ho-prod, release and patch branches
44
+ alike, and rollback_to_snapshot() resets each one should the migration
45
+ fail later. Following the convention in
46
+ Repo.sync_hop_to_active_branches(), those local commits are the
47
+ transaction (a failure propagates and triggers that rollback) while push
48
+ failures are reported rather than raised - the deletion is already
49
+ recorded locally, and an unpushed branch is recoverable.
50
+ """
51
+
52
+ import sys
53
+ from pathlib import Path
54
+
55
+
56
+ def get_description():
57
+ return "Delete release-X.Y.Z.sql files generated before the metadata->data.sql switch"
58
+
59
+
60
+ def _affected_branches(repo):
61
+ """Active release and patch branches, both of which carry release schemas."""
62
+ status = repo.hgit.get_active_branches_status()
63
+ names = []
64
+ for key in ('release_branches', 'patch_branches'):
65
+ for branch in status.get(key) or []:
66
+ name = branch.get('name')
67
+ if name and name not in names:
68
+ names.append(name)
69
+ return names
70
+
71
+
72
+ def _stale_release_schemas(repo, model_dir):
73
+ """Repo-relative paths of the release schemas present on this branch."""
74
+ return [
75
+ str(path.relative_to(repo.base_dir))
76
+ for path in sorted(model_dir.glob('release-*.sql'))
77
+ ]
78
+
79
+
80
+ def migrate(repo):
81
+ model_dir = Path(repo.model_dir)
82
+
83
+ # Only projects predating the a33 metadata->data switch are affected.
84
+ # A leftover model/metadata-*.sql is the proof: it is what the old
85
+ # restore path loaded, so any release schema this project generated
86
+ # was dumped from a database holding half_orm_meta rows only. A
87
+ # project that never had those files has correct release schemas and
88
+ # must not be forced into a needless rebuild.
89
+ if not list(model_dir.glob('metadata-*.sql')):
90
+ return {}
91
+
92
+ git_repo = repo.hgit.git_repo
93
+ current_branch = repo.hgit.branch
94
+ deleted = []
95
+ to_push = []
96
+
97
+ # Other active branches first, each committed on the spot: the
98
+ # current branch has to stay clean while switching away from it.
99
+ for branch in _affected_branches(repo):
100
+ if branch == current_branch:
101
+ continue
102
+ with repo.hgit.on_branch(branch, silent=True):
103
+ stale = _stale_release_schemas(repo, model_dir)
104
+ if not stale:
105
+ continue
106
+
107
+ git_repo.index.remove(stale, working_tree=True)
108
+ git_repo.index.commit(
109
+ '[HOP] Remove stale release schema '
110
+ '(generated before metadata->data.sql; regenerated with '
111
+ 'full data on the next patch apply)',
112
+ skip_hooks=True,
113
+ )
114
+ deleted.extend(f"{branch}:{name}" for name in stale)
115
+ to_push.append(branch)
116
+
117
+ # push_branch() names its target explicitly, so it does not depend on
118
+ # the branch currently checked out.
119
+ for branch in to_push:
120
+ try:
121
+ repo.hgit.push_branch(branch)
122
+ except Exception as e:
123
+ print(
124
+ f" ⚠ Could not push {branch}: {e}\n"
125
+ f" The stale release schema was removed locally; "
126
+ f"push {branch} manually to share the change.",
127
+ file=sys.stderr,
128
+ )
129
+
130
+ # ho-prod last, and removed from the working tree only. The migration
131
+ # runner always stages '.hop/' before committing, and `git add` on a
132
+ # directory records deletions inside it, so the removal lands in the
133
+ # migration commit - which is pushed before .hop/ is synced outwards.
134
+ # Skipping ho-prod would leave a copy here that the sync copies
135
+ # straight back onto every branch cleaned above.
136
+ #
137
+ # Staging it here instead would break that runner: it feeds every
138
+ # path it finds staged to `git add`, and `git add` on an
139
+ # already-staged deletion fails with "did not match any files".
140
+ stale_here = _stale_release_schemas(repo, model_dir)
141
+ for relative in stale_here:
142
+ (Path(repo.base_dir) / relative).unlink()
143
+ deleted.append(f"{current_branch}:{relative}")
144
+
145
+ return {'deleted_release_schemas': deleted}
@@ -66,6 +66,20 @@ def _git_origin_to_https(git_origin: str) -> str:
66
66
  return url
67
67
 
68
68
 
69
+ def _pg_command_error_detail(e: Exception) -> str:
70
+ """Format a psql/pg_dump failure with its actual stderr, when available.
71
+
72
+ str(subprocess.CalledProcessError) only shows the command and exit
73
+ code - the actual SQL error psql printed to stderr (e.g. which
74
+ statement failed and why) is on e.stderr and would otherwise be
75
+ silently dropped from every RepoError raised around a restore.
76
+ """
77
+ stderr = getattr(e, 'stderr', None)
78
+ if stderr:
79
+ return f"{e}\n{stderr.strip() if isinstance(stderr, str) else stderr}"
80
+ return str(e)
81
+
82
+
69
83
  class RepoError(Exception):
70
84
  pass
71
85
 
@@ -2648,9 +2662,21 @@ INSERT INTO public.roles (name) VALUES ('admin'), ('user');
2648
2662
  and should persist across schema resets.
2649
2663
  """
2650
2664
  schemas_to_drop = {'half_orm_meta', 'half_orm_meta.view'}
2651
- # Add user schemas from half_orm metadata
2652
- relations = self.model.desc()
2653
- _ = [schemas_to_drop.add(rel[1][1]) for rel in relations]
2665
+
2666
+ # Enumerate schemas from the PostgreSQL catalog rather than from
2667
+ # self.model.desc(), which only lists *relations*: a schema holding
2668
+ # no table/view (only functions, types, sequences - or nothing at
2669
+ # all) is invisible there, so it would survive the reset and then
2670
+ # collide with the CREATE SCHEMA emitted by the file being
2671
+ # restored ("schema already exists"), leaving the database in a
2672
+ # state that no longer matches the dump.
2673
+ cursor = self.model.execute_query(
2674
+ "SELECT nspname FROM pg_catalog.pg_namespace "
2675
+ "WHERE nspname NOT IN ('pg_catalog', 'information_schema') "
2676
+ "AND nspname NOT LIKE 'pg\\_%'"
2677
+ )
2678
+ for row in cursor:
2679
+ schemas_to_drop.add(row['nspname'])
2654
2680
 
2655
2681
  # Drop each schema with CASCADE
2656
2682
  for schema_name in schemas_to_drop:
@@ -2747,7 +2773,10 @@ INSERT INTO public.roles (name) VALUES ('admin'), ('user');
2747
2773
  'psql', '-v', 'ON_ERROR_STOP=1', '-d', self.database_name, '-f', str(schema_path)
2748
2774
  )
2749
2775
  except Exception as e:
2750
- raise RepoError(f"Failed to load schema from {schema_path.name}: {e}") from e
2776
+ raise RepoError(
2777
+ f"Failed to load schema from {schema_path.name}: "
2778
+ f"{_pg_command_error_detail(e)}"
2779
+ ) from e
2751
2780
 
2752
2781
  # 4. Load data from model/data-X.Y.Z.sql (if exists)
2753
2782
  data_path, version = self._deduce_data_path(schema_path)
@@ -2759,7 +2788,8 @@ INSERT INTO public.roles (name) VALUES ('admin'), ('user');
2759
2788
  )
2760
2789
  except Exception as e:
2761
2790
  raise RepoError(
2762
- f"Failed to load data from {data_path.name}: {e}"
2791
+ f"Failed to load data from {data_path.name}: "
2792
+ f"{_pg_command_error_detail(e)}"
2763
2793
  ) from e
2764
2794
  # else: data file doesn't exist, continue without error (backward compatibility)
2765
2795
 
@@ -2810,7 +2840,10 @@ INSERT INTO public.roles (name) VALUES ('admin'), ('user');
2810
2840
  'psql', '-v', 'ON_ERROR_STOP=1', '-d', self.database_name, '-f', str(schema_path)
2811
2841
  )
2812
2842
  except Exception as e:
2813
- raise RepoError(f"Failed to load schema from {schema_path.name}: {e}") from e
2843
+ raise RepoError(
2844
+ f"Failed to load schema from {schema_path.name}: "
2845
+ f"{_pg_command_error_detail(e)}"
2846
+ ) from e
2814
2847
 
2815
2848
  data_path = Path(self.model_dir) / f"data-{version}.sql"
2816
2849
  if data_path.exists():
@@ -2820,7 +2853,8 @@ INSERT INTO public.roles (name) VALUES ('admin'), ('user');
2820
2853
  )
2821
2854
  except Exception as e:
2822
2855
  raise RepoError(
2823
- f"Failed to load data from {data_path.name}: {e}"
2856
+ f"Failed to load data from {data_path.name}: "
2857
+ f"{_pg_command_error_detail(e)}"
2824
2858
  ) from e
2825
2859
 
2826
2860
  self.model.reconnect(reload=True)
@@ -2876,7 +2910,10 @@ INSERT INTO public.roles (name) VALUES ('admin'), ('user');
2876
2910
  'psql', '-v', 'ON_ERROR_STOP=1', '-d', self.database_name, '-f', str(dump_path)
2877
2911
  )
2878
2912
  except Exception as e:
2879
- raise RepoError(f"Failed to load dump from {dump_path.name}: {e}") from e
2913
+ raise RepoError(
2914
+ f"Failed to load dump from {dump_path.name}: "
2915
+ f"{_pg_command_error_detail(e)}"
2916
+ ) from e
2880
2917
 
2881
2918
  # 3. Reload half_orm metadata cache
2882
2919
  self.model.reconnect(reload=True)
@@ -3005,7 +3042,9 @@ INSERT INTO public.roles (name) VALUES ('admin'), ('user');
3005
3042
  self.model.reconnect(reload=True)
3006
3043
 
3007
3044
  except Exception as e:
3008
- raise RepoError(f"Failed to restore from release schema: {e}") from e
3045
+ raise RepoError(
3046
+ f"Failed to restore from release schema: {_pg_command_error_detail(e)}"
3047
+ ) from e
3009
3048
 
3010
3049
  def get_release_schema_path(self, version: str) -> Path:
3011
3050
  """
@@ -0,0 +1 @@
1
+ 1.0.0-a35
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: half_orm_dev
3
- Version: 1.0.0a34
3
+ Version: 1.0.0a35
4
4
  Summary: half_orm development Framework.
5
5
  Author-email: Joël Maïzi <joel.maizi@collorg.org>
6
6
  License-Expression: GPL-3.0-or-later
@@ -55,6 +55,7 @@ half_orm_dev/migrations/0/18/0/00_add_async_support.py
55
55
  half_orm_dev/migrations/0/18/0/01_update_default_tests.py
56
56
  half_orm_dev/migrations/1/0/0/a20/01_update_gitignore.py
57
57
  half_orm_dev/migrations/1/0/0/a33/00_metadata_to_data_sql.py
58
+ half_orm_dev/migrations/1/0/0/a35/00_drop_stale_release_schemas.py
58
59
  half_orm_dev/migrations/hop/BREAKING_CHANGES-1.0.0.md
59
60
  half_orm_dev/patches/log
60
61
  half_orm_dev/patches/0/1/0/00_half_orm_meta.database.sql
@@ -1 +0,0 @@
1
- 1.0.0-a34
File without changes
File without changes