Multi-platform: support multiple files per version #201

Merged
Oleg-Komarov merged 43 commits from multi-os into main 2024-07-09 16:27:46 +02:00
4 changed files with 70 additions and 9 deletions
Showing only changes of commit ab6e7eedb7 - Show all commits

View File

@ -29,6 +29,7 @@ META_DATA = {
"schema_version": "1.0.0", "schema_version": "1.0.0",
"maintainer": "", "maintainer": "",
"tags": [], "tags": [],
"website": "https://extensions.blender.org/",
} }
@ -368,11 +369,10 @@ class ValidateManifestFields(TestCase):
def test_wrong_optional_type_fields(self): def test_wrong_optional_type_fields(self):
testing_data = { testing_data = {
'blender_version_max': 1, 'blender_version_max': 1,
'website': 1,
'copyright': 1, 'copyright': 1,
'permissions': 'network', 'permissions': 'network',
'tags': 'Development', 'tags': 'Development',
'website': 1, 'website': 'example.com',
} }
complete_data = { complete_data = {
**self.mandatory_fields, **self.mandatory_fields,

View File

@ -261,6 +261,28 @@ class UtilsTest(TestCase):
file_list=['addon/__init__.py', 'addon/wheels/1.whl', 'addon/.git/config'], file_list=['addon/__init__.py', 'addon/wheels/1.whl', 'addon/.git/config'],
expected=[{'code': 'forbidden_filepaths', 'params': {'paths': '.git/'}}], expected=[{'code': 'forbidden_filepaths', 'params': {'paths': '.git/'}}],
), ),
TestParams(
name='empty build.generated.wheels override non-empty wheels',
toml_content={
'type': 'add-on',
'wheels': ['./wheels/1.whl'],
'build': {'generated': {'wheels': []}},
},
manifest_filepath='addon/blender_manifest.toml',
file_list=['addon/__init__.py'],
expected=[],
),
TestParams(
name='non-empty build.generated.wheels override non-empty wheels',
toml_content={
'type': 'add-on',
'wheels': ['./wheels/1.whl', './wheels/2.whl'],
'build': {'generated': {'wheels': ['./wheels/1.whl']}},
},
manifest_filepath='addon/blender_manifest.toml',
file_list=['addon/__init__.py', 'addon/wheels/1.whl'],
expected=[],
),
]: ]:
with self.subTest(**dataclasses.asdict(test)): with self.subTest(**dataclasses.asdict(test)):
self.assertEqual( self.assertEqual(

View File

@ -194,7 +194,15 @@ def validate_file_list(toml_content, manifest_filepath, file_list):
init_filepath = find_exact_path(file_list, expected_init_path) init_filepath = find_exact_path(file_list, expected_init_path)
if not init_filepath: if not init_filepath:
error_codes.append('invalid_missing_init') error_codes.append('invalid_missing_init')
wheels = toml_content.get('wheels') wheels = None
if (
'build' in toml_content
and 'generated' in toml_content['build']
and 'wheels' in toml_content['build']['generated']
):
wheels = toml_content['build']['generated']['wheels']
else:
wheels = toml_content.get('wheels')
if wheels: if wheels:
for wheel in wheels: for wheel in wheels:
expected_wheel_path = _canonical_path(wheel, manifest_filepath) expected_wheel_path = _canonical_path(wheel, manifest_filepath)

View File

@ -2,7 +2,7 @@ from semantic_version import Version
import logging import logging
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.core.validators import validate_unicode_slug from django.core.validators import URLValidator, validate_unicode_slug
from django.utils.deconstruct import deconstructible from django.utils.deconstruct import deconstructible
from django.utils.html import escape from django.utils.html import escape
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
@ -496,16 +496,32 @@ class PlatformsValidator:
class BuildValidator: class BuildValidator:
example = {"generated": {"platforms": ["linux-x64"]}} example = {
"generated": {
"platforms": ["linux-x64"],
"wheels": ["./wheels/mywheel-v1.0.0-py3-none-any.whl"],
}
}
@classmethod @classmethod
def validate(cls, *, name: str, value: dict, manifest: dict) -> str: def validate(cls, *, name: str, value: dict, manifest: dict) -> str:
if 'generated' in value and 'platforms' in value['generated']: if 'generated' not in value:
return PlatformsValidator.validate( return
if 'platforms' in value['generated']:
if plafroms_error := PlatformsValidator.validate(
name=name, name=name,
value=value['generated']['platforms'], value=value['generated']['platforms'],
manifest=manifest, manifest=manifest,
) ):
return plafroms_error
if 'wheels' in value['generated']:
if wheels_error := WheelsValidator.validate(
name=name,
value=value['generated']['wheels'],
manifest=manifest,
):
return wheels_error
class WheelsValidator: class WheelsValidator:
@ -637,6 +653,21 @@ class TaglineValidator(StringValidator):
) )
class WebsiteValidator(StringValidator):
example = 'https://extensions.blender.org/'
@classmethod
def validate(cls, *, name: str, value: str, manifest: dict) -> str:
if not value:
return
try:
URLValidator()(value)
except ValidationError:
return mark_safe(
'Manifest value error: <code>website</code> must be a valid URL',
)
class ManifestValidator: class ManifestValidator:
"""Make sure the manifest has all the expected fields.""" """Make sure the manifest has all the expected fields."""
@ -658,7 +689,7 @@ class ManifestValidator:
'permissions': PermissionsValidator, 'permissions': PermissionsValidator,
'platforms': PlatformsValidator, 'platforms': PlatformsValidator,
'tags': TagsValidator, 'tags': TagsValidator,
'website': StringValidator, 'website': WebsiteValidator,
'wheels': WheelsValidator, 'wheels': WheelsValidator,
} }
all_fields = {**mandatory_fields, **optional_fields} all_fields = {**mandatory_fields, **optional_fields}