Skip to content
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

Remove usage of PHP alias in the Python client #663

Merged
merged 20 commits into from
Oct 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 14 additions & 2 deletions Python-packages/covidcast-py/covidcast/covidcast.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,22 @@
import pandas as pd
import numpy as np
from delphi_epidata import Epidata
from delphi_epidata.delphi_epidata import _HEADERS
from pkg_resources import get_distribution, DistributionNotFound
from epiweeks import Week

from .errors import NoDataWarning


# Point API requests to the default endpoint
Epidata.BASE_URL = "https://api.covidcast.cmu.edu/epidata/api.php"
Epidata.BASE_URL = "https://api.covidcast.cmu.edu/epidata"
# Prepend to Epidata client's user agent to specify this package and version
try:
_ver = get_distribution("covidcast").version
except DistributionNotFound:
_ver = "0.0.0"
_HEADERS['user-agent'] = f"covidcast/{_ver} " + _HEADERS['user-agent']


VALID_GEO_TYPES = {"county", "hrr", "msa", "dma", "state", "hhs", "nation"}

Expand Down Expand Up @@ -463,14 +473,16 @@ def _async_fetch_epidata(data_source: str,
issues: Union[date, tuple, list],
lag: int,
time_type: str = "day") -> Union[pd.DataFrame, None]:
"""Fetch data from Epidata API asynchronously.
"""Fetch data from Epidata API asynchronously [DEPRECATED].

signal() wraps this to support fetching data over a range of dates
and stacks the resulting data frames.

If no data is found, return None, so signal() can easily filter out these
entries.
"""
melange396 marked this conversation as resolved.
Show resolved Hide resolved
warnings.warn("`_async_fetch_epidata` is deprecated and will be removed in a future version.",
category=DeprecationWarning)
dfs = []
params = []
date_range = pd.date_range(start_day, end_day, freq="D" if time_type == "day" else "W")
Expand Down
8 changes: 8 additions & 0 deletions Python-packages/covidcast-py/docs/changelog.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
Changelog
=========

v0.2.2, October 10, 2023
--------------------

- New feature: Web requests now identify themselves with a `covidcast`-specific "user agent" string.
- Update: Now uses newer version of the `delphi-epidata` libarary.
- Bug fix: Removed usage of PHP alias endpoint for compatibility with new `delphi-epidata` version.
- Deprecated function: Private method :py:func:`_async_fetch_epidata` has been deprecated.

v0.2.1, June 1, 2023
--------------------

Expand Down
2 changes: 1 addition & 1 deletion Python-packages/covidcast-py/docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
author = 'Delphi research group'

# The full version, including alpha/beta/rc tags
release = '0.2.1'
release = '0.2.2'


# -- General configuration ---------------------------------------------------
Expand Down
4 changes: 2 additions & 2 deletions Python-packages/covidcast-py/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

setuptools.setup(
name="covidcast",
version="0.2.1", # also update in docs/conf.py
version="0.2.2", # also update in docs/conf.py
author="Alex Reinhart",
author_email="areinhar@stat.cmu.edu",
description="Access COVID-19 data through the Delphi COVIDcast API",
Expand All @@ -22,7 +22,7 @@
install_requires=[
"pandas<2",
"requests",
"delphi-epidata>=4.1.1",
"delphi-epidata>=4.1.11,==4.*",
"geopandas",
"matplotlib",
"numpy",
Expand Down
16 changes: 11 additions & 5 deletions Python-packages/covidcast-py/tests/test_covidcast.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,19 +265,25 @@ def test__async_fetch_epidata(mock_async_epidata):
with warnings.catch_warnings(record=True) as w:
covidcast._async_fetch_epidata("source", "signal", date(2020, 4, 2), date(2020, 4, 2),
"*", None, None, None, None)
assert len(w) == 1
assert len(w) == 2 # including deprecation warning
assert str(w[0].message) == \
"`_async_fetch_epidata` is deprecated and will be removed in a future version."
assert w[0].category is DeprecationWarning
assert str(w[1].message) == \
"Problem obtaining source signal data on 20200402 for geography '*': failed"
assert w[0].category is RuntimeWarning
assert w[1].category is RuntimeWarning

# test warning when a no data response is received
mock_async_epidata.return_value = [({"message": "no results"}, {"time_values": 20200402})] # no data API response
with warnings.catch_warnings(record=True) as w:
covidcast._async_fetch_epidata("source", "signal", date(2020, 4, 2), date(2020, 4, 2),
"county", None, None, None, None)
assert len(w) == 1
assert str(w[0].message) == "No source signal data found on 20200402 for geography 'county'"
assert w[0].category is NoDataWarning
assert len(w) == 2 # including deprecation warning
assert str(w[0].message) == \
"`_async_fetch_epidata` is deprecated and will be removed in a future version."
assert w[0].category is DeprecationWarning
assert str(w[1].message) == "No source signal data found on 20200402 for geography 'county'"
assert w[1].category is NoDataWarning

# test no epidata yields nothing
mock_async_epidata.return_value = [({"message": "success"}, None)] # no epidata
Expand Down
Binary file modified docs/covidcast-py/doctrees/changelog.doctree
Binary file not shown.
Binary file modified docs/covidcast-py/doctrees/environment.pickle
Binary file not shown.
Binary file modified docs/covidcast-py/doctrees/getting_started.doctree
Binary file not shown.
Binary file modified docs/covidcast-py/doctrees/index.doctree
Binary file not shown.
Binary file modified docs/covidcast-py/doctrees/plot_examples.doctree
Binary file not shown.
Binary file modified docs/covidcast-py/doctrees/plotting.doctree
Binary file not shown.
Binary file modified docs/covidcast-py/doctrees/signals.doctree
Binary file not shown.
2 changes: 1 addition & 1 deletion docs/covidcast-py/html/.buildinfo
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Sphinx build info version 1
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
config: adc91b801928f140c7be8ffe81e03415
config: cbbd65a1377a79b8be99216462605909
tags: 645f666f9bcd5a90fca523b33c5a78b7
8 changes: 8 additions & 0 deletions docs/covidcast-py/html/_sources/changelog.rst.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
Changelog
=========

v0.2.2, October 10, 2023
--------------------

- New feature: Web requests now identify themselves with a `covidcast`-specific "user agent" string.
- Update: Now uses newer version of the `delphi-epidata` libarary.
- Bug fix: Removed usage of PHP alias endpoint for compatibility with new `delphi-epidata` version.
- Deprecated function: Private method :py:func:`_async_fetch_epidata` has been deprecated.

v0.2.1, June 1, 2023
--------------------

Expand Down
22 changes: 22 additions & 0 deletions docs/covidcast-py/html/_static/basic.css
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,10 @@ a.headerlink {
visibility: hidden;
}

a:visited {
color: #551A8B;
}

h1:hover > a.headerlink,
h2:hover > a.headerlink,
h3:hover > a.headerlink,
Expand Down Expand Up @@ -670,6 +674,16 @@ dd {
margin-left: 30px;
}

.sig dd {
margin-top: 0px;
margin-bottom: 0px;
}

.sig dl {
margin-top: 0px;
margin-bottom: 0px;
}

dl > dd:last-child,
dl > dd:last-child > :last-child {
margin-bottom: 0;
Expand Down Expand Up @@ -738,6 +752,14 @@ abbr, acronym {
cursor: help;
}

.translated {
background-color: rgba(207, 255, 207, 0.2)
}

.untranslated {
background-color: rgba(255, 207, 207, 0.2)
}

/* -- code displays --------------------------------------------------------- */

pre {
Expand Down
5 changes: 2 additions & 3 deletions docs/covidcast-py/html/_static/documentation_options.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
var DOCUMENTATION_OPTIONS = {
URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'),
VERSION: '0.2.1',
const DOCUMENTATION_OPTIONS = {
VERSION: '0.2.2',
LANGUAGE: 'en',
COLLAPSE_INDEX: false,
BUILDER: 'html',
Expand Down
1 change: 1 addition & 0 deletions docs/covidcast-py/html/_static/pygments.css
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ span.linenos.special { color: #000000; background-color: #ffffc0; padding-left:
.highlight .cs { color: #8f5902; font-style: italic } /* Comment.Special */
.highlight .gd { color: #a40000 } /* Generic.Deleted */
.highlight .ge { color: #000000; font-style: italic } /* Generic.Emph */
.highlight .ges { color: #000000 } /* Generic.EmphStrong */
.highlight .gr { color: #ef2929 } /* Generic.Error */
.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
.highlight .gi { color: #00A000 } /* Generic.Inserted */
Expand Down
26 changes: 17 additions & 9 deletions docs/covidcast-py/html/_static/searchtools.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,12 @@ const _removeChildren = (element) => {
const _escapeRegExp = (string) =>
string.replace(/[.*+\-?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string

const _displayItem = (item, searchTerms) => {
const _displayItem = (item, searchTerms, highlightTerms) => {
const docBuilder = DOCUMENTATION_OPTIONS.BUILDER;
const docUrlRoot = DOCUMENTATION_OPTIONS.URL_ROOT;
const docFileSuffix = DOCUMENTATION_OPTIONS.FILE_SUFFIX;
const docLinkSuffix = DOCUMENTATION_OPTIONS.LINK_SUFFIX;
const showSearchSummary = DOCUMENTATION_OPTIONS.SHOW_SEARCH_SUMMARY;
const contentRoot = document.documentElement.dataset.content_root;

const [docName, title, anchor, descr, score, _filename] = item;

Expand All @@ -75,20 +75,24 @@ const _displayItem = (item, searchTerms) => {
if (dirname.match(/\/index\/$/))
dirname = dirname.substring(0, dirname.length - 6);
else if (dirname === "index/") dirname = "";
requestUrl = docUrlRoot + dirname;
requestUrl = contentRoot + dirname;
linkUrl = requestUrl;
} else {
// normal html builders
requestUrl = docUrlRoot + docName + docFileSuffix;
requestUrl = contentRoot + docName + docFileSuffix;
linkUrl = docName + docLinkSuffix;
}
let linkEl = listItem.appendChild(document.createElement("a"));
linkEl.href = linkUrl + anchor;
linkEl.dataset.score = score;
linkEl.innerHTML = title;
if (descr)
if (descr) {
listItem.appendChild(document.createElement("span")).innerHTML =
" (" + descr + ")";
// highlight search terms in the description
if (SPHINX_HIGHLIGHT_ENABLED) // set in sphinx_highlight.js
highlightTerms.forEach((term) => _highlightText(listItem, term, "highlighted"));
}
else if (showSearchSummary)
fetch(requestUrl)
.then((responseData) => responseData.text())
Expand All @@ -97,6 +101,9 @@ const _displayItem = (item, searchTerms) => {
listItem.appendChild(
Search.makeSearchSummary(data, searchTerms)
);
// highlight search terms in the summary
if (SPHINX_HIGHLIGHT_ENABLED) // set in sphinx_highlight.js
highlightTerms.forEach((term) => _highlightText(listItem, term, "highlighted"));
});
Search.output.appendChild(listItem);
};
Expand All @@ -115,14 +122,15 @@ const _finishSearch = (resultCount) => {
const _displayNextItem = (
results,
resultCount,
searchTerms
searchTerms,
highlightTerms,
) => {
// results left, load the summary and display it
// this is intended to be dynamic (don't sub resultsCount)
if (results.length) {
_displayItem(results.pop(), searchTerms);
_displayItem(results.pop(), searchTerms, highlightTerms);
setTimeout(
() => _displayNextItem(results, resultCount, searchTerms),
() => _displayNextItem(results, resultCount, searchTerms, highlightTerms),
5
);
}
Expand Down Expand Up @@ -360,7 +368,7 @@ const Search = {
// console.info("search results:", Search.lastresults);

// print the results
_displayNextItem(results, results.length, searchTerms);
_displayNextItem(results, results.length, searchTerms, highlightTerms);
},

/**
Expand Down
16 changes: 13 additions & 3 deletions docs/covidcast-py/html/_static/sphinx_highlight.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,19 @@ const _highlight = (node, addItems, text, className) => {
}

span.appendChild(document.createTextNode(val.substr(pos, text.length)));
const rest = document.createTextNode(val.substr(pos + text.length));
parent.insertBefore(
span,
parent.insertBefore(
document.createTextNode(val.substr(pos + text.length)),
rest,
node.nextSibling
)
);
node.nodeValue = val.substr(0, pos);
/* There may be more occurrences of search term in this node. So call this
* function recursively on the remaining fragment.
*/
_highlight(rest, addItems, text, className);

if (isInSVG) {
const rect = document.createElementNS(
Expand Down Expand Up @@ -140,5 +145,10 @@ const SphinxHighlight = {
},
};

_ready(SphinxHighlight.highlightSearchWords);
_ready(SphinxHighlight.initEscapeListener);
_ready(() => {
/* Do not call highlightSearchWords() when we are on the search page.
* It will highlight words from the *previous* search query.
*/
if (typeof Search === "undefined") SphinxHighlight.highlightSearchWords();
SphinxHighlight.initEscapeListener();
});