Skip to content

Commit

Permalink
Retrieve JSON data from an external source
Browse files Browse the repository at this point in the history
Allow the user to define a custom URL to retrieve the JSON
data (instead of hitting Read the Docs API) needed to add the banner
into the page.

This is useful when there is a git tag that doesn't want to be
updated, but now the warning message is out of date. So, by defining a
custom URL (potentially a JSON under the git repository served by
github, for example) this file is retrieved by the documentation and
displayed the custom message needed at certain date.

The JSON file can be updated independently from the documentation/tag/etc.
  • Loading branch information
humitos committed Oct 26, 2018
1 parent 0447ab4 commit 0c17a31
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 14 deletions.
2 changes: 1 addition & 1 deletion versionwarning/_static/js/versionwarning.js

Large diffs are not rendered by default.

35 changes: 32 additions & 3 deletions versionwarning/_static/js/versionwarning.src.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,16 @@ function checkVersion(config) {
});
}

function handleBanner(config) {
console.debug("handleBanner");
if (config.banner.custom) {
injectCustomWarningBanner(config);
}
else {
checkVersion(config);
}
}

function init() {
console.debug("init");
$.ajax({
Expand All @@ -90,11 +100,30 @@ function init() {
if (banner) {
console.debug("There is already a banner added. No checking versions.")
}
else if (config.banner.custom) {
injectCustomWarningBanner(config);
else if (config.meta.json_url && !config.meta.retrieve_data_from_api) {
console.debug("Retrieving dynamic data from 'json_url'.")
$.ajax({
dataType: "json",
cache: "false",
url: config.meta.json_url,
success: function(dynamic_config) {
if (config.version.slug in dynamic_config) {
handleBanner(dynamic_config[config.version.slug]);
}
else if (config.meta.only_override_banner) {
handleBanner(config);
}
else {
log.error("JSON data from " + config.meta.json_url + " does not have a warning banner for " + config.version.slug);
}
},
error: function() {
console.error("Error loading dynamic config object");
},
});
}
else {
checkVersion(config);
handleBanner(config);
}
},
error: function() {
Expand Down
16 changes: 16 additions & 0 deletions versionwarning/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# -*- coding: utf-8 -*-


class ConfigError(Exception):
"""
Incompatible config exception.
This exception is risen when the extension detects configs that are
incompatible or that depends each other.
"""

NO_JSON_URL = (
'No URL defined to retrieve JSON data. '
'The URL is mandatory when "versionwarning_retrieve_data_from_api" '
'is True'
)
5 changes: 5 additions & 0 deletions versionwarning/extension.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ def setup(app):
app.add_config_value('versionwarning_project_slug', os.environ.get('READTHEDOCS_PROJECT', None), 'html')
app.add_config_value('versionwarning_project_version', os.environ.get('READTHEDOCS_VERSION', None), 'html')


app.add_config_value('versionwarning_retrieve_data_from_api', True, 'html')
app.add_config_value('versionwarning_json_url', None, 'html')
app.add_config_value('versionwarning_only_override_banner', True, 'html')

if sphinx.version_info >= (1, 8):
# ``config-initied`` requires Sphinx >= 1.8
app.connect('config-inited', generate_versionwarning_data_json)
Expand Down
39 changes: 29 additions & 10 deletions versionwarning/signals.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import json
import os

from versionwarning.exceptions import ConfigError


STATIC_PATH = os.path.join(os.path.dirname(__file__), '_static')
JSON_DATA_FILENAME = 'versionwarning-data.json'
Expand All @@ -27,6 +29,9 @@ def generate_versionwarning_data_json(app, config=None, **kwargs):
if config is None:
config = app.config

if not config.versionwarning_retrieve_data_from_api and not config.versionwarning_json_url:
raise ConfigError(ConfigError.NO_JSON_URL)

if config.versionwarning_project_version in config.versionwarning_messages:
custom = True
message = config.versionwarning_messages.get(config.versionwarning_project_version)
Expand All @@ -43,30 +48,44 @@ def generate_versionwarning_data_json(app, config=None, **kwargs):
admonition_type=config.versionwarning_admonition_type,
)

data = json.dumps({
'meta': {
'api_url': config.versionwarning_api_url,
},
data = {
'banner': {
'html': banner_html,
'id_div': config.versionwarning_banner_id_div,
'body_selector': config.versionwarning_body_selector,
'custom': custom,
config.versionwarning_project_version: {
'html': banner_html,
'id_div': config.versionwarning_banner_id_div,
'body_selector': config.versionwarning_body_selector,
'custom': custom,
},
},
'project': {
'slug': config.versionwarning_project_slug,
},
'version': {
'slug': config.versionwarning_project_version,
},
}, indent=4)
}

if config.versionwarning_retrieve_data_from_api:
url_key = 'api_url'
url = config.versionwarning_api_url
else:
url_key = 'json_url'
url = config.versionwarning_json_url

data.update({
'meta': {
url_key: url,
'retrieve_data_from_api': config.versionwarning_retrieve_data_from_api,
'only_override_banner': config.versionwarning_only_override_banner,
},
})

data_path = os.path.join(STATIC_PATH, 'data')
if not os.path.exists(data_path):
os.mkdir(data_path)

with open(os.path.join(data_path, JSON_DATA_FILENAME), 'w') as f:
f.write(data)
f.write(json.dumps(data, indent=4))

# Add the path where ``versionwarning-data.json`` file and
# ``versionwarning.js`` are saved
Expand Down

0 comments on commit 0c17a31

Please sign in to comment.