Skip to content

Commit 2e7df1c

Browse files
authored
Merge pull request #1094 from thunderstore-io/api-endpoint-for-package-source-data
Add endpoint for fetching package source (TS-2282)
2 parents db03a91 + 805dbf8 commit 2e7df1c

File tree

8 files changed

+185
-1
lines changed

8 files changed

+185
-1
lines changed
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import pytest
2+
from rest_framework.test import APIClient
3+
4+
from thunderstore.api.urls import cyberstorm_urls
5+
from thunderstore.repository.factories import PackageFactory, PackageVersionFactory
6+
from thunderstore.repository.models import Package
7+
8+
HAS_CYBERSTORM_SOURCE = "packages.api.detail.source" in [
9+
x.name for x in cyberstorm_urls
10+
]
11+
12+
13+
def get_package_source_endpoint_url(package: Package, version: str = "") -> str:
14+
base_url = "/api/cyberstorm/package"
15+
16+
package_name = package.name
17+
namespace_id = package.namespace.name
18+
if not version:
19+
version = package.version_number
20+
21+
return f"{base_url}/{namespace_id}/{package_name}/v/{version}/source/"
22+
23+
24+
@pytest.mark.django_db
25+
def test_package_source_endpoint(api_client: APIClient):
26+
if not HAS_CYBERSTORM_SOURCE:
27+
pytest.skip("Cyberstorm source endpoint is not enabled")
28+
29+
package = PackageFactory(is_active=True)
30+
PackageVersionFactory(package=package)
31+
url = get_package_source_endpoint_url(package)
32+
response = api_client.get(url)
33+
assert response.status_code == 200
34+
35+
36+
@pytest.mark.django_db
37+
def test_package_not_found(api_client: APIClient):
38+
if not HAS_CYBERSTORM_SOURCE:
39+
pytest.skip("Cyberstorm source endpoint is not enabled")
40+
41+
package = PackageFactory(is_active=False)
42+
PackageVersionFactory(package=package)
43+
44+
url = get_package_source_endpoint_url(package)
45+
response = api_client.get(url)
46+
47+
assert response.status_code == 404
48+
assert response.json() == {"detail": "Package not found"}
49+
50+
51+
@pytest.mark.django_db
52+
def test_package_version_not_found(api_client: APIClient):
53+
if not HAS_CYBERSTORM_SOURCE:
54+
pytest.skip("Cyberstorm source endpoint is not enabled")
55+
56+
package = PackageFactory(is_active=True)
57+
PackageVersionFactory(package=package)
58+
version = package.available_versions.first()
59+
version.version_number = "2.0.0"
60+
version.save()
61+
62+
url = get_package_source_endpoint_url(package, version="1.0.0")
63+
response = api_client.get(url)
64+
65+
assert response.status_code == 404
66+
assert response.json() == {"detail": "Package version not found"}
67+
68+
69+
@pytest.mark.django_db
70+
def test_package_source_response_format(api_client: APIClient):
71+
if not HAS_CYBERSTORM_SOURCE:
72+
pytest.skip("Cyberstorm source endpoint is not enabled")
73+
74+
package = PackageFactory(is_active=True)
75+
PackageVersionFactory(package=package)
76+
url = get_package_source_endpoint_url(package)
77+
response = api_client.get(url)
78+
79+
expected_result = {
80+
"is_visible": True,
81+
"namespace": package.namespace.name,
82+
"package_name": package.name,
83+
"version_number": package.version_number,
84+
"decompilations": [],
85+
}
86+
87+
assert response.json() == expected_result

django/thunderstore/api/urls.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
UpdateTeamAPIView,
3737
UpdateTeamMemberAPIView,
3838
)
39+
from thunderstore.plugins.registry import plugin_registry
3940

4041
cyberstorm_urls = [
4142
path(
@@ -219,3 +220,5 @@
219220
name="cyberstorm.team.member.update",
220221
),
221222
]
223+
224+
cyberstorm_urls += plugin_registry.get_cyberstorm_api_urls()

django/thunderstore/core/tests/test_inheritance.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,46 @@
33

44

55
def test_get_effective_bool_choice_depth_first():
6+
assert (
7+
get_effective_bool_choice_depth_first(
8+
OptionalBoolChoice.NONE,
9+
OptionalBoolChoice.NO,
10+
OptionalBoolChoice.YES,
11+
)
12+
== OptionalBoolChoice.YES
13+
)
14+
assert (
15+
get_effective_bool_choice_depth_first(
16+
OptionalBoolChoice.NONE,
17+
OptionalBoolChoice.YES,
18+
OptionalBoolChoice.NO,
19+
)
20+
== OptionalBoolChoice.NO
21+
)
22+
assert (
23+
get_effective_bool_choice_depth_first(
24+
OptionalBoolChoice.YES,
25+
OptionalBoolChoice.NONE,
26+
OptionalBoolChoice.NO,
27+
)
28+
== OptionalBoolChoice.NO
29+
)
30+
assert (
31+
get_effective_bool_choice_depth_first(
32+
OptionalBoolChoice.YES,
33+
OptionalBoolChoice.NO,
34+
OptionalBoolChoice.NONE,
35+
)
36+
== OptionalBoolChoice.NO
37+
)
38+
assert (
39+
get_effective_bool_choice_depth_first(
40+
OptionalBoolChoice.YES,
41+
OptionalBoolChoice.NONE,
42+
OptionalBoolChoice.NONE,
43+
)
44+
== OptionalBoolChoice.YES
45+
)
646
assert (
747
get_effective_bool_choice_depth_first(
848
OptionalBoolChoice.NONE,

django/thunderstore/plugins/base.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ def get_legacy_package_urls(cls) -> List[URLPattern]:
3030
def get_new_package_urls(cls) -> List[URLPattern]:
3131
return []
3232

33+
@classmethod
34+
def get_cyberstorm_api_urls(cls) -> List[URLPattern]:
35+
return []
36+
3337
@classmethod
3438
def get_package_tabs(
3539
cls,

django/thunderstore/plugins/registry.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ def get_legacy_package_urls(self) -> List[URLPattern]:
4444
def get_new_package_urls(self) -> List[URLPattern]:
4545
return list(itertools.chain(*(x.get_new_package_urls() for x in self.plugins)))
4646

47+
def get_cyberstorm_api_urls(self) -> List[URLPattern]:
48+
return list(
49+
itertools.chain(*(x.get_cyberstorm_api_urls() for x in self.plugins))
50+
)
51+
4752
def get_package_tabs(
4853
self, user: "UserType", listing: "PackageListing"
4954
) -> Dict[str, "PartialTab"]:

django/thunderstore/plugins/tests/__init__.py

Whitespace-only changes.
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
from django.urls import URLPattern
2+
3+
from thunderstore.plugins.base import BasePlugin
4+
from thunderstore.plugins.registry import PluginRegistry, plugin_registry
5+
6+
7+
def test_plugin_registry_return_types():
8+
assert isinstance(plugin_registry, PluginRegistry)
9+
assert isinstance(plugin_registry.plugins, set)
10+
11+
assert isinstance(plugin_registry.get_django_settings({}), dict)
12+
assert isinstance(plugin_registry.get_installed_apps([]), list)
13+
assert isinstance(plugin_registry.get_settings_urls(), list)
14+
assert isinstance(plugin_registry.get_legacy_package_urls(), list)
15+
assert isinstance(plugin_registry.get_new_package_urls(), list)
16+
assert isinstance(plugin_registry.get_cyberstorm_api_urls(), list)
17+
assert isinstance(plugin_registry.get_settings_links(), list)
18+
19+
20+
def test_base_plugin_return_types():
21+
base_plugin = BasePlugin()
22+
assert isinstance(base_plugin.get_django_settings({}), dict)
23+
assert isinstance(base_plugin.get_settings_urls(), list)
24+
assert isinstance(base_plugin.get_legacy_package_urls(), list)
25+
assert isinstance(base_plugin.get_new_package_urls(), list)
26+
assert isinstance(base_plugin.get_cyberstorm_api_urls(), list)
27+
assert isinstance(base_plugin.get_settings_links(), list)
28+
29+
30+
def test_plugin_registry_get_new_package_urls():
31+
urls = plugin_registry.get_new_package_urls()
32+
if plugin_registry.plugins:
33+
for url in urls:
34+
assert isinstance(url, URLPattern)
35+
else:
36+
assert urls == []
37+
38+
39+
def test_plugin_registry_get_cyberstorm_api_urls():
40+
urls = plugin_registry.get_cyberstorm_api_urls()
41+
if plugin_registry.plugins:
42+
for url in urls:
43+
assert isinstance(url, URLPattern)
44+
else:
45+
assert urls == []

python-packages

0 commit comments

Comments
 (0)