diff --git a/examples/valid/mamba/recipe.yaml b/examples/valid/mamba/recipe.yaml index 67564e2..5991dc6 100644 --- a/examples/valid/mamba/recipe.yaml +++ b/examples/valid/mamba/recipe.yaml @@ -30,6 +30,7 @@ outputs: build: script: ${{ "build_mamba.sh" if unix else "build_mamba.bat" }} + files: "**" requirements: build: @@ -86,6 +87,12 @@ outputs: build: script: ${{ "build_mamba.sh" if unix else "build_mamba.bat" }} string: py${{ CONDA_PY }}h${{ PKG_HASH }}_${{ PKG_BUILDNUM }} + files: + include: + - include/*.hpp + exclude: + - foo/*.hpp + requirements: build: - ${{ compiler('cxx') }} @@ -134,6 +141,8 @@ outputs: build: script: ${{ "build_mamba.sh" if unix else "build_mamba.bat" }} string: py${{ CONDA_PY }}h${{ PKG_HASH }}_${{ PKG_BUILDNUM }} + files: + - foo.* python: entry_points: - mamba = mamba.mamba:main diff --git a/examples/valid/single-output/recipe.yaml b/examples/valid/single-output/recipe.yaml new file mode 100644 index 0000000..c95934e --- /dev/null +++ b/examples/valid/single-output/recipe.yaml @@ -0,0 +1,184 @@ +# yaml-language-server: $schema=../../../schema.json +schema_version: 1 +# a recipe with all possible fields +package: + name: single_output + version: "0.1.0" + +source: + # url source + - url: https://github.com/test/test-package.tar.gz + sha256: 1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef + md5: 1234567890abcdef1234567890abcdef + file_name: test-package.tar.gz + target_directory: test-package + patches: + - file.patch + # path source + - path: ./some-file.tar.gz + # currently not valid + sha256: 1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef + md5: 1234567890abcdef1234567890abcdef + patches: + - file.patch + file_name: test-package.tar.gz + target_directory: test-package + - git: https://github.com/test/package + depth: 10 + patches: + - file.patch + lfs: false + target_directory: test-package-git + +build: + number: 0 + string: "blabla" + skip: + - false + noarch: generic + merge_build_and_host_envs: true + files: + include: + - include/* + - "**/foo.txt" + - x.txt + - out/** + exclude: + - foo/* + - bar.txt + - baz/ + script: + env: + TEST: MYENV_VAR + secrets: + - SECRET_VARIABLE + content: + - test + python: + entry_points: + - test = test:main + skip_pyc_compilation: + - test/bla/**/*.py + use_python_app_entrypoint: true + + always_copy_files: + - file1 + - file2/**/* + always_include_files: + - file1 + - file2/**/* + + dynamic_linking: + rpaths: ["lib/"] + binary_relocation: + - lib/* + missing_dso_allowlist: + - /all/lib/**/* + rpath_allowlist: + - bla/* + overdepending_behavior: error + overlinking_behavior: ignore + + variant: + use_keys: + - key1 + - key2 + ignore_keys: + - python + - numpy + down_prioritize_variant: -5 + + prefix_detection: + force_file_type: + text: + - bla/*.txt + binary: + - bla/*.so + ignore: true + ignore_binary_files: true + # post_process: + # - regex: "complicated(.*)regex" + # replacement: "simple_string" + # files: + # - "*.cmake" + # - "bla/" + +requirements: + build: + - ${{ compiler('c') }} + - cmake + host: + - openssl + run: + - python >=3.11 + - perl + run_constraints: + - python * *cpython + run_exports: + weak: + - python + strong: + - python + weak_constraints: + - python + strong_constraints: + - python + noarch: + - python + ignore_run_exports: + from_package: + - python + by_name: + - python + +tests: + - script: | + echo FOO + requirements: + run: + - bash + build: + - bash + files: + source: + - include/ + - src/*.c + - src_file.txt + - package_contents: + lib: + - test + - test.so.* + include: + - test.h + - test.h* + bin: + - test + - test.exe + - foo* + site_packages: + - numpy + - numpy/foo/__init__.py + files: + - test.txt + - license.txt + - python: + imports: + - numpy + - pypy + pip_check: false + +about: + homepage: https://cool-website.com + license: BSD-3-Clause + license_file: LICENSE + summary: A summary + description: | + More description + documentation: https://cool-docs.com + repository: https://github.com/some-repo/some-package + +extra: + recipe-maintainers: + - some-maintainer + random_keys: + with: random_value \ No newline at end of file diff --git a/model.py b/model.py index 6ecf754..5d96571 100644 --- a/model.py +++ b/model.py @@ -14,7 +14,6 @@ NonEmptyStr = constr(min_length=1) PathNoBackslash = constr(pattern=r"^[^\\]+$") -Glob = NonEmptyStr UnsignedInt = conint(ge=0) GitUrl = constr(pattern=r"((git|ssh|http(s)?)|(git@[\w\.]+))(:(\/\/)?)([\w\.@:\/\\-~]+)") @@ -39,9 +38,25 @@ class IfStatement(StrictBaseModel, Generic[T]): ################### -# Package section # +# Glob section # ################### +SingleGlob = NonEmptyStr + +GlobVec = ConditionalList[SingleGlob] + + +class GlobDict(StrictBaseModel): + include: GlobVec = Field(..., description="Glob patterns to include") + exclude: GlobVec = Field([], description="Glob patterns to exclude") + + +Glob = SingleGlob | GlobVec | GlobDict + +#################### +# Package section # +#################### + class SimplePackage(StrictBaseModel): name: str = Field(description="The package name") @@ -227,6 +242,10 @@ class Build(StrictBaseModel): description="Options that influence how the prefix replacement is done.", ) + files: Glob = Field( + None, description="Glob patterns to include or exclude files from the package." + ) + class BaseScript(StrictBaseModel): interpreter: NonEmptyStr | None = Field( diff --git a/schema.json b/schema.json index 053a1f7..8a19c20 100644 --- a/schema.json +++ b/schema.json @@ -427,6 +427,40 @@ ] }, "type": "array" + }, + { + "$ref": "#/$defs/GlobDict" + }, + { + "items": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "$ref": "#/$defs/IfStatement" + }, + { + "items": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "$ref": "#/$defs/IfStatement" + } + ] + }, + "type": "array" + }, + { + "$ref": "#/$defs/GlobDict" + } + ] + }, + "type": "array" } ], "default": [], @@ -492,6 +526,37 @@ ], "default": null, "description": "Options that influence how the prefix replacement is done." + }, + "files": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "$ref": "#/$defs/IfStatement" + }, + { + "items": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "$ref": "#/$defs/IfStatement" + } + ] + }, + "type": "array" + }, + { + "$ref": "#/$defs/GlobDict" + } + ], + "default": null, + "description": "Glob patterns to include or exclude files from the package.", + "title": "Files" } }, "title": "Build", @@ -868,6 +933,40 @@ ] }, "type": "array" + }, + { + "$ref": "#/$defs/GlobDict" + }, + { + "items": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "$ref": "#/$defs/IfStatement" + }, + { + "items": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "$ref": "#/$defs/IfStatement" + } + ] + }, + "type": "array" + }, + { + "$ref": "#/$defs/GlobDict" + } + ] + }, + "type": "array" } ], "default": true, @@ -896,6 +995,40 @@ ] }, "type": "array" + }, + { + "$ref": "#/$defs/GlobDict" + }, + { + "items": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "$ref": "#/$defs/IfStatement" + }, + { + "items": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "$ref": "#/$defs/IfStatement" + } + ] + }, + "type": "array" + }, + { + "$ref": "#/$defs/GlobDict" + } + ] + }, + "type": "array" } ], "default": [], @@ -924,6 +1057,40 @@ ] }, "type": "array" + }, + { + "$ref": "#/$defs/GlobDict" + }, + { + "items": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "$ref": "#/$defs/IfStatement" + }, + { + "items": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "$ref": "#/$defs/IfStatement" + } + ] + }, + "type": "array" + }, + { + "$ref": "#/$defs/GlobDict" + } + ] + }, + "type": "array" } ], "default": [], @@ -1054,6 +1221,40 @@ ] }, "type": "array" + }, + { + "$ref": "#/$defs/GlobDict" + }, + { + "items": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "$ref": "#/$defs/IfStatement" + }, + { + "items": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "$ref": "#/$defs/IfStatement" + } + ] + }, + "type": "array" + }, + { + "$ref": "#/$defs/GlobDict" + } + ] + }, + "type": "array" } ], "default": [], @@ -1082,6 +1283,40 @@ ] }, "type": "array" + }, + { + "$ref": "#/$defs/GlobDict" + }, + { + "items": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "$ref": "#/$defs/IfStatement" + }, + { + "items": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "$ref": "#/$defs/IfStatement" + } + ] + }, + "type": "array" + }, + { + "$ref": "#/$defs/GlobDict" + } + ] + }, + "type": "array" } ], "default": [], @@ -1371,6 +1606,71 @@ "title": "GitTag", "type": "object" }, + "GlobDict": { + "additionalProperties": false, + "properties": { + "include": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "$ref": "#/$defs/IfStatement" + }, + { + "items": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "$ref": "#/$defs/IfStatement" + } + ] + }, + "type": "array" + } + ], + "description": "Glob patterns to include", + "title": "Include" + }, + "exclude": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "$ref": "#/$defs/IfStatement" + }, + { + "items": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "$ref": "#/$defs/IfStatement" + } + ] + }, + "type": "array" + } + ], + "default": [], + "description": "Glob patterns to exclude", + "title": "Exclude" + } + }, + "required": [ + "include" + ], + "title": "GlobDict", + "type": "object" + }, "IfStatement": { "additionalProperties": false, "properties": { @@ -2209,6 +2509,40 @@ ] }, "type": "array" + }, + { + "$ref": "#/$defs/GlobDict" + }, + { + "items": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "$ref": "#/$defs/IfStatement" + }, + { + "items": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "$ref": "#/$defs/IfStatement" + } + ] + }, + "type": "array" + }, + { + "$ref": "#/$defs/GlobDict" + } + ] + }, + "type": "array" } ], "default": [], @@ -2275,6 +2609,37 @@ "default": null, "description": "Options that influence how the prefix replacement is done." }, + "files": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "$ref": "#/$defs/IfStatement" + }, + { + "items": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "$ref": "#/$defs/IfStatement" + } + ] + }, + "type": "array" + }, + { + "$ref": "#/$defs/GlobDict" + } + ], + "default": null, + "description": "Glob patterns to include or exclude files from the package.", + "title": "Files" + }, "cache_only": { "default": false, "description": "Do not output a package but use this output as an input to others.", @@ -2662,6 +3027,40 @@ ] }, "type": "array" + }, + { + "$ref": "#/$defs/GlobDict" + }, + { + "items": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "$ref": "#/$defs/IfStatement" + }, + { + "items": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "$ref": "#/$defs/IfStatement" + } + ] + }, + "type": "array" + }, + { + "$ref": "#/$defs/GlobDict" + } + ] + }, + "type": "array" } ], "default": [], diff --git a/test/test_recipe.py b/test/test_recipe.py index dd07ae9..d364bb8 100644 --- a/test/test_recipe.py +++ b/test/test_recipe.py @@ -10,6 +10,7 @@ params=[ "mamba", "xtensor", + "single-output", "zlib" ], ) @@ -20,7 +21,6 @@ def valid_recipe(request) -> str: recipe_yml = yaml.safe_load(recipe) return recipe_yml - @pytest.fixture( scope="module", params=[ @@ -46,7 +46,6 @@ def recipe_schema(): def test_recipe_schema_valid(recipe_schema, valid_recipe): validate(instance=valid_recipe, schema=recipe_schema) - def test_recipe_schema_invalid(recipe_schema, invalid_recipe): with pytest.raises(ValidationError): validate(instance=invalid_recipe, schema=recipe_schema)