zodb-convert 0.0.0.dev4__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.
@@ -0,0 +1,21 @@
1
+ ---
2
+ name: CI
3
+
4
+ on:
5
+ push:
6
+ branches-ignore: [main]
7
+ pull_request:
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ concurrency:
13
+ group: ci-${{ github.ref }}
14
+ cancel-in-progress: true
15
+
16
+ jobs:
17
+ qa:
18
+ uses: "./.github/workflows/qa.yaml"
19
+
20
+ tests:
21
+ uses: "./.github/workflows/tests.yaml"
@@ -0,0 +1,23 @@
1
+ ---
2
+ name: QA
3
+
4
+ on:
5
+ workflow_call:
6
+
7
+ permissions:
8
+ contents: read
9
+
10
+ jobs:
11
+ lint:
12
+ name: Ruff
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+
17
+ - uses: astral-sh/setup-uv@v6
18
+
19
+ - name: Run ruff check
20
+ run: uvx ruff check .
21
+
22
+ - name: Run ruff format check
23
+ run: uvx ruff format --check .
@@ -0,0 +1,80 @@
1
+ ---
2
+ name: Build & upload PyPI package
3
+
4
+ on:
5
+ push:
6
+ branches: [main]
7
+ release:
8
+ types:
9
+ - published
10
+ workflow_dispatch:
11
+
12
+ concurrency:
13
+ group: release-${{ github.ref }}
14
+ cancel-in-progress: true
15
+
16
+ jobs:
17
+ qa:
18
+ uses: "./.github/workflows/qa.yaml"
19
+
20
+ tests:
21
+ uses: "./.github/workflows/tests.yaml"
22
+
23
+ build-package:
24
+ name: Build & verify package
25
+ needs:
26
+ - qa
27
+ - tests
28
+ runs-on: ubuntu-latest
29
+ permissions:
30
+ contents: read
31
+
32
+ steps:
33
+ - uses: actions/checkout@v4
34
+ with:
35
+ fetch-depth: 0
36
+ persist-credentials: false
37
+
38
+ - uses: hynek/build-and-inspect-python-package@v2
39
+
40
+ release-test-pypi:
41
+ name: Publish in-dev package to test.pypi.org
42
+ environment: release-test-pypi
43
+ if: github.event_name == 'push' && github.ref == 'refs/heads/main'
44
+ runs-on: ubuntu-latest
45
+ needs:
46
+ - build-package
47
+ permissions:
48
+ id-token: write
49
+
50
+ steps:
51
+ - name: Download packages built by build-and-inspect-python-package
52
+ uses: actions/download-artifact@v4
53
+ with:
54
+ name: Packages
55
+ path: dist
56
+
57
+ - name: Upload package to Test PyPI
58
+ uses: pypa/gh-action-pypi-publish@release/v1
59
+ with:
60
+ repository-url: https://test.pypi.org/legacy/
61
+
62
+ release-pypi:
63
+ name: Publish released package to pypi.org
64
+ environment: release-pypi
65
+ if: github.event.action == 'published'
66
+ runs-on: ubuntu-latest
67
+ needs:
68
+ - build-package
69
+ permissions:
70
+ id-token: write
71
+
72
+ steps:
73
+ - name: Download packages built by build-and-inspect-python-package
74
+ uses: actions/download-artifact@v4
75
+ with:
76
+ name: Packages
77
+ path: dist
78
+
79
+ - name: Upload package to PyPI
80
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,83 @@
1
+ ---
2
+ name: Tests
3
+
4
+ on:
5
+ workflow_call:
6
+
7
+ permissions:
8
+ contents: read
9
+
10
+ jobs:
11
+ test:
12
+ name: Python ${{ matrix.python-version }}
13
+ runs-on: ubuntu-latest
14
+ strategy:
15
+ fail-fast: false
16
+ matrix:
17
+ python-version: ["3.12", "3.13", "3.14"]
18
+
19
+ steps:
20
+ - uses: actions/checkout@v4
21
+ with:
22
+ fetch-depth: 0
23
+
24
+ - uses: astral-sh/setup-uv@v6
25
+ with:
26
+ enable-cache: true
27
+ cache-dependency-glob: "pyproject.toml"
28
+
29
+ - name: Set up Python ${{ matrix.python-version }}
30
+ run: uv python install ${{ matrix.python-version }}
31
+
32
+ - name: Install dependencies
33
+ run: uv venv && uv pip install -e ".[test]"
34
+
35
+ - name: Run tests with coverage
36
+ run: uv run pytest --cov --cov-report=
37
+
38
+ - name: Rename coverage data
39
+ run: mv .coverage .coverage.${{ matrix.python-version }}
40
+
41
+ - name: Upload coverage data
42
+ uses: actions/upload-artifact@v4
43
+ with:
44
+ name: coverage-data-${{ matrix.python-version }}
45
+ path: .coverage.${{ matrix.python-version }}
46
+ include-hidden-files: true
47
+ if-no-files-found: ignore
48
+
49
+ coverage:
50
+ name: Combine & check coverage
51
+ if: always()
52
+ needs: test
53
+ runs-on: ubuntu-latest
54
+
55
+ steps:
56
+ - uses: actions/checkout@v4
57
+
58
+ - uses: astral-sh/setup-uv@v6
59
+ with:
60
+ enable-cache: true
61
+ cache-dependency-glob: "pyproject.toml"
62
+
63
+ - name: Install dependencies
64
+ run: uv venv && uv pip install -e ".[test]"
65
+
66
+ - uses: actions/download-artifact@v4
67
+ with:
68
+ pattern: coverage-data-*
69
+ merge-multiple: true
70
+
71
+ - name: Combine coverage & check threshold
72
+ run: |
73
+ uv run coverage combine
74
+ uv run coverage html --skip-covered --skip-empty
75
+ uv run coverage report --format=markdown >> $GITHUB_STEP_SUMMARY
76
+ uv run coverage report
77
+
78
+ - name: Upload HTML report if check failed
79
+ uses: actions/upload-artifact@v4
80
+ with:
81
+ name: html-report
82
+ path: htmlcov
83
+ if: ${{ failure() }}
@@ -0,0 +1,10 @@
1
+ __pycache__/
2
+ *.pyc
3
+ *.pyo
4
+ *.egg-info/
5
+ dist/
6
+ build/
7
+ .venv/
8
+ .pytest_cache/
9
+ .coverage
10
+ *.egg
@@ -0,0 +1,15 @@
1
+ repos:
2
+ - repo: https://github.com/astral-sh/ruff-pre-commit
3
+ rev: v0.15.0
4
+ hooks:
5
+ - id: ruff
6
+ args: [--fix]
7
+ - id: ruff-format
8
+
9
+ - repo: https://github.com/pre-commit/pre-commit-hooks
10
+ rev: v5.0.0
11
+ hooks:
12
+ - id: trailing-whitespace
13
+ - id: end-of-file-fixer
14
+ - id: check-yaml
15
+ - id: check-added-large-files
@@ -0,0 +1,23 @@
1
+ # Changelog
2
+
3
+ ## 1.0.0a1 (unreleased)
4
+
5
+ Initial release. Derived from
6
+ [RelStorage's zodbconvert](https://github.com/zodb/relstorage)
7
+ (Copyright Zope Foundation and Contributors, ZPL-2.1).
8
+
9
+ ### Differences from RelStorage's zodbconvert
10
+
11
+ - **Standalone package**: no RelStorage dependency -- works with any
12
+ ZODB-compatible storage (FileStorage, RelStorage, zodb-pgjsonb, ZEO, ...).
13
+ - **zope.conf extraction**: `--source-zope-conf` / `--dest-zope-conf` flags
14
+ extract storage configuration from existing Zope config files, no need to
15
+ write a separate conversion config.
16
+ - **Mixed mode**: combine a traditional config file with zope.conf extraction
17
+ (e.g. destination from config file, source from zope.conf).
18
+ - **Enhanced progress reporting**: multi-tier output with per-transaction
19
+ logging for small conversions, interval-based updates with throughput and
20
+ ETA for large ones, and a summary at completion.
21
+ - **Incremental copy**: `--incremental` resumes from the last transaction in
22
+ the destination storage.
23
+ - **Dry-run mode**: `--dry-run` previews what would be copied.
@@ -0,0 +1,43 @@
1
+ Zope Public License (ZPL) Version 2.1
2
+
3
+ A copyright notice accompanies this license document that identifies the
4
+ copyright holders.
5
+
6
+ This license has been certified as open source. It has also been designated as
7
+ GPL compatible by the Free Software Foundation (FSF).
8
+
9
+ Redistribution and use in source and binary forms, with or without
10
+ modification, are permitted provided that the following conditions are met:
11
+
12
+ 1. Redistributions in source code must retain the accompanying copyright
13
+ notice, this list of conditions, and the following disclaimer.
14
+
15
+ 2. Redistributions in binary form must reproduce the accompanying copyright
16
+ notice, this list of conditions, and the following disclaimer in the
17
+ documentation and/or other materials provided with the distribution.
18
+
19
+ 3. Names of the copyright holders must not be used to endorse or promote
20
+ products derived from this software without prior written permission from
21
+ the copyright holders.
22
+
23
+ 4. The right to distribute this software or to use it for any purpose does not
24
+ give you the right to use Servicemarks (sm) or Trademarks (tm) of the
25
+ copyright holders. Use of them is covered by separate agreement with the
26
+ copyright holders.
27
+
28
+ 5. If any files are modified, you must cause the modified files to carry
29
+ prominent notices stating that you changed the files and the date of any
30
+ change.
31
+
32
+ Disclaimer
33
+
34
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED
35
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
36
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
37
+ EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
38
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
39
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
40
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
41
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
42
+ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
43
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,139 @@
1
+ Metadata-Version: 2.4
2
+ Name: zodb-convert
3
+ Version: 0.0.0.dev4
4
+ Summary: Generic ZODB storage conversion tool
5
+ Project-URL: Homepage, https://github.com/bluedynamics/zodb-convert
6
+ Project-URL: Repository, https://github.com/bluedynamics/zodb-convert
7
+ Project-URL: Issues, https://github.com/bluedynamics/zodb-convert/issues
8
+ License-Expression: ZPL-2.1
9
+ License-File: LICENSE.txt
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Framework :: ZODB
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: Zope Public License
14
+ Classifier: Programming Language :: Python :: 3 :: Only
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Programming Language :: Python :: 3.14
18
+ Classifier: Topic :: Database
19
+ Requires-Python: >=3.12
20
+ Requires-Dist: transaction
21
+ Requires-Dist: zconfig
22
+ Requires-Dist: zodb>=5.8
23
+ Requires-Dist: zope-interface
24
+ Provides-Extra: test
25
+ Requires-Dist: coverage[toml]>=7.0; extra == 'test'
26
+ Requires-Dist: pytest; extra == 'test'
27
+ Requires-Dist: pytest-cov; extra == 'test'
28
+ Description-Content-Type: text/markdown
29
+
30
+ # zodb-convert
31
+
32
+ Generic ZODB storage conversion tool. Copies data between any two ZODB-compatible storages.
33
+
34
+ Derived from [RelStorage's zodbconvert](https://github.com/zodb/relstorage) by the
35
+ Zope Foundation and Contributors, extracted as a standalone generic tool.
36
+
37
+ ## Installation
38
+
39
+ ```bash
40
+ pip install zodb-convert
41
+ ```
42
+
43
+ To convert between specific storage types, install their packages too:
44
+
45
+ ```bash
46
+ pip install zodb-convert ZODB RelStorage # FileStorage ↔ RelStorage
47
+ pip install zodb-convert ZODB zodb-pgjsonb # FileStorage ↔ PGJsonb
48
+ ```
49
+
50
+ ## Usage
51
+
52
+ ### Traditional config file
53
+
54
+ Create a config file (`convert.conf`):
55
+
56
+ ```
57
+ <filestorage source>
58
+ path /data/Data.fs
59
+ blob-dir /data/blobs
60
+ </filestorage>
61
+
62
+ <filestorage destination>
63
+ path /backup/Data.fs
64
+ blob-dir /backup/blobs
65
+ </filestorage>
66
+ ```
67
+
68
+ For storages that need blob wrapping:
69
+
70
+ ```
71
+ <blobstorage source>
72
+ blob-dir /data/blobs
73
+ <filestorage>
74
+ path /data/Data.fs
75
+ </filestorage>
76
+ </blobstorage>
77
+
78
+ <filestorage destination>
79
+ path /backup/Data.fs
80
+ blob-dir /backup/blobs
81
+ </filestorage>
82
+ ```
83
+
84
+ For third-party storages, use `%import`:
85
+
86
+ ```
87
+ %import relstorage
88
+
89
+ <relstorage source>
90
+ <postgresql>
91
+ dsn dbname=zodb user=zodb
92
+ </postgresql>
93
+ </relstorage>
94
+
95
+ <filestorage destination>
96
+ path /backup/Data.fs
97
+ </filestorage>
98
+ ```
99
+
100
+ Run:
101
+
102
+ ```bash
103
+ zodb-convert convert.conf
104
+ ```
105
+
106
+ ### Using existing zope.conf files
107
+
108
+ Extract storage configuration directly from Zope config files:
109
+
110
+ ```bash
111
+ zodb-convert --source-zope-conf /old/etc/zope.conf --dest-zope-conf /new/etc/zope.conf
112
+ ```
113
+
114
+ Specify which database to use (defaults to "main"):
115
+
116
+ ```bash
117
+ zodb-convert --source-zope-conf zope.conf --source-db main \
118
+ --dest-zope-conf other.conf --dest-db catalog
119
+ ```
120
+
121
+ ### Mixed mode
122
+
123
+ Combine traditional config with zope.conf extraction:
124
+
125
+ ```bash
126
+ zodb-convert convert.conf --source-zope-conf /old/etc/zope.conf
127
+ ```
128
+
129
+ Where `convert.conf` contains only the destination storage section.
130
+
131
+ ### Options
132
+
133
+ - `--dry-run` — show what would be copied without making changes
134
+ - `--incremental` — resume from the last transaction in the destination
135
+ - `-v` / `--verbose` — increase verbosity (`-v` for INFO, `-vv` for DEBUG)
136
+
137
+ ## License
138
+
139
+ ZPL-2.1 — see [LICENSE.txt](LICENSE.txt)
@@ -0,0 +1,110 @@
1
+ # zodb-convert
2
+
3
+ Generic ZODB storage conversion tool. Copies data between any two ZODB-compatible storages.
4
+
5
+ Derived from [RelStorage's zodbconvert](https://github.com/zodb/relstorage) by the
6
+ Zope Foundation and Contributors, extracted as a standalone generic tool.
7
+
8
+ ## Installation
9
+
10
+ ```bash
11
+ pip install zodb-convert
12
+ ```
13
+
14
+ To convert between specific storage types, install their packages too:
15
+
16
+ ```bash
17
+ pip install zodb-convert ZODB RelStorage # FileStorage ↔ RelStorage
18
+ pip install zodb-convert ZODB zodb-pgjsonb # FileStorage ↔ PGJsonb
19
+ ```
20
+
21
+ ## Usage
22
+
23
+ ### Traditional config file
24
+
25
+ Create a config file (`convert.conf`):
26
+
27
+ ```
28
+ <filestorage source>
29
+ path /data/Data.fs
30
+ blob-dir /data/blobs
31
+ </filestorage>
32
+
33
+ <filestorage destination>
34
+ path /backup/Data.fs
35
+ blob-dir /backup/blobs
36
+ </filestorage>
37
+ ```
38
+
39
+ For storages that need blob wrapping:
40
+
41
+ ```
42
+ <blobstorage source>
43
+ blob-dir /data/blobs
44
+ <filestorage>
45
+ path /data/Data.fs
46
+ </filestorage>
47
+ </blobstorage>
48
+
49
+ <filestorage destination>
50
+ path /backup/Data.fs
51
+ blob-dir /backup/blobs
52
+ </filestorage>
53
+ ```
54
+
55
+ For third-party storages, use `%import`:
56
+
57
+ ```
58
+ %import relstorage
59
+
60
+ <relstorage source>
61
+ <postgresql>
62
+ dsn dbname=zodb user=zodb
63
+ </postgresql>
64
+ </relstorage>
65
+
66
+ <filestorage destination>
67
+ path /backup/Data.fs
68
+ </filestorage>
69
+ ```
70
+
71
+ Run:
72
+
73
+ ```bash
74
+ zodb-convert convert.conf
75
+ ```
76
+
77
+ ### Using existing zope.conf files
78
+
79
+ Extract storage configuration directly from Zope config files:
80
+
81
+ ```bash
82
+ zodb-convert --source-zope-conf /old/etc/zope.conf --dest-zope-conf /new/etc/zope.conf
83
+ ```
84
+
85
+ Specify which database to use (defaults to "main"):
86
+
87
+ ```bash
88
+ zodb-convert --source-zope-conf zope.conf --source-db main \
89
+ --dest-zope-conf other.conf --dest-db catalog
90
+ ```
91
+
92
+ ### Mixed mode
93
+
94
+ Combine traditional config with zope.conf extraction:
95
+
96
+ ```bash
97
+ zodb-convert convert.conf --source-zope-conf /old/etc/zope.conf
98
+ ```
99
+
100
+ Where `convert.conf` contains only the destination storage section.
101
+
102
+ ### Options
103
+
104
+ - `--dry-run` — show what would be copied without making changes
105
+ - `--incremental` — resume from the last transaction in the destination
106
+ - `-v` / `--verbose` — increase verbosity (`-v` for INFO, `-vv` for DEBUG)
107
+
108
+ ## License
109
+
110
+ ZPL-2.1 — see [LICENSE.txt](LICENSE.txt)
@@ -0,0 +1,106 @@
1
+ [build-system]
2
+ requires = ["hatchling", "hatch-vcs"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "zodb-convert"
7
+ dynamic = ["version"]
8
+ description = "Generic ZODB storage conversion tool"
9
+ readme = "README.md"
10
+ license = "ZPL-2.1"
11
+ requires-python = ">=3.12"
12
+ classifiers = [
13
+ "Development Status :: 3 - Alpha",
14
+ "Intended Audience :: Developers",
15
+ "License :: OSI Approved :: Zope Public License",
16
+ "Programming Language :: Python :: 3 :: Only",
17
+ "Programming Language :: Python :: 3.12",
18
+ "Programming Language :: Python :: 3.13",
19
+ "Programming Language :: Python :: 3.14",
20
+ "Topic :: Database",
21
+ "Framework :: ZODB",
22
+ ]
23
+ dependencies = [
24
+ "ZODB>=5.8",
25
+ "ZConfig",
26
+ "zope.interface",
27
+ "transaction",
28
+ ]
29
+
30
+ [project.urls]
31
+ Homepage = "https://github.com/bluedynamics/zodb-convert"
32
+ Repository = "https://github.com/bluedynamics/zodb-convert"
33
+ Issues = "https://github.com/bluedynamics/zodb-convert/issues"
34
+
35
+ [project.scripts]
36
+ zodb-convert = "zodb_convert.cli:main"
37
+
38
+ [project.optional-dependencies]
39
+ test = [
40
+ "pytest",
41
+ "pytest-cov",
42
+ "coverage[toml]>=7.0",
43
+ ]
44
+
45
+ [tool.hatch.build.targets.wheel]
46
+ packages = ["src/zodb_convert"]
47
+
48
+ [tool.hatch.version]
49
+ source = "vcs"
50
+ root = "../.."
51
+ raw-options = { local_scheme = "no-local-version" }
52
+ fallback-version = "0.0.0.dev0"
53
+
54
+ [tool.pytest.ini_options]
55
+ testpaths = ["tests"]
56
+
57
+ [tool.coverage.run]
58
+ parallel = true
59
+ source = ["zodb_convert"]
60
+ relative_files = true
61
+
62
+ [tool.coverage.report]
63
+ show_missing = true
64
+ fail_under = 90
65
+ exclude_lines = [
66
+ "pragma: no cover",
67
+ "if TYPE_CHECKING:",
68
+ ]
69
+
70
+ [tool.ruff]
71
+ target-version = "py312"
72
+
73
+ [tool.ruff.lint]
74
+ select = [
75
+ "A",
76
+ "B",
77
+ "C4",
78
+ "E",
79
+ "F",
80
+ "I",
81
+ "RUF",
82
+ "SIM",
83
+ "T20",
84
+ "UP",
85
+ "W",
86
+ ]
87
+ ignore = [
88
+ "E501",
89
+ "RUF001",
90
+ "RUF002",
91
+ ]
92
+
93
+ [tool.ruff.lint.isort]
94
+ force-single-line = true
95
+ from-first = true
96
+ lines-after-imports = 2
97
+ lines-between-types = 1
98
+ no-sections = true
99
+ order-by-type = false
100
+
101
+ [tool.ruff.lint.pycodestyle]
102
+ max-line-length = 120
103
+ max-doc-length = 120
104
+
105
+ [tool.ruff.lint.per-file-ignores]
106
+ "tests/*" = ["T201"]
File without changes