Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve JSON Schema and add export script #3461

Merged
merged 1 commit into from
May 8, 2024
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
12 changes: 11 additions & 1 deletion crates/distribution-types/src/index_url.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ static PYPI_URL: Lazy<Url> = Lazy::new(|| Url::parse("https://pypi.org/simple").
static DEFAULT_INDEX_URL: Lazy<IndexUrl> =
Lazy::new(|| IndexUrl::Pypi(VerbatimUrl::from_url(PYPI_URL.clone())));

/// The url of an index, newtype'd to avoid mixing it with file urls.
/// The URL of an index to use for fetching packages (e.g., PyPI).
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
pub enum IndexUrl {
Pypi(VerbatimUrl),
Expand All @@ -36,6 +36,11 @@ impl schemars::JsonSchema for IndexUrl {
fn json_schema(_gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
schemars::schema::SchemaObject {
instance_type: Some(schemars::schema::InstanceType::String.into()),
format: Some("uri".to_owned()),
metadata: Some(Box::new(schemars::schema::Metadata {
description: Some("The URL of an index to use for fetching packages (e.g., `https://pypi.org/simple`).".to_string()),
..schemars::schema::Metadata::default()
})),
..schemars::schema::SchemaObject::default()
}
.into()
Expand Down Expand Up @@ -169,6 +174,11 @@ impl schemars::JsonSchema for FlatIndexLocation {
fn json_schema(_gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
schemars::schema::SchemaObject {
instance_type: Some(schemars::schema::InstanceType::String.into()),
format: Some("uri".to_owned()),
metadata: Some(Box::new(schemars::schema::Metadata {
description: Some("The path to a directory of distributions, or a URL to an HTML file with a flat listing of distributions.".to_string()),
..schemars::schema::Metadata::default()
})),
..schemars::schema::SchemaObject::default()
}
.into()
Expand Down
4 changes: 4 additions & 0 deletions crates/uv-configuration/src/name_specifiers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ impl schemars::JsonSchema for PackageNameSpecifier {
),
..schemars::schema::StringValidation::default()
})),
metadata: Some(Box::new(schemars::schema::Metadata {
description: Some("The name of a package, or `:all:` or `:none:` to select or omit all packages, respectively.".to_string()),
..schemars::schema::Metadata::default()
})),
..schemars::schema::SchemaObject::default()
}
.into()
Expand Down
11 changes: 11 additions & 0 deletions crates/uv-configuration/src/target_triple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,46 +21,57 @@ pub enum TargetTriple {

/// An x86 Windows target.
#[cfg_attr(feature = "clap", value(name = "x86_64-pc-windows-msvc"))]
#[cfg_attr(feature = "schemars", schemars(rename = "x86_64-pc-windows-msvc"))]
X8664PcWindowsMsvc,

/// An x86 Linux target. Equivalent to `x86_64-manylinux_2_17`.
#[cfg_attr(feature = "clap", value(name = "x86_64-unknown-linux-gnu"))]
#[cfg_attr(feature = "schemars", schemars(rename = "x86_64-unknown-linux-gnu"))]
X8664UnknownLinuxGnu,

/// An ARM-based macOS target, as seen on Apple Silicon devices.
#[cfg_attr(feature = "clap", value(name = "aarch64-apple-darwin"))]
#[cfg_attr(feature = "schemars", schemars(rename = "aarch64-apple-darwin"))]
Aarch64AppleDarwin,

/// An x86 macOS target.
#[cfg_attr(feature = "clap", value(name = "x86_64-apple-darwin"))]
#[cfg_attr(feature = "schemars", schemars(rename = "x86_64-apple-darwin"))]
X8664AppleDarwin,

/// An ARM64 Linux target. Equivalent to `aarch64-manylinux_2_17`.
#[cfg_attr(feature = "clap", value(name = "aarch64-unknown-linux-gnu"))]
#[cfg_attr(feature = "schemars", schemars(rename = "aarch64-unknown-linux-gnu"))]
Aarch64UnknownLinuxGnu,

/// An ARM64 Linux target.
#[cfg_attr(feature = "clap", value(name = "aarch64-unknown-linux-musl"))]
#[cfg_attr(feature = "schemars", schemars(rename = "aarch64-unknown-linux-musl"))]
Aarch64UnknownLinuxMusl,

/// An `x86_64` Linux target.
#[cfg_attr(feature = "clap", value(name = "x86_64-unknown-linux-musl"))]
#[cfg_attr(feature = "schemars", schemars(rename = "x86_64-unknown-linux-musl"))]
X8664UnknownLinuxMusl,

/// An `x86_64` target for the `manylinux_2_17` platform.
#[cfg_attr(feature = "clap", value(name = "x86_64-manylinux_2_17"))]
#[cfg_attr(feature = "schemars", schemars(rename = "x86_64-manylinux_2_17"))]
X8664Manylinux217,

/// An `x86_64` target for the `manylinux_2_28` platform.
#[cfg_attr(feature = "clap", value(name = "x86_64-manylinux_2_28"))]
#[cfg_attr(feature = "schemars", schemars(rename = "x86_64-manylinux_2_28"))]
X8664Manylinux228,

/// An ARM64 target for the `manylinux_2_17` platform.
#[cfg_attr(feature = "clap", value(name = "aarch64-manylinux_2_17"))]
#[cfg_attr(feature = "schemars", schemars(rename = "aarch64-manylinux_2_17"))]
Aarch64Manylinux217,

/// An ARM64 target for the `manylinux_2_28` platform.
#[cfg_attr(feature = "clap", value(name = "aarch64-manylinux_2_28"))]
#[cfg_attr(feature = "schemars", schemars(rename = "aarch64-manylinux_2_28"))]
Aarch64Manylinux228,
}

Expand Down
16 changes: 14 additions & 2 deletions crates/uv-interpreter/src/python_version.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,20 @@ impl schemars::JsonSchema for PythonVersion {
String::from("PythonVersion")
}

fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
<String>::json_schema(gen)
fn json_schema(_gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
schemars::schema::SchemaObject {
instance_type: Some(schemars::schema::InstanceType::String.into()),
string: Some(Box::new(schemars::schema::StringValidation {
pattern: Some(r"^3\.\d+(\.\d+)?$".to_string()),
..schemars::schema::StringValidation::default()
})),
metadata: Some(Box::new(schemars::schema::Metadata {
description: Some("A Python version specifier, e.g. `3.7` or `3.8.0`.".to_string()),
..schemars::schema::Metadata::default()
})),
..schemars::schema::SchemaObject::default()
}
.into()
}
}

Expand Down
4 changes: 2 additions & 2 deletions crates/uv-normalize/src/extra_name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ use crate::{validate_and_normalize_owned, validate_and_normalize_ref, InvalidNam

/// The normalized name of an extra dependency group.
///
/// Converts the name to lowercase and collapses any run of the characters `-`, `_` and `.`
/// down to a single `-`, e.g., `---`, `.`, and `__` all get converted to just `-`.
/// Converts the name to lowercase and collapses runs of `-`, `_`, and `.` down to a single `-`.
/// For example, `---`, `.`, and `__` are all converted to a single `-`.
///
/// See:
/// - <https://peps.python.org/pep-0685/#specification/>
Expand Down
4 changes: 2 additions & 2 deletions crates/uv-normalize/src/package_name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ use crate::{validate_and_normalize_owned, validate_and_normalize_ref, InvalidNam

/// The normalized name of a package.
///
/// Converts the name to lowercase and collapses any run of the characters `-`, `_` and `.`
/// down to a single `-`, e.g., `---`, `.`, and `__` all get converted to just `-`.
/// Converts the name to lowercase and collapses runs of `-`, `_`, and `.` down to a single `-`.
/// For example, `---`, `.`, and `__` are all converted to a single `-`.
///
/// See: <https://packaging.python.org/en/latest/specifications/name-normalization/>
#[derive(
Expand Down
14 changes: 6 additions & 8 deletions crates/uv-requirements/src/pyproject.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
//! Reading from `pyproject.toml`
//! * `project.{dependencies,optional-dependencies}`,
//! * `tool.uv.sources` and
//! Reads the following fields from from `pyproject.toml`:
//!
//! * `project.{dependencies,optional-dependencies}`
//! * `tool.uv.sources`
//! * `tool.uv.workspace`
//!
//! and lowering them into a dependency specification.
//! Then lowers them into a dependency specification.

use std::collections::HashMap;
use std::io;
Expand Down Expand Up @@ -75,7 +76,7 @@ pub enum LoweringError {
pub struct PyProjectToml {
/// PEP 621-compliant project metadata.
pub project: Option<Project>,
/// Proprietary additions.
/// Tool-specific metadata.
pub tool: Option<Tool>,
}

Expand All @@ -99,14 +100,12 @@ pub struct Project {
pub dynamic: Option<Vec<String>>,
}

/// `tool`.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
pub struct Tool {
pub uv: Option<ToolUv>,
}

/// `tool.uv`.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
#[serde(deny_unknown_fields)]
Expand All @@ -115,7 +114,6 @@ pub struct ToolUv {
pub workspace: Option<ToolUvWorkspace>,
}

/// `tool.uv.workspace`.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
#[serde(deny_unknown_fields)]
Expand Down
6 changes: 5 additions & 1 deletion crates/uv-resolver/src/exclude_newer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,11 @@ impl schemars::JsonSchema for ExcludeNewer {
),
..schemars::schema::StringValidation::default()
})),
..Default::default()
metadata: Some(Box::new(schemars::schema::Metadata {
description: Some("Exclude distributions uploaded after the given timestamp.\n\nAccepts both RFC 3339 timestamps (e.g., `2006-12-02T02:07:43Z`) and UTC dates in the same format (e.g., `2006-12-02`).".to_string()),
..schemars::schema::Metadata::default()
})),
..schemars::schema::SchemaObject::default()
}
.into()
}
Expand Down
111 changes: 111 additions & 0 deletions scripts/update_schemastore.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
"""Update uv.json in schemastore.

This script will clone astral-sh/schemastore, update the schema and push the changes
to a new branch tagged with the uv git hash. You should see a URL to create the PR
to schemastore in the CLI.
"""

from __future__ import annotations

import json
from pathlib import Path
from subprocess import check_call, check_output
from tempfile import TemporaryDirectory

SCHEMASTORE_FORK = "[email protected]:astral-sh/schemastore.git"
SCHEMASTORE_UPSTREAM = "[email protected]:SchemaStore/schemastore.git"
UV_REPOSITORY = "https://github.com/astral-sh/uv"
UV_JSON_PATH = Path("schemas/json/uv.json")


def update_schemastore(schemastore: Path, *, root: Path) -> None:
if not schemastore.is_dir():
check_call(["git", "clone", SCHEMASTORE_FORK, schemastore])
check_call(
[
"git",
"remote",
"add",
"upstream",
SCHEMASTORE_UPSTREAM,
],
cwd=schemastore,
)
# Create a new branch tagged with the current uv commit up to date with the latest
# upstream schemastore
check_call(["git", "fetch", "upstream"], cwd=schemastore)
current_sha = check_output(["git", "rev-parse", "HEAD"], text=True).strip()
branch = f"update-uv-{current_sha}"
check_call(
["git", "switch", "-c", branch],
cwd=schemastore,
)
check_call(
["git", "reset", "--hard", "upstream/master"],
cwd=schemastore,
)

# Run npm install
src = schemastore.joinpath("src")
check_call(["npm", "install"], cwd=src)

# Update the schema and format appropriately
schema = json.loads(root.joinpath("uv.schema.json").read_text())
schema["$id"] = "https://json.schemastore.org/uv.json"
src.joinpath(UV_JSON_PATH).write_text(
json.dumps(dict(schema.items()), indent=2, ensure_ascii=False),
)
check_call(
[
"node_modules/.bin/prettier",
"--plugin",
"prettier-plugin-sort-json",
"--write",
UV_JSON_PATH,
],
cwd=src,
)

# Check if the schema has changed
# https://stackoverflow.com/a/9393642/3549270
if check_output(["git", "status", "-s"], cwd=schemastore).strip():
# Schema has changed, commit and push
commit_url = f"{UV_REPOSITORY}/commit/{current_sha}"
commit_body = f"This updates uv's JSON schema to [{current_sha}]({commit_url})"
# https://stackoverflow.com/a/22909204/3549270
check_call(
[
"git",
"commit",
"-a",
"-m",
"Update uv's JSON schema",
"-m",
commit_body,
],
cwd=schemastore,
)
# This should show the link to create a PR
check_call(
["git", "push", "--set-upstream", "origin", branch],
cwd=schemastore,
)
else:
print("No changes")


def main() -> None:
root = Path(
check_output(["git", "rev-parse", "--show-toplevel"], text=True).strip(),
)

schemastore = root.joinpath("schemastore")
if schemastore.is_dir():
update_schemastore(schemastore, root=root)
else:
with TemporaryDirectory() as temp_dir:
update_schemastore(Path(temp_dir).joinpath("schemastore"))


if __name__ == "__main__":
main()
Loading
Loading