Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
36 changes: 20 additions & 16 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,27 +51,29 @@ jobs:
- name: Install uv and Python
uses: astral-sh/setup-uv@v5
with:
python-version: "3.9"
# Match the Python the with-connect Connect image provides (3.14):
# rsconnect records the client Python in the deploy manifest and
# Connect must have a matching Local environment to build the
# content. 3.14 also satisfies the with-connect tool's own
# requires-python (>=3.13), so no separate UV_PYTHON override.
python-version: "3.14"
- name: Install dependencies
run: |
uv pip install --upgrade pip
uv pip install ".[dev]"
uv pip install --upgrade git+https://github.com/rstudio/vetiver-python@${{ github.sha }}
echo {{ github.sha }}
- name: run Connect
run: |
docker compose up --build -d
pip freeze > requirements.txt
make dev
cat requirements.txt
env:
RSC_LICENSE: ${{ secrets.RSC_LICENSE }}
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}

# NOTE: edited to run checks for python package
- name: Run tests
run: |
pytest vetiver -m 'rsc_test'
- name: Run Connect integration tests
uses: posit-dev/with-connect@0783dabdd24e360e985a4588ce1239c3dc31c542
with:
license: ${{ secrets.RSC_LICENSE }}
# Plain freeze (unlike the Makefile/weekly jobs, which filter): here
# vetiver is installed from git+...@<sha>, so the freeze yields an
# installable git URL and Connect deploys THIS PR's vetiver. Filtering
# would deploy released vetiver and miss PR-level serving regressions.
command: |
pip freeze > requirements.txt
pytest vetiver/tests/test_rsconnect.py -m 'rsc_test'

test-docker:
name: "Test Docker"
Expand Down Expand Up @@ -129,7 +131,9 @@ jobs:
run: |
python -m pip install --upgrade pip
python -m pip install -e .[dev]
python -m pip install 'pydantic<2.0.0'
# FastAPI >=0.116 unconditionally imports `IncEx` from pydantic v2,
# so pin to the last release that still supports pydantic v1.
python -m pip install 'pydantic<2.0.0' 'fastapi<0.116'

- name: Run tests
run: |
Expand Down
84 changes: 43 additions & 41 deletions .github/workflows/weekly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,6 @@ jobs:
python -m pip install '.[all]'
python -m pip install --upgrade git+https://github.com/rstudio/pins-python

- name: run Connect
run: |
docker compose up --build -d
make dev
env:
RSC_LICENSE: ${{ secrets.RSC_LICENSE }}
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}

- name: Run tests
run: |
make test
Expand Down Expand Up @@ -84,14 +76,6 @@ jobs:
python -m pip install .[dev]
python -m pip install --upgrade git+https://github.com/rstudio/pins-python

- name: run Connect
run: |
docker compose up --build -d
make dev
env:
RSC_LICENSE: ${{ secrets.RSC_LICENSE }}
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}

- name: Run Tests
run: |
make test
Expand All @@ -103,7 +87,7 @@ jobs:
strategy:
matrix:
# Minimum and Maximum supported versions
python-version: ['3.9']
python-version: ['3.14']

steps:
- name: Get latest release with tag from GitHub API
Expand All @@ -129,19 +113,28 @@ jobs:
python -m pip install --upgrade pip
python -m pip install .[dev]
python -m pip install --upgrade git+https://github.com/rstudio/rsconnect-python
pip freeze > requirements.txt

- name: run Connect
run: |
docker compose up --build -d
make dev
env:
RSC_LICENSE: ${{ secrets.RSC_LICENSE }}
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}

- name: Run Tests
run: |
pytest -m 'rsc_test'
- name: Run Connect integration tests
uses: posit-dev/with-connect@0783dabdd24e360e985a4588ce1239c3dc31c542
with:
license: ${{ secrets.RSC_LICENSE }}
command: |
pip freeze | grep -v '^vetiver' | grep -v '^-e ' > requirements.txt
echo 'vetiver' >> requirements.txt
pytest vetiver/tests/test_rsconnect.py -m 'rsc_test'

- name: Open issue on failure
if: failure() && github.event_name == 'schedule'
uses: actions/github-script@v7
with:
script: |
github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: `Weekly canary failed: ${context.job}`,
body: `The weekly Connect canary failed on run ${context.runId}. This often means a change in rsconnect-python \`main\` broke vetiver. See https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`,
labels: ["ci-failure"]
})

vetiver_latest_rsconnect_latest:
name: 'vetiver latest, rsconnect latest'
Expand All @@ -164,16 +157,25 @@ jobs:
python -m pip install --upgrade pip
python -m pip install '.[all]'
python -m pip install --upgrade git+https://github.com/rstudio/rsconnect-python
pip freeze > requirements.txt

- name: run Connect
run: |
docker compose up --build -d
make dev
env:
RSC_LICENSE: ${{ secrets.RSC_LICENSE }}
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}

- name: Run Tests
run: |
pytest -m 'rsc_test'
- name: Run Connect integration tests
uses: posit-dev/with-connect@0783dabdd24e360e985a4588ce1239c3dc31c542
with:
license: ${{ secrets.RSC_LICENSE }}
command: |
pip freeze | grep -v '^vetiver' | grep -v '^-e ' > requirements.txt
echo 'vetiver' >> requirements.txt
pytest vetiver/tests/test_rsconnect.py -m 'rsc_test'

- name: Open issue on failure
if: failure() && github.event_name == 'schedule'
uses: actions/github-script@v7
with:
script: |
github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: `Weekly canary failed: ${context.job}`,
body: `The weekly Connect canary failed on run ${context.runId}. This often means a change in rsconnect-python \`main\` broke vetiver. See https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`,
labels: ["ci-failure"]
})
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -149,3 +149,6 @@ NOTES.md
/.quarto/

/.luarc.json

# Local Connect license for with-connect integration tests
rstudio-connect.lic
25 changes: 4 additions & 21 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
.PHONY: clean-pyc clean-build clean docs
UNAME := $(shell uname)

RSC_API_KEYS=vetiver/tests/rsconnect_api_keys.json

ifeq ($(UNAME), Darwin)
BROWSER := open
else
Expand All @@ -19,9 +17,6 @@ help:
@echo "coverage - check code coverage quickly with the default Python"
@echo "docs - generate HTML documentation, including API docs"
@echo "release - package and upload a release"
@echo "dev - generate Connect API keys"
@echo "dev-start - start up development Connect in Docker"
@echo "dev-stop - stop Connect dev container"

clean: clean-build clean-pyc clean-test

Expand All @@ -47,7 +42,10 @@ test-pdb: clean-test
pytest -m 'not rsc_test and not docker' --pdb

test-rsc: clean-test
pytest
uv run pip freeze | grep -v '^vetiver' | grep -v '^-e ' > requirements.txt
echo 'vetiver' >> requirements.txt
uvx --from git+https://github.com/posit-dev/with-connect@0783dabdd24e360e985a4588ce1239c3dc31c542 \
with-connect -- uv run --with pytest pytest vetiver/tests/test_rsconnect.py -m 'rsc_test'

coverage:
coverage report -m
Expand All @@ -60,21 +58,6 @@ docs doc documentation:
release: dist
twine upload dist/*

dev: vetiver/tests/rsconnect_api_keys.json

dev-start:
docker compose up -d
docker compose exec -T rsconnect bash < script/setup-rsconnect/add-users.sh
# curl fails with error 52 without a short sleep....
sleep 5
curl -s --retry 10 --retry-connrefused http://localhost:3939

dev-stop:
docker compose down
rm -f $(RSC_API_KEYS)

typecheck:
pyright

$(RSC_API_KEYS): dev-start
python script/setup-rsconnect/dump_api_keys.py $@
15 changes: 0 additions & 15 deletions docker-compose.yml

This file was deleted.

3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ dev = [
]
docs = [
"quartodoc",
# quartodoc 0.11.x is incompatible with the griffe 2.x rewrite
# (it imports griffe.loader / passes removed parse_numpy kwargs).
"griffe<2",
# quarto render dependencies
"jupyter"
]
Expand Down
1 change: 0 additions & 1 deletion script/setup-rsconnect/add-users.sh

This file was deleted.

21 changes: 0 additions & 21 deletions script/setup-rsconnect/dump_api_keys.py

This file was deleted.

22 changes: 0 additions & 22 deletions script/setup-rsconnect/rstudio-connect.gcfg

This file was deleted.

4 changes: 0 additions & 4 deletions script/setup-rsconnect/users.txt

This file was deleted.

7 changes: 4 additions & 3 deletions vetiver/data/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@ def __dir__():

def _load_data_csv(name):
import pandas as pd
import pkg_resources
from importlib.resources import files

fname = pkg_resources.resource_filename("vetiver.data", f"{name}.csv")
return pd.read_csv(fname)
fname = files("vetiver.data").joinpath(f"{name}.csv")
with fname.open("rb") as f:
return pd.read_csv(f)


def __getattr__(name):
Expand Down
3 changes: 1 addition & 2 deletions vetiver/monitor.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import plotly.express as px
import pandas as pd
import numpy as np
from datetime import timedelta


Expand Down Expand Up @@ -55,7 +54,7 @@ def compute_metrics(

df = data[[truth, estimate, date_var]].copy()

if not np.issubdtype(df[date_var], np.datetime64):
if not pd.api.types.is_datetime64_any_dtype(df[date_var]):
df[date_var] = pd.to_datetime(df[date_var])

df = df.set_index(date_var).sort_index()
Expand Down
3 changes: 2 additions & 1 deletion vetiver/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -394,8 +394,9 @@ def predict(endpoint, data: Union[dict, pd.DataFrame, pd.Series], **kw) -> pd.Da
# TO DO: dispatch

if isinstance(data, pd.DataFrame):
headers = {"Content-Type": "application/json", **kw.pop("headers", {})}
response = requester.post(
endpoint, data=data.to_json(orient="records"), **kw
endpoint, data=data.to_json(orient="records"), headers=headers, **kw
) # TO DO: httpx deprecating data in favor of content for TestClient
elif isinstance(data, pd.Series):
response = requester.post(endpoint, json=[data.to_dict()], **kw)
Expand Down
1 change: 0 additions & 1 deletion vetiver/tests/rsconnect_api_keys.json

This file was deleted.

2 changes: 1 addition & 1 deletion vetiver/tests/test_monitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

import pytest

rng = pd.date_range("1/1/2012", periods=10, freq="S")
rng = pd.date_range("1/1/2012", periods=10, freq="s")
new = dict(x=range(len(rng)), y=range(len(rng)))
df = pd.DataFrame(new, index=rng)
td = timedelta(seconds=2)
Expand Down
13 changes: 11 additions & 2 deletions vetiver/tests/test_prepare_docker.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,17 @@ def create_vetiver_model():
return vetiver.VetiverModel(model.fit(X, y), "model", prototype_data=X)


@pytest.fixture(scope="module")
@pytest.fixture(autouse=True)
def _restore_fs_protocol():
# board.fs is a cached fsspec LocalFileSystem singleton; the tests below
# mutate its `protocol` to simulate cloud backends. Restore it afterwards
# so the mutation does not leak into other tests (e.g. test_write_app).
fs = pins.board_temp(allow_pickle_read=True).fs
original = fs.protocol
yield
fs.protocol = original


def test_warning_if_no_protocol(create_vetiver_model):
with pytest.warns(UserWarning):
board = pins.board_temp(allow_pickle_read=True)
Expand All @@ -49,7 +59,6 @@ def test_warning_if_no_protocol(create_vetiver_model):
(("gcs", "gs"), "gcsfs"),
],
)
@pytest.fixture(scope="module")
def test_get_board_pkgs(prot, output, create_vetiver_model):
board = pins.board_temp(allow_pickle_read=True)
board.fs.protocol = prot
Expand Down
Loading
Loading