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.
- zodb_convert-0.0.0.dev4/.github/workflows/ci.yaml +21 -0
- zodb_convert-0.0.0.dev4/.github/workflows/qa.yaml +23 -0
- zodb_convert-0.0.0.dev4/.github/workflows/release.yaml +80 -0
- zodb_convert-0.0.0.dev4/.github/workflows/tests.yaml +83 -0
- zodb_convert-0.0.0.dev4/.gitignore +10 -0
- zodb_convert-0.0.0.dev4/.pre-commit-config.yaml +15 -0
- zodb_convert-0.0.0.dev4/CHANGES.md +23 -0
- zodb_convert-0.0.0.dev4/LICENSE.txt +43 -0
- zodb_convert-0.0.0.dev4/PKG-INFO +139 -0
- zodb_convert-0.0.0.dev4/README.md +110 -0
- zodb_convert-0.0.0.dev4/pyproject.toml +106 -0
- zodb_convert-0.0.0.dev4/src/zodb_convert/__init__.py +0 -0
- zodb_convert-0.0.0.dev4/src/zodb_convert/cli.py +164 -0
- zodb_convert-0.0.0.dev4/src/zodb_convert/config.py +133 -0
- zodb_convert-0.0.0.dev4/src/zodb_convert/copier.py +194 -0
- zodb_convert-0.0.0.dev4/src/zodb_convert/progress.py +142 -0
- zodb_convert-0.0.0.dev4/tests/__init__.py +0 -0
- zodb_convert-0.0.0.dev4/tests/conftest.py +79 -0
- zodb_convert-0.0.0.dev4/tests/test_cli.py +249 -0
- zodb_convert-0.0.0.dev4/tests/test_config.py +325 -0
- zodb_convert-0.0.0.dev4/tests/test_copier.py +255 -0
- zodb_convert-0.0.0.dev4/tests/test_progress.py +98 -0
- zodb_convert-0.0.0.dev4/uv.lock +471 -0
|
@@ -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,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
|