Skip to content

Commit 1094e78

Browse files
committed
Re-add the management command for importing via API
1 parent 15aa854 commit 1094e78

File tree

3 files changed

+97
-0
lines changed

3 files changed

+97
-0
lines changed

readthedocs/projects/management/__init__.py

Whitespace-only changes.

readthedocs/projects/management/commands/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
# -*- coding: utf-8 -*-
2+
3+
"""Import project command."""
4+
5+
import json
6+
import os
7+
8+
from django.contrib.auth.models import User
9+
from django.core.management import call_command
10+
from django.core.management.base import BaseCommand
11+
import requests
12+
13+
from ...models import Project
14+
15+
16+
class Command(BaseCommand):
17+
18+
"""
19+
Import project from production API.
20+
21+
This is a helper to debug issues with projects on the server more easily
22+
locally. It allows you to import projects based on the data that the public
23+
API provides.
24+
"""
25+
26+
help = (
27+
"Retrieves the data of a project from readthedocs.org's API and puts "
28+
'it into the local database. This is mostly useful for debugging '
29+
'issues with projects on the live site.'
30+
)
31+
32+
def add_arguments(self, parser):
33+
parser.add_argument('project_slug', nargs='+', type=str)
34+
35+
def handle(self, *args, **options):
36+
auth = None
37+
user1 = User.objects.filter(pk__gt=0).order_by('pk').first()
38+
39+
if 'READ_THE_DOCS_USERNAME' in os.environ and 'READ_THE_DOCS_PASSWORD' in os.environ:
40+
# Authenticating allows returning additional useful fields in the API
41+
# See: `ProjectAdminSerializer`
42+
username = os.environ['READ_THE_DOCS_USERNAME']
43+
auth = (username, os.environ['READ_THE_DOCS_PASSWORD'])
44+
self.stdout.write('Using basic auth for user {username}'.format(username=username))
45+
46+
for slug in options['project_slug']:
47+
self.stdout.write('Importing {slug} ...'.format(slug=slug))
48+
49+
resp = requests.get(
50+
'https://readthedocs.org/api/v2/project/',
51+
params={'slug': slug},
52+
auth=auth,
53+
)
54+
resp.raise_for_status() # This should only fail if RTD is having issues
55+
response_data = resp.json()
56+
57+
if response_data['count'] == 1:
58+
project_data = response_data['results'][0]
59+
else:
60+
self.stderr.write(
61+
'Cannot find {slug} in API. Response was:\n{response}'.format(
62+
slug=slug,
63+
response=json.dumps(response_data),
64+
),
65+
)
66+
67+
try:
68+
project = Project.objects.get(slug=slug)
69+
self.stdout.write('Project {slug} already exists. Updating...'.format(slug=slug))
70+
except Project.DoesNotExist:
71+
project = Project(slug=slug)
72+
73+
exclude_attributes = (
74+
'absolute_url',
75+
'analytics_code',
76+
'canonical_url',
77+
'show_advertising',
78+
79+
# These fields could be nice to add
80+
'users',
81+
'features',
82+
'environment_variables',
83+
)
84+
85+
for attribute in project_data:
86+
if attribute not in exclude_attributes:
87+
setattr(project, attribute, project_data[attribute])
88+
self.stdout.write(' - Setting {key} to {val}'.format(
89+
key=attribute,
90+
val=project_data[attribute]),
91+
)
92+
project.user = user1
93+
project.save()
94+
if user1:
95+
project.users.add(user1)
96+
97+
call_command('update_repos', project.slug, version='all')

0 commit comments

Comments
 (0)