Skip to content

Commit 8106c8e

Browse files
committed
Merge branch 'master' into use-setting-for-footer-api
2 parents afef2e6 + 98a7ff1 commit 8106c8e

File tree

12 files changed

+144
-36
lines changed

12 files changed

+144
-36
lines changed

CHANGELOG.rst

+20
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,23 @@
1+
Version 3.7.4
2+
-------------
3+
4+
:Date: September 05, 2019
5+
6+
* `@ericholscher <http://github.com/ericholscher>`__: Remove paid support callout (`#6140 <https://github.com/readthedocs/readthedocs.org/pull/6140>`__)
7+
* `@ericholscher <http://github.com/ericholscher>`__: Fix IntegrationAdmin with raw_id_fields for Projects (`#6136 <https://github.com/readthedocs/readthedocs.org/pull/6136>`__)
8+
* `@ericholscher <http://github.com/ericholscher>`__: Fix link to html_extra_path (`#6135 <https://github.com/readthedocs/readthedocs.org/pull/6135>`__)
9+
* `@stsewd <http://github.com/stsewd>`__: Move out authorization from FooterHTML view (`#6133 <https://github.com/readthedocs/readthedocs.org/pull/6133>`__)
10+
* `@agjohnson <http://github.com/agjohnson>`__: Add setting for always cleaning the build post-build (`#6132 <https://github.com/readthedocs/readthedocs.org/pull/6132>`__)
11+
* `@pyup-bot <http://github.com/pyup-bot>`__: pyup: Scheduled weekly dependency update for week 35 (`#6129 <https://github.com/readthedocs/readthedocs.org/pull/6129>`__)
12+
* `@stsewd <http://github.com/stsewd>`__: Refactor footer_html view to class (`#6125 <https://github.com/readthedocs/readthedocs.org/pull/6125>`__)
13+
* `@ericholscher <http://github.com/ericholscher>`__: Use raw_id_fields in the TokenAdmin (`#6116 <https://github.com/readthedocs/readthedocs.org/pull/6116>`__)
14+
* `@davidfischer <http://github.com/davidfischer>`__: Fixed footer ads supported on all themes (`#6115 <https://github.com/readthedocs/readthedocs.org/pull/6115>`__)
15+
* `@stsewd <http://github.com/stsewd>`__: Don't log BuildEnvironmentWarning as error (`#6112 <https://github.com/readthedocs/readthedocs.org/pull/6112>`__)
16+
* `@pllim <http://github.com/pllim>`__: Use the force when fetching with Git (`#6109 <https://github.com/readthedocs/readthedocs.org/pull/6109>`__)
17+
* `@dojutsu-user <http://github.com/dojutsu-user>`__: Record search queries smartly (`#6088 <https://github.com/readthedocs/readthedocs.org/pull/6088>`__)
18+
* `@stsewd <http://github.com/stsewd>`__: Add move method to automation rule (`#5998 <https://github.com/readthedocs/readthedocs.org/pull/5998>`__)
19+
* `@dojutsu-user <http://github.com/dojutsu-user>`__: Index more domain data into elasticsearch (`#5979 <https://github.com/readthedocs/readthedocs.org/pull/5979>`__)
20+
121
Version 3.7.3
222
-------------
323

docs/custom_installs/index.rst

+2-3
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,8 @@ It has those features and more!
1212

1313
.. warning::
1414
These documents are maintained by the community, and might not be up to date.
15-
Read the Docs developers do not support custom installs of our software
16-
in our public issue tracker. For additional support of a custom installation,
17-
please see our `paid support plans <https://readthedocs.com/services/#open-source-support>`_.
15+
Read the Docs developers do not support custom installs of our software,
16+
as mentioned in our :doc:`/open-source-philosophy`.
1817

1918
.. toctree::
2019
:maxdepth: 2

docs/faq.rst

+15-9
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ To accomplish this, you can add a ``robots.txt`` file to your documentation's ro
257257

258258

259259
Minimal example of ``robots.txt``
260-
+++++++++++++++++++++++++++++++++
260+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
261261

262262
::
263263

@@ -270,22 +270,28 @@ Minimal example of ``robots.txt``
270270
See `Google's docs`_ for its full syntax.
271271

272272
This file has to be served as is under ``/robots.txt``.
273-
Depending if you are using Sphinx or MkDocs, you will need a different configuration for this.
274273

274+
Setup
275+
~~~~~
275276

276-
Sphinx
277-
~~~~~~
277+
The ``robots.txt`` file will be served from the **default version** of your Project.
278+
This is because the ``robots.txt`` file is served at the top-level of your domain,
279+
so we must choose a version to find the file in.
280+
The **default version** is the best place to look for it.
281+
282+
Sphinx and Mkdocs both have different ways of outputting static files in the build:
278283

279-
Sphinx uses `html_extra`_ option to add static files to the output.
280-
You need to create a ``robots.txt`` file and put it under the path defined in ``html_extra``.
284+
Sphinx
285+
++++++
281286

287+
Sphinx uses `html_extra_path`_ option to add static files to the output.
288+
You need to create a ``robots.txt`` file and put it under the path defined in ``html_extra_path``.
282289

283290
MkDocs
284-
~~~~~~
291+
++++++
285292

286293
MkDocs needs the ``robots.txt`` to be at the directory defined at `docs_dir`_ config.
287294

288-
289295
.. _Google's docs: https://support.google.com/webmasters/answer/6062608
290-
.. _html_extra: https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-html_extra_path
296+
.. _html_extra_path: https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-html_extra_path
291297
.. _docs_dir: https://www.mkdocs.org/user-guide/configuration/#docs_dir

readthedocs/core/static-src/core/js/doc-embed/rtd-data.js

-4
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,6 @@ var configMethods = {
2222
return constants.ALABASTER_LIKE_THEMES.indexOf(this.get_theme_name()) > -1;
2323
},
2424

25-
theme_supports_paid_promo: function () {
26-
return this.is_rtd_like_theme() || this.is_alabaster_like_theme();
27-
},
28-
2925
is_sphinx_builder: function () {
3026
return (!('builder' in this) || this.builder !== 'mkdocs');
3127
},

readthedocs/core/static-src/core/js/doc-embed/sponsorship.js

-4
Original file line numberDiff line numberDiff line change
@@ -320,10 +320,6 @@ function init() {
320320
request_data.project = rtd.project;
321321
request_data.theme = rtd.get_theme_name();
322322

323-
// These will get community only ads temporarily
324-
// After the fixed footer rollout is complete, this can be removed
325-
request_data.community_only = (rtd.theme_supports_paid_promo() || explicit_placement) ? 0 : 1;
326-
327323
if (typeof URL !== 'undefined' && typeof URLSearchParams !== 'undefined') {
328324
// Force a specific promo to be displayed
329325
params = new URL(window.location).searchParams;

readthedocs/core/static/core/js/readthedocs-doc-embed.js

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

readthedocs/projects/static/projects/js/tools.js

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

readthedocs/search/api.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import itertools
22
import logging
33

4+
from django.utils import timezone
45
from rest_framework import generics, serializers
56
from rest_framework.exceptions import ValidationError
67
from rest_framework.pagination import PageNumberPagination
@@ -160,15 +161,19 @@ def list(self, request, *args, **kwargs):
160161

161162
project_slug = self.request.query_params.get('project', None)
162163
version_slug = self.request.query_params.get('version', None)
163-
query = self.request.query_params.get('q', '')
164164
total_results = response.data.get('count', 0)
165+
time = timezone.now()
166+
167+
query = self.request.query_params.get('q', '')
168+
query = query.lower().strip()
165169

166170
# record the search query with a celery task
167171
tasks.record_search_query.delay(
168172
project_slug,
169173
version_slug,
170174
query,
171175
total_results,
176+
time.isoformat(),
172177
)
173178

174179
return response

readthedocs/search/tasks.py

+45-9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import logging
22

3+
from dateutil.parser import parse
34
from django.apps import apps
45
from django.utils import timezone
56
from django_elasticsearch_dsl.registries import registry
@@ -142,20 +143,46 @@ def delete_old_search_queries_from_db():
142143

143144

144145
@app.task(queue='web')
145-
def record_search_query(project_slug, version_slug, query, total_results):
146-
"""Record search query in database."""
147-
if not project_slug or not version_slug or not query or not total_results:
146+
def record_search_query(project_slug, version_slug, query, total_results, time_string):
147+
"""Record/update search query in database."""
148+
if not project_slug or not version_slug or not query:
148149
log.debug(
149150
'Not recording the search query. Passed arguments: '
150-
'project_slug: %s, version_slug: %s, query: %s, total_results: %s' % (
151-
project_slug, version_slug, query, total_results
151+
'project_slug: %s, version_slug: %s, query: %s, total_results: %s, time: %s' % (
152+
project_slug, version_slug, query, total_results, time_string
152153
)
153154
)
154155
return
155156

156-
project_qs = Project.objects.filter(slug=project_slug)
157+
time = parse(time_string)
158+
before_10_sec = time - timezone.timedelta(seconds=10)
159+
partial_query_qs = SearchQuery.objects.filter(
160+
project__slug=project_slug,
161+
version__slug=version_slug,
162+
created__gte=before_10_sec,
163+
).order_by('-created')
164+
165+
# check if partial query exists,
166+
# if yes, then just update the object.
167+
for partial_query in partial_query_qs.iterator():
168+
if query.startswith(partial_query.query):
169+
partial_query.created = time
170+
partial_query.query = query
171+
partial_query.save()
172+
return
173+
174+
# don't record query with zero results.
175+
if not total_results:
176+
log.debug(
177+
'Not recording search query because of zero results. Passed arguments: '
178+
'project_slug: %s, version_slug: %s, query: %s, total_results: %s, time: %s' % (
179+
project_slug, version_slug, query, total_results, time
180+
)
181+
)
182+
return
157183

158-
if not project_qs.exists():
184+
project = Project.objects.filter(slug=project_slug).first()
185+
if not project:
159186
log.debug(
160187
'Not recording the search query because project does not exist. '
161188
'project_slug: %s' % (
@@ -164,15 +191,24 @@ def record_search_query(project_slug, version_slug, query, total_results):
164191
)
165192
return
166193

167-
project = project_qs.first()
168194
version_qs = Version.objects.filter(project=project, slug=version_slug)
169195

170196
if not version_qs.exists():
197+
log.debug(
198+
'Not recording the search query because version does not exist. '
199+
'project_slug: %s, version_slug: %s' % (
200+
project_slug, version_slug
201+
)
202+
)
171203
return
172204

173205
version = version_qs.first()
174-
SearchQuery.objects.create(
206+
207+
# make a new SearchQuery object.
208+
obj = SearchQuery.objects.create(
175209
project=project,
176210
version=version,
177211
query=query,
178212
)
213+
obj.created = time
214+
obj.save()

readthedocs/search/tests/test_search_tasks.py

+43
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"""Tests for search tasks."""
22

3+
import mock
34
import pytest
45

56
from django.urls import reverse
@@ -43,6 +44,48 @@ def test_search_query_recorded_when_results_not_zero(self, api_client):
4344
SearchQuery.objects.all().count() == 1
4445
), 'there should be 1 obj since a search is made which returns one result.'
4546

47+
def test_partial_queries_are_not_recorded(self, api_client):
48+
"""Test if partial queries are not recorded."""
49+
50+
assert (
51+
SearchQuery.objects.all().count() == 0
52+
), 'no SearchQuery should be present if there is no search made.'
53+
54+
time = timezone.now()
55+
search_params = { 'q': 'stack', 'project': 'docs', 'version': 'latest' }
56+
57+
with mock.patch('django.utils.timezone.now') as test_time:
58+
test_time.return_value = time
59+
resp = api_client.get(self.url, search_params)
60+
assert resp.status_code, 200
61+
62+
assert (
63+
SearchQuery.objects.all().count() == 1
64+
), 'one SearchQuery should be present'
65+
66+
# update the time and the search query and make another search request
67+
time = time + timezone.timedelta(seconds=2)
68+
search_params['q'] = 'stack over'
69+
with mock.patch('django.utils.timezone.now') as test_time:
70+
test_time.return_value = time
71+
resp = api_client.get(self.url, search_params)
72+
assert resp.status_code, 200
73+
74+
# update the time and the search query and make another search request
75+
time = time + timezone.timedelta(seconds=2)
76+
search_params['q'] = 'stack overflow'
77+
with mock.patch('django.utils.timezone.now') as test_time:
78+
test_time.return_value = time
79+
resp = api_client.get(self.url, search_params)
80+
assert resp.status_code, 200
81+
82+
assert (
83+
SearchQuery.objects.all().count() == 1
84+
), 'one SearchQuery should be present'
85+
assert (
86+
SearchQuery.objects.all().first().query == 'stack overflow'
87+
), 'one SearchQuery should be there because partial queries gets updated'
88+
4689
def test_search_query_not_recorded_when_results_are_zero(self, api_client):
4790
"""Test that search queries are not recorded when they have zero results."""
4891

readthedocs/vcs_support/base.py

+10-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
# -*- coding: utf-8 -*-
2-
31
"""Base classes for VCS backends."""
42
import logging
53
import os
64
import shutil
75

6+
from readthedocs.doc_builder.exceptions import BuildEnvironmentWarning
7+
from readthedocs.projects.exceptions import RepositoryError
8+
89

910
log = logging.getLogger(__name__)
1011

@@ -102,7 +103,13 @@ def run(self, *cmd, **kwargs):
102103
'shell': False,
103104
})
104105

105-
build_cmd = self.environment.run(*cmd, **kwargs)
106+
try:
107+
build_cmd = self.environment.run(*cmd, **kwargs)
108+
except BuildEnvironmentWarning as e:
109+
# Re raise as RepositoryError,
110+
# so isn't logged as ERROR.
111+
raise RepositoryError(str(e))
112+
106113
# Return a tuple to keep compatibility
107114
return (build_cmd.exit_code, build_cmd.output, build_cmd.error)
108115

setup.cfg

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[metadata]
22
name = readthedocs
3-
version = 3.7.3
3+
version = 3.7.4
44
license = MIT
55
description = Read the Docs builds and hosts documentation
66
author = Read the Docs, Inc

0 commit comments

Comments
 (0)