Skip to content

Commit b5fc464

Browse files
committed
Merge tag '8.7.0' into rel
2 parents f32a0f2 + 55fd87e commit b5fc464

File tree

110 files changed

+6629
-6388
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

110 files changed

+6629
-6388
lines changed

CHANGELOG.rst

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,22 @@
1+
Version 8.7.0
2+
-------------
3+
4+
:Date: October 11, 2022
5+
6+
* `@github-actions[bot] <https://github.com/github-actions[bot]>`__: Dependencies: all packages updated via pip-tools (`#9648 <https://github.com/readthedocs/readthedocs.org/pull/9648>`__)
7+
* `@humitos <https://github.com/humitos>`__: Settings: enable `django-debug-toolbar` when Django Admin is enabled (`#9641 <https://github.com/readthedocs/readthedocs.org/pull/9641>`__)
8+
* `@stsewd <https://github.com/stsewd>`__: Subscriptions: use stripe price instead of relying on plan object (`#9640 <https://github.com/readthedocs/readthedocs.org/pull/9640>`__)
9+
* `@github-actions[bot] <https://github.com/github-actions[bot]>`__: Dependencies: all packages updated via pip-tools (`#9636 <https://github.com/readthedocs/readthedocs.org/pull/9636>`__)
10+
* `@humitos <https://github.com/humitos>`__: Query: minor improvement (`#9634 <https://github.com/readthedocs/readthedocs.org/pull/9634>`__)
11+
* `@ericholscher <https://github.com/ericholscher>`__: Release 8.6.0 (`#9630 <https://github.com/readthedocs/readthedocs.org/pull/9630>`__)
12+
* `@humitos <https://github.com/humitos>`__: Run django-upgrade (`#9628 <https://github.com/readthedocs/readthedocs.org/pull/9628>`__)
13+
* `@stsewd <https://github.com/stsewd>`__: Search: refactor serializer's context (`#9624 <https://github.com/readthedocs/readthedocs.org/pull/9624>`__)
14+
* `@benjaoming <https://github.com/benjaoming>`__: Docs: Re-scope Intersphinx article as a how-to (`#9622 <https://github.com/readthedocs/readthedocs.org/pull/9622>`__)
15+
* `@evildmp <https://github.com/evildmp>`__: Made some small changes to the MyST migration how-to (`#9620 <https://github.com/readthedocs/readthedocs.org/pull/9620>`__)
16+
* `@stsewd <https://github.com/stsewd>`__: Search: move api.py into a module (`#9616 <https://github.com/readthedocs/readthedocs.org/pull/9616>`__)
17+
* `@humitos <https://github.com/humitos>`__: Build: remove `DEDUPLICATE_BUILDS` feature (`#9591 <https://github.com/readthedocs/readthedocs.org/pull/9591>`__)
18+
* `@stsewd <https://github.com/stsewd>`__: Email: render template before sending it to the task (`#9538 <https://github.com/readthedocs/readthedocs.org/pull/9538>`__)
19+
120
Version 8.6.0
221
-------------
322

dockerfiles/settings/proxito.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@
66
class ProxitoDevSettings(CommunityProxitoSettingsMixin, DockerBaseSettings):
77

88
# El Proxito does not have django-debug-toolbar installed
9-
DEBUG_TOOLBAR_CONFIG = {
10-
'SHOW_TOOLBAR_CALLBACK': lambda request: False,
11-
}
9+
@property
10+
def DEBUG_TOOLBAR_CONFIG(self):
11+
return {
12+
'SHOW_TOOLBAR_CALLBACK': lambda request: False,
13+
}
1214

1315

1416
ProxitoDevSettings.load_settings(__name__)

docs/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@
6969

7070
master_doc = "index"
7171
copyright = "2010, Read the Docs, Inc & contributors"
72-
version = "8.6.0"
72+
version = "8.7.0"
7373
release = version
7474
exclude_patterns = ["_build"]
7575
default_role = "obj"

docs/user/guides/authors.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@ and :doc:`/intro/getting-started-with-mkdocs`.
1414
:maxdepth: 1
1515

1616
cross-referencing-with-sphinx
17-
intersphinx
17+
Link to external projects (Intersphinx) <intersphinx>
1818
jupyter
1919
Migrate from rST to MyST <migrate-rest-myst>

docs/user/guides/intersphinx.rst

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
Link to Other Projects' Documentation With Intersphinx
2-
======================================================
1+
How to Link to Other Documentation Projects With Intersphinx
2+
============================================================
3+
4+
This section shows you how to maintain references to named sections of other external Sphinx projects.
35

46
You may be familiar with using the :ref:`:ref: role <sphinx:ref-role>` to
57
:doc:`link to any location of your docs </guides/cross-referencing-with-sphinx>`.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "readthedocs",
3-
"version": "8.6.0",
3+
"version": "8.7.0",
44
"description": "Read the Docs build dependencies",
55
"author": "Read the Docs, Inc <[email protected]>",
66
"scripts": {

readthedocs/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
"""Read the Docs."""
22

33

4-
__version__ = "8.6.0"
4+
__version__ = "8.7.0"

readthedocs/analytics/tests.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,9 @@ def test_get_client_ip_with_x_forwarded_for(self):
8888

8989
def test_get_client_ip_with_remote_addr(self):
9090

91-
request = RequestFactory().get('/')
92-
self.assertIsNone(request.META.get('HTTP_X_FORWARDED_FOR'))
93-
request.META['REMOTE_ADDR'] = '203.0.113.195'
91+
request = RequestFactory().get("/")
92+
self.assertIsNone(request.headers.get("X-Forwarded-For"))
93+
request.META["REMOTE_ADDR"] = "203.0.113.195"
9494
client_ip = get_client_ip(request)
9595
self.assertEqual(client_ip, '203.0.113.195')
9696

readthedocs/analytics/utils.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
1-
# -*- coding: utf-8 -*-
21

32
"""Utilities related to analytics."""
43

54
import hashlib
65
import ipaddress
7-
import structlog
86

97
import requests
8+
import structlog
109
from django.conf import settings
1110
from django.utils.crypto import get_random_string
1211
from django.utils.encoding import force_bytes, force_str
1312
from user_agents import parse
1413

15-
1614
log = structlog.get_logger(__name__) # noqa
1715

1816

@@ -24,7 +22,7 @@ def get_client_ip(request):
2422
header. If ``HTTP_X_FORWARDED_FOR`` is not found, it returns the value of
2523
``REMOTE_ADDR`` header and returns ``None`` if both the headers are not found.
2624
"""
27-
x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR', None)
25+
x_forwarded_for = request.headers.get("X-Forwarded-For", None)
2826
if x_forwarded_for:
2927
# HTTP_X_FORWARDED_FOR can be a comma-separated list of IPs.
3028
# The client's IP will be the first one.
@@ -114,6 +112,6 @@ def generate_client_id(ip_address, user_agent):
114112
# Since no IP and no UA were specified,
115113
# there's no way to distinguish sessions.
116114
# Instead, just treat every user differently
117-
hash_id.update(force_bytes(get_random_string()))
115+
hash_id.update(force_bytes(get_random_string(length=12)))
118116

119117
return hash_id.hexdigest()

readthedocs/api/v2/proxied_urls.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
from readthedocs.analytics.proxied_api import AnalyticsView
1111
from readthedocs.api.v2.views.proxied import ProxiedEmbedAPI, ProxiedFooterHTML
12-
from readthedocs.search.proxied_api import ProxiedPageSearchAPIView
12+
from readthedocs.search.api.v2.views import ProxiedPageSearchAPIView
1313

1414
api_footer_urls = [
1515
re_path(r'footer_html/', ProxiedFooterHTML.as_view(), name='footer_html'),

readthedocs/api/v2/urls.py

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,11 @@
11
"""Define routes between URL paths and views/endpoints."""
22

33
from django.conf import settings
4-
from django.conf.urls import include, re_path
4+
from django.conf.urls import re_path
5+
from django.urls import include
56
from rest_framework import routers
67

7-
from readthedocs.api.v2.views import (
8-
core_views,
9-
footer_views,
10-
integrations,
11-
task_views,
12-
)
8+
from readthedocs.api.v2.views import core_views, footer_views, integrations, task_views
139
from readthedocs.constants import pattern_opts
1410
from readthedocs.gold.views import StripeEventView
1511

@@ -24,7 +20,6 @@
2420
VersionViewSet,
2521
)
2622

27-
2823
router = routers.DefaultRouter()
2924
router.register(r'build', BuildViewSet, basename='build')
3025
router.register(r'command', BuildCommandViewSet, basename='buildcommandresult')
@@ -117,9 +112,7 @@
117112

118113
if 'readthedocsext.donate' in settings.INSTALLED_APPS:
119114
# pylint: disable=import-error
120-
from readthedocsext.donate.restapi.urls import (
121-
urlpatterns as sustainability_urls,
122-
)
115+
from readthedocsext.donate.restapi.urls import urlpatterns as sustainability_urls
123116

124117
urlpatterns += [
125118
re_path(r'^sustainability/', include(sustainability_urls)),

readthedocs/builds/constants.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,10 +140,8 @@
140140
}
141141

142142
BUILD_STATUS_NORMAL = 'normal'
143-
BUILD_STATUS_DUPLICATED = 'duplicated'
144143
BUILD_STATUS_CHOICES = (
145144
(BUILD_STATUS_NORMAL, 'Normal'),
146-
(BUILD_STATUS_DUPLICATED, 'Duplicated'),
147145
)
148146

149147

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Generated by Django 3.2.15 on 2022-10-06 09:03
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
("builds", "0044_alter_version_documentation_type"),
10+
]
11+
12+
operations = [
13+
migrations.AlterField(
14+
model_name="build",
15+
name="status",
16+
field=models.CharField(
17+
blank=True,
18+
choices=[("normal", "Normal")],
19+
default=None,
20+
max_length=32,
21+
null=True,
22+
verbose_name="Status",
23+
),
24+
),
25+
]

readthedocs/builds/tasks.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -542,8 +542,6 @@ def send(self):
542542

543543
def send_email(self, email):
544544
"""Send email notifications for build failures."""
545-
# We send only what we need from the Django model objects here to avoid
546-
# serialization problems in the ``readthedocs.core.tasks.send_email_task``
547545
protocol = 'http' if settings.DEBUG else 'https'
548546
context = {
549547
'version': {

readthedocs/core/tasks.py

Lines changed: 11 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,21 @@
1-
# -*- coding: utf-8 -*-
2-
31
"""Basic tasks."""
42

53
import structlog
6-
74
from django.conf import settings
85
from django.core.mail import EmailMultiAlternatives
9-
from django.template import TemplateDoesNotExist
10-
from django.template.loader import get_template
116
from django.utils import timezone
127
from messages_extends.models import Message as PersistentMessage
138

149
from readthedocs.worker import app
1510

16-
1711
log = structlog.get_logger(__name__)
1812

1913
EMAIL_TIME_LIMIT = 30
2014

2115

2216
@app.task(queue='web', time_limit=EMAIL_TIME_LIMIT)
2317
def send_email_task(
24-
recipient, subject, template, template_html, context=None,
25-
from_email=None, **kwargs
18+
recipient, subject, content, content_html=None, from_email=None, **kwargs
2619
):
2720
"""
2821
Send multipart email.
@@ -33,34 +26,26 @@ def send_email_task(
3326
subject
3427
Email subject header
3528
36-
template
29+
content
3730
Plain text template to send
3831
39-
template_html
40-
HTML template to send as new message part
41-
42-
context
43-
A dictionary to pass into the template calls
32+
content_html
33+
HTML content to send as new message part
4434
4535
kwargs
4636
Additional options to the EmailMultiAlternatives option.
4737
"""
4838
msg = EmailMultiAlternatives(
4939
subject,
50-
get_template(template).render(context), from_email or
51-
settings.DEFAULT_FROM_EMAIL,
52-
[recipient], **kwargs
40+
content,
41+
from_email or settings.DEFAULT_FROM_EMAIL,
42+
[recipient],
43+
**kwargs
5344
)
54-
try:
55-
msg.attach_alternative(
56-
get_template(template_html).render(context),
57-
'text/html',
58-
)
59-
except (TypeError, TemplateDoesNotExist):
60-
# TypeError is raised when ``template_html`` is ``None``
61-
pass
45+
if content_html:
46+
msg.attach_alternative(content_html, "text/html")
47+
log.info("Sending email to recipient.", recipient=recipient)
6248
msg.send()
63-
log.info('Sent email to recipient.', recipient=recipient)
6449

6550

6651
@app.task(queue='web')

0 commit comments

Comments
 (0)