mindoff-dataport 0.1.0__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.
- mindoff_dataport-0.1.0/.github/workflows/cd.yml +141 -0
- mindoff_dataport-0.1.0/.github/workflows/pr_ci.yml +108 -0
- mindoff_dataport-0.1.0/.github/workflows/pr_merge_ci.yml +99 -0
- mindoff_dataport-0.1.0/.github/workflows/root_ci.yml +81 -0
- mindoff_dataport-0.1.0/.gitignore +106 -0
- mindoff_dataport-0.1.0/CHANGELOG.md +22 -0
- mindoff_dataport-0.1.0/PKG-INFO +879 -0
- mindoff_dataport-0.1.0/README.md +845 -0
- mindoff_dataport-0.1.0/pyproject.toml +74 -0
- mindoff_dataport-0.1.0/pytest.ini +5 -0
- mindoff_dataport-0.1.0/run_env.bat +7 -0
- mindoff_dataport-0.1.0/run_env.sh +5 -0
- mindoff_dataport-0.1.0/src/mindoff_dataport/__init__.py +86 -0
- mindoff_dataport-0.1.0/src/mindoff_dataport/bundle.py +921 -0
- mindoff_dataport-0.1.0/src/mindoff_dataport/extractor.py +257 -0
- mindoff_dataport-0.1.0/src/mindoff_dataport/pdf_renderer.py +1201 -0
- mindoff_dataport-0.1.0/src/mindoff_dataport/schema.py +95 -0
- mindoff_dataport-0.1.0/src/mindoff_dataport/style_conversion.py +144 -0
- mindoff_dataport-0.1.0/src/mindoff_dataport/template_contract.py +441 -0
- mindoff_dataport-0.1.0/src/mindoff_dataport/xlsx_builder.py +175 -0
- mindoff_dataport-0.1.0/src/mindoff_dataport/xlsx_renderer.py +1153 -0
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
name: CD
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
concurrency:
|
|
8
|
+
group: cd-${{ github.ref_name }}
|
|
9
|
+
cancel-in-progress: false
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
validate-tag:
|
|
13
|
+
name: Validate release tag
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- name: Check tag format
|
|
17
|
+
run: |
|
|
18
|
+
TAG="${{ github.ref_name }}"
|
|
19
|
+
echo "[INFO] Release tag: $TAG"
|
|
20
|
+
if ! echo "$TAG" | grep -qE '^v[0-9]+\.[0-9]+\.[0-9]+$'; then
|
|
21
|
+
echo "[ERROR] Tag '$TAG' does not match required format vX.Y.Z — aborting."
|
|
22
|
+
exit 1
|
|
23
|
+
fi
|
|
24
|
+
echo "[INFO] Tag format is valid."
|
|
25
|
+
|
|
26
|
+
version-changelog:
|
|
27
|
+
name: Version changelog
|
|
28
|
+
runs-on: ubuntu-latest
|
|
29
|
+
needs: validate-tag
|
|
30
|
+
permissions:
|
|
31
|
+
contents: write
|
|
32
|
+
steps:
|
|
33
|
+
- uses: actions/checkout@v4
|
|
34
|
+
with:
|
|
35
|
+
ref: root
|
|
36
|
+
token: ${{ secrets.PAT_TOKEN }}
|
|
37
|
+
|
|
38
|
+
- name: Replace "Recent Changes" with release version
|
|
39
|
+
run: |
|
|
40
|
+
VERSION="${{ github.ref_name }}"
|
|
41
|
+
sed -i "s/^## Recent Changes$/## ${VERSION}/" CHANGELOG.md
|
|
42
|
+
echo "[INFO] Replaced 'Recent Changes' with '${VERSION}'"
|
|
43
|
+
|
|
44
|
+
- name: Commit versioned changelog
|
|
45
|
+
run: |
|
|
46
|
+
git config user.name "github-actions[bot]"
|
|
47
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
48
|
+
git add CHANGELOG.md
|
|
49
|
+
git commit -m "📝 Update changelog for release: ${{ github.ref_name }}"
|
|
50
|
+
git push
|
|
51
|
+
|
|
52
|
+
publish:
|
|
53
|
+
name: Publish to PyPI
|
|
54
|
+
runs-on: ubuntu-latest
|
|
55
|
+
needs: version-changelog
|
|
56
|
+
permissions:
|
|
57
|
+
id-token: write
|
|
58
|
+
contents: write
|
|
59
|
+
steps:
|
|
60
|
+
- uses: actions/checkout@v4
|
|
61
|
+
with:
|
|
62
|
+
ref: root
|
|
63
|
+
token: ${{ secrets.PAT_TOKEN }}
|
|
64
|
+
|
|
65
|
+
- uses: actions/setup-python@v5
|
|
66
|
+
with:
|
|
67
|
+
python-version: "3.13"
|
|
68
|
+
cache: pip
|
|
69
|
+
|
|
70
|
+
- name: Install build tools
|
|
71
|
+
run: |
|
|
72
|
+
python -m pip install --upgrade pip
|
|
73
|
+
pip install build twine
|
|
74
|
+
|
|
75
|
+
- name: Sync pyproject.toml version with release tag
|
|
76
|
+
run: |
|
|
77
|
+
TAG_VERSION="${{ github.ref_name }}"
|
|
78
|
+
TAG_VERSION="${TAG_VERSION#v}"
|
|
79
|
+
PROJECT_VERSION=$(python -c "import tomllib; print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])")
|
|
80
|
+
echo "[INFO] Tag: $TAG_VERSION | pyproject.toml: $PROJECT_VERSION"
|
|
81
|
+
|
|
82
|
+
if [ "$TAG_VERSION" != "$PROJECT_VERSION" ]; then
|
|
83
|
+
echo "[WARN] Version mismatch — updating pyproject.toml to $TAG_VERSION"
|
|
84
|
+
sed -i "s/^version = \".*\"/version = \"${TAG_VERSION}\"/" pyproject.toml
|
|
85
|
+
|
|
86
|
+
UPDATED=$(python -c "import tomllib; print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])")
|
|
87
|
+
if [ "$UPDATED" != "$TAG_VERSION" ]; then
|
|
88
|
+
echo "[ERROR] Failed to update version in pyproject.toml — aborting."
|
|
89
|
+
exit 1
|
|
90
|
+
fi
|
|
91
|
+
|
|
92
|
+
git config user.name "github-actions[bot]"
|
|
93
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
94
|
+
git add pyproject.toml
|
|
95
|
+
git commit -m "🔖 Bump version to ${TAG_VERSION} to match release tag"
|
|
96
|
+
git push
|
|
97
|
+
echo "[INFO] pyproject.toml updated and pushed."
|
|
98
|
+
else
|
|
99
|
+
echo "[INFO] Versions match — no update needed."
|
|
100
|
+
fi
|
|
101
|
+
|
|
102
|
+
- name: Remove old build artifacts
|
|
103
|
+
run: rm -rf dist/ build/ *.egg-info
|
|
104
|
+
|
|
105
|
+
- name: Build package
|
|
106
|
+
run: python -m build
|
|
107
|
+
|
|
108
|
+
- name: Validate distribution metadata
|
|
109
|
+
run: python -m twine check dist/*
|
|
110
|
+
|
|
111
|
+
- name: Publish to PyPI
|
|
112
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
113
|
+
with:
|
|
114
|
+
packages-dir: dist/
|
|
115
|
+
|
|
116
|
+
revert-changelog:
|
|
117
|
+
name: Revert changelog on failure
|
|
118
|
+
runs-on: ubuntu-latest
|
|
119
|
+
needs: publish
|
|
120
|
+
if: failure()
|
|
121
|
+
permissions:
|
|
122
|
+
contents: write
|
|
123
|
+
steps:
|
|
124
|
+
- uses: actions/checkout@v4
|
|
125
|
+
with:
|
|
126
|
+
ref: root
|
|
127
|
+
token: ${{ secrets.PAT_TOKEN }}
|
|
128
|
+
|
|
129
|
+
- name: Revert versioned heading back to "Recent Changes"
|
|
130
|
+
run: |
|
|
131
|
+
VERSION="${{ github.ref_name }}"
|
|
132
|
+
sed -i "s/^## ${VERSION}$/## Recent Changes/" CHANGELOG.md
|
|
133
|
+
echo "[INFO] Reverted '${VERSION}' back to 'Recent Changes'"
|
|
134
|
+
|
|
135
|
+
- name: Commit revert
|
|
136
|
+
run: |
|
|
137
|
+
git config user.name "github-actions[bot]"
|
|
138
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
139
|
+
git add CHANGELOG.md
|
|
140
|
+
git commit -m "⏪ Revert changelog — release ${{ github.ref_name }} failed"
|
|
141
|
+
git push
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
name: PR CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
types: [opened, synchronize, reopened, edited]
|
|
6
|
+
branches:
|
|
7
|
+
- root
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
|
|
10
|
+
concurrency:
|
|
11
|
+
group: ci-${{ github.event.pull_request.number || github.ref }}
|
|
12
|
+
cancel-in-progress: true
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
smoke-minimal:
|
|
16
|
+
name: Smoke (minimal install)
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
if: github.event.action != 'labeled' && github.event.action != 'unlabeled' && github.event.action != 'edited'
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v4
|
|
21
|
+
|
|
22
|
+
- uses: actions/setup-python@v5
|
|
23
|
+
with:
|
|
24
|
+
python-version: "3.13"
|
|
25
|
+
cache: pip
|
|
26
|
+
|
|
27
|
+
- name: Install minimal package
|
|
28
|
+
run: |
|
|
29
|
+
python -m pip install --upgrade pip
|
|
30
|
+
pip install -e .
|
|
31
|
+
|
|
32
|
+
- name: Import smoke check
|
|
33
|
+
run: python -c "import mindoff_dataport; print('smoke ok')"
|
|
34
|
+
|
|
35
|
+
test:
|
|
36
|
+
name: Test (Python ${{ matrix.python-version }})
|
|
37
|
+
runs-on: ubuntu-latest
|
|
38
|
+
if: github.event.action != 'labeled' && github.event.action != 'unlabeled' && github.event.action != 'edited'
|
|
39
|
+
strategy:
|
|
40
|
+
fail-fast: false
|
|
41
|
+
matrix:
|
|
42
|
+
python-version: ["3.12", "3.13"]
|
|
43
|
+
env:
|
|
44
|
+
PYTHONDONTWRITEBYTECODE: "1"
|
|
45
|
+
PYTHONUNBUFFERED: "1"
|
|
46
|
+
steps:
|
|
47
|
+
- uses: actions/checkout@v4
|
|
48
|
+
|
|
49
|
+
- uses: actions/setup-python@v5
|
|
50
|
+
with:
|
|
51
|
+
python-version: ${{ matrix.python-version }}
|
|
52
|
+
cache: pip
|
|
53
|
+
|
|
54
|
+
- name: Install dependencies
|
|
55
|
+
run: |
|
|
56
|
+
python -m pip install --upgrade pip
|
|
57
|
+
pip install -e ".[dev]"
|
|
58
|
+
|
|
59
|
+
- name: Run tests with coverage (min 90%)
|
|
60
|
+
run: |
|
|
61
|
+
PYTHONPATH=src python -m pytest \
|
|
62
|
+
--cov=mindoff_dataport \
|
|
63
|
+
--cov-branch \
|
|
64
|
+
--cov-report=xml \
|
|
65
|
+
--cov-fail-under=90
|
|
66
|
+
|
|
67
|
+
- name: Upload coverage report
|
|
68
|
+
uses: actions/upload-artifact@v4
|
|
69
|
+
with:
|
|
70
|
+
name: coverage-py${{ matrix.python-version }}
|
|
71
|
+
path: coverage.xml
|
|
72
|
+
|
|
73
|
+
lint-pr-title:
|
|
74
|
+
name: Lint PR title
|
|
75
|
+
runs-on: ubuntu-latest
|
|
76
|
+
steps:
|
|
77
|
+
- name: Check PR title and label
|
|
78
|
+
uses: actions/github-script@v7
|
|
79
|
+
with:
|
|
80
|
+
script: |
|
|
81
|
+
const title = context.payload.pull_request.title;
|
|
82
|
+
const labels = context.payload.pull_request.labels.map(l => l.name);
|
|
83
|
+
|
|
84
|
+
const titleRegex = /^\p{Emoji}[\p{Emoji}️⃣]*\s+[A-Z][a-z]+/u;
|
|
85
|
+
if (!titleRegex.test(title)) {
|
|
86
|
+
core.setFailed(
|
|
87
|
+
`PR title "${title}" does not match the required format.\n` +
|
|
88
|
+
`Expected: {emoji} {Sentence starting with a capitalised Verb}\n` +
|
|
89
|
+
`Example: ✨ Add dataframe repeat support`
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const allowedLabels = [
|
|
94
|
+
"bug",
|
|
95
|
+
"feature",
|
|
96
|
+
"enhancement",
|
|
97
|
+
"documentation",
|
|
98
|
+
"internal",
|
|
99
|
+
];
|
|
100
|
+
|
|
101
|
+
const hasAllowed = labels.some(l => allowedLabels.includes(l));
|
|
102
|
+
if (!hasAllowed) {
|
|
103
|
+
core.setFailed(
|
|
104
|
+
`PR must have at least one of the allowed labels:\n` +
|
|
105
|
+
allowedLabels.join(", ") + "\n" +
|
|
106
|
+
`Current labels: ${labels.join(", ") || "(none)"}`
|
|
107
|
+
);
|
|
108
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
name: PR Merge CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
types: [closed]
|
|
6
|
+
branches:
|
|
7
|
+
- root
|
|
8
|
+
|
|
9
|
+
concurrency:
|
|
10
|
+
group: merge-${{ github.ref }}
|
|
11
|
+
cancel-in-progress: false
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
update-changelog:
|
|
15
|
+
name: Update changelog
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
if: |
|
|
18
|
+
github.event.pull_request.merged == true &&
|
|
19
|
+
contains(fromJson('["root"]'), github.base_ref)
|
|
20
|
+
permissions:
|
|
21
|
+
contents: write
|
|
22
|
+
pull-requests: read
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@v4
|
|
25
|
+
with:
|
|
26
|
+
ref: ${{ github.base_ref }}
|
|
27
|
+
token: ${{ secrets.PAT_TOKEN }}
|
|
28
|
+
|
|
29
|
+
- name: Append entry to CHANGELOG.md
|
|
30
|
+
uses: actions/github-script@v7
|
|
31
|
+
with:
|
|
32
|
+
script: |
|
|
33
|
+
const fs = require("fs");
|
|
34
|
+
|
|
35
|
+
const pr = context.payload.pull_request;
|
|
36
|
+
const title = pr.title;
|
|
37
|
+
const number = pr.number;
|
|
38
|
+
const prUrl = pr.html_url;
|
|
39
|
+
const labels = pr.labels.map(l => l.name);
|
|
40
|
+
|
|
41
|
+
const labelToCategory = {
|
|
42
|
+
"bug": "Fixes",
|
|
43
|
+
"feature": "Features",
|
|
44
|
+
"enhancement": "Enhancements",
|
|
45
|
+
"documentation": "Documentation",
|
|
46
|
+
"internal": "Internal",
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const allowedLabels = Object.keys(labelToCategory);
|
|
50
|
+
const matchedLabel = labels.find(l => allowedLabels.includes(l));
|
|
51
|
+
const category = matchedLabel ? labelToCategory[matchedLabel] : "Miscellaneous";
|
|
52
|
+
|
|
53
|
+
const entry = `- ${title} ([#${number}](${prUrl}))`;
|
|
54
|
+
|
|
55
|
+
let changelog = fs.readFileSync("CHANGELOG.md", "utf8");
|
|
56
|
+
|
|
57
|
+
const recentHeader = "## Recent Changes";
|
|
58
|
+
const categoryHeader = `### ${category}`;
|
|
59
|
+
|
|
60
|
+
if (!changelog.includes(recentHeader)) {
|
|
61
|
+
const titleLine = "<h1>Release Notes</h1>";
|
|
62
|
+
if (changelog.includes(titleLine)) {
|
|
63
|
+
const titleIdx = changelog.indexOf(titleLine);
|
|
64
|
+
const insertPos = changelog.indexOf("\n", titleIdx + titleLine.length);
|
|
65
|
+
changelog =
|
|
66
|
+
changelog.slice(0, insertPos + 1) +
|
|
67
|
+
`\n${recentHeader}\n\n` +
|
|
68
|
+
changelog.slice(insertPos + 1);
|
|
69
|
+
} else {
|
|
70
|
+
changelog = `${recentHeader}\n\n${changelog}`;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const recentIdx = changelog.indexOf(recentHeader);
|
|
75
|
+
const afterRecent = changelog.indexOf("\n## ", recentIdx + recentHeader.length);
|
|
76
|
+
const blockEnd = afterRecent === -1 ? changelog.length : afterRecent;
|
|
77
|
+
|
|
78
|
+
let block = changelog.slice(recentIdx, blockEnd);
|
|
79
|
+
|
|
80
|
+
if (block.includes(categoryHeader)) {
|
|
81
|
+
block = block.replace(
|
|
82
|
+
new RegExp(`(${categoryHeader}[^\\n]*)`),
|
|
83
|
+
`$1\n${entry}`
|
|
84
|
+
);
|
|
85
|
+
} else {
|
|
86
|
+
block = block.trimEnd() + `\n\n${categoryHeader}\n${entry}\n`;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
changelog = changelog.slice(0, recentIdx) + block + changelog.slice(blockEnd);
|
|
90
|
+
fs.writeFileSync("CHANGELOG.md", changelog, "utf8");
|
|
91
|
+
console.log("CHANGELOG.md updated successfully.");
|
|
92
|
+
|
|
93
|
+
- name: Commit changelog update
|
|
94
|
+
run: |
|
|
95
|
+
git config user.name "github-actions[bot]"
|
|
96
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
97
|
+
git add CHANGELOG.md
|
|
98
|
+
git diff --cached --quiet || git commit -m "📝 Update changelog for PR #${{ github.event.pull_request.number }}"
|
|
99
|
+
git push
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
name: Root CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- root
|
|
7
|
+
paths:
|
|
8
|
+
- "src/**"
|
|
9
|
+
- "pyproject.toml"
|
|
10
|
+
- "pytest.ini"
|
|
11
|
+
- ".github/workflows/root_ci.yml"
|
|
12
|
+
workflow_dispatch:
|
|
13
|
+
|
|
14
|
+
concurrency:
|
|
15
|
+
group: root-stability-${{ github.sha }}
|
|
16
|
+
cancel-in-progress: false
|
|
17
|
+
|
|
18
|
+
jobs:
|
|
19
|
+
smoke-minimal:
|
|
20
|
+
name: Smoke (minimal install)
|
|
21
|
+
runs-on: ubuntu-latest
|
|
22
|
+
steps:
|
|
23
|
+
- uses: actions/checkout@v4
|
|
24
|
+
|
|
25
|
+
- uses: actions/setup-python@v5
|
|
26
|
+
with:
|
|
27
|
+
python-version: "3.13"
|
|
28
|
+
cache: pip
|
|
29
|
+
|
|
30
|
+
- name: Install minimal package
|
|
31
|
+
run: |
|
|
32
|
+
python -m pip install --upgrade pip
|
|
33
|
+
pip install -e .
|
|
34
|
+
|
|
35
|
+
- name: Import smoke check
|
|
36
|
+
run: python -c "import mindoff_dataport; print('smoke ok')"
|
|
37
|
+
|
|
38
|
+
test:
|
|
39
|
+
name: Test (Python ${{ matrix.python-version }})
|
|
40
|
+
runs-on: ubuntu-latest
|
|
41
|
+
strategy:
|
|
42
|
+
fail-fast: false
|
|
43
|
+
matrix:
|
|
44
|
+
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
|
45
|
+
env:
|
|
46
|
+
PYTHONDONTWRITEBYTECODE: "1"
|
|
47
|
+
PYTHONUNBUFFERED: "1"
|
|
48
|
+
steps:
|
|
49
|
+
- uses: actions/checkout@v4
|
|
50
|
+
|
|
51
|
+
- uses: actions/setup-python@v5
|
|
52
|
+
with:
|
|
53
|
+
python-version: ${{ matrix.python-version }}
|
|
54
|
+
cache: pip
|
|
55
|
+
|
|
56
|
+
- name: Install dependencies
|
|
57
|
+
run: |
|
|
58
|
+
python -m pip install --upgrade pip
|
|
59
|
+
pip install -e ".[dev]"
|
|
60
|
+
|
|
61
|
+
- name: Run tests with coverage (min 90%)
|
|
62
|
+
run: |
|
|
63
|
+
PYTHONPATH=src python -m pytest \
|
|
64
|
+
--cov=mindoff_dataport \
|
|
65
|
+
--cov-branch \
|
|
66
|
+
--cov-report=xml \
|
|
67
|
+
--cov-fail-under=90
|
|
68
|
+
|
|
69
|
+
- name: Upload coverage to Codecov
|
|
70
|
+
uses: codecov/codecov-action@v4
|
|
71
|
+
with:
|
|
72
|
+
files: coverage.xml
|
|
73
|
+
flags: root
|
|
74
|
+
name: root-ci
|
|
75
|
+
fail_ci_if_error: true
|
|
76
|
+
|
|
77
|
+
- name: Upload coverage report
|
|
78
|
+
uses: actions/upload-artifact@v4
|
|
79
|
+
with:
|
|
80
|
+
name: coverage-py${{ matrix.python-version }}
|
|
81
|
+
path: coverage.xml
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# Python bytecode and caches
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# Virtual environments
|
|
7
|
+
.venv/
|
|
8
|
+
venv/
|
|
9
|
+
env/
|
|
10
|
+
ENV/
|
|
11
|
+
|
|
12
|
+
# Test and coverage artifacts
|
|
13
|
+
.pytest_cache/
|
|
14
|
+
.pytest_tmp/
|
|
15
|
+
.pytest_tmp*/
|
|
16
|
+
.tmp/
|
|
17
|
+
.coverage
|
|
18
|
+
.coverage.*
|
|
19
|
+
htmlcov/
|
|
20
|
+
temp_pytest_workspace/
|
|
21
|
+
|
|
22
|
+
# Packaging / build artifacts
|
|
23
|
+
build/
|
|
24
|
+
dist/
|
|
25
|
+
*.egg-info/
|
|
26
|
+
.eggs/
|
|
27
|
+
*.whl
|
|
28
|
+
pip-wheel-metadata/
|
|
29
|
+
|
|
30
|
+
# Type checkers / linters
|
|
31
|
+
.mypy_cache/
|
|
32
|
+
.pyre/
|
|
33
|
+
.ruff_cache/
|
|
34
|
+
|
|
35
|
+
# Jupyter
|
|
36
|
+
.ipynb_checkpoints/
|
|
37
|
+
|
|
38
|
+
# IDE/editor files
|
|
39
|
+
.vscode/
|
|
40
|
+
.idea/
|
|
41
|
+
*.swp
|
|
42
|
+
*.swo
|
|
43
|
+
|
|
44
|
+
# OS files
|
|
45
|
+
.DS_Store
|
|
46
|
+
Thumbs.db
|
|
47
|
+
|
|
48
|
+
# Local tooling
|
|
49
|
+
.claude/
|
|
50
|
+
CLAUDE.md
|
|
51
|
+
claude.md
|
|
52
|
+
AGENTS.md
|
|
53
|
+
|
|
54
|
+
# Generated example outputs
|
|
55
|
+
examples/output/*
|
|
56
|
+
!examples/output/.gitkeep
|
|
57
|
+
examples/repeat_block/output.xlsx
|
|
58
|
+
examples/repeat_block/output.pdf
|
|
59
|
+
examples/repeat_block/output.part*.xlsx
|
|
60
|
+
examples/repeat_block/report_bundle_*/
|
|
61
|
+
examples/basic/output.xlsx
|
|
62
|
+
examples/basic/output.pdf
|
|
63
|
+
examples/basic/output.part*.xlsx
|
|
64
|
+
examples/basic/report_bundle_*/
|
|
65
|
+
examples/repeat_block_multiple/output.xlsx
|
|
66
|
+
examples/repeat_block_multiple/output.pdf
|
|
67
|
+
examples/repeat_block_multiple/output.part*.xlsx
|
|
68
|
+
examples/repeat_block_multiple/report_bundle_*/
|
|
69
|
+
examples/dynamic_sheets/output.xlsx
|
|
70
|
+
examples/dynamic_sheets/output.pdf
|
|
71
|
+
examples/dynamic_sheets/output.part*.xlsx
|
|
72
|
+
examples/dynamic_sheets/report_bundle_*/
|
|
73
|
+
examples/dataframe_header_content/output*.xlsx
|
|
74
|
+
examples/dataframe_header_content/output.pdf
|
|
75
|
+
examples/dataframe_header_content/report_bundle_*/
|
|
76
|
+
examples/streaming_split_workbooks/output*.xlsx
|
|
77
|
+
examples/streaming_split_workbooks/output*.zip
|
|
78
|
+
examples/streaming_split_workbooks/report_bundle_*/
|
|
79
|
+
examples/sizing_modes/output*.xlsx
|
|
80
|
+
examples/sizing_modes/report_bundle_*/
|
|
81
|
+
examples/merged_cells/output*.xlsx
|
|
82
|
+
examples/merged_cells/output.pdf
|
|
83
|
+
examples/merged_cells/report_bundle_*/
|
|
84
|
+
examples/formulas/output*.xlsx
|
|
85
|
+
examples/formulas/report_bundle_*/
|
|
86
|
+
examples/gridlines_and_styles/output*.xlsx
|
|
87
|
+
examples/gridlines_and_styles/output.pdf
|
|
88
|
+
examples/gridlines_and_styles/report_bundle_*/
|
|
89
|
+
examples/pdf_pagination/output.pdf
|
|
90
|
+
examples/pdf_pagination/report_bundle_*/
|
|
91
|
+
examples/pdf_custom_fonts/output.pdf
|
|
92
|
+
examples/pdf_custom_fonts/report_bundle_*/
|
|
93
|
+
examples/bundle_path/output*.xlsx
|
|
94
|
+
examples/bundle_path/report_bundle/
|
|
95
|
+
examples/auto_delete_bundle/output*.xlsx
|
|
96
|
+
examples/auto_delete_bundle/temporary_bundle/
|
|
97
|
+
examples/lazy_parquet_large/output*.xlsx
|
|
98
|
+
examples/lazy_parquet_large/report_bundle_*/
|
|
99
|
+
examples/multi_sheet_static/output*.xlsx
|
|
100
|
+
examples/multi_sheet_static/report_bundle_*/
|
|
101
|
+
examples/image_reserved/output.*
|
|
102
|
+
examples/image_reserved/report_bundle_*/
|
|
103
|
+
|
|
104
|
+
# Transient streaming export scratch dirs (created during local/debug runs)
|
|
105
|
+
streaming_*/
|
|
106
|
+
concept/
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<h1>Release Notes</h1>
|
|
2
|
+
|
|
3
|
+
## v0.1.0
|
|
4
|
+
|
|
5
|
+
### Enhancements
|
|
6
|
+
- ✨ Add parquet-backed PDF and XLSX export support
|
|
7
|
+
- ✨ Add hybrid parquet streaming bundle
|
|
8
|
+
- ✨ Add streaming export support
|
|
9
|
+
- ✨ Update renderer and streaming
|
|
10
|
+
- ✨ Update export API and guidance
|
|
11
|
+
|
|
12
|
+
### Internal
|
|
13
|
+
- ♻️ Refactor export pipeline
|
|
14
|
+
- ♻️ Rename package to mindoff_dataport
|
|
15
|
+
- ♻️ Move tests into src/tests
|
|
16
|
+
- ♻️ Trim examples to core features only
|
|
17
|
+
- ♻️ Promote mo_dataport API alias and expand package metadata
|
|
18
|
+
- 🔧 Refresh project setup
|
|
19
|
+
- 🙈 Move example outputs under ignored folder
|
|
20
|
+
|
|
21
|
+
### Documentation
|
|
22
|
+
- 📝 Refresh README and example import alias
|