From 0b8588b18d747dc40a4919de21ba5d07fa8f5fd2 Mon Sep 17 00:00:00 2001 From: Zois Pagoulatos Date: Mon, 6 Apr 2026 22:44:40 +0200 Subject: [PATCH 1/7] feat(python): replace PyFlow with uv support --- python/pep518.go | 10 +++++----- python/run.go | 4 +--- python/uv.go | 21 +++++++++++++++++++++ python/virtualenv.go | 13 +++---------- 4 files changed, 30 insertions(+), 18 deletions(-) create mode 100644 python/uv.go diff --git a/python/pep518.go b/python/pep518.go index 0d2204a..b9d4154 100644 --- a/python/pep518.go +++ b/python/pep518.go @@ -9,10 +9,10 @@ import ( func pep518Proc(path string) { tomlContent := readPyProjectToml(path) - if isPoetry(tomlContent) { + if isUv(path) { + uvProc(path) + } else if isPoetry(tomlContent) { poetryProc(path) - } else if isPyFlow(tomlContent) { - pyflowProc(path) } } @@ -30,6 +30,6 @@ func isPoetry(tomlContent string) bool { return strings.Contains(tomlContent, "tool.poetry") } -func isPyFlow(tomlContent string) bool { - return strings.Contains(tomlContent, "tool.pyflow") +func isUv(path string) bool { + return fileExists(filepath.Join(path, "uv.lock")) } diff --git a/python/run.go b/python/run.go index 7c12b07..1a8bb2c 100644 --- a/python/run.go +++ b/python/run.go @@ -6,9 +6,7 @@ import ( ) func getPythonCommand(path string) string { - if dirExists(filepath.Join(path, "./__pypackages__")) { - return "pyflow" - } else if dirExists(filepath.Join(path, "./.venv")) { + if dirExists(filepath.Join(path, "./.venv")) { return filepath.Join(path, ".venv/bin/python") } else { return "python" diff --git a/python/uv.go b/python/uv.go new file mode 100644 index 0000000..8ffbe23 --- /dev/null +++ b/python/uv.go @@ -0,0 +1,21 @@ +package python + +import ( + "fmt" + "os/exec" + + log "github.com/sirupsen/logrus" +) + +func uvProc(path string) { + log.Info("Found 'uv.lock'. Creating virtual environment using 'uv'.") + + // install dependencies + cmd := exec.Command("uv", "sync") + cmd.Dir = path + out, err := cmd.CombinedOutput() + if err != nil { + log.Error(fmt.Sprintf("%s", err.Error())) + } + log.Debug(string(out)) +} diff --git a/python/virtualenv.go b/python/virtualenv.go index 155b26b..6827150 100644 --- a/python/virtualenv.go +++ b/python/virtualenv.go @@ -8,17 +8,10 @@ import ( log "github.com/sirupsen/logrus" ) -// CleanUpVirtualEnv Cleans up a virtual env by deleting .venv/ and __pypackages__/ dirs +// CleanUpVirtualEnv Cleans up a virtual env by deleting .venv/ dir func CleanUpVirtualEnv(path string) { log.Info(fmt.Sprintf("Teardown: Current working directory: %s", path)) - // cleanup __pypackages__ dir - if dirExists(filepath.Join(path, "./__pypackages__")) { - log.Debug("Deleting '__pypackages__/' directory") - - os.RemoveAll(filepath.Join(path, "./__pypackages__")) - } - // cleanup virtual env if dirExists(filepath.Join(path, "./.venv")) { log.Debug("Deleting '.venv/' directory") @@ -27,12 +20,12 @@ func CleanUpVirtualEnv(path string) { } } -// SetupVirtualEnv Creates a virtual environment using Poetry, PyFlow, pipenv or pip/venv +// SetupVirtualEnv Creates a virtual environment using uv, Poetry, pipenv or pip/venv func SetupVirtualEnv(path string) { log.Info(fmt.Sprintf("Setup: Current working directory: %s", path)) if fileExists(filepath.Join(path, "pyproject.toml")) { - // Poetry or PyFlow + // uv or Poetry pep518Proc(path) } else if fileExists(filepath.Join(path, "Pipfile")) { pipenvProc(path) From 0fa3bd036afaf1e681c91c95aa7b0708b08bdb1e Mon Sep 17 00:00:00 2001 From: Zois Pagoulatos Date: Mon, 6 Apr 2026 22:45:46 +0200 Subject: [PATCH 2/7] chore: remove PyFlow source and artifact files --- .gitignore | 2 +- pyflow.lock | 29 ----------------------------- pyproject.toml.pyflow | 13 ------------- python/pyflow.go | 21 --------------------- 4 files changed, 1 insertion(+), 64 deletions(-) delete mode 100644 pyflow.lock delete mode 100644 pyproject.toml.pyflow delete mode 100644 python/pyflow.go diff --git a/.gitignore b/.gitignore index bbc8d3a..23af2aa 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ .venv/ -__pypackages__/ \ No newline at end of file +.sisyphus/ \ No newline at end of file diff --git a/pyflow.lock b/pyflow.lock deleted file mode 100644 index 8a1e31f..0000000 --- a/pyflow.lock +++ /dev/null @@ -1,29 +0,0 @@ -[[package]] -id = 1 -name = "pendulum" -version = "2.1.0" -source = "pypi+https://pypi.org/pypi/pendulum/2.1.0/json" -dependencies = ["python-dateutil 2.8.1 pypi+https://pypi.org/pypi/python-dateutil/2.8.1/json", "pytzdata 2019.3.0 pypi+https://pypi.org/pypi/pytzdata/2019.3.0/json"] - -[[package]] -id = 3 -name = "python-dateutil" -version = "2.8.1" -source = "pypi+https://pypi.org/pypi/python-dateutil/2.8.1/json" -dependencies = ["six 1.15.0 pypi+https://pypi.org/pypi/six/1.15.0/json"] - -[[package]] -id = 4 -name = "six" -version = "1.15.0" -source = "pypi+https://pypi.org/pypi/six/1.15.0/json" -dependencies = [] - -[[package]] -id = 2 -name = "pytzdata" -version = "2019.3.0" -source = "pypi+https://pypi.org/pypi/pytzdata/2019.3.0/json" -dependencies = [] - -[metadata] diff --git a/pyproject.toml.pyflow b/pyproject.toml.pyflow deleted file mode 100644 index aa7f248..0000000 --- a/pyproject.toml.pyflow +++ /dev/null @@ -1,13 +0,0 @@ -# See PEP 518: https://www.python.org/dev/peps/pep-0518/ for info on this file's structure. - -[tool.pyflow] -name = "" -py_version = "3.7" -version = "0.1.0" - -[tool.pyflow.scripts] - -[tool.pyflow.dependencies] -pendulum = ">=2.1.0" - -[tool.pyflow.dev-dependencies] diff --git a/python/pyflow.go b/python/pyflow.go deleted file mode 100644 index ca2c5cd..0000000 --- a/python/pyflow.go +++ /dev/null @@ -1,21 +0,0 @@ -package python - -import ( - "fmt" - "os/exec" - - log "github.com/sirupsen/logrus" -) - -func pyflowProc(path string) { - log.Info("Found 'pyproject.toml'. Creating virtual environment using 'PyFlow'.") - - // install dependencies - cmd := exec.Command("pyflow", "install") - cmd.Dir = path - out, err := cmd.CombinedOutput() - if err != nil { - log.Error(fmt.Sprintf("%s", err.Error())) - } - log.Debug(string(out)) -} From 963fd58e80ccd557f2285b24b1d0d203c527c74a Mon Sep 17 00:00:00 2001 From: Zois Pagoulatos Date: Mon, 6 Apr 2026 22:46:54 +0200 Subject: [PATCH 3/7] docs: add AGENTS.md --- AGENTS.md | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..ed6994c --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,96 @@ +# AGENTS.md + +This file documents the go-python-runner project for AI coding agents. + +## Project Overview + +`go-python-runner` is a Go library that runs Python scripts in isolated virtual environments. It detects which Python package manager a project uses, creates the virtual environment, and provides the correct Python binary path to execute scripts. + +Module path: `github.com/zoispag/go-python-runner` + +## Repository Structure + +``` +go-python-runner/ +├── main.go # Demo entry point (runs script.py in CWD) +├── python/ # Core library package +│ ├── virtualenv.go # Public API: SetupVirtualEnv, CleanUpVirtualEnv +│ ├── run.go # Public API: GetPythonRunCommand, ExecutePython +│ ├── pep518.go # Routes pyproject.toml projects to uv or Poetry +│ ├── uv.go # uv handler: runs `uv sync` +│ ├── poetry.go # Poetry handler: runs `poetry install` +│ ├── pipenv.go # pipenv handler: runs `pipenv install` +│ ├── pip.go # pip+venv handler: creates venv and pip installs +│ └── utility.go # fileExists() and dirExists() helpers +├── go.mod +└── go.sum +``` + +## Public API + +All public functions are in the `python` package (`github.com/zoispag/go-python-runner/python`). + +### `SetupVirtualEnv(path string)` +Creates a virtual environment at the given path by detecting which package manager to use and running the appropriate install command. See package manager detection below. + +### `CleanUpVirtualEnv(path string)` +Deletes the `.venv/` directory if it exists at the given path. + +### `ExecutePython(path string, scriptName string) ([]byte, error)` +Runs the given Python script using the virtual environment's Python binary. Returns combined stdout+stderr output. + +### `GetPythonRunCommand(path string, scriptName string) *exec.Cmd` +Returns an `*exec.Cmd` for running the Python script, allowing the caller to control execution (Start, Wait, pipes, etc.). + +## Package Manager Detection & Precedence + +`SetupVirtualEnv` checks for indicator files in this order: + +| Priority | Tool | Indicator file | Install command | +|----------|------|---------------|-----------------| +| 1 | **uv** | `uv.lock` (+ `pyproject.toml`) | `uv sync` | +| 2 | **Poetry** | `pyproject.toml` with `[tool.poetry]` section | `poetry install` | +| 3 | **pipenv** | `Pipfile` | `pipenv install` | +| 4 | **pip + venv** | `requirements.txt` | `python3 -m venv .venv` + `pip install -r requirements.txt` | + +All supported tools install dependencies into `.venv/` in the project directory. `GetPythonRunCommand` / `ExecutePython` use `.venv/bin/python` if `.venv/` exists, otherwise fall back to system `python`. + +## Handler Pattern + +Every package manager handler follows the same structure: + +```go +func xyzProc(path string) { + log.Info("Found ''. Creating virtual environment using ''.") + cmd := exec.Command("", "") + cmd.Dir = path + out, err := cmd.CombinedOutput() + if err != nil { + log.Error(fmt.Sprintf("%s", err.Error())) + } + log.Debug(string(out)) +} +``` + +Errors are logged via `log.Error`, not returned. This is the established convention — do not change handlers to return errors. + +## Build & Run Commands + +```bash +go build ./... # Build +go vet ./... # Vet +go run . # Run demo (uses CWD as Python project path) +GO_DEBUG_MODE=on go run main.go # Run with debug logging +``` + +## Conventions + +- Error handling: use `log.Error(fmt.Sprintf(...))` — never return errors from handlers +- New package manager: add `.go` in `python/`, add detection + routing in `pep518.go` or `virtualenv.go` +- Do not modify public function signatures in `virtualenv.go` or `run.go` +- Do not change `ioutil.ReadFile` in `pep518.go` to `os.ReadFile` — leave deprecated API as-is +- Do not fix `fileExists("poetry.toml")` in `poetryProc` — pre-existing CWD-relative behaviour, out of scope + +## Commit Rules + +- Never add `Co-authored-by` trailers or any co-author lines to commits From d1d8e952a5013b24fc7751411c6a0b19879aebee Mon Sep 17 00:00:00 2001 From: Zois Pagoulatos Date: Mon, 6 Apr 2026 22:47:40 +0200 Subject: [PATCH 4/7] docs: update README to replace PyFlow with uv --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index c960201..19e7bf7 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,8 @@ It runs a python script in an isolated environment (virtual environment) via a go wrapper. It will install dependecies, using one of the following package managers with the following order: -1. Poetry (using `pyproject.toml`) -2. PyFlow (using `pyproject.toml`) +1. uv (using `uv.lock` + `pyproject.toml`) +2. Poetry (using `pyproject.toml`) 3. pipenv (using `Pipfile`) 4. pip & venv (using `requirements.txt`) @@ -26,7 +26,7 @@ This will create a vitual enviroment given the existence of proper files (`pypro python.CleanUpVirtualEnv("/path/to/python/script/") ``` -This will delete the `.venv` directory if exists. In case of pyflow, it will also delete the `__pypackages__` directory. +This will delete the `.venv` directory if exists. #### Run python script inside virtual environment @@ -81,8 +81,8 @@ func main() { ### Python package managers +- [uv](https://docs.astral.sh/uv/getting-started/installation/) - [Poetry](https://python-poetry.org/docs/#installation) -- [PyFlow](https://github.com/David-OConnor/pyflow#installation) - [pipenv](https://pipenv-fork.readthedocs.io/en/latest/install.html) ### Contribute From a455344951a9956ef0aac0eeec067508d99f4022 Mon Sep 17 00:00:00 2001 From: Zois Pagoulatos Date: Mon, 6 Apr 2026 23:14:26 +0200 Subject: [PATCH 5/7] test: add e2e tests and testdata fixtures per package manager - Add testdata/{uv,poetry,pipenv,pip}/ fixtures (pyproject.toml/lockfiles/script.py) - Add python/e2e_test.go with one test per package manager; skips if tool not on PATH - Add .github/workflows/test.yml: matrix CI over uv/poetry/pipenv/pip - Remove root-level Python demo files (Pipfile*, pyproject.toml, poetry*, requirements.txt, script.py, main.go) - Update AGENTS.md with testdata layout and test commands --- .github/workflows/test.yml | 54 ++++++++++++ AGENTS.md | 23 +++-- Pipfile.lock | 67 --------------- main.go | 36 -------- poetry.lock | 77 ----------------- poetry.toml | 2 - pyproject.toml | 15 ---- python/e2e_test.go | 107 +++++++++++++++++++++++ requirements.txt | 1 - testdata/pip/requirements.txt | 1 + script.py => testdata/pip/script.py | 3 +- Pipfile => testdata/pipenv/Pipfile | 6 +- testdata/pipenv/Pipfile.lock | 119 +++++++++++++++++++++++++ testdata/pipenv/script.py | 4 + testdata/poetry/poetry.lock | 129 ++++++++++++++++++++++++++++ testdata/poetry/poetry.toml | 2 + testdata/poetry/pyproject.toml | 13 +++ testdata/poetry/script.py | 4 + testdata/uv/pyproject.toml | 8 ++ testdata/uv/script.py | 4 + testdata/uv/uv.lock | 87 +++++++++++++++++++ 21 files changed, 551 insertions(+), 211 deletions(-) create mode 100644 .github/workflows/test.yml delete mode 100644 Pipfile.lock delete mode 100644 main.go delete mode 100644 poetry.lock delete mode 100644 poetry.toml delete mode 100644 pyproject.toml create mode 100644 python/e2e_test.go delete mode 100644 requirements.txt create mode 100644 testdata/pip/requirements.txt rename script.py => testdata/pip/script.py (62%) rename Pipfile => testdata/pipenv/Pipfile (62%) create mode 100644 testdata/pipenv/Pipfile.lock create mode 100644 testdata/pipenv/script.py create mode 100644 testdata/poetry/poetry.lock create mode 100644 testdata/poetry/poetry.toml create mode 100644 testdata/poetry/pyproject.toml create mode 100644 testdata/poetry/script.py create mode 100644 testdata/uv/pyproject.toml create mode 100644 testdata/uv/script.py create mode 100644 testdata/uv/uv.lock diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..c0e40e7 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,54 @@ +name: Test + +on: + push: + branches: [master] + pull_request: + branches: [master] + +jobs: + test: + name: E2E (${{ matrix.pm }}) + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + pm: [uv, poetry, pipenv, pip] + + steps: + - uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version-file: go.mod + cache: true + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.13" + + - name: Install uv + if: matrix.pm == 'uv' + uses: astral-sh/setup-uv@v5 + + - name: Install Poetry + if: matrix.pm == 'poetry' + uses: snok/install-poetry@v1 + with: + virtualenvs-in-project: true + + - name: Install pipenv + if: matrix.pm == 'pipenv' + run: pip install pipenv + + - name: go build + run: go build ./... + + - name: go vet + run: go vet ./... + + - name: go test + run: go test -v -timeout 120s ./python/ -run TestE2E diff --git a/AGENTS.md b/AGENTS.md index ed6994c..5477cdd 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -12,7 +12,6 @@ Module path: `github.com/zoispag/go-python-runner` ``` go-python-runner/ -├── main.go # Demo entry point (runs script.py in CWD) ├── python/ # Core library package │ ├── virtualenv.go # Public API: SetupVirtualEnv, CleanUpVirtualEnv │ ├── run.go # Public API: GetPythonRunCommand, ExecutePython @@ -21,7 +20,16 @@ go-python-runner/ │ ├── poetry.go # Poetry handler: runs `poetry install` │ ├── pipenv.go # pipenv handler: runs `pipenv install` │ ├── pip.go # pip+venv handler: creates venv and pip installs -│ └── utility.go # fileExists() and dirExists() helpers +│ ├── utility.go # fileExists() and dirExists() helpers +│ └── e2e_test.go # E2E tests (one per package manager) +├── testdata/ # E2E test fixtures (one subdir per package manager) +│ ├── uv/ # uv fixture: pyproject.toml, uv.lock, script.py +│ ├── poetry/ # Poetry fixture: pyproject.toml, poetry.lock, poetry.toml, script.py +│ ├── pipenv/ # pipenv fixture: Pipfile, Pipfile.lock, script.py +│ └── pip/ # pip fixture: requirements.txt, script.py +├── .github/workflows/ +│ ├── codeql-analysis.yml +│ └── test.yml # E2E CI: matrix over uv/poetry/pipenv/pip ├── go.mod └── go.sum ``` @@ -74,15 +82,16 @@ func xyzProc(path string) { Errors are logged via `log.Error`, not returned. This is the established convention — do not change handlers to return errors. -## Build & Run Commands +## Build, Test & Run Commands ```bash -go build ./... # Build -go vet ./... # Vet -go run . # Run demo (uses CWD as Python project path) -GO_DEBUG_MODE=on go run main.go # Run with debug logging +go build ./... # Build +go vet ./... # Vet +go test -v -timeout 120s ./python/ # Run all E2E tests ``` +The E2E tests in `python/e2e_test.go` copy each `testdata//` fixture into a temp directory, call `SetupVirtualEnv`, run `script.py` via `ExecutePython`, assert an ISO 8601 timestamp is printed, then call `CleanUpVirtualEnv`. Each test skips automatically if the required tool is not on `PATH`. + ## Conventions - Error handling: use `log.Error(fmt.Sprintf(...))` — never return errors from handlers diff --git a/Pipfile.lock b/Pipfile.lock deleted file mode 100644 index 64f9bd9..0000000 --- a/Pipfile.lock +++ /dev/null @@ -1,67 +0,0 @@ -{ - "_meta": { - "hash": { - "sha256": "061b9b9c5aaa9803e9875cfc5373069db0b59b6f8a1732659b778aa3a11ef4a8" - }, - "pipfile-spec": 6, - "requires": { - "python_version": "3.7" - }, - "sources": [ - { - "name": "pypi", - "url": "https://pypi.org/simple", - "verify_ssl": true - } - ] - }, - "default": { - "pendulum": { - "hashes": [ - "sha256:093cab342e10516660e64b935a6da1a043e0286de36cc229fb48471415981ffe", - "sha256:0cbbd4f30c69a283690d9ed8e58e44a990e067e59ee05b5ef55d022b38659aeb", - "sha256:2788945a0111d5325fd27ae3e3b18b741e440d20bdb7d4ea22fce7c9a4fbbf40", - "sha256:4420e058110740a8193fb0709350dfc6ac790a99c345fc4e92e24df0f834ddcb", - "sha256:575934b65b298eeb99c5a5b1673c945fc5c99e2b56caff772a91bc4b1eba7b82", - "sha256:6cf0f876cd088ee1578266f4231121376747aa90c3ed3b8e212a8344a9920061", - "sha256:70007aebc4494163f8705909a1996ce21ab853801b57fba4c2dd53c3df5c38f0", - "sha256:701127e1f0ff7c253cc0c07f29becc5f9210547914e0bbe59ffd9fa064d7c3c8", - "sha256:75a62e3f98499283fafe8ef4b44f81052e84825b00a0b64609dd8a06985382b9", - "sha256:816e01dcb0ba4ffcf2ceaafe4d644174fea680361e909f6f8ba0a4fdb2ccae24", - "sha256:9eda38ff65b1f297d860d3f562480e048673fb4b81fdd5c8c55decb519b97ed2", - "sha256:a79a72a7fd1092a7c69ddd8580a0be5365ded40c9f9c865623c7665742e3b888", - "sha256:aa13ddea12fd871d3191f633f08090b91ea2e80fb0ed50a7a149add7f680b12d", - "sha256:aa560bd39d94f3889646422f1e65b8dfd025bf6288d43e5c2e31d4f972aaf2e4", - "sha256:ac3c6a992beeb4c9bd90c317a1bb2a6cba159b49a49b6dd3c86b5bacb86f3d50", - "sha256:d42d1e870541eeaf3fe0500aac0c76a85bd4bd53ebed74f9a7daf8f01ac77374", - "sha256:eb7e349bb2d1b2b418d094e2179d6768561e8242fd8cb640b5aaba735f3e91d1", - "sha256:edd00e6b43698762e10bfda508cc9c06bad88c0703a9b37e412aec1189e06e23", - "sha256:ff7f3420de0c0cf21c1fc813d581fcfa4a1fb6d87f09485880b3e1204eb9cdd7" - ], - "index": "pypi", - "version": "==2.1.0" - }, - "python-dateutil": { - "hashes": [ - "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c", - "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a" - ], - "version": "==2.8.1" - }, - "pytzdata": { - "hashes": [ - "sha256:84c52b9a47d097fcd483f047a544979de6c3a86e94c845e3569e9f8acd0fa071", - "sha256:fac06f7cdfa903188dc4848c655e4adaee67ee0f2fe08e7daf815cf2a761ee5e" - ], - "version": "==2019.3" - }, - "six": { - "hashes": [ - "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259", - "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced" - ], - "version": "==1.15.0" - } - }, - "develop": {} -} diff --git a/main.go b/main.go deleted file mode 100644 index 8ae6665..0000000 --- a/main.go +++ /dev/null @@ -1,36 +0,0 @@ -package main - -import ( - "fmt" - "os" - - log "github.com/sirupsen/logrus" - python "github.com/zoispag/go-python-runner/python" -) - -func init() { - // Output to stdout instead of the default stderr - // Can be any io.Writer, see below for File example - log.SetOutput(os.Stdout) - - // Set debug mode on - if os.Getenv("GO_DEBUG_MODE") == "on" { - log.SetLevel(log.DebugLevel) - } -} - -func main() { - path, err := os.Getwd() - if err != nil { - log.Error(fmt.Sprintf("Job resulted in error: %s", err.Error())) - } - python.CleanUpVirtualEnv(path) - python.SetupVirtualEnv(path) - - cmd := python.GetPythonRunCommand(path, "script.py") - out, err := cmd.CombinedOutput() - if err != nil { - log.Error(fmt.Sprintf("Job resulted in error: %s", err.Error())) - } - log.Info(string(out)) -} diff --git a/poetry.lock b/poetry.lock deleted file mode 100644 index 3a2bbaf..0000000 --- a/poetry.lock +++ /dev/null @@ -1,77 +0,0 @@ -[[package]] -category = "main" -description = "Python datetimes made easy" -name = "pendulum" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "2.1.0" - -[package.dependencies] -python-dateutil = ">=2.6,<3.0" -pytzdata = ">=2018.3" - -[[package]] -category = "main" -description = "Extensions to the standard Python datetime module" -name = "python-dateutil" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -version = "2.8.1" - -[package.dependencies] -six = ">=1.5" - -[[package]] -category = "main" -description = "The Olson timezone database for Python." -name = "pytzdata" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "2019.3" - -[[package]] -category = "main" -description = "Python 2 and 3 compatibility utilities" -name = "six" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" -version = "1.14.0" - -[metadata] -content-hash = "889a067a4895dfd3d40a87c14783c86d2b9bbbfc79f9a1fc0548b03dd52be4d3" -python-versions = "^3.7" - -[metadata.files] -pendulum = [ - {file = "pendulum-2.1.0-cp27-cp27m-macosx_10_13_x86_64.whl", hash = "sha256:9eda38ff65b1f297d860d3f562480e048673fb4b81fdd5c8c55decb519b97ed2"}, - {file = "pendulum-2.1.0-cp27-cp27m-win_amd64.whl", hash = "sha256:70007aebc4494163f8705909a1996ce21ab853801b57fba4c2dd53c3df5c38f0"}, - {file = "pendulum-2.1.0-cp35-cp35m-macosx_10_13_x86_64.whl", hash = "sha256:575934b65b298eeb99c5a5b1673c945fc5c99e2b56caff772a91bc4b1eba7b82"}, - {file = "pendulum-2.1.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:d42d1e870541eeaf3fe0500aac0c76a85bd4bd53ebed74f9a7daf8f01ac77374"}, - {file = "pendulum-2.1.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:ff7f3420de0c0cf21c1fc813d581fcfa4a1fb6d87f09485880b3e1204eb9cdd7"}, - {file = "pendulum-2.1.0-cp35-cp35m-win_amd64.whl", hash = "sha256:ac3c6a992beeb4c9bd90c317a1bb2a6cba159b49a49b6dd3c86b5bacb86f3d50"}, - {file = "pendulum-2.1.0-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:75a62e3f98499283fafe8ef4b44f81052e84825b00a0b64609dd8a06985382b9"}, - {file = "pendulum-2.1.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:a79a72a7fd1092a7c69ddd8580a0be5365ded40c9f9c865623c7665742e3b888"}, - {file = "pendulum-2.1.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:701127e1f0ff7c253cc0c07f29becc5f9210547914e0bbe59ffd9fa064d7c3c8"}, - {file = "pendulum-2.1.0-cp36-cp36m-win_amd64.whl", hash = "sha256:816e01dcb0ba4ffcf2ceaafe4d644174fea680361e909f6f8ba0a4fdb2ccae24"}, - {file = "pendulum-2.1.0-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:edd00e6b43698762e10bfda508cc9c06bad88c0703a9b37e412aec1189e06e23"}, - {file = "pendulum-2.1.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:4420e058110740a8193fb0709350dfc6ac790a99c345fc4e92e24df0f834ddcb"}, - {file = "pendulum-2.1.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:aa560bd39d94f3889646422f1e65b8dfd025bf6288d43e5c2e31d4f972aaf2e4"}, - {file = "pendulum-2.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:2788945a0111d5325fd27ae3e3b18b741e440d20bdb7d4ea22fce7c9a4fbbf40"}, - {file = "pendulum-2.1.0-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:eb7e349bb2d1b2b418d094e2179d6768561e8242fd8cb640b5aaba735f3e91d1"}, - {file = "pendulum-2.1.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:6cf0f876cd088ee1578266f4231121376747aa90c3ed3b8e212a8344a9920061"}, - {file = "pendulum-2.1.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:aa13ddea12fd871d3191f633f08090b91ea2e80fb0ed50a7a149add7f680b12d"}, - {file = "pendulum-2.1.0-cp38-cp38m-win_amd64.whl", hash = "sha256:0cbbd4f30c69a283690d9ed8e58e44a990e067e59ee05b5ef55d022b38659aeb"}, - {file = "pendulum-2.1.0.tar.gz", hash = "sha256:093cab342e10516660e64b935a6da1a043e0286de36cc229fb48471415981ffe"}, -] -python-dateutil = [ - {file = "python-dateutil-2.8.1.tar.gz", hash = "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c"}, - {file = "python_dateutil-2.8.1-py2.py3-none-any.whl", hash = "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a"}, -] -pytzdata = [ - {file = "pytzdata-2019.3-py2.py3-none-any.whl", hash = "sha256:84c52b9a47d097fcd483f047a544979de6c3a86e94c845e3569e9f8acd0fa071"}, - {file = "pytzdata-2019.3.tar.gz", hash = "sha256:fac06f7cdfa903188dc4848c655e4adaee67ee0f2fe08e7daf815cf2a761ee5e"}, -] -six = [ - {file = "six-1.14.0-py2.py3-none-any.whl", hash = "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c"}, - {file = "six-1.14.0.tar.gz", hash = "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a"}, -] diff --git a/poetry.toml b/poetry.toml deleted file mode 100644 index efa46ec..0000000 --- a/poetry.toml +++ /dev/null @@ -1,2 +0,0 @@ -[virtualenvs] -in-project = true \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml deleted file mode 100644 index 5805c22..0000000 --- a/pyproject.toml +++ /dev/null @@ -1,15 +0,0 @@ -[tool.poetry] -name = "go-python-runner" -version = "0.1.0" -description = "" -authors = ["Zois Pagoulatos "] - -[tool.poetry.dependencies] -python = "^3.7" -pendulum = "^2.1.0" - -[tool.poetry.dev-dependencies] - -[build-system] -requires = ["poetry>=0.12"] -build-backend = "poetry.masonry.api" diff --git a/python/e2e_test.go b/python/e2e_test.go new file mode 100644 index 0000000..6ac226b --- /dev/null +++ b/python/e2e_test.go @@ -0,0 +1,107 @@ +package python_test + +import ( + "io/fs" + "os" + "os/exec" + "path/filepath" + "regexp" + "testing" + + python "github.com/zoispag/go-python-runner/python" +) + +// iso8601Re matches the ISO 8601 datetime string printed by script.py. +var iso8601Re = regexp.MustCompile(`^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}`) + +// copyDir recursively copies src into dst (dst must already exist). +func copyDir(t *testing.T, src, dst string) { + t.Helper() + err := filepath.WalkDir(src, func(path string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + rel, _ := filepath.Rel(src, path) + target := filepath.Join(dst, rel) + if d.IsDir() { + return os.MkdirAll(target, 0755) + } + data, err := os.ReadFile(path) + if err != nil { + return err + } + return os.WriteFile(target, data, 0644) + }) + if err != nil { + t.Fatalf("copyDir %s -> %s: %v", src, dst, err) + } +} + +// fixtureDir returns the absolute path to testdata/. +func fixtureDir(t *testing.T, name string) string { + t.Helper() + // This file lives in python/; testdata is one level up. + abs, err := filepath.Abs(filepath.Join("..", "testdata", name)) + if err != nil { + t.Fatalf("fixtureDir %s: %v", name, err) + } + return abs +} + +// requireTool skips the test if the named binary is not on PATH. +func requireTool(t *testing.T, tool string) { + t.Helper() + if _, err := exec.LookPath(tool); err != nil { + t.Skipf("%s not found on PATH — skipping", tool) + } +} + +func runE2E(t *testing.T, pmName string) { + t.Helper() + + // Copy fixture into a temp dir so .venv doesn't pollute the source tree. + tmp := t.TempDir() + copyDir(t, fixtureDir(t, pmName), tmp) + + // SetupVirtualEnv must create .venv. + python.SetupVirtualEnv(tmp) + venvPath := filepath.Join(tmp, ".venv") + if _, err := os.Stat(venvPath); os.IsNotExist(err) { + t.Fatalf("SetupVirtualEnv did not create .venv for %s", pmName) + } + + // ExecutePython must run script.py and return an ISO 8601 timestamp. + out, err := python.ExecutePython(tmp, filepath.Join(tmp, "script.py")) + if err != nil { + t.Fatalf("ExecutePython error for %s: %v\noutput: %s", pmName, err, out) + } + if !iso8601Re.Match(out) { + t.Fatalf("unexpected output for %s: %q (want ISO 8601 timestamp)", pmName, out) + } + + // CleanUpVirtualEnv must remove .venv. + python.CleanUpVirtualEnv(tmp) + if _, err := os.Stat(venvPath); !os.IsNotExist(err) { + t.Fatalf("CleanUpVirtualEnv did not remove .venv for %s", pmName) + } +} + +func TestE2EUv(t *testing.T) { + requireTool(t, "uv") + runE2E(t, "uv") +} + +func TestE2EPoetry(t *testing.T) { + requireTool(t, "poetry") + runE2E(t, "poetry") +} + +func TestE2EPipenv(t *testing.T) { + requireTool(t, "pipenv") + runE2E(t, "pipenv") +} + +func TestE2EPip(t *testing.T) { + requireTool(t, "python3") + runE2E(t, "pip") +} diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 667545a..0000000 --- a/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -pendulum==2.1.0 \ No newline at end of file diff --git a/testdata/pip/requirements.txt b/testdata/pip/requirements.txt new file mode 100644 index 0000000..d1aedd1 --- /dev/null +++ b/testdata/pip/requirements.txt @@ -0,0 +1 @@ +pendulum>=3.0 diff --git a/script.py b/testdata/pip/script.py similarity index 62% rename from script.py rename to testdata/pip/script.py index 3afdfc8..151fffa 100644 --- a/script.py +++ b/testdata/pip/script.py @@ -1,5 +1,4 @@ import pendulum now = pendulum.now("Europe/Paris") - -print(now.to_iso8601_string()) \ No newline at end of file +print(now.to_iso8601_string()) diff --git a/Pipfile b/testdata/pipenv/Pipfile similarity index 62% rename from Pipfile rename to testdata/pipenv/Pipfile index 21d71a4..64b6756 100644 --- a/Pipfile +++ b/testdata/pipenv/Pipfile @@ -3,10 +3,8 @@ name = "pypi" url = "https://pypi.org/simple" verify_ssl = true -[dev-packages] - [packages] -pendulum = ">=2.1.0" +pendulum = ">=3.0" [requires] -python_version = "3.7" +python_version = "3.13" diff --git a/testdata/pipenv/Pipfile.lock b/testdata/pipenv/Pipfile.lock new file mode 100644 index 0000000..fa5787f --- /dev/null +++ b/testdata/pipenv/Pipfile.lock @@ -0,0 +1,119 @@ +{ + "_meta": { + "hash": { + "sha256": "6728a3d826c9c2f296999077b1299230f4dc6ce02f3f7ec03e662c171a51d429" + }, + "pipfile-spec": 6, + "requires": { + "python_version": "3.13" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "pendulum": { + "hashes": [ + "sha256:04310463879a8d84534756ef9820d433e88b879203b6e10a5b416899dc05e7f1", + "sha256:063ab61af953bb56ad5bc8e131fd0431c915ed766d90ccecd7549c8090b51004", + "sha256:1ba955511c12fec2252038b0c866c25c0c30b720bf74d3023710f121e42b1498", + "sha256:249d18f5543c9f43aba3bd77b34864ec8cf6f64edbead405f442e23c94fce63d", + "sha256:26401e2de77c437e8f3b6160c08c6c5d45518d906f8f9b48fd7cb5aa0f4e2aff", + "sha256:26a3ae26c9dd70a4256f1c2f51addc43641813574c0db6ce5664f9861cd93621", + "sha256:2b10d91dc00f424444a42f47c69e6b3bfd79376f330179dc06bc342184b35f9a", + "sha256:2dd31fd46aa8fceaff5de674b8d57b0b659753986cb78fa9e24368da7f8e4eec", + "sha256:3159cceb54f5aa8b85b141c7f0ce3fac8bdd1ffdc7c79e67dca9133eac7c4d11", + "sha256:326ef1baa8657c9c4aead5c4eac06a46355ba4e338816153e2929b0b548554b5", + "sha256:38a300df5a82ebea8634a1aed3d98c92968ba856d2ca7ba2acf7228f0e0e99af", + "sha256:39ef129d7b90aab49708645867abdd207b714ba7bff12dae549975b0aca09716", + "sha256:3a2af22eeec438fbaac72bb7fba783e0950a514fba980d9a32db394b51afccec", + "sha256:3a8d4212b1577ee3a034d18b360a9afa55bfc72789aeb805353be8b2ac132035", + "sha256:3aaa50342dc174acebdc21089315012e63789353957b39ac83cac9f9fc8d1075", + "sha256:4115bf364a2ec6d5ddc476751ceaa4164a04f2c15589f0d29aa210ddb784b15d", + "sha256:4151a903356413fdd9549de0997b708fb95a214ed97803ffb479ffd834088378", + "sha256:446f63d84ef21281844ceb45141536d3aabe291a821b6505e21a0d0e3ea95d67", + "sha256:4a6bf778c6b42830b001c714dae5b9dad78da38e2e08203a4b0f5d53f8fa5e63", + "sha256:55d7ba6bb74171c3ee409bf30076ee3a259a3c2bb147ac87ebb76aaa3cf5d3a2", + "sha256:5b4f7491951c11bbdb20893817352c9140d31d1ae333839c34c0bca081a50a86", + "sha256:5cd956d4176afc7bfe8a91bf3f771b46ff8d326f6c5bf778eb5010eb742ebba6", + "sha256:5d775cc608c909ad415c8e789c84a9f120bb6a794c4215b2d8d910893cf0ec6a", + "sha256:625209bb7133d990905e8935e1c04f0a82315ae777b67910969b16f665d62c0b", + "sha256:63070ff03e30a57b16c8e793ee27da8dac4123c1d6e0cf74c460ce9ee8a64aa4", + "sha256:637e65af042f383a2764a886aa28ccc6f853bf7a142df18e41c720542934c13b", + "sha256:70214f30114ee6de09b0abbb90e74f68682f194485200897930125de36024c21", + "sha256:71d46bcc86269f97bfd8c5f1475d55e717696a0a010b1871023605ca94624031", + "sha256:7bac7df7696e1c942e17c0556b3a7bcdd1d7aa5b24faee7620cb071e754a0622", + "sha256:7c644cc15eec5fb02291f0f193195156780fd5a0affd7a349592403826d1a35e", + "sha256:85c7689defc65c4dc29bf257f7cca55d210fabb455de9476e1748d2ab2ae80d7", + "sha256:86029fd802c5650f2cbef3f9302608325a676d3a883d6a5782bc855e5d03918b", + "sha256:8de794a7f665aebc8c1ba4dd4b05ab8fe1a36ce9c0498366adf1d1edd79b2686", + "sha256:927e9c9ab52ff68e71b76dd410e5f1cd78f5ea6e7f0a9f5eb549aea16a4d5354", + "sha256:937a529aa302efa18dcf25e53834964a87ffb2df8f80e3669ab7757a6126beaf", + "sha256:9585594d32faa71efa5a78f576f1ee4f79e9c5340d7c6f0cd6c5dfe725effaaa", + "sha256:a50d8cf42f06d3d8c3f8bb2a7ac47fa93b5145e69de6a7209be6a47afdd9cf76", + "sha256:a7d2e9bfb065727d8676e7ada3793b47a24349500a5e9637404355e482c822be", + "sha256:a8c67fb9a1fe8fc1adae2cc01b0c292b268c12475b4609ff4aed71c9dd367b4d", + "sha256:acfdee9ddc56053cb7c8c075afbfde0857322d09e56a56195b9cd127fae87e4c", + "sha256:addb0512f919fe5b70c8ee534ee71c775630d3efe567ea5763d92acff857cfc3", + "sha256:b6f1d8641e8bd48b9b6f77f96fd498d3ecec63611ba8e7207e63936307846042", + "sha256:baa9a66c980defda6cfe1275103a94b22e90d83ebd7a84cc961cee6cbd25a244", + "sha256:bf0b489def51202a39a2a665dcc4162d5e46934a740fe4c4fe3068979610156c", + "sha256:c17ac069e88c5a1e930a5ae0ef17357a14b9cc5a28abadda74eaa8106d241c8e", + "sha256:c352c63c1ff05f2198409b28498d7158547a8be23e1fbd4aa2cf5402fb239b55", + "sha256:c39ea5e9ffa20ea8bae986d00e0908bd537c8468b71d6b6503ab0b4c3d76e0ea", + "sha256:c8dde63e2796b62070a49ce813ce200aba9186130307f04ec78affcf6c2e8122", + "sha256:ce87750e0a644e8ddafa3e9437f0ff35af8d17eb5c77824864246ccf6b44d24a", + "sha256:d3cad6be303b4b9737f629191b73920e0e4c2fe1fbd5813b7a19b05f29d09a1c", + "sha256:d53134418e04335c3029a32e9341cccc9b085a28744fb5ee4e6a8f5039363b1a", + "sha256:d5e216e5a412563ea2ecf5de467dcf3d02717947fcdabe6811d5ee360726b02b", + "sha256:d6e46c28f4d067233c4a4c42748f4ffa641d9289c09e0e81488beb6d4b3fab51", + "sha256:db0f6a8a04475d9cba26ce701e7d66d266fd97227f2f5f499270eba04be1c7e9", + "sha256:de8c1ad1d1aa7d4ceae341528bab35a0f8c88a5aa63f2f5d84e16b517d1b32c2", + "sha256:dfbcd7a2a5ebabf5abaf07062555cd7bef9a472a6aa5281a6302afe66a481561", + "sha256:e1fbb540edecb21f8244aebfb05a1f2333ddc6c7819378c099d4a61cc91ae93c", + "sha256:e398d9e3db42d17f0c2cd39663c1c873ea6f11763ed6d126e2dcc92fc340d0dc", + "sha256:e5afc753e570cce1f44197676371f68953f7d4f022303d141bb09f804d5fe6d7", + "sha256:e5bbb92b155cd5018b3cf70ee49ed3b9c94398caaaa7ed97fe41e5bb5a968418", + "sha256:e80feda2d10fa3ff8b1526715f7d33dcb7e08494b3088f2c8a3ac92d4a4331ce", + "sha256:ef8f783fa7a14973b0596d8af2a5b2d90858a55030e9b4c6885eb4284b88314f", + "sha256:f00d033fe9b31c41deb6484f36a788b99b936cf8d10a994784e809a59b72d7db", + "sha256:f3a9c18a89b4d9ef39c5fa6a78722aaff8d5be2597c129a3b16b9f40a561acf3", + "sha256:faef52a7ed99729f0838353b956f3fabf6c550c062db247e9e2fc2b48fcb9457", + "sha256:fd55c12560816d9122ca2142d9e428f32c0c083bf77719320b1767539c7a3a3b", + "sha256:ffc169ad7595228d4dfc44d4e016846ff1bb5873b9f7ec70b0b1b51da0c77b3f" + ], + "index": "pypi", + "markers": "python_version >= '3.9'", + "version": "==3.2.0" + }, + "python-dateutil": { + "hashes": [ + "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", + "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", + "version": "==2.9.0.post0" + }, + "six": { + "hashes": [ + "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", + "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", + "version": "==1.17.0" + }, + "tzdata": { + "hashes": [ + "sha256:4b1d2be7ac37ceafd7327b961aa3a54e467efbdb563a23655fbfe0d39cfc42a9", + "sha256:67658a1903c75917309e753fdc349ac0efd8c27db7a0cb406a25be4840f87f98" + ], + "markers": "python_version >= '2'", + "version": "==2026.1" + } + }, + "develop": {} +} diff --git a/testdata/pipenv/script.py b/testdata/pipenv/script.py new file mode 100644 index 0000000..151fffa --- /dev/null +++ b/testdata/pipenv/script.py @@ -0,0 +1,4 @@ +import pendulum + +now = pendulum.now("Europe/Paris") +print(now.to_iso8601_string()) diff --git a/testdata/poetry/poetry.lock b/testdata/poetry/poetry.lock new file mode 100644 index 0000000..cc4ae4c --- /dev/null +++ b/testdata/poetry/poetry.lock @@ -0,0 +1,129 @@ +# This file is automatically @generated by Poetry 2.3.3 and should not be changed by hand. + +[[package]] +name = "pendulum" +version = "3.2.0" +description = "Python datetimes made easy" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "pendulum-3.2.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:4a6bf778c6b42830b001c714dae5b9dad78da38e2e08203a4b0f5d53f8fa5e63"}, + {file = "pendulum-3.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:625209bb7133d990905e8935e1c04f0a82315ae777b67910969b16f665d62c0b"}, + {file = "pendulum-3.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b6f1d8641e8bd48b9b6f77f96fd498d3ecec63611ba8e7207e63936307846042"}, + {file = "pendulum-3.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3a8d4212b1577ee3a034d18b360a9afa55bfc72789aeb805353be8b2ac132035"}, + {file = "pendulum-3.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e398d9e3db42d17f0c2cd39663c1c873ea6f11763ed6d126e2dcc92fc340d0dc"}, + {file = "pendulum-3.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:04310463879a8d84534756ef9820d433e88b879203b6e10a5b416899dc05e7f1"}, + {file = "pendulum-3.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:5b4f7491951c11bbdb20893817352c9140d31d1ae333839c34c0bca081a50a86"}, + {file = "pendulum-3.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ffc169ad7595228d4dfc44d4e016846ff1bb5873b9f7ec70b0b1b51da0c77b3f"}, + {file = "pendulum-3.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:446f63d84ef21281844ceb45141536d3aabe291a821b6505e21a0d0e3ea95d67"}, + {file = "pendulum-3.2.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:5d775cc608c909ad415c8e789c84a9f120bb6a794c4215b2d8d910893cf0ec6a"}, + {file = "pendulum-3.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8de794a7f665aebc8c1ba4dd4b05ab8fe1a36ce9c0498366adf1d1edd79b2686"}, + {file = "pendulum-3.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bac7df7696e1c942e17c0556b3a7bcdd1d7aa5b24faee7620cb071e754a0622"}, + {file = "pendulum-3.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:db0f6a8a04475d9cba26ce701e7d66d266fd97227f2f5f499270eba04be1c7e9"}, + {file = "pendulum-3.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c352c63c1ff05f2198409b28498d7158547a8be23e1fbd4aa2cf5402fb239b55"}, + {file = "pendulum-3.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de8c1ad1d1aa7d4ceae341528bab35a0f8c88a5aa63f2f5d84e16b517d1b32c2"}, + {file = "pendulum-3.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1ba955511c12fec2252038b0c866c25c0c30b720bf74d3023710f121e42b1498"}, + {file = "pendulum-3.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4115bf364a2ec6d5ddc476751ceaa4164a04f2c15589f0d29aa210ddb784b15d"}, + {file = "pendulum-3.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:4151a903356413fdd9549de0997b708fb95a214ed97803ffb479ffd834088378"}, + {file = "pendulum-3.2.0-cp311-cp311-win_arm64.whl", hash = "sha256:acfdee9ddc56053cb7c8c075afbfde0857322d09e56a56195b9cd127fae87e4c"}, + {file = "pendulum-3.2.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:bf0b489def51202a39a2a665dcc4162d5e46934a740fe4c4fe3068979610156c"}, + {file = "pendulum-3.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:937a529aa302efa18dcf25e53834964a87ffb2df8f80e3669ab7757a6126beaf"}, + {file = "pendulum-3.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85c7689defc65c4dc29bf257f7cca55d210fabb455de9476e1748d2ab2ae80d7"}, + {file = "pendulum-3.2.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d5e216e5a412563ea2ecf5de467dcf3d02717947fcdabe6811d5ee360726b02b"}, + {file = "pendulum-3.2.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3a2af22eeec438fbaac72bb7fba783e0950a514fba980d9a32db394b51afccec"}, + {file = "pendulum-3.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3159cceb54f5aa8b85b141c7f0ce3fac8bdd1ffdc7c79e67dca9133eac7c4d11"}, + {file = "pendulum-3.2.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c39ea5e9ffa20ea8bae986d00e0908bd537c8468b71d6b6503ab0b4c3d76e0ea"}, + {file = "pendulum-3.2.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e5afc753e570cce1f44197676371f68953f7d4f022303d141bb09f804d5fe6d7"}, + {file = "pendulum-3.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:fd55c12560816d9122ca2142d9e428f32c0c083bf77719320b1767539c7a3a3b"}, + {file = "pendulum-3.2.0-cp312-cp312-win_arm64.whl", hash = "sha256:faef52a7ed99729f0838353b956f3fabf6c550c062db247e9e2fc2b48fcb9457"}, + {file = "pendulum-3.2.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:addb0512f919fe5b70c8ee534ee71c775630d3efe567ea5763d92acff857cfc3"}, + {file = "pendulum-3.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3aaa50342dc174acebdc21089315012e63789353957b39ac83cac9f9fc8d1075"}, + {file = "pendulum-3.2.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:927e9c9ab52ff68e71b76dd410e5f1cd78f5ea6e7f0a9f5eb549aea16a4d5354"}, + {file = "pendulum-3.2.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:249d18f5543c9f43aba3bd77b34864ec8cf6f64edbead405f442e23c94fce63d"}, + {file = "pendulum-3.2.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c644cc15eec5fb02291f0f193195156780fd5a0affd7a349592403826d1a35e"}, + {file = "pendulum-3.2.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:063ab61af953bb56ad5bc8e131fd0431c915ed766d90ccecd7549c8090b51004"}, + {file = "pendulum-3.2.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:26a3ae26c9dd70a4256f1c2f51addc43641813574c0db6ce5664f9861cd93621"}, + {file = "pendulum-3.2.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:2b10d91dc00f424444a42f47c69e6b3bfd79376f330179dc06bc342184b35f9a"}, + {file = "pendulum-3.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:63070ff03e30a57b16c8e793ee27da8dac4123c1d6e0cf74c460ce9ee8a64aa4"}, + {file = "pendulum-3.2.0-cp313-cp313-win_arm64.whl", hash = "sha256:c8dde63e2796b62070a49ce813ce200aba9186130307f04ec78affcf6c2e8122"}, + {file = "pendulum-3.2.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:c17ac069e88c5a1e930a5ae0ef17357a14b9cc5a28abadda74eaa8106d241c8e"}, + {file = "pendulum-3.2.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:e1fbb540edecb21f8244aebfb05a1f2333ddc6c7819378c099d4a61cc91ae93c"}, + {file = "pendulum-3.2.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a8c67fb9a1fe8fc1adae2cc01b0c292b268c12475b4609ff4aed71c9dd367b4d"}, + {file = "pendulum-3.2.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:baa9a66c980defda6cfe1275103a94b22e90d83ebd7a84cc961cee6cbd25a244"}, + {file = "pendulum-3.2.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ef8f783fa7a14973b0596d8af2a5b2d90858a55030e9b4c6885eb4284b88314f"}, + {file = "pendulum-3.2.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a7d2e9bfb065727d8676e7ada3793b47a24349500a5e9637404355e482c822be"}, + {file = "pendulum-3.2.0-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:55d7ba6bb74171c3ee409bf30076ee3a259a3c2bb147ac87ebb76aaa3cf5d3a2"}, + {file = "pendulum-3.2.0-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:a50d8cf42f06d3d8c3f8bb2a7ac47fa93b5145e69de6a7209be6a47afdd9cf76"}, + {file = "pendulum-3.2.0-cp314-cp314-win_amd64.whl", hash = "sha256:e5bbb92b155cd5018b3cf70ee49ed3b9c94398caaaa7ed97fe41e5bb5a968418"}, + {file = "pendulum-3.2.0-cp314-cp314-win_arm64.whl", hash = "sha256:d53134418e04335c3029a32e9341cccc9b085a28744fb5ee4e6a8f5039363b1a"}, + {file = "pendulum-3.2.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:70214f30114ee6de09b0abbb90e74f68682f194485200897930125de36024c21"}, + {file = "pendulum-3.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d3cad6be303b4b9737f629191b73920e0e4c2fe1fbd5813b7a19b05f29d09a1c"}, + {file = "pendulum-3.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2dd31fd46aa8fceaff5de674b8d57b0b659753986cb78fa9e24368da7f8e4eec"}, + {file = "pendulum-3.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce87750e0a644e8ddafa3e9437f0ff35af8d17eb5c77824864246ccf6b44d24a"}, + {file = "pendulum-3.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:326ef1baa8657c9c4aead5c4eac06a46355ba4e338816153e2929b0b548554b5"}, + {file = "pendulum-3.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f00d033fe9b31c41deb6484f36a788b99b936cf8d10a994784e809a59b72d7db"}, + {file = "pendulum-3.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:86029fd802c5650f2cbef3f9302608325a676d3a883d6a5782bc855e5d03918b"}, + {file = "pendulum-3.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:dfbcd7a2a5ebabf5abaf07062555cd7bef9a472a6aa5281a6302afe66a481561"}, + {file = "pendulum-3.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:38a300df5a82ebea8634a1aed3d98c92968ba856d2ca7ba2acf7228f0e0e99af"}, + {file = "pendulum-3.2.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:9585594d32faa71efa5a78f576f1ee4f79e9c5340d7c6f0cd6c5dfe725effaaa"}, + {file = "pendulum-3.2.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:26401e2de77c437e8f3b6160c08c6c5d45518d906f8f9b48fd7cb5aa0f4e2aff"}, + {file = "pendulum-3.2.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:637e65af042f383a2764a886aa28ccc6f853bf7a142df18e41c720542934c13b"}, + {file = "pendulum-3.2.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d6e46c28f4d067233c4a4c42748f4ffa641d9289c09e0e81488beb6d4b3fab51"}, + {file = "pendulum-3.2.0-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:71d46bcc86269f97bfd8c5f1475d55e717696a0a010b1871023605ca94624031"}, + {file = "pendulum-3.2.0-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:5cd956d4176afc7bfe8a91bf3f771b46ff8d326f6c5bf778eb5010eb742ebba6"}, + {file = "pendulum-3.2.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:39ef129d7b90aab49708645867abdd207b714ba7bff12dae549975b0aca09716"}, + {file = "pendulum-3.2.0-py3-none-any.whl", hash = "sha256:f3a9c18a89b4d9ef39c5fa6a78722aaff8d5be2597c129a3b16b9f40a561acf3"}, + {file = "pendulum-3.2.0.tar.gz", hash = "sha256:e80feda2d10fa3ff8b1526715f7d33dcb7e08494b3088f2c8a3ac92d4a4331ce"}, +] + +[package.dependencies] +python-dateutil = ">=2.6" +tzdata = ">=2020.1" + +[package.extras] +test = ["time-machine (>=2.6.0,<3.0.0) ; implementation_name != \"pypy\""] + +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +description = "Extensions to the standard Python datetime module" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +groups = ["main"] +files = [ + {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, + {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, +] + +[package.dependencies] +six = ">=1.5" + +[[package]] +name = "six" +version = "1.17.0" +description = "Python 2 and 3 compatibility utilities" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +groups = ["main"] +files = [ + {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, + {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, +] + +[[package]] +name = "tzdata" +version = "2026.1" +description = "Provider of IANA time zone data" +optional = false +python-versions = ">=2" +groups = ["main"] +files = [ + {file = "tzdata-2026.1-py2.py3-none-any.whl", hash = "sha256:4b1d2be7ac37ceafd7327b961aa3a54e467efbdb563a23655fbfe0d39cfc42a9"}, + {file = "tzdata-2026.1.tar.gz", hash = "sha256:67658a1903c75917309e753fdc349ac0efd8c27db7a0cb406a25be4840f87f98"}, +] + +[metadata] +lock-version = "2.1" +python-versions = "^3.12" +content-hash = "451f2889bc1f7c9f8fed82cde527a219b301428c0c2a879ed3068f0284bf2bc8" diff --git a/testdata/poetry/poetry.toml b/testdata/poetry/poetry.toml new file mode 100644 index 0000000..ab1033b --- /dev/null +++ b/testdata/poetry/poetry.toml @@ -0,0 +1,2 @@ +[virtualenvs] +in-project = true diff --git a/testdata/poetry/pyproject.toml b/testdata/poetry/pyproject.toml new file mode 100644 index 0000000..3ddd56f --- /dev/null +++ b/testdata/poetry/pyproject.toml @@ -0,0 +1,13 @@ +[tool.poetry] +name = "go-python-runner-testdata-poetry" +version = "0.1.0" +description = "go-python-runner poetry e2e test fixture" +authors = [] + +[tool.poetry.dependencies] +python = "^3.12" +pendulum = "^3.0" + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" diff --git a/testdata/poetry/script.py b/testdata/poetry/script.py new file mode 100644 index 0000000..151fffa --- /dev/null +++ b/testdata/poetry/script.py @@ -0,0 +1,4 @@ +import pendulum + +now = pendulum.now("Europe/Paris") +print(now.to_iso8601_string()) diff --git a/testdata/uv/pyproject.toml b/testdata/uv/pyproject.toml new file mode 100644 index 0000000..13f9846 --- /dev/null +++ b/testdata/uv/pyproject.toml @@ -0,0 +1,8 @@ +[project] +name = "go-python-runner-testdata-uv" +version = "0.1.0" +description = "go-python-runner uv e2e test fixture" +requires-python = ">=3.12" +dependencies = [ + "pendulum>=3.2.0", +] diff --git a/testdata/uv/script.py b/testdata/uv/script.py new file mode 100644 index 0000000..151fffa --- /dev/null +++ b/testdata/uv/script.py @@ -0,0 +1,4 @@ +import pendulum + +now = pendulum.now("Europe/Paris") +print(now.to_iso8601_string()) diff --git a/testdata/uv/uv.lock b/testdata/uv/uv.lock new file mode 100644 index 0000000..666b892 --- /dev/null +++ b/testdata/uv/uv.lock @@ -0,0 +1,87 @@ +version = 1 +revision = 3 +requires-python = ">=3.12" + +[[package]] +name = "pendulum" +version = "3.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "python-dateutil" }, + { name = "tzdata" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/cb/72/9a51afa0a822b09e286c4cb827ed7b00bc818dac7bd11a5f161e493a217d/pendulum-3.2.0.tar.gz", hash = "sha256:e80feda2d10fa3ff8b1526715f7d33dcb7e08494b3088f2c8a3ac92d4a4331ce", size = 86912, upload-time = "2026-01-30T11:22:24.093Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/41/56/dd0ea9f97d25a0763cda09e2217563b45714786118d8c68b0b745395d6eb/pendulum-3.2.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:bf0b489def51202a39a2a665dcc4162d5e46934a740fe4c4fe3068979610156c", size = 337830, upload-time = "2026-01-30T11:21:08.298Z" }, + { url = "https://files.pythonhosted.org/packages/cf/98/83d62899bf7226fc12396de4bc1fb2b5da27e451c7c60790043aaf8b4731/pendulum-3.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:937a529aa302efa18dcf25e53834964a87ffb2df8f80e3669ab7757a6126beaf", size = 327574, upload-time = "2026-01-30T11:21:09.715Z" }, + { url = "https://files.pythonhosted.org/packages/76/fa/ff2aa992b23f0543c709b1a3f3f9ed760ec71fd02c8bb01f93bf008b52e4/pendulum-3.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85c7689defc65c4dc29bf257f7cca55d210fabb455de9476e1748d2ab2ae80d7", size = 339891, upload-time = "2026-01-30T11:21:11.089Z" }, + { url = "https://files.pythonhosted.org/packages/c5/4e/25b4fa11d19503d50d7b52d7ef943c0f20fd54422aaeb9e38f588c815c50/pendulum-3.2.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d5e216e5a412563ea2ecf5de467dcf3d02717947fcdabe6811d5ee360726b02b", size = 373726, upload-time = "2026-01-30T11:21:12.493Z" }, + { url = "https://files.pythonhosted.org/packages/4f/30/0acad6396c4e74e5c689aa4f0b0c49e2ecdcfce368e7b5bf35ca1c0fc61a/pendulum-3.2.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3a2af22eeec438fbaac72bb7fba783e0950a514fba980d9a32db394b51afccec", size = 379827, upload-time = "2026-01-30T11:21:14.08Z" }, + { url = "https://files.pythonhosted.org/packages/3a/f7/e6a2fdf2a23d59b4b48b8fa89e8d4bf2dd371aea2c6ba8fcecec20a4acb9/pendulum-3.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3159cceb54f5aa8b85b141c7f0ce3fac8bdd1ffdc7c79e67dca9133eac7c4d11", size = 348921, upload-time = "2026-01-30T11:21:15.816Z" }, + { url = "https://files.pythonhosted.org/packages/7f/f2/c15fa7f9ad4e181aa469b6040b574988bd108ccdf4ae509ad224f9e4db44/pendulum-3.2.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c39ea5e9ffa20ea8bae986d00e0908bd537c8468b71d6b6503ab0b4c3d76e0ea", size = 517188, upload-time = "2026-01-30T11:21:17.835Z" }, + { url = "https://files.pythonhosted.org/packages/47/c7/5f80b12ee88ec26e930c3a5a602608a63c29cf60c81a0eb066d583772550/pendulum-3.2.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e5afc753e570cce1f44197676371f68953f7d4f022303d141bb09f804d5fe6d7", size = 561833, upload-time = "2026-01-30T11:21:19.232Z" }, + { url = "https://files.pythonhosted.org/packages/90/15/1ac481626cb63db751f6281e294661947c1f0321ebe5d1c532a3b51a8006/pendulum-3.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:fd55c12560816d9122ca2142d9e428f32c0c083bf77719320b1767539c7a3a3b", size = 258725, upload-time = "2026-01-30T11:21:20.558Z" }, + { url = "https://files.pythonhosted.org/packages/40/ae/50b0398d7d027eb70a3e1e336de7b6e599c6b74431cb7d3863287e1292bb/pendulum-3.2.0-cp312-cp312-win_arm64.whl", hash = "sha256:faef52a7ed99729f0838353b956f3fabf6c550c062db247e9e2fc2b48fcb9457", size = 253089, upload-time = "2026-01-30T11:21:22.497Z" }, + { url = "https://files.pythonhosted.org/packages/27/8c/400c8b8dbd7524424f3d9902ded64741e82e5e321d1aabbd68ade89e71cf/pendulum-3.2.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:addb0512f919fe5b70c8ee534ee71c775630d3efe567ea5763d92acff857cfc3", size = 337820, upload-time = "2026-01-30T11:21:24.305Z" }, + { url = "https://files.pythonhosted.org/packages/59/38/7c16f26cc55d9206d71da294ce6857d0da381e26bc9e0c2a069424c2b173/pendulum-3.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3aaa50342dc174acebdc21089315012e63789353957b39ac83cac9f9fc8d1075", size = 327551, upload-time = "2026-01-30T11:21:25.747Z" }, + { url = "https://files.pythonhosted.org/packages/0b/cd/f36ec5d56d55104232380fdbf84ff53cc05607574af3cbdc8a43991ac8a7/pendulum-3.2.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:927e9c9ab52ff68e71b76dd410e5f1cd78f5ea6e7f0a9f5eb549aea16a4d5354", size = 339894, upload-time = "2026-01-30T11:21:27.229Z" }, + { url = "https://files.pythonhosted.org/packages/aa/4e/b9a1e546519c3a92d5bc17787cea925e06a20def2ae344fa136d2fc40338/pendulum-3.2.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:249d18f5543c9f43aba3bd77b34864ec8cf6f64edbead405f442e23c94fce63d", size = 373766, upload-time = "2026-01-30T11:21:28.642Z" }, + { url = "https://files.pythonhosted.org/packages/ea/a6/6471ab87ae2260594501f071586a765fc894817043b7d2d4b04e2eff4f31/pendulum-3.2.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c644cc15eec5fb02291f0f193195156780fd5a0affd7a349592403826d1a35e", size = 379837, upload-time = "2026-01-30T11:21:30.637Z" }, + { url = "https://files.pythonhosted.org/packages/0d/79/0ba0c14e862388f7b822626e6e989163c23bebe7f96de5ec4b207cbe7c3d/pendulum-3.2.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:063ab61af953bb56ad5bc8e131fd0431c915ed766d90ccecd7549c8090b51004", size = 348904, upload-time = "2026-01-30T11:21:32.436Z" }, + { url = "https://files.pythonhosted.org/packages/17/34/df922c7c0b12719589d4954bfa5bdca9e02bcde220f5c5c1838a87118960/pendulum-3.2.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:26a3ae26c9dd70a4256f1c2f51addc43641813574c0db6ce5664f9861cd93621", size = 517173, upload-time = "2026-01-30T11:21:34.428Z" }, + { url = "https://files.pythonhosted.org/packages/87/ec/3b9e061eeee97b72a47c1434ee03f6d85f0284d9285d92b12b0fff2d19ac/pendulum-3.2.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:2b10d91dc00f424444a42f47c69e6b3bfd79376f330179dc06bc342184b35f9a", size = 561744, upload-time = "2026-01-30T11:21:35.861Z" }, + { url = "https://files.pythonhosted.org/packages/fd/7e/f12fdb6070b7975c1fcfa5685dbe4ab73c788878a71f4d1d7e3c87979e37/pendulum-3.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:63070ff03e30a57b16c8e793ee27da8dac4123c1d6e0cf74c460ce9ee8a64aa4", size = 258746, upload-time = "2026-01-30T11:21:37.782Z" }, + { url = "https://files.pythonhosted.org/packages/c9/b8/5abd872056357f069ae34a9b24a75ac58e79092d16201d779a8dd31386bb/pendulum-3.2.0-cp313-cp313-win_arm64.whl", hash = "sha256:c8dde63e2796b62070a49ce813ce200aba9186130307f04ec78affcf6c2e8122", size = 253028, upload-time = "2026-01-30T11:21:39.381Z" }, + { url = "https://files.pythonhosted.org/packages/82/99/5b9cc823862450910bcb2c7cdc6884c0939b268639146d30e4a4f55eb1f1/pendulum-3.2.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:c17ac069e88c5a1e930a5ae0ef17357a14b9cc5a28abadda74eaa8106d241c8e", size = 338281, upload-time = "2026-01-30T11:21:40.812Z" }, + { url = "https://files.pythonhosted.org/packages/cd/3a/64a35260f6ac36c0ad50eeb5f1a465b98b0d7603f79a5c2077c41326d639/pendulum-3.2.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:e1fbb540edecb21f8244aebfb05a1f2333ddc6c7819378c099d4a61cc91ae93c", size = 328030, upload-time = "2026-01-30T11:21:42.778Z" }, + { url = "https://files.pythonhosted.org/packages/da/6b/1140e09310035a2afb05bb90a2b8fbda9d3222e03b92de9533123afe6b65/pendulum-3.2.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a8c67fb9a1fe8fc1adae2cc01b0c292b268c12475b4609ff4aed71c9dd367b4d", size = 340206, upload-time = "2026-01-30T11:21:44.148Z" }, + { url = "https://files.pythonhosted.org/packages/52/4a/a493de56cbc24a64b21ac6ba98513a9ec5c67daa3dba325e39a8e53f30d8/pendulum-3.2.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:baa9a66c980defda6cfe1275103a94b22e90d83ebd7a84cc961cee6cbd25a244", size = 373976, upload-time = "2026-01-30T11:21:45.56Z" }, + { url = "https://files.pythonhosted.org/packages/3c/4c/f083c4fd1a161d4ab218680cc906338c541497b3098373f2241f58c429cb/pendulum-3.2.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ef8f783fa7a14973b0596d8af2a5b2d90858a55030e9b4c6885eb4284b88314f", size = 380075, upload-time = "2026-01-30T11:21:46.959Z" }, + { url = "https://files.pythonhosted.org/packages/57/b6/333a0fcb33bf15eb879a46a11ce6300c1698a141e689665fe430783ff8d6/pendulum-3.2.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a7d2e9bfb065727d8676e7ada3793b47a24349500a5e9637404355e482c822be", size = 349026, upload-time = "2026-01-30T11:21:48.271Z" }, + { url = "https://files.pythonhosted.org/packages/43/1a/dfb526ec0cba1e7cd6a5e4f4dd64a6ada7428d1449c54b15f7b295f6e122/pendulum-3.2.0-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:55d7ba6bb74171c3ee409bf30076ee3a259a3c2bb147ac87ebb76aaa3cf5d3a2", size = 517395, upload-time = "2026-01-30T11:21:49.643Z" }, + { url = "https://files.pythonhosted.org/packages/c9/37/b4f2b5f1200351c4869b8b46ad5c21019e3dbe0417f5867ae969fad7b5fe/pendulum-3.2.0-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:a50d8cf42f06d3d8c3f8bb2a7ac47fa93b5145e69de6a7209be6a47afdd9cf76", size = 561926, upload-time = "2026-01-30T11:21:51.698Z" }, + { url = "https://files.pythonhosted.org/packages/a0/9e/567376582da58f5fe8e4f579db2bcfbf243cf619a5825bdf1023ad1436b3/pendulum-3.2.0-cp314-cp314-win_amd64.whl", hash = "sha256:e5bbb92b155cd5018b3cf70ee49ed3b9c94398caaaa7ed97fe41e5bb5a968418", size = 258817, upload-time = "2026-01-30T11:21:53.074Z" }, + { url = "https://files.pythonhosted.org/packages/95/67/dfffd7eb50d67fa821cd4d92cf71575ead6162930202bc40dfcedf78c38c/pendulum-3.2.0-cp314-cp314-win_arm64.whl", hash = "sha256:d53134418e04335c3029a32e9341cccc9b085a28744fb5ee4e6a8f5039363b1a", size = 253292, upload-time = "2026-01-30T11:21:54.484Z" }, + { url = "https://files.pythonhosted.org/packages/02/fb/d65db067a67df7252f18b0cb7420dda84078b9e8bfb375215469c14a50be/pendulum-3.2.0-py3-none-any.whl", hash = "sha256:f3a9c18a89b4d9ef39c5fa6a78722aaff8d5be2597c129a3b16b9f40a561acf3", size = 114111, upload-time = "2026-01-30T11:22:22.361Z" }, +] + +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, +] + +[[package]] +name = "six" +version = "1.17.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, +] + +[[package]] +name = "tzdata" +version = "2026.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/19/f5/cd531b2d15a671a40c0f66cf06bc3570a12cd56eef98960068ebbad1bf5a/tzdata-2026.1.tar.gz", hash = "sha256:67658a1903c75917309e753fdc349ac0efd8c27db7a0cb406a25be4840f87f98", size = 197639, upload-time = "2026-04-03T11:25:22.002Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b0/70/d460bd685a170790ec89317e9bd33047988e4bce507b831f5db771e142de/tzdata-2026.1-py2.py3-none-any.whl", hash = "sha256:4b1d2be7ac37ceafd7327b961aa3a54e467efbdb563a23655fbfe0d39cfc42a9", size = 348952, upload-time = "2026-04-03T11:25:20.313Z" }, +] + +[[package]] +name = "uv-test" +version = "0.1.0" +source = { virtual = "." } +dependencies = [ + { name = "pendulum" }, +] + +[package.metadata] +requires-dist = [{ name = "pendulum", specifier = ">=3.2.0" }] From cb22673a348dc6f8baa196921ee9a9db77b39d4c Mon Sep 17 00:00:00 2001 From: Zois Pagoulatos Date: Mon, 6 Apr 2026 23:18:16 +0200 Subject: [PATCH 6/7] ci: update all GitHub Actions to latest versions - actions/checkout: v2/v4 -> v6 - actions/setup-go: v5 -> v6 - actions/setup-python: v5 -> v6 - astral-sh/setup-uv: v5 -> v8 - github/codeql-action/*: v1 -> v4 - Remove stale PR checkout workaround from codeql-analysis.yml --- .github/workflows/codeql-analysis.yml | 57 +++++---------------------- .github/workflows/test.yml | 8 ++-- 2 files changed, 14 insertions(+), 51 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index ef5f3d1..cb318b7 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -1,15 +1,9 @@ -# For most projects, this workflow file will not need changing; you simply need -# to commit it to your repository. -# -# You may wish to alter this file to override the set of languages analyzed, -# or to provide custom queries or build logic. name: "CodeQL" on: push: branches: [master] pull_request: - # The branches below must be a subset of the branches above branches: [master] schedule: - cron: '0 1 * * 4' @@ -23,50 +17,19 @@ jobs: strategy: fail-fast: false matrix: - # Override automatic language detection by changing the below list - # Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python'] language: ['go'] - # Learn more... - # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection steps: - - name: Checkout repository - uses: actions/checkout@v2 - with: - # We must fetch at least the immediate parents so that if this is - # a pull request then we can checkout the head. - fetch-depth: 2 + - name: Checkout repository + uses: actions/checkout@v6 - # If this run was triggered by a pull request event, then checkout - # the head of the pull request instead of the merge commit. - - run: git checkout HEAD^2 - if: ${{ github.event_name == 'pull_request' }} + - name: Initialize CodeQL + uses: github/codeql-action/init@v4 + with: + languages: ${{ matrix.language }} - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v1 - with: - languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - # queries: ./path/to/local/query, your-org/your-repo/queries@main + - name: Autobuild + uses: github/codeql-action/autobuild@v4 - # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v1 - - # ℹ️ Command-line programs to run using the OS shell. - # 📚 https://git.io/JvXDl - - # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines - # and modify them (or add more) to build your code if your project - # uses a compiled language - - #- run: | - # make bootstrap - # make release - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v4 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c0e40e7..6f7b62e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -17,22 +17,22 @@ jobs: pm: [uv, poetry, pipenv, pip] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Set up Go - uses: actions/setup-go@v5 + uses: actions/setup-go@v6 with: go-version-file: go.mod cache: true - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: "3.13" - name: Install uv if: matrix.pm == 'uv' - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@v8 - name: Install Poetry if: matrix.pm == 'poetry' From 679a844180470cd04c057d491bc3cf9f9ffb1da4 Mon Sep 17 00:00:00 2001 From: Zois Pagoulatos Date: Mon, 6 Apr 2026 23:20:19 +0200 Subject: [PATCH 7/7] ci: fix setup-uv version to v8.0.0 (no floating v8 tag yet) --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6f7b62e..eb83c60 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -32,7 +32,7 @@ jobs: - name: Install uv if: matrix.pm == 'uv' - uses: astral-sh/setup-uv@v8 + uses: astral-sh/setup-uv@v8.0.0 - name: Install Poetry if: matrix.pm == 'poetry'