Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
0131bac
Absorb ConfigSecretsSanitizer into DefaultSanitizer
matyas-jirat-keboola Feb 17, 2026
96d1117
Stream cassette interactions to disk to avoid OOM on large jobs
matyas-jirat-keboola Feb 22, 2026
c37bdb4
freezetime update
matyas-jirat-keboola Feb 22, 2026
995fb05
Eliminate deepcopy and reduce post-run memory pressure during recording
matyas-jirat-keboola Feb 22, 2026
9d5769a
Eliminate VCR body copy overhead with zero-copy _VCRRecordingReader
matyas-jirat-keboola Feb 22, 2026
4444801
Eliminate two more large allocations per response during recording
matyas-jirat-keboola Feb 22, 2026
03a45f8
Apply code review fixes across all four source modules
matyas-jirat-keboola Feb 22, 2026
941c8bc
Release _VCRRecordingReader._data after body is fully consumed
matyas-jirat-keboola Feb 22, 2026
5e44d38
Extract nested functions, rename symbols, reorder by importance
matyas-jirat-keboola Feb 22, 2026
00d1211
Fix _zero_copy_vcr_response_init not receiving self when monkey-patched
matyas-jirat-keboola Feb 22, 2026
419a9b1
Fix issues 4-8 and add comprehensive unit tests
matyas-jirat-keboola Feb 22, 2026
697bd91
Address code review: pin vcrpy, fix temp cleanup, sort keys, flag-bas…
matyas-jirat-keboola Feb 23, 2026
5247f58
Tighten vcrpy pin to >=8.1.1,<9
matyas-jirat-keboola Feb 23, 2026
5d2be49
Tighten freezegun pin to >=1.5.5,<2
matyas-jirat-keboola Feb 23, 2026
fab73f4
Add CI pipeline and uv lockfile
matyas-jirat-keboola Feb 23, 2026
f193713
Fix decode_compressed_response bypass in _append_interaction
matyas-jirat-keboola Feb 23, 2026
84af9a6
Default scaffold freeze_time to now() instead of 2025-01-01
matyas-jirat-keboola Feb 23, 2026
fe8a236
Add PyPI/TestPyPI publishing pipeline
matyas-jirat-keboola Feb 23, 2026
2933574
PyPi and Pipeline updates
matyas-jirat-keboola Feb 24, 2026
4a44ff4
Updates for PyPi and Pipeline
matyas-jirat-keboola Feb 24, 2026
d54a94c
Published version
matyas-jirat-keboola Feb 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .flake8

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know this is inspired by another of our projects, but I think we can safely ditch flake8 in 2026, it was great while it lasted! 🫡 😁

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup that will be the next update where I test pipeline

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[flake8]
exclude =
.git,
__pycache__,
tests,
example
.venv
max-line-length = 120
extend-ignore = E203
60 changes: 60 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
name: Build & Deploy to PyPI

on:
workflow_dispatch:
inputs:
note:
description: 'This workflow publishes to TestPyPI only. For production, create a GitHub Release.'
required: false
default: ""

release:
types: [published]

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout 🛒
uses: actions/checkout@v4

- name: Install uv 💜
uses: astral-sh/setup-uv@v6

- name: Install and run ruff 🐶
uses: astral-sh/ruff-action@v3

- name: Set up Python 🐍
uses: actions/setup-python@v5
with:
python-version: "3.13"

- name: Install dependencies 📦
run: uv sync --all-groups --frozen

- name: Lint with flake8 ❄️
run: uv run flake8

- name: Test with pytest ✅
run: uv run pytest tests/

- name: Version replacement based on tag ↔️
if: github.ref_type == 'tag'
run: |
TAG_VERSION=${GITHUB_REF#refs/tags/}
echo "Tag version: $TAG_VERSION"
uv version $TAG_VERSION

- name: Build package 📦
run: uv build

- name: Publish to TestPyPI 🧪
env:
UV_PUBLISH_TOKEN: ${{ secrets.UV_PUBLISH_TOKEN_TEST_PYPI }}
run: uv publish --index testpypi

- name: Publish to PyPI 🚀
if: github.event_name == 'release'
env:
UV_PUBLISH_TOKEN: ${{ secrets.UV_PUBLISH_TOKEN }}
run: uv publish
70 changes: 70 additions & 0 deletions .github/workflows/push.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
name: Build & Test

on:
push:
branches-ignore:
- main

jobs:
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- name: Checkout 🛒
uses: actions/checkout@v4

- name: Install and run ruff 🐶
uses: astral-sh/ruff-action@v3

- name: Install uv 💜
uses: astral-sh/setup-uv@v6

- name: Install dependencies 📦
run: uv sync --all-groups --frozen

- name: Lint with flake8 ❄️
run: uv run flake8

test-310:
name: Test (Python 3.10)
runs-on: ubuntu-latest
needs: lint
steps:
- name: Checkout 🛒
uses: actions/checkout@v4

- name: Install uv 💜
uses: astral-sh/setup-uv@v6

- name: Set up Python 3.10 🐍
uses: actions/setup-python@v5
with:
python-version: "3.10"

- name: Install dependencies 📦
run: uv sync --all-groups --frozen

- name: Test with pytest ✅
run: uv run pytest tests/

test-313:
name: Test (Python 3.13)
runs-on: ubuntu-latest
needs: lint
steps:
- name: Checkout 🛒
uses: actions/checkout@v4

- name: Install uv 💜
uses: astral-sh/setup-uv@v6

- name: Set up Python 3.13 🐍
uses: actions/setup-python@v5
with:
python-version: "3.13"

- name: Install dependencies 📦
run: uv sync --all-groups --frozen

- name: Test with pytest ✅
run: uv run pytest tests/
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ venv/
.pytest_cache/
.ruff_cache/
*.lock
!uv.lock

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why? 🤔

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will get rid of it. It is longer to explain then get rid of it.

35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# keboola.vcr

VCR recording, sanitization, and validation for Keboola component HTTP interactions.

## Installation

```bash
pip install keboola.vcr
```

## Usage

```python
from keboola.vcr.recorder import VCRRecorder
from keboola.vcr.sanitizers import DefaultSanitizer

recorder = VCRRecorder(
cassette_dir="tests/cassettes/my_test",
secrets={"api_key": "secret"},
)
```

## Features

- **Recording**: Captures real HTTP interactions via vcrpy and stores them as JSON cassettes
- **Sanitization**: Redacts secrets, tokens, and sensitive fields before saving cassettes
- **Scaffolding**: Generates test directory structures from component config definitions
- **Validation**: Compares output snapshots to detect regressions

## Development

```bash
uv sync --all-groups
uv run pytest tests/
```
31 changes: 21 additions & 10 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,38 +1,49 @@
[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"
requires = ["uv_build>=0.10.0,<0.11.0"]
build-backend = "uv_build"

[project]
name = "keboola.vcr"
version = "0.1.0"
description = "VCR recording, sanitization, and validation for Keboola component HTTP interactions"
readme = "README.md"
license = {text = "MIT"}
requires-python = ">=3.8"
requires-python = ">=3.10"
classifiers = [
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
]
dependencies = [
"vcrpy>=4.0.0",
"freezegun>=1.0.0",
"vcrpy>=8.1.1,<9", # cassette._save and cassette.append are private API we depend on
"freezegun>=1.5.5,<2",
]

[dependency-groups]
dev = [
"pytest>=7.0",
"pytest-cov>=4.0",
"ruff>=0.1.0",
"flake8>=5.0.4",
]

[project.urls]
Homepage = "https://github.com/keboola/python-vcr-tests"
Repository = "https://github.com/keboola/python-vcr-tests"

[tool.setuptools.packages.find]
where = ["src"]
include = ["keboola.vcr*"]
[tool.uv.build-backend]
module-name = "keboola.vcr"

[[tool.uv.index]]
name = "testpypi"
url = "https://test.pypi.org/simple/"
publish-url = "https://test.pypi.org/legacy/"
explicit = true

[tool.ruff]
line-length = 120
Expand Down
4 changes: 2 additions & 2 deletions src/keboola/vcr/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
HeaderSanitizer,
UrlPatternSanitizer,
BodyFieldSanitizer,
QueryParameterTokenSanitizer,
QueryParamSanitizer,
ResponseUrlSanitizer,
CallbackSanitizer,
CompositeSanitizer,
Expand Down Expand Up @@ -63,7 +63,7 @@
"HeaderSanitizer",
"UrlPatternSanitizer",
"BodyFieldSanitizer",
"QueryParameterTokenSanitizer",
"QueryParamSanitizer",
"ResponseUrlSanitizer",
"CallbackSanitizer",
"CompositeSanitizer",
Expand Down
Loading