Skip to content

Commit

Permalink
ci: setup build/publish with uv (#573)
Browse files Browse the repository at this point in the history
* ci: setup build/publish with uv

* chore: move complicated script into package.json

* Update pyproject.toml

Co-authored-by: Trevor Manz <[email protected]>

* chore: update dev specification

* ci: use workspace for uv and clean up gitignores

* chore: combine ruff config

---------

Co-authored-by: Trevor Manz <[email protected]>
  • Loading branch information
domoritz and manzt authored Oct 31, 2024
1 parent 4d25a98 commit c711428
Show file tree
Hide file tree
Showing 18 changed files with 2,160 additions and 96 deletions.
30 changes: 14 additions & 16 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,29 +41,27 @@ jobs:
steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
- uses: astral-sh/setup-uv@v3
with:
python-version-file: ".python-version"
cache: "pip"
cache-dependency-path: "**/pyproject.toml"
version: ">=0.4.0"
enable-cache: true
cache-dependency-glob: "**/pyproject.toml"

- name: Install dependencies
- name: Format and lint
run: |
python -m pip install --upgrade pip
pip install hatch
uv run ruff check
uv run ruff format --check
- name: Build and lint Widget
run: |
cd packages/widget
hatch build
hatch fmt --check
- name: Build widget
run: uv build --package duckdb-server

- name: Build, lint, and test Server
- name: Build and test server
run: |
cd packages/duckdb-server
hatch build
hatch fmt --check
hatch run test:cov
uv build
uv run mypy
uv run --with pytest-cov pytest --cov-report=term-missing --color=yes --cov=pkg
rust:
name: Test in Rust
Expand Down
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,9 @@ docs/.vitepress/dist
node_modules
packages/*/dist
packages/*/test-output
**/__pycache__
**/.ruff_cache
**/.pytest_cache
**/.mypy_cache
**/.coverage
**/.venv
2 changes: 1 addition & 1 deletion .python-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.11
3.12
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ To run local interactive examples:

To launch a local DuckDB server:

* Install [hatch](https://hatch.pypa.io/latest/install/), if not already present.
* Install [uv](https://docs.astral.sh/uv/), if not already present.
* Run `npm run server` to launch the [`duckdb-server`](https://github.com/uwdata/mosaic/tree/main/packages/duckdb-server). This runs the server in development mode, so the server will restart if you change its code.

To use Mosaic with DuckDB Python in Jupyter Notebooks:
Expand Down
2 changes: 1 addition & 1 deletion dev/notebooks/weather.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.8"
"version": "3.11.10"
}
},
"nbformat": 4,
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"build": "lerna run build",
"lint": "lerna run lint",
"test": "lerna run test",
"server": "cd packages/duckdb-server && hatch run serve",
"server": "cd packages/duckdb-server && npm run dev",
"server:rust": "cd packages/duckdb-server-rust && cargo run",
"server:node": "nodemon packages/duckdb/bin/run-server.js",
"dev": "vite",
Expand Down
6 changes: 0 additions & 6 deletions packages/duckdb-server/.gitignore

This file was deleted.

16 changes: 10 additions & 6 deletions packages/duckdb-server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,25 @@ _Note:_ This package provides a local DuckDB server. To instead use DuckDB-WASM

## Installation and usage

We recommend running the server in an isolated environment with [pipx](https://github.com/pypa/pipx). For example, to directly run the server, use:
We recommend running the server in an isolated environment with [uvx](https://docs.astral.sh/uv/). For example, to directly run the server, use:

```bash
pipx run duckdb-server
uvx duckdb-server
```

Alternatively, you can install the server with `pip install duckdb-server`. Then you can start the server with `duckdb-server`.

## Developer Setup

We use [hatch](https://hatch.pypa.io/latest/) to manage our development setup.
We use [uv](https://docs.astral.sh/uv/) to manage our development setup.

Start the server in development with `hatch run serve`. The server restarts when you change the code.
Start the server with `uv run duckdb-server`. The server will not restart when the code changes.

To run the tests, use `hatch run test:cov`.
Start the server in development with `npm run dev`. The server restarts when you change the code.

Run `uv run ruff check --fix` and `uv run ruff format` to lint the code.

To run the tests, use `uv run pytest`.

To set up a local certificate for SSL, use https://github.com/FiloSottile/mkcert.

Expand Down Expand Up @@ -54,4 +58,4 @@ Loads the bundled results.

## Publishing

Run the build with `hatch build`. Then publish with `hatch publish`. We publish using tokens so when asked, set the username to `__token__` and then use your token as the password. Alternatively, create a [`.pypirc` file](https://packaging.python.org/en/latest/guides/distributing-packages-using-setuptools/#create-an-account).
Run the build with `uv build`. Then publish with `uvx twine upload --skip-existing dist/*`. We publish using tokens so when asked, set the username to `__token__` and then use your token as the password. Alternatively, create a [`.pypirc` file](https://packaging.python.org/en/latest/guides/distributing-packages-using-setuptools/#create-an-account).
8 changes: 5 additions & 3 deletions packages/duckdb-server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
"version": "0.11.0",
"private": true,
"scripts": {
"prepublishOnly": "rimraf dist && mkdir dist && hatch run test:cov && hatch fmt --check && hatch build",
"publish": "hatch publish --user __token__",
"release": "npm run prepublishOnly && npm run publish"
"prepublishOnly": "uv run pytest && uv run ruff check && uv run ruff format --check",
"publish": "uv build && uvx twine upload --skip-existing dist/*",
"release": "npm run prepublishOnly && npm run publish",
"dev": "uv run watchmedo auto-restart --pattern '*.py' --recursive --signal SIGTERM uv run duckdb-server",
"clean": "rimraf dist"
}
}
8 changes: 6 additions & 2 deletions packages/duckdb-server/pkg/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,9 @@ def handle_query(handler: Handler, con, cache, query):
json = retrieve(cache, query, partial(get_json, con))
handler.json(json)
elif command == "create-bundle":
create_bundle(con, cache, query.get("queries"), BUNDLE_DIR / query.get("name"))
create_bundle(
con, cache, query.get("queries"), BUNDLE_DIR / query.get("name")
)
handler.done()
elif command == "load-bundle":
load_bundle(con, cache, BUNDLE_DIR / query.get("name"))
Expand Down Expand Up @@ -164,7 +166,9 @@ async def http_handler(res, req):
{
"compression": CompressOptions.SHARED_COMPRESSOR,
"message": ws_message,
"drain": lambda ws: logger.warning(f"WebSocket backpressure: {ws.get_buffered_amount()}"),
"drain": lambda ws: logger.warning(
f"WebSocket backpressure: {ws.get_buffered_amount()}"
),
},
)

Expand Down
5 changes: 4 additions & 1 deletion packages/duckdb-server/pkg/tests/test_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@


def test_key():
assert get_key("SELECT 1", "arrow") == "e004ebd5b5532a4b85984a62f8ad48a81aa3460c1ca07701f386135d72cdecf5.arrow"
assert (
get_key("SELECT 1", "arrow")
== "e004ebd5b5532a4b85984a62f8ad48a81aa3460c1ca07701f386135d72cdecf5.arrow"
)


def test_query_json():
Expand Down
44 changes: 16 additions & 28 deletions packages/duckdb-server/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "duckdb-server"
description = "A DuckDB server for Mosaic"
dynamic = ["version"]
readme = "README.md"
requires-python = ">=3.9"
requires-python = ">=3.10"
dependencies = [
"diskcache",
"duckdb==1.1.1",
Expand All @@ -23,36 +19,28 @@ duckdb-server = "pkg.__main__:serve"
[project.urls]
homepage = "https://github.com/uwdata/mosaic"

[project.optional-dependencies]
dev = [
"watchdog[watchmedo]"
]

[tool.hatch.envs.default]
python = "3.11"
features = ["dev"]
installer = "uv"

[tool.hatch.envs.default.scripts]
serve = "watchmedo auto-restart --pattern '*.py' --recursive --signal SIGTERM python pkg/__main__.py"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.hatch.envs.test]
installer = "uv"
dependencies = [
"coverage[toml]",
"pytest",
"pytest-cov",
[dependency-groups]
dev = [
"watchdog",
"mypy>=1.11.1",
"pytest>=7.4.4",
"ruff>=0.6.1",
"types-ujson",
]

[tool.hatch.envs.test.scripts]
cov = 'pytest --cov-report=term-missing --cov-config=pyproject.toml --cov=pkg'

[tool.hatch.build.targets.wheel]
packages = ["pkg"]

[tool.hatch.version]
path = "package.json"
pattern = "\"version\": \"(?P<version>.+?)\""

[tool.ruff]
lint.ignore = ["G004", "TRY301", "EM102", "EM101", "TRY003", "FBT002", "S608", "TRY002", "ARG001"]
# https://mypy.readthedocs.io/en/stable/config_file.html
[tool.mypy]
files = "pkg/**/*.py"
strict = false
ignore_missing_imports = true
3 changes: 0 additions & 3 deletions packages/widget/.gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1 @@
dist
__pycache__
.ruff_cache
mosaic_widget/static
12 changes: 5 additions & 7 deletions packages/widget/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,14 @@ Learn how to install and use the widget in the [Mosaic documentation](https://uw

## Developer Setup

We use [hatch](https://hatch.pypa.io/latest/) to manage our development setup.
We use [uv](https://docs.astral.sh/uv/) to manage our development setup.

To activate the environment, run `hatch shell`.

This should install the widget in development mode so you can start Jupyter.

You can start Jupyter with `ANYWIDGET_HMR=1 jupyter lab --notebook-dir=../../dev/notebooks`. If you cannot import the widget module, make sure that your Jupyter uses the right environment. You can add your environment to Jupyter by running `python -m ipykernel install --user --name=mosaic` and then select `mosaic` in the Jupyter environment dropdown.
You can start Jupyter with `ANYWIDGET_HMR=1 uv run jupyter lab --notebook-dir=../../dev/notebooks`.

Run `npm run build` to build the widget JavaScript code. If you want to live edit the widget code, run `npm run dev` in a separate terminal.

Run `uv run ruff check --fix` and `uv run ruff format` to lint the code.

## Publishing

Run the build with `npm run build` and `hatch build`. Then publish with `hatch publish`. We publish using tokens so when asked, set the username to `__token__` and then use your token as the password. Alternatively, create a [`.pypirc` file](https://packaging.python.org/en/latest/guides/distributing-packages-using-setuptools/#create-an-account).
Run the build with `uv build`. Then publish with `uvx twine upload --skip-existing dist/*`. We publish using tokens so when asked, set the username to `__token__` and then use your token as the password. Alternatively, create a [`.pypirc` file](https://packaging.python.org/en/latest/guides/distributing-packages-using-setuptools/#create-an-account).
7 changes: 4 additions & 3 deletions packages/widget/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@
"dev": "npm run build -- --watch",
"test": "tsc -p jsconfig.json",
"lint": "eslint src",
"prepublishOnly": "rimraf dist && mkdir dist && npm run test && npm run lint && hatch fmt --check && npm run build && hatch build",
"publish": "hatch publish --user __token__",
"release": "npm run prepublishOnly && npm run publish"
"prepublishOnly": "npm run test && npm run lint && uv run ruff check && uv run ruff format --check && npm run build",
"publish": "uv build && uvx twine upload --skip-existing dist/*",
"release": "npm run prepublishOnly && npm run publish",
"clean": "rimraf dist"
},
"dependencies": {
"@uwdata/mosaic-core": "^0.11.0",
Expand Down
25 changes: 8 additions & 17 deletions packages/widget/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "mosaic-widget"
description = "A Jupyter widget for Mosaic"
dynamic = ["version"]
readme = "README.md"
requires-python = ">=3.9"
requires-python = ">=3.10"
dependencies = [
"anywidget>=0.9.0",
"duckdb==1.1.1",
Expand All @@ -17,29 +13,24 @@ dependencies = [
[project.urls]
homepage = "https://github.com/uwdata/mosaic"

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.hatch.build]
only-packages = true
artifacts = [
"mosaic_widget/static/"
]

[project.optional-dependencies]
[dependency-groups]
dev = [
"jupyterlab",
"jupyterlab>=4.2.5",
"pandas",
"pyyaml",
"watchfiles"
"ruff>=0.6.2"
]

[tool.hatch.envs.default]
python = "3.11"
features = ["dev"]
installer = "uv"

[tool.hatch.version]
path = "package.json"
pattern = "\"version\": \"(?P<version>.+?)\""

[tool.ruff]
extend-include = ["*.ipynb"]
lint.ignore = ["G004", "TRY301", "EM102", "TRY003", "FBT002"]
13 changes: 13 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[tool.uv.workspace]
members = [
"packages/duckdb-server",
"packages/widget"
]

# https://github.com/charliermarsh/ruff
[tool.ruff]
extend-include = ["*.ipynb"]

[tool.ruff.lint]
pydocstyle = { convention = "numpy" }
ignore = ["G004", "TRY301", "EM102", "EM101", "TRY003", "FBT002", "S608", "TRY002", "ARG001"]
Loading

0 comments on commit c711428

Please sign in to comment.