-
Notifications
You must be signed in to change notification settings - Fork 649
Add downloads factories #1317
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
Merged
Merged
Add downloads factories #1317
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
f1af10f
Add downloads factories
05f6b48
Use v2 API
773104e
Raise an exception when the a response indicates a client or server e…
53cffc2
Don't use bulk_create
66b6e77
Add Accept header
e16e962
Clarify _get_id a bit
2bdf485
s/oss/oses
247713d
Add TODO
ba95630
some very minor style changes
berkerpeksag File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
from urllib.parse import urljoin | ||
|
||
import factory | ||
import requests | ||
|
||
from users.factories import UserFactory | ||
|
||
from .models import OS, Release, ReleaseFile | ||
|
||
|
||
class OSFactory(factory.DjangoModelFactory): | ||
|
||
class Meta: | ||
model = OS | ||
django_get_or_create = ('slug',) | ||
|
||
creator = factory.SubFactory(UserFactory) | ||
|
||
|
||
class ReleaseFactory(factory.DjangoModelFactory): | ||
|
||
class Meta: | ||
model = Release | ||
django_get_or_create = ('slug',) | ||
|
||
creator = factory.SubFactory(UserFactory) | ||
is_published = True | ||
|
||
|
||
class ReleaseFileFactory(factory.DjangoModelFactory): | ||
|
||
class Meta: | ||
model = ReleaseFile | ||
django_get_or_create = ('slug',) | ||
|
||
creator = factory.SubFactory(UserFactory) | ||
release = factory.SubFactory(ReleaseFactory) | ||
os = factory.SubFactory(OSFactory) | ||
|
||
|
||
class APISession(requests.Session): | ||
base_url = 'https://www.python.org/api/v2/' | ||
|
||
def __init__(self, *args, **kwargs): | ||
super().__init__(*args, **kwargs) | ||
self.headers.update( | ||
{ | ||
'Accept': 'application/json', | ||
'User-Agent': ( | ||
f'pythondotorg/create_initial_data' | ||
f' ({requests.utils.default_user_agent()})' | ||
), | ||
} | ||
) | ||
|
||
def request(self, method, url, **kwargs): | ||
url = urljoin(self.base_url, url) | ||
response = super().request(method, url, **kwargs) | ||
response.raise_for_status() | ||
return response | ||
|
||
|
||
def _get_id(obj, key): | ||
""" | ||
Get the ID of an object by extracting it from the resource_uri field. | ||
""" | ||
key = obj.pop(key, '') | ||
if key: | ||
# i.e. /foo/1/ -> /foo/1 -> ('/foo', '/', '1') -> '1' | ||
return key.rstrip('/').rpartition('/')[-1] | ||
|
||
|
||
def initial_data(): | ||
""" | ||
Create the data for the downloads section by importing | ||
it from the python.org API. | ||
""" | ||
objects = { | ||
'oses': {}, | ||
'releases': {}, | ||
'release_files': {}, | ||
} | ||
|
||
with APISession() as session: | ||
for key, resource_uri in [ | ||
('oses', 'downloads/os/'), | ||
('releases', 'downloads/release/'), | ||
('release_files', 'downloads/release_file/'), | ||
]: | ||
response = session.get(resource_uri) | ||
object_list = response.json() | ||
|
||
for obj in object_list: | ||
objects[key][_get_id(obj, 'resource_uri')] = obj | ||
|
||
# Create the list of operating systems | ||
objects['oses'] = {k: OSFactory(**obj) for k, obj in objects['oses'].items()} | ||
|
||
# Create all the releases | ||
for key, obj in objects['releases'].items(): | ||
# TODO: We are ignoring release pages for now. | ||
obj.pop('release_page') | ||
objects['releases'][key] = ReleaseFactory(**obj) | ||
|
||
# Create all release files. | ||
for key, obj in tuple(objects['release_files'].items()): | ||
release_id = _get_id(obj, 'release') | ||
try: | ||
release = objects['releases'][release_id] | ||
except KeyError: | ||
# Release files for draft releases are available through the API, | ||
# the releases are not. See #1308 for details. | ||
objects['release_files'].pop(key) | ||
else: | ||
obj['release'] = release | ||
obj['os'] = objects['oses'][_get_id(obj, 'os')] | ||
objects['release_files'][key] = ReleaseFileFactory(**obj) | ||
|
||
return { | ||
'oses': list(objects.pop('oses').values()), | ||
'releases': list(objects.pop('releases').values()), | ||
'release_files': list(objects.pop('release_files').values()), | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add
is_latest
as well? We need it to makeupdate_supernav()
work. 5ad3ebf should expose it in both APIs.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's no need to add
is_latest
to the factory, if it's on the model then it's also on the factory. So in this caseis_latest
will default toFalse
. Ininitial_data
the release is created like thisReleaseFactory(**obj)
, so all fields that are available in the API are set on the newly created instance. So this should already setis_latest
correctly.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, yes, I missed you've added
is_published = True
because its default value isFalse
. Good point!