Skip to content

Commit f57a585

Browse files
jaap3berkerpeksag
authored andcommitted
Add downloads factories (#1317)
This commit recreates the downloads section by importing data from the python.org API.
1 parent b815845 commit f57a585

File tree

1 file changed

+123
-0
lines changed

1 file changed

+123
-0
lines changed

downloads/factories.py

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
from urllib.parse import urljoin
2+
3+
import factory
4+
import requests
5+
6+
from users.factories import UserFactory
7+
8+
from .models import OS, Release, ReleaseFile
9+
10+
11+
class OSFactory(factory.DjangoModelFactory):
12+
13+
class Meta:
14+
model = OS
15+
django_get_or_create = ('slug',)
16+
17+
creator = factory.SubFactory(UserFactory)
18+
19+
20+
class ReleaseFactory(factory.DjangoModelFactory):
21+
22+
class Meta:
23+
model = Release
24+
django_get_or_create = ('slug',)
25+
26+
creator = factory.SubFactory(UserFactory)
27+
is_published = True
28+
29+
30+
class ReleaseFileFactory(factory.DjangoModelFactory):
31+
32+
class Meta:
33+
model = ReleaseFile
34+
django_get_or_create = ('slug',)
35+
36+
creator = factory.SubFactory(UserFactory)
37+
release = factory.SubFactory(ReleaseFactory)
38+
os = factory.SubFactory(OSFactory)
39+
40+
41+
class APISession(requests.Session):
42+
base_url = 'https://www.python.org/api/v2/'
43+
44+
def __init__(self, *args, **kwargs):
45+
super().__init__(*args, **kwargs)
46+
self.headers.update(
47+
{
48+
'Accept': 'application/json',
49+
'User-Agent': (
50+
f'pythondotorg/create_initial_data'
51+
f' ({requests.utils.default_user_agent()})'
52+
),
53+
}
54+
)
55+
56+
def request(self, method, url, **kwargs):
57+
url = urljoin(self.base_url, url)
58+
response = super().request(method, url, **kwargs)
59+
response.raise_for_status()
60+
return response
61+
62+
63+
def _get_id(obj, key):
64+
"""
65+
Get the ID of an object by extracting it from the resource_uri field.
66+
"""
67+
key = obj.pop(key, '')
68+
if key:
69+
# i.e. /foo/1/ -> /foo/1 -> ('/foo', '/', '1') -> '1'
70+
return key.rstrip('/').rpartition('/')[-1]
71+
72+
73+
def initial_data():
74+
"""
75+
Create the data for the downloads section by importing
76+
it from the python.org API.
77+
"""
78+
objects = {
79+
'oses': {},
80+
'releases': {},
81+
'release_files': {},
82+
}
83+
84+
with APISession() as session:
85+
for key, resource_uri in [
86+
('oses', 'downloads/os/'),
87+
('releases', 'downloads/release/'),
88+
('release_files', 'downloads/release_file/'),
89+
]:
90+
response = session.get(resource_uri)
91+
object_list = response.json()
92+
93+
for obj in object_list:
94+
objects[key][_get_id(obj, 'resource_uri')] = obj
95+
96+
# Create the list of operating systems
97+
objects['oses'] = {k: OSFactory(**obj) for k, obj in objects['oses'].items()}
98+
99+
# Create all the releases
100+
for key, obj in objects['releases'].items():
101+
# TODO: We are ignoring release pages for now.
102+
obj.pop('release_page')
103+
objects['releases'][key] = ReleaseFactory(**obj)
104+
105+
# Create all release files.
106+
for key, obj in tuple(objects['release_files'].items()):
107+
release_id = _get_id(obj, 'release')
108+
try:
109+
release = objects['releases'][release_id]
110+
except KeyError:
111+
# Release files for draft releases are available through the API,
112+
# the releases are not. See #1308 for details.
113+
objects['release_files'].pop(key)
114+
else:
115+
obj['release'] = release
116+
obj['os'] = objects['oses'][_get_id(obj, 'os')]
117+
objects['release_files'][key] = ReleaseFileFactory(**obj)
118+
119+
return {
120+
'oses': list(objects.pop('oses').values()),
121+
'releases': list(objects.pop('releases').values()),
122+
'release_files': list(objects.pop('release_files').values()),
123+
}

0 commit comments

Comments
 (0)