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

download attribute in project schema #713

Merged
merged 10 commits into from
Feb 4, 2025
11 changes: 11 additions & 0 deletions schema/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,17 @@
"Tools"
],
"type": "string"
},
"downloads": {
"description": "Optional list of download URLs.",
"type": "array",
"items": {
"type": "string",
"format": "uri"
},
"minItems": 1,
"uniqueItems": true,
"optional": true
}
},
"required": [
Expand Down
12 changes: 12 additions & 0 deletions schema/tests/data/project/negative/downloads-empty.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
name: "Test Project"
level: 3
leaders:
- github: "testuser1"
- github: "testuser2"
downloads: []
pitch: A very brief, one-line description of your project
tags:
- example-tag-1
- example-tag-2
- example-tag-3
type: code
14 changes: 14 additions & 0 deletions schema/tests/data/project/negative/downloads-non-unique.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
name: "Test Project"
level: 3
leaders:
- github: "testuser1"
- github: "testuser2"
downloads:
- https://abc.com/download
- https://abc.com/download
pitch: A very brief, one-line description of your project
tags:
- example-tag-1
- example-tag-2
- example-tag-3
type: code
14 changes: 14 additions & 0 deletions schema/tests/data/project/negative/downloads-non-uri.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
name: "Test Project"
level: 3
leaders:
- github: "testuser1"
- github: "testuser2"
downloads:
- example-url-1
- example-url-2
pitch: A very brief, one-line description of your project
tags:
- example-tag-1
- example-tag-2
- example-tag-3
type: code
9 changes: 9 additions & 0 deletions schema/tests/project_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@ def test_positive(project_schema):
("level-invalid.yaml", "2.5 is not one of [2, 3, 3.5, 4]"),
("name-empty.yaml", "'' is too short"),
("name-none.yaml", "None is not of type 'string'"),
("downloads-empty.yaml", "[] should be non-empty"),
(
"downloads-non-unique.yaml",
"['https://abc.com/download', 'https://abc.com/download'] has non-unique elements",
),
(
"downloads-non-uri.yaml",
"['example-url-1', 'example-url-2'] has non-uri elements",
),
],
)
def test_negative(project_schema, file_path, error_message):
Expand Down
24 changes: 24 additions & 0 deletions schema/utils/validators.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,32 @@
import re
from urllib.parse import urlparse

from jsonschema import validate
from jsonschema.exceptions import ValidationError


def is_valid_url(url):
parsed_url = urlparse(url)

# A valid URL must have a scheme (http or https) and a netloc (domain)
if not parsed_url.scheme or not parsed_url.netloc:
return False

# valid domain format check
domain_regex = r"^(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9-]{2,}$"
if not re.match(domain_regex, parsed_url.netloc):
return False

return True


def validate_data(schema, data):
# Perform URL validation before schema validation
arkid15r marked this conversation as resolved.
Show resolved Hide resolved
if "downloads" in data:
invalid_urls = [url for url in data["downloads"] if not is_valid_url(url)]
if invalid_urls:
return f"{invalid_urls} has non-uri elements"

try:
validate(schema=schema, instance=data)
except ValidationError as e:
Expand Down