Commit ddbcfcda by Arun Babu Neelicattu Committed by Bjorn Neergaard

schema: validate source objects in poetry

This change is intended to help migrate validation of sections in
pyproject.toml that are not relevant to poetry-core into poetry. This
allows for poetry frontend specific configuration to be introduced
without dependent changes in poetry-core.
parent 711cca93
......@@ -17,6 +17,7 @@ from poetry.core.toml.file import TOMLFile
from tomlkit.toml_document import TOMLDocument
from poetry.config.config import Config
from poetry.json import validate_object
from poetry.packages.locker import Locker
from poetry.plugins.plugin import Plugin
from poetry.plugins.plugin_manager import PluginManager
......@@ -300,3 +301,13 @@ class Factory(BaseFactory):
)
return cast(TOMLDocument, pyproject)
@classmethod
def validate(
cls, config: dict[str, Any], strict: bool = False
) -> dict[str, list[str]]:
results = super().validate(config, strict)
results["errors"].extend(validate_object(config))
return results
......@@ -3,10 +3,13 @@ from __future__ import annotations
import json
import os
from pathlib import Path
from typing import Any
import jsonschema
from poetry.core.json import SCHEMA_DIR as CORE_SCHEMA_DIR
SCHEMA_DIR = os.path.join(os.path.dirname(__file__), "schemas")
......@@ -16,14 +19,9 @@ class ValidationError(ValueError):
pass
def validate_object(obj: dict[str, Any], schema_name: str) -> list[str]:
schema_file = os.path.join(SCHEMA_DIR, f"{schema_name}.json")
if not os.path.exists(schema_file):
raise ValueError(f"Schema {schema_name} does not exist.")
with open(schema_file, encoding="utf-8") as f:
schema = json.loads(f.read())
def validate_object(obj: dict[str, Any]) -> list[str]:
schema_file = Path(SCHEMA_DIR, "poetry.json")
schema = json.loads(schema_file.read_text(encoding="utf-8"))
validator = jsonschema.Draft7Validator(schema)
validation_errors = sorted(
......@@ -41,4 +39,17 @@ def validate_object(obj: dict[str, Any], schema_name: str) -> list[str]:
errors.append(message)
core_schema = json.loads(
Path(CORE_SCHEMA_DIR, "poetry-schema.json").read_text(encoding="utf-8")
)
if core_schema["additionalProperties"]:
# TODO: make this un-conditional once core update to >1.1.0b2
properties = {*schema["properties"].keys(), *core_schema["properties"].keys()}
additional_properties = set(obj.keys()) - properties
for key in additional_properties:
errors.append(
f"Additional properties are not allowed ('{key}' was unexpected)"
)
return errors
{
"$schema": "http://json-schema.org/draft-04/schema#",
"additionalProperties": true,
"type": "object",
"required": [],
"properties": {
"source": {
"type": "array",
"description": "A set of additional repositories where packages can be found.",
"additionalProperties": {
"$ref": "#/definitions/repository"
},
"items": {
"$ref": "#/definitions/repository"
}
}
},
"definitions": {
"repository": {
"type": "object",
"additionalProperties": false,
"required": [
"name",
"url"
],
"properties": {
"name": {
"type": "string",
"description": "The name of the repository"
},
"url": {
"type": "string",
"description": "The url of the repository",
"format": "uri"
},
"default": {
"type": "boolean",
"description": "Make this repository the default (disable PyPI)"
},
"secondary": {
"type": "boolean",
"description": "Declare this repository as secondary, i.e. it will only be looked up last for packages."
},
"links": {
"type": "boolean",
"description": "Declare this as a link source. Links at uri/path can point to sdist or bdist archives."
},
"indexed": {
"type": "boolean",
"description": "For PEP 503 simple API repositories, pre-fetch and index the available packages. (experimental)"
}
}
}
}
}
[tool.poetry]
name = "foobar"
version = "0.1.0"
description = ""
[tool.poetry.dependencies]
python = "^3.10"
[[tool.poetry.source]]
name = "pypi-simple"
default = false
secondary = false
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
[tool.poetry]
name = "foobar"
version = "0.1.0"
description = ""
[tool.poetry.dependencies]
python = "^3.10"
[[tool.poetry.source]]
name = "pypi-simple"
url = "https://pypi.org/simple/"
default = false
secondary = false
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
from __future__ import annotations
from pathlib import Path
from poetry.core.toml import TOMLFile
from poetry.factory import Factory
FIXTURE_DIR = Path(__file__).parent / "fixtures" / "source"
def test_pyproject_toml_valid() -> None:
toml = TOMLFile(FIXTURE_DIR / "complete_valid.toml").read()
content = toml["tool"]["poetry"]
assert Factory.validate(content) == {"errors": [], "warnings": []}
def test_pyproject_toml_invalid() -> None:
toml = TOMLFile(FIXTURE_DIR / "complete_invalid.toml").read()
content = toml["tool"]["poetry"]
assert Factory.validate(content) == {
"errors": ["[source.0] 'url' is a required property"],
"warnings": [],
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment