Skip to content
Open
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
39 changes: 34 additions & 5 deletions conda_recipe_v2_schema/model.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from __future__ import annotations

import json
from typing import Annotated, Any, Generic, Literal, TypeVar, Union
import sys
from typing import Annotated, Any, ClassVar, Generic, Literal, TypeVar, Union

from pydantic import (
AnyHttpUrl,
Expand All @@ -13,6 +14,19 @@
constr,
)

SCHEMA_DRAFT = "http://json-schema.org/draft-07/schema#"
SCHEMA_URI = (
"https://raw.githubusercontent.com/prefix-dev/recipe-format/refs/heads/main/schema.json"
)
SCHEMA_HTML = "https://github.com/prefix-dev/recipe-format"

SCHEMA_HEADER = {
"$id": SCHEMA_URI,
"$schema": SCHEMA_DRAFT,
"title": "conda recipe file",
}


NonEmptyStr = constr(min_length=1)
PathNoBackslash = constr(pattern=r"^[^\\]+$")
UnsignedInt = conint(ge=0)
Expand All @@ -21,7 +35,7 @@


class StrictBaseModel(BaseModel):
model_config = ConfigDict(extra="forbid")
model_config: ClassVar[ConfigDict] = ConfigDict(extra="forbid")


###########################
Expand Down Expand Up @@ -704,6 +718,14 @@ class Output(StrictBaseModel):


class BaseRecipe(StrictBaseModel):
schema_: str | None = Field(
SCHEMA_URI,
alias="$schema",
title="Schema",
description="An identifier for the schema used to validate this recipe",
json_schema_extra={"format": "uri-reference"},
)

schema_version: SchemaVersion = Field(
1,
description="The version of the YAML schema for a recipe. If the version is omitted it is assumed to be 1.",
Expand Down Expand Up @@ -771,9 +793,16 @@ class SimpleRecipe(BaseRecipe):
Recipe = TypeAdapter(SimpleRecipe | ComplexRecipe)


def main():
print(json.dumps(Recipe.json_schema(), indent=2))
def top_level_schema() -> dict[str, Any]:
schema = Recipe.json_schema()
any_of = schema.pop("anyOf")
return {**SCHEMA_HEADER, "oneOf": any_of, **schema}


def main() -> int:
print(json.dumps(top_level_schema(), indent=2))
return 0


if __name__ == "__main__":
main()
sys.exit(main())
1 change: 1 addition & 0 deletions examples/invalid/dollarschema.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
$schema: NO
49 changes: 40 additions & 9 deletions schema.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
{
"$id": "https://raw.githubusercontent.com/prefix-dev/recipe-format/refs/heads/main/schema.json",
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "conda recipe file",
"oneOf": [
{
"$ref": "#/$defs/SimpleRecipe"
},
{
"$ref": "#/$defs/ComplexRecipe"
}
],
"$defs": {
"About": {
"additionalProperties": false,
Expand Down Expand Up @@ -809,6 +820,20 @@
"ComplexRecipe": {
"additionalProperties": false,
"properties": {
"$schema": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": "https://raw.githubusercontent.com/prefix-dev/recipe-format/refs/heads/main/schema.json",
"description": "An identifier for the schema used to validate this recipe",
"format": "uri-reference",
"title": "Schema"
},
"schema_version": {
"default": 1,
"description": "The version of the YAML schema for a recipe. If the version is omitted it is assumed to be 1.",
Expand Down Expand Up @@ -4092,6 +4117,20 @@
"SimpleRecipe": {
"additionalProperties": false,
"properties": {
"$schema": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": "https://raw.githubusercontent.com/prefix-dev/recipe-format/refs/heads/main/schema.json",
"description": "An identifier for the schema used to validate this recipe",
"format": "uri-reference",
"title": "Schema"
},
"schema_version": {
"default": 1,
"description": "The version of the YAML schema for a recipe. If the version is omitted it is assumed to be 1.",
Expand Down Expand Up @@ -4916,13 +4955,5 @@
"title": "Variant",
"type": "object"
}
},
"anyOf": [
{
"$ref": "#/$defs/SimpleRecipe"
},
{
"$ref": "#/$defs/ComplexRecipe"
}
]
}
}
5 changes: 3 additions & 2 deletions tests/test_recipe.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from jsonschema.exceptions import ValidationError
from pydantic import ValidationError as PydanticValidationError

from conda_recipe_v2_schema.model import Recipe
from conda_recipe_v2_schema.model import Recipe, top_level_schema


@pytest.fixture(
Expand All @@ -25,6 +25,7 @@ def valid_recipe(request) -> str:
scope="module",
params=[
"complex1",
"dollarschema",
"simple1",
],
)
Expand Down Expand Up @@ -53,7 +54,7 @@ def test_recipe_schema_invalid(recipe_schema, invalid_recipe):


def test_recipe_schema_not_changed(recipe_schema):
assert recipe_schema == Recipe.json_schema()
assert recipe_schema == top_level_schema()


def test_patches_valid_conditional():
Expand Down