Skip to content

Commit 464d10d

Browse files
committed
refactor(python,cli): move pip installable to cli crate
1 parent 5c8e260 commit 464d10d

File tree

10 files changed

+258
-35
lines changed

10 files changed

+258
-35
lines changed

.github/workflows/cli.yml

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
name: Python
2+
3+
on:
4+
push:
5+
tags:
6+
- 'stac-cli-*'
7+
workflow_dispatch:
8+
9+
permissions:
10+
contents: read
11+
12+
concurrency:
13+
group: ${{ github.workflow }}-${{ github.ref }}
14+
cancel-in-progress: true
15+
16+
jobs:
17+
linux:
18+
runs-on: ${{ matrix.platform.runner }}
19+
strategy:
20+
matrix:
21+
platform:
22+
- runner: ubuntu-latest
23+
target: x86_64
24+
# - runner: ubuntu-latest
25+
# target: x86
26+
# - runner: ubuntu-latest
27+
# target: aarch64
28+
# - runner: ubuntu-latest
29+
# target: armv7
30+
# - runner: ubuntu-latest
31+
# target: s390x
32+
# - runner: ubuntu-latest
33+
# target: ppc64le
34+
steps:
35+
- uses: actions/checkout@v4
36+
- uses: actions/setup-python@v5
37+
with:
38+
python-version: 3.x
39+
- name: Set up Rust cache
40+
uses: Swatinem/rust-cache@v2
41+
- name: Build wheels
42+
uses: PyO3/maturin-action@v1
43+
with:
44+
target: ${{ matrix.platform.target }}
45+
args: --release --out dist --find-interpreter --manifest-path cli/Cargo.toml
46+
sccache: 'true'
47+
- name: Upload wheels
48+
uses: actions/upload-artifact@v4
49+
with:
50+
name: wheels-linux-${{ matrix.platform.target }}
51+
path: dist
52+
53+
# musllinux:
54+
# runs-on: ${{ matrix.platform.runner }}
55+
# strategy:
56+
# matrix:
57+
# platform:
58+
# - runner: ubuntu-latest
59+
# target: x86_64
60+
# - runner: ubuntu-latest
61+
# target: x86
62+
# - runner: ubuntu-latest
63+
# target: aarch64
64+
# - runner: ubuntu-latest
65+
# target: armv7
66+
# steps:
67+
# - uses: actions/checkout@v4
68+
# - uses: actions/setup-python@v5
69+
# with:
70+
# python-version: 3.x
71+
# - name: Build wheels
72+
# uses: PyO3/maturin-action@v1
73+
# with:
74+
# target: ${{ matrix.platform.target }}
75+
# args: --release --out dist --find-interpreter --manifest-path cli/Cargo.toml -F openssl-vendored
76+
# sccache: 'true'
77+
# manylinux: musllinux_1_2
78+
# - name: Upload wheels
79+
# uses: actions/upload-artifact@v4
80+
# with:
81+
# name: wheels-musllinux-${{ matrix.platform.target }}
82+
# path: dist
83+
84+
windows:
85+
runs-on: ${{ matrix.platform.runner }}
86+
strategy:
87+
matrix:
88+
platform:
89+
- runner: windows-latest
90+
target: x64
91+
- runner: windows-latest
92+
target: x86
93+
steps:
94+
- uses: actions/checkout@v4
95+
- name: Set up Rust cache
96+
uses: Swatinem/rust-cache@v2
97+
- uses: actions/setup-python@v5
98+
with:
99+
python-version: 3.x
100+
architecture: ${{ matrix.platform.target }}
101+
- name: Build wheels
102+
uses: PyO3/maturin-action@v1
103+
with:
104+
target: ${{ matrix.platform.target }}
105+
args: --release --out dist --find-interpreter --manifest-path cli/Cargo.toml
106+
sccache: 'true'
107+
- name: Upload wheels
108+
uses: actions/upload-artifact@v4
109+
with:
110+
name: wheels-windows-${{ matrix.platform.target }}
111+
path: dist
112+
113+
macos:
114+
runs-on: ${{ matrix.platform.runner }}
115+
strategy:
116+
matrix:
117+
platform:
118+
- runner: macos-12
119+
target: x86_64
120+
- runner: macos-14
121+
target: aarch64
122+
steps:
123+
- uses: actions/checkout@v4
124+
- name: Set up Rust cache
125+
uses: Swatinem/rust-cache@v2
126+
- uses: actions/setup-python@v5
127+
with:
128+
python-version: 3.x
129+
- name: Build wheels
130+
uses: PyO3/maturin-action@v1
131+
with:
132+
target: ${{ matrix.platform.target }}
133+
args: --release --out dist --find-interpreter --manifest-path cli/Cargo.toml
134+
sccache: 'true'
135+
- name: Upload wheels
136+
uses: actions/upload-artifact@v4
137+
with:
138+
name: wheels-macos-${{ matrix.platform.target }}
139+
path: dist
140+
141+
sdist:
142+
runs-on: ubuntu-latest
143+
steps:
144+
- uses: actions/checkout@v4
145+
- name: Set up Rust cache
146+
uses: Swatinem/rust-cache@v2
147+
- name: Build sdist
148+
uses: PyO3/maturin-action@v1
149+
with:
150+
command: sdist
151+
args: --out dist --manifest-path cli/Cargo.toml
152+
- name: Upload sdist
153+
uses: actions/upload-artifact@v4
154+
with:
155+
name: wheels-sdist
156+
path: dist
157+
158+
release:
159+
name: Release
160+
runs-on: ubuntu-latest
161+
needs:
162+
- linux
163+
# - musllinux
164+
- windows
165+
- macos
166+
- sdist
167+
if: startsWith(github.ref, 'refs/tags/stac-cli-')
168+
environment:
169+
name: pypi
170+
url: https://pypi.org/p/stacrs
171+
permissions:
172+
id-token: write
173+
steps:
174+
- uses: actions/download-artifact@v4
175+
- name: Publish to PyPI
176+
uses: PyO3/maturin-action@v1
177+
with:
178+
command: upload
179+
args: --non-interactive --skip-existing wheels-*/*

cli/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
1313
- Auto-create collections when serving ([#304](https://github.com/stac-utils/stac-rs/pull/304))
1414
- Auto-add items when serving ([#312](https://github.com/stac-utils/stac-rs/pull/312))
1515
- Searching geoparquet files with DuckDB ([#331](https://github.com/stac-utils/stac-rs/pull/331))
16+
- Python package ([#335](https://github.com/stac-utils/stac-rs/pull/335))
1617

1718
## [0.2.0] - 2024-08-12
1819

cli/Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,13 @@ duckdb = ["dep:stac-duckdb"]
1616
gdal = ["stac/gdal"]
1717
geoparquet = ["dep:bytes", "stac/geoparquet-compression"]
1818
pgstac = ["stac-server/pgstac"]
19+
python = ["dep:pyo3"]
1920

2021
[dependencies]
2122
axum = "0.7"
2223
bytes = { version = "1", optional = true }
2324
clap = { version = "4", features = ["derive"] }
25+
pyo3 = { version = "0.22", optional = true }
2426
reqwest = "0.12"
2527
serde = "1"
2628
serde_json = "1"
@@ -43,6 +45,9 @@ url = "2"
4345
assert_cmd = "2"
4446
tokio-test = "0.4"
4547

48+
[lib]
49+
crate-type = ["lib", "cdylib"]
50+
4651
[[bin]]
4752
name = "stacrs"
4853
path = "src/main.rs"

cli/pyproject.toml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
[build-system]
2+
requires = ["maturin>=1.7,<2.0"]
3+
build-backend = "maturin"
4+
5+
[project]
6+
name = "stacrs-cli"
7+
description = "A STAC command-line interface written in Rust"
8+
readme = "README.md"
9+
authors = [{ name = "Pete Gadomski", email = "[email protected]" }]
10+
requires-python = ">=3.8"
11+
classifiers = [
12+
"Development Status :: 3 - Alpha",
13+
"Intended Audience :: Science/Research",
14+
"Natural Language :: English",
15+
"Programming Language :: Rust",
16+
"Programming Language :: Python :: Implementation :: CPython",
17+
"Programming Language :: Python :: Implementation :: PyPy",
18+
"License :: OSI Approved :: Apache Software License",
19+
"License :: OSI Approved :: MIT License",
20+
]
21+
keywords = ["stac", "geospatial"]
22+
dynamic = ["version"]
23+
24+
[project.urls]
25+
Repository = "https://github.com/stac-utils/stac-rs"
26+
Issues = "https://github.com/stac-utils/stac-rs/issues"
27+
28+
[project.scripts]
29+
stacrs = "stacrs_cli:main"
30+
31+
[tool.maturin]
32+
features = ["pyo3/extension-module", "python"]
33+
module-name = "stacrs_cli"

cli/src/lib.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,5 +96,42 @@ pub async fn run(args: Args) -> Result<()> {
9696
result
9797
}
9898

99+
#[cfg(feature = "python")]
100+
mod python {
101+
use crate::Args;
102+
use clap::Parser;
103+
use pyo3::{
104+
prelude::{PyModule, PyModuleMethods},
105+
pyfunction, pymodule, wrap_pyfunction, Bound, PyResult,
106+
};
107+
108+
#[pyfunction]
109+
fn main() -> PyResult<i64> {
110+
std::process::exit(
111+
tokio::runtime::Builder::new_multi_thread()
112+
.enable_all()
113+
.build()
114+
.unwrap()
115+
.block_on(async {
116+
// We skip one because the first argument is going to be the python interpreter.
117+
let args = Args::parse_from(std::env::args_os().skip(1));
118+
match super::run(args).await {
119+
Ok(()) => 0,
120+
Err(err) => {
121+
eprintln!("ERROR: {}", err);
122+
err.code()
123+
}
124+
}
125+
}),
126+
)
127+
}
128+
129+
#[pymodule]
130+
fn stacrs_cli(m: &Bound<'_, PyModule>) -> PyResult<()> {
131+
m.add_function(wrap_pyfunction!(main, m)?)?;
132+
Ok(())
133+
}
134+
}
135+
99136
#[cfg(test)]
100137
use {assert_cmd as _, tokio_test as _};

python/CHANGELOG.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66

77
## [Unreleased]
88

9-
- `main` and entry point script ([#333](https://github.com/stac-utils/stac-rs/pull/333))
109
- `migrate_href` ([#334](https://github.com/stac-utils/stac-rs/pull/334))
1110

1211
## [0.0.3] - 2024-08-29

python/Cargo.toml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,7 @@ name = "stacrs"
1313
crate-type = ["cdylib"]
1414

1515
[dependencies]
16-
clap = "4"
1716
pyo3 = "0.22"
1817
pythonize = "0.22"
1918
stac = { path = "../core", features = ["reqwest"] }
20-
stac-cli = { path = "../cli", default-features = false }
2119
stac-validate = { path = "../validate" }
22-
tokio = { version = "1", features = ["rt-multi-thread"] }

python/docs/api.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ API documentation for **stacrs**.
55
## Migrate
66

77
::: stacrs.migrate
8+
::: stacrs.migrate_href
89

910
## Validate
1011

python/pyproject.toml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,5 @@ Repository = "https://github.com/stac-utils/stac-rs"
2727
Documentation = "https://stacrs.readthedocs.io/"
2828
Issues = "https://github.com/stac-utils/stac-rs/issues"
2929

30-
[project.scripts]
31-
stacrs = "stacrs:main"
32-
3330
[tool.maturin]
3431
features = ["pyo3/extension-module"]

python/src/lib.rs

Lines changed: 2 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,11 @@
1-
use clap::Parser;
1+
#![deny(unused_crate_dependencies)]
2+
23
use pyo3::{create_exception, exceptions::PyException, prelude::*, types::PyDict};
34
use stac::{Migrate, Value};
4-
use stac_cli::Args;
55
use stac_validate::Validate;
66

77
create_exception!(stacrs, StacrsError, PyException, "An error in stacrs");
88

9-
/// Runs the command-line interface.
10-
///
11-
/// Returns:
12-
/// int: The exit code
13-
#[pyfunction]
14-
fn main() -> PyResult<i64> {
15-
std::process::exit(
16-
tokio::runtime::Builder::new_multi_thread()
17-
.enable_all()
18-
.build()
19-
.unwrap()
20-
.block_on(async {
21-
// We skip one because the first argument is going to be the python interpreter.
22-
let args = Args::parse_from(std::env::args_os().skip(1));
23-
match stac_cli::run(args).await {
24-
Ok(()) => 0,
25-
Err(err) => {
26-
eprintln!("ERROR: {}", err);
27-
err.code()
28-
}
29-
}
30-
}),
31-
)
32-
}
33-
349
/// Migrates a STAC dictionary to another version.
3510
///
3611
/// Migration can be as simple as updating the `stac_version` attribute, but
@@ -171,7 +146,6 @@ fn validate_value(value: Value) -> PyResult<()> {
171146
/// A collection of functions for working with STAC, using Rust under the hood.
172147
#[pymodule]
173148
fn stacrs(m: &Bound<'_, PyModule>) -> PyResult<()> {
174-
m.add_function(wrap_pyfunction!(main, m)?)?;
175149
m.add_function(wrap_pyfunction!(migrate, m)?)?;
176150
m.add_function(wrap_pyfunction!(migrate_href, m)?)?;
177151
m.add_function(wrap_pyfunction!(validate_href, m)?)?;

0 commit comments

Comments
 (0)