From 11eacd18f8f3d840f411294feebe40f63beb61b7 Mon Sep 17 00:00:00 2001 From: tjann <18621425+tjann@users.noreply.github.com> Date: Mon, 20 Jul 2020 20:28:58 -0700 Subject: [PATCH 1/4] Remove API key requirement and rebrand to Python API (not Python Client API). --- .../python-api-v1-0-0-feedback.md | 2 +- CHANGELOG.md | 18 ++++---- README.md | 9 +--- datacommons/__init__.py | 5 +-- datacommons/core.py | 2 +- datacommons/examples/core.py | 2 +- datacommons/examples/places.py | 2 +- datacommons/examples/populations.py | 2 +- datacommons/examples/query.py | 2 +- datacommons/places.py | 2 +- datacommons/populations.py | 2 +- datacommons/query.py | 11 ++--- datacommons/test/core_test.py | 41 +------------------ datacommons/test/places_test.py | 33 +-------------- datacommons/test/populations_test.py | 30 +------------- datacommons/test/query_test.py | 11 +---- datacommons/utils.py | 30 +++----------- notebooks/README.md | 4 +- notebooks/analyzing_census_data.ipynb | 8 ++-- .../analyzing_education_achievement.ipynb | 2 +- notebooks/analyzing_income_distribution.ipynb | 2 +- notebooks/analyzing_obesity_prevalence.ipynb | 2 +- notebooks/getting_started.ipynb | 24 +++++------ setup.py | 2 +- 24 files changed, 56 insertions(+), 192 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/python-api-v1-0-0-feedback.md b/.github/ISSUE_TEMPLATE/python-api-v1-0-0-feedback.md index 7d70a410..35c70deb 100644 --- a/.github/ISSUE_TEMPLATE/python-api-v1-0-0-feedback.md +++ b/.github/ISSUE_TEMPLATE/python-api-v1-0-0-feedback.md @@ -1,6 +1,6 @@ --- name: Python API v1.0.0 Feedback -about: Feedback for the new Python Client API +about: Feedback for the new Python API title: "[API v1.0.0 Feedback] description of feedback" labels: python api feedback assignees: ACscooter diff --git a/CHANGELOG.md b/CHANGELOG.md index 82556fe6..d993417c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ **Release Status** - Current head of branch [`master`](https://github.com/datacommonsorg/api-python/tree/master) -New features added to the Python Client API +New features added to the Python API - Add get_stats API to get observations given a StatisticalVariable and place dcids. @@ -25,7 +25,7 @@ Bugs fixed in new release **Release Status** - Current head of branch [`master`](https://github.com/datacommonsorg/api-python/tree/master) -New features added to the Python Client API +New features added to the Python API - Handle and ignore NaN in API argument. @@ -41,7 +41,7 @@ Bugs fixed in new release **Release Status** - Current head of branch [`master`](https://github.com/datacommonsorg/api-python/tree/master) -New features added to the Python Client API +New features added to the Python API - Use six package for urllib. @@ -53,7 +53,7 @@ New features added to the Python Client API **Release Status** - Current head of branch [`master`](https://github.com/datacommonsorg/api-python/tree/master) -New features added to the Python Client API +New features added to the Python API - Support python 2.7. @@ -65,7 +65,7 @@ New features added to the Python Client API **Release Status** - Current head of branch [`master`](https://github.com/datacommonsorg/api-python/tree/master) -New features added to the Python Client API +New features added to the Python API - Add a new API for getting related places. @@ -79,7 +79,7 @@ New features added to the Python Client API **Release Status** - Current head of branch [`master`](https://github.com/datacommonsorg/api-python/tree/master) -New features added to the Python Client API +New features added to the Python API - Remove the dependency on Pandas and Numpy in package dependency. - Replace requests with urllib. @@ -93,7 +93,7 @@ New features added to the Python Client API **Release Status** - Current head of branch [`master`](https://github.com/datacommonsorg/api-python/tree/master) -New features added to the Python Client API +New features added to the Python API - Remove the dependency on Pandas. @@ -106,7 +106,7 @@ New features added to the Python Client API **Release Status** - Current head of branch [`stable-1.x`](https://github.com/datacommonsorg/api-python/tree/stable-1.x) -New features added to the Python Client API +New features added to the Python API - Added two new functions `get_pop_obs` and `get_place_obs` - SPARQL query is now supported as a function `query` instead of a class. @@ -123,7 +123,7 @@ Bugs fixed in new release **Release Tag** - [v1.0.0](https://github.com/datacommonsorg/api-python/releases/tag/v1.0.0) -New release of the Python Client API. +New release of the Python API. - New functions in the API built on top of the [Data Commons REST API](https://github.com/datacommonsorg/mixer). - `get_property_labels` diff --git a/README.md b/README.md index 4ef720e7..446bdee0 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Data Commons Python Client API +# Data Commons Python API This is a Python library for accessing data in the Data Commons knowledge graph. To get started, install this package from pip. @@ -9,11 +9,6 @@ Once the package is installed, import `datacommons`. import datacommons as dc -You will also need to provision an API key by enabling the Data Commons API on -GCP. Once you have the API key, simply add the following line to your code. - - dc.set_api_key('YOUR-API-KEY') - For more detail on getting started with the API, please visit [Getting Started](http://docs.datacommons.org/api/). @@ -34,7 +29,7 @@ Apache 2.0 ## Development -The Python Client API currently supports `python>=2.7`. We use +The Python API currently supports `python>=2.7`. We use [bazel](https://bazel.build/) as our build system. To test, first install bazel then run the following: diff --git a/datacommons/__init__.py b/datacommons/__init__.py index e96aa3bb..1bba1698 100644 --- a/datacommons/__init__.py +++ b/datacommons/__init__.py @@ -15,10 +15,7 @@ # Data Commons SPARQL query support from datacommons.query import query -# Data Commons Python Client API +# Data Commons Python API from datacommons.core import get_property_labels, get_property_values, get_triples from datacommons.places import get_places_in, get_related_places, get_stats from datacommons.populations import get_populations, get_observations, get_pop_obs, get_place_obs - -# Other utilities -from .utils import set_api_key diff --git a/datacommons/core.py b/datacommons/core.py index a3b6b2c6..75060388 100644 --- a/datacommons/core.py +++ b/datacommons/core.py @@ -11,7 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -""" Data Commons Python Client API Core. +""" Data Commons Python API Core. Provides primitive operations for working with collections of nodes. For a collection of nodes identified by their dcids, this submodule implements the diff --git a/datacommons/examples/core.py b/datacommons/examples/core.py index 11dac44b..6eb4aa10 100644 --- a/datacommons/examples/core.py +++ b/datacommons/examples/core.py @@ -11,7 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -""" Data Commons Python Client API examples. +""" Data Commons Python API examples. Basic demo for get_property_labels, get_property_values, and get_triples. """ diff --git a/datacommons/examples/places.py b/datacommons/examples/places.py index 1fda4462..ee9c71ec 100644 --- a/datacommons/examples/places.py +++ b/datacommons/examples/places.py @@ -11,7 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -""" Data Commons Python Client API examples. +""" Data Commons Python API examples. Basic demo for get_places_in """ diff --git a/datacommons/examples/populations.py b/datacommons/examples/populations.py index 5719653b..3804dbf3 100644 --- a/datacommons/examples/populations.py +++ b/datacommons/examples/populations.py @@ -11,7 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -""" Data Commons Python Client API examples. +""" Data Commons Python API examples. Basic demo for get_populations and get_observations. """ diff --git a/datacommons/examples/query.py b/datacommons/examples/query.py index bd7d634d..8be1bfe4 100644 --- a/datacommons/examples/query.py +++ b/datacommons/examples/query.py @@ -11,7 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -""" Data Commons Python Client API examples. +""" Data Commons Python API examples. Example on how to use the Client API SPARQL query wrapper. """ diff --git a/datacommons/places.py b/datacommons/places.py index d75bca71..3a56d996 100644 --- a/datacommons/places.py +++ b/datacommons/places.py @@ -11,7 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -""" Data Commons Python Client API Places Module. +""" Data Commons Python API Places Module. Provides convenience functions for working with Places in the Data Commons knowledge graph. This submodule implements the ability to access :obj:`Place`'s diff --git a/datacommons/populations.py b/datacommons/populations.py index ddc971c7..4677d009 100644 --- a/datacommons/populations.py +++ b/datacommons/populations.py @@ -11,7 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -""" Data Commons Python Client API Populations Module. +""" Data Commons Python API Populations Module. Provides convenience functions for accessing :obj:`StatisticalPopulation`'s and :obj:`Observation`'s in the Data Commons knowledge graph. Implements the diff --git a/datacommons/query.py b/datacommons/query.py index 7a2b9ec5..a5452170 100644 --- a/datacommons/query.py +++ b/datacommons/query.py @@ -11,7 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -""" Data Commons Python Client API Query Module. +""" Data Commons Python API Query Module. Implements functions for sending graph queries to the Data Commons knowledge graph. @@ -21,7 +21,7 @@ from __future__ import division from __future__ import print_function -from datacommons.utils import _API_ROOT, _API_ENDPOINTS, _ENV_VAR_API_KEY +from datacommons.utils import _API_ROOT, _API_ENDPOINTS import json import os @@ -86,14 +86,9 @@ def query(query_string, select=None): ... print(r) {"?name": "Maryland", "?dcid": "geoId/24"} """ - # Get the API Key and perform the POST request. - if not os.environ.get(_ENV_VAR_API_KEY, None): - raise ValueError( - 'Request error: Must set an API key before using the API!') - req_url = _API_ROOT + _API_ENDPOINTS['query'] + req_url = _API_ROOT + _API_ENDPOINTS['query'] headers = { - 'x-api-key': os.environ[_ENV_VAR_API_KEY], 'Content-Type': 'application/json' } req = six.moves.urllib.request.Request( diff --git a/datacommons/test/core_test.py b/datacommons/test/core_test.py index 709785a2..e1244c01 100644 --- a/datacommons/test/core_test.py +++ b/datacommons/test/core_test.py @@ -11,9 +11,9 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -""" Data Commons Python Client API unit tests. +""" Data Commons Python API unit tests. -Unit tests for core methods in the Data Commons Python Client API. +Unit tests for core methods in the Data Commons Python API. """ from __future__ import absolute_import @@ -43,11 +43,6 @@ def read(self): req = args[0] data = json.loads(req.data) - # If the API key does not match, then return 403 Forbidden - api_key = req.get_header('X-api-key') - if api_key != 'TEST-API-KEY': - return urllib.error.HTTPError - # Mock responses for urlopen requests to get_property_labels. if req.full_url == utils._API_ROOT + utils._API_ENDPOINTS['get_property_labels']: if data['dcids'] == ['geoId/0649670']: @@ -323,9 +318,6 @@ def test_single_dcid(self, urlopen_mock): """ Calling get_property_labels with a single dcid returns a valid result. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - # Test for outgoing property labels out_props = dc.get_property_labels(['geoId/0649670']) self.assertDictEqual(out_props, @@ -340,9 +332,6 @@ def test_multiple_dcids(self, urlopen_mock): """ Calling get_property_labels returns valid results with multiple dcids. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - dcids = ['State', 'County', 'City'] expected_in = ["typeOf"] expected_out = ["name", "provenance", "subClassOf", "typeOf", "url"] @@ -368,9 +357,6 @@ def test_bad_dcids(self, urlopen_mock): """ Calling get_property_labels with dcids that do not exist returns empty results. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - # Test for outgoing property labels out_props = dc.get_property_labels(['dc/MadDcid']) self.assertDictEqual(out_props, {'dc/MadDcid': []}) @@ -382,8 +368,6 @@ def test_bad_dcids(self, urlopen_mock): @mock.patch('urllib.request.urlopen', side_effect=request_mock) def test_no_dcids(self, urlopen_mock): """ Calling get_property_labels with no dcids returns empty results. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') # Test for outgoing property labels out_props = dc.get_property_labels([]) @@ -404,9 +388,6 @@ def test_multiple_dcids(self, urlopen_mock): """ Calling get_property_values with multiple dcids returns valid results. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - dcids = ['geoId/06085', 'geoId/24031'] # Get the containedInPlace Towns for Santa Clara and Montgomery County. @@ -444,9 +425,6 @@ def test_bad_dcids(self, urlopen_mock): """ Calling get_property_values with dcids that do not exist returns empty results. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - bad_dcids_1 = ['geoId/06085', 'dc/MadDcid'] bad_dcids_2 = ['dc/MadDcid', 'dc/MadderDcid'] @@ -470,9 +448,6 @@ def test_bad_property(self, urlopen_mock): """ Calling get_property_values with a property that does not exist returns empty results. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - # Get propery values for a property that does not exist. prop_vals = dc.get_property_values( ['geoId/06085', 'geoId/24031'], 'madProperty') @@ -484,9 +459,6 @@ def test_bad_property(self, urlopen_mock): @mock.patch('urllib.request.urlopen', side_effect=request_mock) def test_no_dcids(self, urlopen_mock): """ Calling get_property_values with no dcids returns empty results. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - # Get property values with an empty list of dcids. prop_vals = dc.get_property_values([], 'containedInPlace') self.assertDictEqual(prop_vals, {}) @@ -497,9 +469,6 @@ class TestGetTriples(unittest.TestCase): @mock.patch('urllib.request.urlopen', side_effect=request_mock) def test_multiple_dcids(self, urlopen_mock): """ Calling get_triples with proper dcids returns valid results. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - # Call get_triples triples = dc.get_triples(['geoId/06085', 'geoId/24031']) self.assertDictEqual(triples, { @@ -520,9 +489,6 @@ def test_bad_dcids(self, urlopen_mock): """ Calling get_triples with dcids that do not exist returns empty results. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - # Call get_triples where one dcid does not exist triples_1 = dc.get_triples(['geoId/06085', 'dc/MadDcid']) self.assertDictEqual(triples_1, { @@ -544,9 +510,6 @@ def test_bad_dcids(self, urlopen_mock): @mock.patch('urllib.request.urlopen', side_effect=request_mock) def test_no_dcids(self, urlopen_mock): """ Calling get_triples with no dcids returns empty results. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - # Call get_triples with no dcids triples_1 = dc.get_triples([]) self.assertDictEqual(triples_1, {}) diff --git a/datacommons/test/places_test.py b/datacommons/test/places_test.py index e5cc4f6a..29a843ed 100644 --- a/datacommons/test/places_test.py +++ b/datacommons/test/places_test.py @@ -11,9 +11,9 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -""" Data Commons Python Client API unit tests. +""" Data Commons Python API unit tests. -Unit tests for Place methods in the Data Commons Python Client API. +Unit tests for Place methods in the Data Commons Python API. """ from __future__ import absolute_import @@ -42,11 +42,6 @@ def read(self): req = args[0] data = json.loads(req.data) - # If the API key does not match, then return 403 Forbidden - api_key = req.get_header('X-api-key') - if api_key != 'TEST-API-KEY': - return urllib.error.HTTPError(None, 403, None, None, None) - # Mock responses for urlopen requests to get_places_in. if req.full_url == utils._API_ROOT + utils._API_ENDPOINTS['get_places_in']: if (data['dcids'] == ['geoId/06085', 'geoId/24031'] @@ -186,9 +181,6 @@ class TestGetPlacesIn(unittest.TestCase): @mock.patch('urllib.request.urlopen', side_effect=request_mock) def test_multiple_dcids(self, urlopen): """ Calling get_places_in with proper dcids returns valid results. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - # Call get_places_in places = dc.get_places_in(['geoId/06085', 'geoId/24031'], 'City') self.assertDictEqual(places, { @@ -201,9 +193,6 @@ def test_bad_dcids(self, urlopen): """ Calling get_places_in with dcids that do not exist returns empty results. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - # Call get_places_in with one dcid that does not exist bad_dcids_1 = dc.get_places_in(['geoId/06085', 'dc/MadDcid'], 'City') self.assertDictEqual(bad_dcids_1, { @@ -221,9 +210,6 @@ def test_bad_dcids(self, urlopen): @mock.patch('urllib.request.urlopen', side_effect=request_mock) def test_no_dcids(self, urlopen): """ Calling get_places_in with no dcids returns empty results. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - # Call get_places_in with no dcids. bad_dcids = dc.get_places_in(['dc/MadDcid', 'dc/MadderDcid'], 'City') self.assertDictEqual(bad_dcids, { @@ -238,9 +224,6 @@ class TestGetStats(unittest.TestCase): @mock.patch('urllib.request.urlopen', side_effect=request_mock) def test_multiple_dcids(self, urlopen): """ Calling get_stats with proper dcids returns valid results. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - # Call get_stats stats = dc.get_stats(['geoId/05', 'geoId/06'], 'dc/0hyp6tkn18vcb', 'all') self.assertDictEqual( @@ -332,9 +315,6 @@ def test_bad_dcids(self, urlopen): """ Calling get_stats with dcids that do not exist returns empty results. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - # Call get_stats with one dcid that does not exist bad_dcids_1 = dc.get_stats(['geoId/05', 'dc/MadDcid'], 'dc/0hyp6tkn18vcb') self.assertDictEqual( @@ -355,9 +335,6 @@ def test_bad_dcids(self, urlopen): @mock.patch('urllib.request.urlopen', side_effect=request_mock) def test_no_dcids(self, urlopen): """ Calling get_stats with no dcids returns empty results. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - # Call get_stats with no dcids. no_dcids = dc.get_stats([], 'dc/0hyp6tkn18vcb') self.assertDictEqual({}, no_dcids) @@ -365,9 +342,6 @@ def test_no_dcids(self, urlopen): @mock.patch('urllib.request.urlopen', side_effect=request_mock) def test_no_data(self, urlopen): """ Calling get_stats with for None data. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - # Call get_stats with no dcids. result = dc.get_stats(['geoId/00'], 'dc/0hyp6tkn18vcb') self.assertDictEqual({}, result) @@ -375,9 +349,6 @@ def test_no_data(self, urlopen): @mock.patch('six.moves.urllib.request.urlopen', side_effect=request_mock) def test_batch_request(self, mock_urlopen): """ Make multiple calls to REST API when number of geos exceeds the batch size. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - save_batch_size = dc.utils._QUERY_BATCH_SIZE dc.utils._QUERY_BATCH_SIZE = 1 diff --git a/datacommons/test/populations_test.py b/datacommons/test/populations_test.py index cd1e2f03..c075e8c9 100644 --- a/datacommons/test/populations_test.py +++ b/datacommons/test/populations_test.py @@ -11,7 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -""" Data Commons Python Client API unit tests. +""" Data Commons Python API unit tests. Unit tests for Population and Observation methods in the Data Commons Python Client API. @@ -47,10 +47,6 @@ def read(self): if req.data: data = json.loads(req.data) - api_key = req.get_header('X-api-key') - if api_key != 'TEST-API-KEY': - return urllib.error.HTTPError(None, 403, None, None, None) - constrained_props = [ { 'property': 'placeOfBirth', @@ -214,9 +210,6 @@ class TestGetPopulations(unittest.TestCase): @mock.patch('urllib.request.urlopen', side_effect=request_mock) def test_multiple_dcids(self, urlopen): """ Calling get_populations with proper dcids returns valid results. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - # Call get_populations populations = dc.get_populations(['geoId/06085', 'geoId/4805000'], 'Person', constraining_properties=self._constraints) @@ -231,9 +224,6 @@ def test_bad_dcids(self, urlopen): """ Calling get_populations with dcids that do not exist returns empty results. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - # Call get_populations pops_1 = dc.get_populations(['geoId/06085', 'dc/MadDcid'], 'Person', constraining_properties=self._constraints) @@ -247,9 +237,6 @@ def test_bad_dcids(self, urlopen): @mock.patch('urllib.request.urlopen', side_effect=request_mock) def test_no_dcids(self, urlopen): """ Calling get_populations with no dcids returns empty results. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - pops = dc.get_populations( [], 'Person', constraining_properties=self._constraints) self.assertDictEqual(pops, {}) @@ -260,9 +247,6 @@ class TestGetObservations(unittest.TestCase): @mock.patch('urllib.request.urlopen', side_effect=request_mock) def test_multiple_dcids(self, urlopen): """ Calling get_observations with proper dcids returns valid results. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - dcids = ['dc/p/x6t44d8jd95rd', 'dc/p/lr52m1yr46r44', 'dc/p/fs929fynprzs'] expected = { 'dc/p/lr52m1yr46r44': 3075662.0, @@ -279,9 +263,6 @@ def test_bad_dcids(self, urlopen): """ Calling get_observations with dcids that do not exist returns empty results. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - # Get the input dcids_1 = ['dc/p/x6t44d8jd95rd', 'dc/MadDcid'] dcids_2 = ['dc/MadDcid', 'dc/MadderDcid'] @@ -301,9 +282,6 @@ def test_bad_dcids(self, urlopen): @mock.patch('urllib.request.urlopen', side_effect=request_mock) def test_no_dcids(self, urlopen): """ Calling get_observations with no dcids returns empty results. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - actual = dc.get_observations([], 'count', 'measuredValue', '2018-12', observation_period='P1M', measurement_method='BLSSeasonallyAdjusted') @@ -316,9 +294,6 @@ class TestGetPopObs(unittest.TestCase): @mock.patch('urllib.request.urlopen', side_effect=request_mock) def test_valid_dcid(self, urlopen): """ Calling get_pop_obs with valid dcid returns valid results. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - # Call get_pop_obs pop_obs = dc.get_pop_obs('geoId/06085') self.assertDictEqual(pop_obs, { @@ -361,9 +336,6 @@ class TestGetPlaceObs(unittest.TestCase): @mock.patch('urllib.request.urlopen', side_effect=request_mock) def test_valid(self, urlopen): """ Calling get_place_obs with valid parameters returns a valid result. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - # Call get_place_obs pvs = { 'placeOfBirth': 'BornInOtherStateInTheUnitedStates', diff --git a/datacommons/test/query_test.py b/datacommons/test/query_test.py index 6b4f4233..6a2bbed5 100644 --- a/datacommons/test/query_test.py +++ b/datacommons/test/query_test.py @@ -11,7 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -""" Data Commons Python Client API unit tests. +""" Data Commons Python API unit tests. Unit tests for the SPARQL query wrapper. """ @@ -53,12 +53,6 @@ def read(self): req = args[0] data = json.loads(req.data) - # If the API key does not match, then return 403 Forbidden - api_key = req.get_header('X-api-key') - if api_key != 'TEST-API-KEY': - return urllib.error.HTTPError(None, 403, None, None, None) - - # Mock responses for urlopen requests to query. if req.full_url == utils._API_ROOT + utils._API_ENDPOINTS['query']\ and data['sparql'] == accepted_query: return MockResponse(json.dumps({ @@ -110,9 +104,6 @@ class TestQuery(unittest.TestCase): @mock.patch('urllib.request.urlopen', side_effect=request_mock) def test_rows(self, urlopen): """ Sending a valid query returns the correct response. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - # Create the SPARQL query query_string = (''' SELECT ?name ?dcid diff --git a/datacommons/utils.py b/datacommons/utils.py index f7ed1b9c..ade2a2f5 100644 --- a/datacommons/utils.py +++ b/datacommons/utils.py @@ -11,9 +11,9 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -""" Data Commons utilities library +""" Data Commons Utilities Library. -Various functions that can aid in the extension of the DataCommons API. +Various functions that can aid in the extension of the Data Commons API. """ from __future__ import absolute_import @@ -24,6 +24,7 @@ import base64 import json +import logging import os import six.moves.urllib.error import six.moves.urllib.request @@ -57,27 +58,13 @@ # Batch size for heavyweight queries. _QUERY_BATCH_SIZE = 500 -# Environment variable names used by the package -_ENV_VAR_API_KEY = 'DC_API_KEY' # Name the API key variable - # --------------------------- API UTILITY FUNCTIONS --------------------------- def set_api_key(api_key): - """ Sets an environment variable :code:`"DC_API_KEY"` to given :code:`api_key`. - - An API key is required to use the Python Client API. This can be provided to - the API after importing the library, or set as an environment variable - :code:`"DC_API_KEY"`. - - For more details about how to get an API key and provide it to the Python - Client API, please visit :ref:`getting_started` - - Args: - api_key (:obj:`str`): The api key. - """ - os.environ[_ENV_VAR_API_KEY] = api_key + """DEPRECATED FUNCTION--API keys no longer required.""" + logging.warning('Data Commons has removed the API key requirement. This function will be removed by June 1st, 2020.') # ------------------------- INTERNAL HELPER FUNCTIONS ------------------------- @@ -89,14 +76,7 @@ def _send_request(req_url, req_json={}, compress=False, post=True): Returns: The payload returned by sending the POST/GET request formatted as a dict. """ - # Get the API key - if not os.environ.get(_ENV_VAR_API_KEY, None): - raise ValueError( - 'Request error: Must set an API key before using the API! You can ' - 'call datacommons.set_api_key or assign the key to an environment ' - 'variable named {}'.format(_ENV_VAR_API_KEY)) headers = { - 'x-api-key': os.environ[_ENV_VAR_API_KEY], 'Content-Type': 'application/json' } diff --git a/notebooks/README.md b/notebooks/README.md index 75ebfe4e..8d591aef 100644 --- a/notebooks/README.md +++ b/notebooks/README.md @@ -1,6 +1,6 @@ -# Python Client API Notebooks +# Python API Notebooks -This directory contains iPython notebooks that use the Python Client API to +This directory contains iPython notebooks that use the Python API to perform various statistical analyses on interesting datasets. You can click on each link to see a live colab version. diff --git a/notebooks/analyzing_census_data.ipynb b/notebooks/analyzing_census_data.ipynb index 9f23fe2a..c70df907 100644 --- a/notebooks/analyzing_census_data.ipynb +++ b/notebooks/analyzing_census_data.ipynb @@ -36,7 +36,7 @@ "source": [ "# Analyzing Census Data with Data Commons\n", "\n", - "Datacommons is intended for various data science tasks. This tutorial introduces the datacommons knowledge graph and discusses two tools to help integrate its data into your data science projects: (1) the [datacommons browser](https://browser.datacommons.org/) and (2) the [Python Client API](https://github.com/google/datacommons). Before getting started, we will need to install the Python API package. \n" + "Datacommons is intended for various data science tasks. This tutorial introduces the datacommons knowledge graph and discusses two tools to help integrate its data into your data science projects: (1) the [datacommons browser](https://browser.datacommons.org/) and (2) the [Python API](https://github.com/google/datacommons). Before getting started, we will need to install the Python API package. \n" ] }, { @@ -106,7 +106,7 @@ "source": [ "## Python API\n", "\n", - "The [Python Client API](https://github.com/datacommonsorg/api-python) provides functions for users to extract structured information from Data Commons programmatically and view them in different formats such as Python `dict`'s and [Pandas](https://pandas.pydata.org/) DataFrames. DataFrames allow access to all the data processing, analytical and visualization tools provided by packages such as Pandas, NumPy, SciPy, and Matplotlib.\n", + "The [Python API](https://github.com/datacommonsorg/api-python) provides functions for users to extract structured information from Data Commons programmatically and view them in different formats such as Python `dict`'s and [Pandas](https://pandas.pydata.org/) DataFrames. DataFrames allow access to all the data processing, analytical and visualization tools provided by packages such as Pandas, NumPy, SciPy, and Matplotlib.\n", "\n", "Every notebook begins by loading the dataCommons client as follows:\n" ] @@ -139,7 +139,7 @@ "colab_type": "text" }, "source": [ - "We will also need to provide an API key to access the Data Commons Python Client API. This notebook is setup to read from a `json` file stored at `key_path` in your Google Drive. This text file should have one line:\n", + "We will also need to provide an API key to access the Data Commons Python API. This notebook is setup to read from a `json` file stored at `key_path` in your Google Drive. This text file should have one line:\n", "\n", " ```\n", "{\n", @@ -147,7 +147,7 @@ "}\n", " ```\n", " \n", - " If you want to make a copy of this notebook, make sure to replace `key_path` with the path to a file containing your API key. For more detail, visit the [Creating an API Key](https://datacommons.readthedocs.io/en/latest/started.html#creating-an-api-key) page of the Python Client API documentation.\n", + " If you want to make a copy of this notebook, make sure to replace `key_path` with the path to a file containing your API key. For more detail, visit the [Creating an API Key](https://datacommons.readthedocs.io/en/latest/started.html#creating-an-api-key) page of the Python API documentation.\n", "\n" ] }, diff --git a/notebooks/analyzing_education_achievement.ipynb b/notebooks/analyzing_education_achievement.ipynb index 906e50d3..ad2cbc5e 100644 --- a/notebooks/analyzing_education_achievement.ipynb +++ b/notebooks/analyzing_education_achievement.ipynb @@ -125,7 +125,7 @@ "colab_type": "text" }, "source": [ - "We will also need to assign an API key to the library. See the [Analyzing Statistics in Data Commons Using the Python Client API](https://colab.research.google.com/drive/1ZNXTHu3J0W3vo9Mg3kNUpk0hnD6Ce1u6#scrollTo=ijxoBhFHjo3Z) to see how to set this up for a Colab Notebook." + "We will also need to assign an API key to the library. See the [Analyzing Statistics in Data Commons Using the Python API](https://colab.research.google.com/drive/1ZNXTHu3J0W3vo9Mg3kNUpk0hnD6Ce1u6#scrollTo=ijxoBhFHjo3Z) to see how to set this up for a Colab Notebook." ] }, { diff --git a/notebooks/analyzing_income_distribution.ipynb b/notebooks/analyzing_income_distribution.ipynb index cb5e3f77..d360b826 100644 --- a/notebooks/analyzing_income_distribution.ipynb +++ b/notebooks/analyzing_income_distribution.ipynb @@ -97,7 +97,7 @@ "colab_type": "text" }, "source": [ - "We will also need to provide the API with an API key. See the [Analyzing Statistics in Data Commons Using the Python Client API](https://colab.research.google.com/drive/1ZNXTHu3J0W3vo9Mg3kNUpk0hnD6Ce1u6#scrollTo=ijxoBhFHjo3Z) to see how to set this up for a Colab Notebook." + "We will also need to provide the API with an API key. See the [Analyzing Statistics in Data Commons Using the Python API](https://colab.research.google.com/drive/1ZNXTHu3J0W3vo9Mg3kNUpk0hnD6Ce1u6#scrollTo=ijxoBhFHjo3Z) to see how to set this up for a Colab Notebook." ] }, { diff --git a/notebooks/analyzing_obesity_prevalence.ipynb b/notebooks/analyzing_obesity_prevalence.ipynb index 99266ed1..13ac21ff 100644 --- a/notebooks/analyzing_obesity_prevalence.ipynb +++ b/notebooks/analyzing_obesity_prevalence.ipynb @@ -104,7 +104,7 @@ "colab_type": "text" }, "source": [ - "We will also need to provide the API with an API key. See the [Analyzing Statistics in Data Commons Using the Python Client API](https://colab.research.google.com/drive/1ZNXTHu3J0W3vo9Mg3kNUpk0hnD6Ce1u6#scrollTo=ijxoBhFHjo3Z) to see how to set this up for a Colab Notebook." + "We will also need to provide the API with an API key. See the [Analyzing Statistics in Data Commons Using the Python API](https://colab.research.google.com/drive/1ZNXTHu3J0W3vo9Mg3kNUpk0hnD6Ce1u6#scrollTo=ijxoBhFHjo3Z) to see how to set this up for a Colab Notebook." ] }, { diff --git a/notebooks/getting_started.ipynb b/notebooks/getting_started.ipynb index fff4188b..47f27d36 100644 --- a/notebooks/getting_started.ipynb +++ b/notebooks/getting_started.ipynb @@ -3,7 +3,7 @@ "nbformat_minor": 0, "metadata": { "colab": { - "name": "Getting Started with the Python Client API", + "name": "Getting Started with the Python API", "version": "0.3.2", "provenance": [], "collapsed_sections": [] @@ -38,7 +38,7 @@ "\n", "- Sending an issue request to the [datacommons issues page](https://github.com/google/datacommons/issues). When creating an issue please mark the issue using the **api feedback** label!\n", "\n", - "**DISCLAIMER** this notebook uses an experimental version of the Data Commons Python Client API. The semantics and availability of this API may be subject to change without prior notice! " + "**DISCLAIMER** this notebook uses an experimental version of the Data Commons Python API. The semantics and availability of this API may be subject to change without prior notice! " ] }, { @@ -48,11 +48,11 @@ "colab_type": "text" }, "source": [ - "# Getting Started with the Python Client API\n", + "# Getting Started with the Python API\n", "\n", - "This tutorial introduces the Data Commons open knowledge graph and discusses how to programmtically access its data through the Python Client API. We will use the task of plotting employment data provided by the Bureau of Labor Statistics as an example to demonstrate various functionalities supported by the Python Client API.\n", + "This tutorial introduces the Data Commons open knowledge graph and discusses how to programmtically access its data through the Python API. We will use the task of plotting employment data provided by the Bureau of Labor Statistics as an example to demonstrate various functionalities supported by the Python API.\n", "\n", - "Before proceeding, we will need to install the Python Client API package." + "Before proceeding, we will need to install the Python API package." ] }, { @@ -106,7 +106,7 @@ "\n", "### The Data Commons Browser\n", "\n", - "Throughout this tutorial, we will be using the [Data Commons browser](https://browser.datacommons.org). The browser provides a human readable way of navigating nodes within the knowledge graph. This is particularly useful for discovering what parameters to pass into the Python Client API in order to correctly query for nodes in the graph. " + "Throughout this tutorial, we will be using the [Data Commons browser](https://browser.datacommons.org). The browser provides a human readable way of navigating nodes within the knowledge graph. This is particularly useful for discovering what parameters to pass into the Python API in order to correctly query for nodes in the graph. " ] }, { @@ -116,9 +116,9 @@ "colab_type": "text" }, "source": [ - "## The Python Client API\n", + "## The Python API\n", "\n", - "The Python Client API provides functions for users to programmatically access nodes in the Data Commons open knowledge graph. In this tutorial, we will be demonstrating how to use the API access nodes in the Data Commons graph and store their information in a [Pandas](https://pandas.pydata.org) Data Frame. For a discussion on how to use the API generally, please refer to the [API Documentation](https://datacommons.readthedocs.io/en/dev2/).\n", + "The Python API provides functions for users to programmatically access nodes in the Data Commons open knowledge graph. In this tutorial, we will be demonstrating how to use the API access nodes in the Data Commons graph and store their information in a [Pandas](https://pandas.pydata.org) Data Frame. For a discussion on how to use the API generally, please refer to the [API Documentation](https://datacommons.readthedocs.io/en/dev2/).\n", "\n", "Let's begin by importing the Python Client and other helpful libraries.\n", "\n" @@ -218,7 +218,7 @@ "source": [ "## Using the API To Plot Unemployment Data\n", "\n", - "The [Bureau of Labor Statistics](https://www.bls.gov) provides a monthly count for number of individuals who are employed at the State, County, and City level. This data is surfaced in the Data Commons; for example, one can find employment statistics associated with Santa Clara County [here](https://browser.datacommons.org/kg?dcid=dc/p/y6xm2mny8mck1&db=). Our task for this tutorial will be to extract employment data associated with counties in California from Data Commons using the Python Client API and view it in a Pandas DataFrame. We will focus on how functions such as\n", + "The [Bureau of Labor Statistics](https://www.bls.gov) provides a monthly count for number of individuals who are employed at the State, County, and City level. This data is surfaced in the Data Commons; for example, one can find employment statistics associated with Santa Clara County [here](https://browser.datacommons.org/kg?dcid=dc/p/y6xm2mny8mck1&db=). Our task for this tutorial will be to extract employment data associated with counties in California from Data Commons using the Python API and view it in a Pandas DataFrame. We will focus on how functions such as\n", "\n", "- `get_property_values`\n", "- `get_places_in`\n", @@ -754,7 +754,7 @@ "\n", "There are two other properties defined: `numConstraints` and `employment`. These two properties help us describe entities contained in this statistical population. Properties used to describe the entities captured by a StatisticalPopulation are called *constraining properties*. In the example above, `employment=BLS_Employed` is a constraining property that tells us the Statistical Population captures employed persons. `numConstraints` denotes how many constraining properties there are, and in the example above, `numConstraints=1` tells us that `employment` is the only constraining property.\n", "\n", - "To query for `StatisticalPopulation`s using the Data Commons Python Client API, we call **`get_populations`**. The function accepts the following parameters.\n", + "To query for `StatisticalPopulation`s using the Data Commons Python API, we call **`get_populations`**. The function accepts the following parameters.\n", "\n", "- **`dcids`** - A list or Pandas Series of dcids denoting the locations of populations to query for.\n", "- **`population_type`** - The `populationType` of the `StatisticalPopulation`\n", @@ -961,7 +961,7 @@ "\n", "The final property of interest is **`measuredValue`**. This property tells us that the raw value observed by the observation (whose value is 1,015,129) in this case. The `measuredValue` is also a *statistic type* associated with the observation. For a single observation, there could be many statistics that describe it. One would be the raw value represented by `measuredValue`, while others include `meanValue`, `medianValue`, `marginOfError`, and more.\n", "\n", - "These parameters are useful for deciding what values to provide to the API. To query for `Observation`s using the Python Client API we call **`get_observations`** which accepts the following parameters.\n", + "These parameters are useful for deciding what values to provide to the API. To query for `Observation`s using the Python API we call **`get_observations`** which accepts the following parameters.\n", "\n", "- **`dcids`** - A list or Pandas Series of dcids of nodes that are observed by observations being queried for.\n", "- **`measured_property`** - The `measuredProperty` of the observation.\n", @@ -1218,7 +1218,7 @@ "colab_type": "text" }, "source": [ - "This wraps up our tutorial on how to use the Data Commons Python Client API to access statistics in the knowledge graph and view it in a Pandas Data Frame. From this tutorial we should now know\n", + "This wraps up our tutorial on how to use the Data Commons Python API to access statistics in the knowledge graph and view it in a Pandas Data Frame. From this tutorial we should now know\n", "\n", "- How statistics are modeled in the graph\n", "- What API methods are available for accessing these statistics\n", diff --git a/setup.py b/setup.py index a7db4358..b3720138 100644 --- a/setup.py +++ b/setup.py @@ -20,7 +20,7 @@ # Package metadata. NAME = 'datacommons' -DESCRIPTION = 'A library to access Data Commons Python Client API.' +DESCRIPTION = 'A library to access Data Commons Python API.' URL = 'https://github.com/datacommonsorg/api-python' EMAIL = 'support@datacommons.org' AUTHOR = 'datacommons.org' From d328aa1134cbeb4a847ddeab7c4ee31ef534a4ee Mon Sep 17 00:00:00 2001 From: tjann <18621425+tjann@users.noreply.github.com> Date: Mon, 20 Jul 2020 20:28:58 -0700 Subject: [PATCH 2/4] Remove API key requirement and rebrand to Python API (not Python Client API). --- .../python-api-v1-0-0-feedback.md | 2 +- CHANGELOG.md | 18 ++++---- README.md | 5 --- datacommons/__init__.py | 5 +-- datacommons/core.py | 2 +- datacommons/examples/core.py | 2 +- datacommons/examples/places.py | 2 +- datacommons/examples/populations.py | 2 +- datacommons/examples/query.py | 2 +- datacommons/places.py | 2 +- datacommons/populations.py | 2 +- datacommons/query.py | 11 ++--- datacommons/test/core_test.py | 41 +------------------ datacommons/test/places_test.py | 33 +-------------- datacommons/test/populations_test.py | 30 +------------- datacommons/test/query_test.py | 11 +---- datacommons/utils.py | 30 +++----------- notebooks/README.md | 4 +- notebooks/analyzing_census_data.ipynb | 8 ++-- .../analyzing_education_achievement.ipynb | 2 +- notebooks/analyzing_income_distribution.ipynb | 2 +- notebooks/analyzing_obesity_prevalence.ipynb | 2 +- notebooks/getting_started.ipynb | 24 +++++------ setup.py | 2 +- 24 files changed, 54 insertions(+), 190 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/python-api-v1-0-0-feedback.md b/.github/ISSUE_TEMPLATE/python-api-v1-0-0-feedback.md index 7d70a410..35c70deb 100644 --- a/.github/ISSUE_TEMPLATE/python-api-v1-0-0-feedback.md +++ b/.github/ISSUE_TEMPLATE/python-api-v1-0-0-feedback.md @@ -1,6 +1,6 @@ --- name: Python API v1.0.0 Feedback -about: Feedback for the new Python Client API +about: Feedback for the new Python API title: "[API v1.0.0 Feedback] description of feedback" labels: python api feedback assignees: ACscooter diff --git a/CHANGELOG.md b/CHANGELOG.md index 82556fe6..d993417c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ **Release Status** - Current head of branch [`master`](https://github.com/datacommonsorg/api-python/tree/master) -New features added to the Python Client API +New features added to the Python API - Add get_stats API to get observations given a StatisticalVariable and place dcids. @@ -25,7 +25,7 @@ Bugs fixed in new release **Release Status** - Current head of branch [`master`](https://github.com/datacommonsorg/api-python/tree/master) -New features added to the Python Client API +New features added to the Python API - Handle and ignore NaN in API argument. @@ -41,7 +41,7 @@ Bugs fixed in new release **Release Status** - Current head of branch [`master`](https://github.com/datacommonsorg/api-python/tree/master) -New features added to the Python Client API +New features added to the Python API - Use six package for urllib. @@ -53,7 +53,7 @@ New features added to the Python Client API **Release Status** - Current head of branch [`master`](https://github.com/datacommonsorg/api-python/tree/master) -New features added to the Python Client API +New features added to the Python API - Support python 2.7. @@ -65,7 +65,7 @@ New features added to the Python Client API **Release Status** - Current head of branch [`master`](https://github.com/datacommonsorg/api-python/tree/master) -New features added to the Python Client API +New features added to the Python API - Add a new API for getting related places. @@ -79,7 +79,7 @@ New features added to the Python Client API **Release Status** - Current head of branch [`master`](https://github.com/datacommonsorg/api-python/tree/master) -New features added to the Python Client API +New features added to the Python API - Remove the dependency on Pandas and Numpy in package dependency. - Replace requests with urllib. @@ -93,7 +93,7 @@ New features added to the Python Client API **Release Status** - Current head of branch [`master`](https://github.com/datacommonsorg/api-python/tree/master) -New features added to the Python Client API +New features added to the Python API - Remove the dependency on Pandas. @@ -106,7 +106,7 @@ New features added to the Python Client API **Release Status** - Current head of branch [`stable-1.x`](https://github.com/datacommonsorg/api-python/tree/stable-1.x) -New features added to the Python Client API +New features added to the Python API - Added two new functions `get_pop_obs` and `get_place_obs` - SPARQL query is now supported as a function `query` instead of a class. @@ -123,7 +123,7 @@ Bugs fixed in new release **Release Tag** - [v1.0.0](https://github.com/datacommonsorg/api-python/releases/tag/v1.0.0) -New release of the Python Client API. +New release of the Python API. - New functions in the API built on top of the [Data Commons REST API](https://github.com/datacommonsorg/mixer). - `get_property_labels` diff --git a/README.md b/README.md index 8cc64cc3..74577e5a 100644 --- a/README.md +++ b/README.md @@ -9,11 +9,6 @@ Once the package is installed, import `datacommons`. import datacommons as dc -You will also need to provision an API key by enabling the Data Commons API on -GCP. Once you have the API key, simply add the following line to your code. - - dc.set_api_key('YOUR-API-KEY') - For more detail on getting started with the API, please visit [Getting Started](http://docs.datacommons.org/api/). diff --git a/datacommons/__init__.py b/datacommons/__init__.py index e96aa3bb..1bba1698 100644 --- a/datacommons/__init__.py +++ b/datacommons/__init__.py @@ -15,10 +15,7 @@ # Data Commons SPARQL query support from datacommons.query import query -# Data Commons Python Client API +# Data Commons Python API from datacommons.core import get_property_labels, get_property_values, get_triples from datacommons.places import get_places_in, get_related_places, get_stats from datacommons.populations import get_populations, get_observations, get_pop_obs, get_place_obs - -# Other utilities -from .utils import set_api_key diff --git a/datacommons/core.py b/datacommons/core.py index a3b6b2c6..75060388 100644 --- a/datacommons/core.py +++ b/datacommons/core.py @@ -11,7 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -""" Data Commons Python Client API Core. +""" Data Commons Python API Core. Provides primitive operations for working with collections of nodes. For a collection of nodes identified by their dcids, this submodule implements the diff --git a/datacommons/examples/core.py b/datacommons/examples/core.py index 11dac44b..6eb4aa10 100644 --- a/datacommons/examples/core.py +++ b/datacommons/examples/core.py @@ -11,7 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -""" Data Commons Python Client API examples. +""" Data Commons Python API examples. Basic demo for get_property_labels, get_property_values, and get_triples. """ diff --git a/datacommons/examples/places.py b/datacommons/examples/places.py index 1fda4462..ee9c71ec 100644 --- a/datacommons/examples/places.py +++ b/datacommons/examples/places.py @@ -11,7 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -""" Data Commons Python Client API examples. +""" Data Commons Python API examples. Basic demo for get_places_in """ diff --git a/datacommons/examples/populations.py b/datacommons/examples/populations.py index 5719653b..3804dbf3 100644 --- a/datacommons/examples/populations.py +++ b/datacommons/examples/populations.py @@ -11,7 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -""" Data Commons Python Client API examples. +""" Data Commons Python API examples. Basic demo for get_populations and get_observations. """ diff --git a/datacommons/examples/query.py b/datacommons/examples/query.py index bd7d634d..8be1bfe4 100644 --- a/datacommons/examples/query.py +++ b/datacommons/examples/query.py @@ -11,7 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -""" Data Commons Python Client API examples. +""" Data Commons Python API examples. Example on how to use the Client API SPARQL query wrapper. """ diff --git a/datacommons/places.py b/datacommons/places.py index 37deab6d..6f95262d 100644 --- a/datacommons/places.py +++ b/datacommons/places.py @@ -11,7 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -""" Data Commons Python Client API Places Module. +""" Data Commons Python API Places Module. Provides convenience functions for working with Places in the Data Commons Graph. This submodule implements the ability to access :obj:`Place`'s diff --git a/datacommons/populations.py b/datacommons/populations.py index 3d2b8a3f..2b1bd42c 100644 --- a/datacommons/populations.py +++ b/datacommons/populations.py @@ -11,7 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -""" Data Commons Python Client API Populations Module. +""" Data Commons Python API Populations Module. Provides convenience functions for accessing :obj:`StatisticalPopulation`'s and :obj:`Observation`'s in the Data Commons Graph. Implements the diff --git a/datacommons/query.py b/datacommons/query.py index 6b53b020..d9de2d97 100644 --- a/datacommons/query.py +++ b/datacommons/query.py @@ -11,7 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -""" Data Commons Python Client API Query Module. +""" Data Commons Python API Query Module. Implements functions for sending graph queries to the Data Commons Graph. """ @@ -20,7 +20,7 @@ from __future__ import division from __future__ import print_function -from datacommons.utils import _API_ROOT, _API_ENDPOINTS, _ENV_VAR_API_KEY +from datacommons.utils import _API_ROOT, _API_ENDPOINTS import json import os @@ -85,14 +85,9 @@ def query(query_string, select=None): ... print(r) {"?name": "Maryland", "?dcid": "geoId/24"} """ - # Get the API Key and perform the POST request. - if not os.environ.get(_ENV_VAR_API_KEY, None): - raise ValueError( - 'Request error: Must set an API key before using the API!') - req_url = _API_ROOT + _API_ENDPOINTS['query'] + req_url = _API_ROOT + _API_ENDPOINTS['query'] headers = { - 'x-api-key': os.environ[_ENV_VAR_API_KEY], 'Content-Type': 'application/json' } req = six.moves.urllib.request.Request( diff --git a/datacommons/test/core_test.py b/datacommons/test/core_test.py index 0c67514a..a370bff7 100644 --- a/datacommons/test/core_test.py +++ b/datacommons/test/core_test.py @@ -11,9 +11,9 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -""" Data Commons Python Client API unit tests. +""" Data Commons Python API unit tests. -Unit tests for core methods in the Data Commons Python Client API. +Unit tests for core methods in the Data Commons Python API. """ from __future__ import absolute_import @@ -43,11 +43,6 @@ def read(self): req = args[0] data = json.loads(req.data) - # If the API key does not match, then return 403 Forbidden - api_key = req.get_header('X-api-key') - if api_key != 'TEST-API-KEY': - return urllib.error.HTTPError - # Mock responses for urlopen requests to get_property_labels. if req.full_url == utils._API_ROOT + utils._API_ENDPOINTS['get_property_labels']: if data['dcids'] == ['geoId/0649670']: @@ -323,9 +318,6 @@ def test_single_dcid(self, urlopen_mock): """ Calling get_property_labels with a single dcid returns a valid result. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - # Test for outgoing property labels out_props = dc.get_property_labels(['geoId/0649670']) self.assertDictEqual(out_props, @@ -340,9 +332,6 @@ def test_multiple_dcids(self, urlopen_mock): """ Calling get_property_labels returns valid results with multiple dcids. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - dcids = ['State', 'County', 'City'] expected_in = ["typeOf"] expected_out = ["name", "provenance", "subClassOf", "typeOf", "url"] @@ -368,9 +357,6 @@ def test_bad_dcids(self, urlopen_mock): """ Calling get_property_labels with dcids that do not exist returns empty results. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - # Test for outgoing property labels out_props = dc.get_property_labels(['dc/MadDcid']) self.assertDictEqual(out_props, {'dc/MadDcid': []}) @@ -382,8 +368,6 @@ def test_bad_dcids(self, urlopen_mock): @mock.patch('six.moves.urllib.request.urlopen', side_effect=request_mock) def test_no_dcids(self, urlopen_mock): """ Calling get_property_labels with no dcids returns empty results. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') # Test for outgoing property labels out_props = dc.get_property_labels([]) @@ -404,9 +388,6 @@ def test_multiple_dcids(self, urlopen_mock): """ Calling get_property_values with multiple dcids returns valid results. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - dcids = ['geoId/06085', 'geoId/24031'] # Get the containedInPlace Towns for Santa Clara and Montgomery County. @@ -444,9 +425,6 @@ def test_bad_dcids(self, urlopen_mock): """ Calling get_property_values with dcids that do not exist returns empty results. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - bad_dcids_1 = ['geoId/06085', 'dc/MadDcid'] bad_dcids_2 = ['dc/MadDcid', 'dc/MadderDcid'] @@ -470,9 +448,6 @@ def test_bad_property(self, urlopen_mock): """ Calling get_property_values with a property that does not exist returns empty results. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - # Get propery values for a property that does not exist. prop_vals = dc.get_property_values( ['geoId/06085', 'geoId/24031'], 'madProperty') @@ -484,9 +459,6 @@ def test_bad_property(self, urlopen_mock): @mock.patch('six.moves.urllib.request.urlopen', side_effect=request_mock) def test_no_dcids(self, urlopen_mock): """ Calling get_property_values with no dcids returns empty results. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - # Get property values with an empty list of dcids. prop_vals = dc.get_property_values([], 'containedInPlace') self.assertDictEqual(prop_vals, {}) @@ -497,9 +469,6 @@ class TestGetTriples(unittest.TestCase): @mock.patch('six.moves.urllib.request.urlopen', side_effect=request_mock) def test_multiple_dcids(self, urlopen_mock): """ Calling get_triples with proper dcids returns valid results. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - # Call get_triples triples = dc.get_triples(['geoId/06085', 'geoId/24031']) self.assertDictEqual(triples, { @@ -520,9 +489,6 @@ def test_bad_dcids(self, urlopen_mock): """ Calling get_triples with dcids that do not exist returns empty results. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - # Call get_triples where one dcid does not exist triples_1 = dc.get_triples(['geoId/06085', 'dc/MadDcid']) self.assertDictEqual(triples_1, { @@ -544,9 +510,6 @@ def test_bad_dcids(self, urlopen_mock): @mock.patch('six.moves.urllib.request.urlopen', side_effect=request_mock) def test_no_dcids(self, urlopen_mock): """ Calling get_triples with no dcids returns empty results. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - # Call get_triples with no dcids triples_1 = dc.get_triples([]) self.assertDictEqual(triples_1, {}) diff --git a/datacommons/test/places_test.py b/datacommons/test/places_test.py index 1ea935b1..a6ad7cd1 100644 --- a/datacommons/test/places_test.py +++ b/datacommons/test/places_test.py @@ -11,9 +11,9 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -""" Data Commons Python Client API unit tests. +""" Data Commons Python API unit tests. -Unit tests for Place methods in the Data Commons Python Client API. +Unit tests for Place methods in the Data Commons Python API. """ from __future__ import absolute_import @@ -42,11 +42,6 @@ def read(self): req = args[0] data = json.loads(req.data) - # If the API key does not match, then return 403 Forbidden - api_key = req.get_header('X-api-key') - if api_key != 'TEST-API-KEY': - return urllib.error.HTTPError(None, 403, None, None, None) - # Mock responses for urlopen requests to get_places_in. if req.full_url == utils._API_ROOT + utils._API_ENDPOINTS['get_places_in']: if (data['dcids'] == ['geoId/06085', 'geoId/24031'] @@ -186,9 +181,6 @@ class TestGetPlacesIn(unittest.TestCase): @mock.patch('six.moves.urllib.request.urlopen', side_effect=request_mock) def test_multiple_dcids(self, urlopen): """ Calling get_places_in with proper dcids returns valid results. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - # Call get_places_in places = dc.get_places_in(['geoId/06085', 'geoId/24031'], 'City') self.assertDictEqual(places, { @@ -201,9 +193,6 @@ def test_bad_dcids(self, urlopen): """ Calling get_places_in with dcids that do not exist returns empty results. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - # Call get_places_in with one dcid that does not exist bad_dcids_1 = dc.get_places_in(['geoId/06085', 'dc/MadDcid'], 'City') self.assertDictEqual(bad_dcids_1, { @@ -221,9 +210,6 @@ def test_bad_dcids(self, urlopen): @mock.patch('six.moves.urllib.request.urlopen', side_effect=request_mock) def test_no_dcids(self, urlopen): """ Calling get_places_in with no dcids returns empty results. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - # Call get_places_in with no dcids. bad_dcids = dc.get_places_in(['dc/MadDcid', 'dc/MadderDcid'], 'City') self.assertDictEqual(bad_dcids, { @@ -238,9 +224,6 @@ class TestGetStats(unittest.TestCase): @mock.patch('six.moves.urllib.request.urlopen', side_effect=request_mock) def test_multiple_dcids(self, urlopen): """ Calling get_stats with proper dcids returns valid results. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - # Call get_stats stats = dc.get_stats(['geoId/05', 'geoId/06'], 'dc/0hyp6tkn18vcb', 'all') self.assertDictEqual( @@ -332,9 +315,6 @@ def test_bad_dcids(self, urlopen): """ Calling get_stats with dcids that do not exist returns empty results. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - # Call get_stats with one dcid that does not exist bad_dcids_1 = dc.get_stats(['geoId/05', 'dc/MadDcid'], 'dc/0hyp6tkn18vcb') self.assertDictEqual( @@ -355,9 +335,6 @@ def test_bad_dcids(self, urlopen): @mock.patch('six.moves.urllib.request.urlopen', side_effect=request_mock) def test_no_dcids(self, urlopen): """ Calling get_stats with no dcids returns empty results. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - # Call get_stats with no dcids. no_dcids = dc.get_stats([], 'dc/0hyp6tkn18vcb') self.assertDictEqual({}, no_dcids) @@ -365,9 +342,6 @@ def test_no_dcids(self, urlopen): @mock.patch('six.moves.urllib.request.urlopen', side_effect=request_mock) def test_no_data(self, urlopen): """ Calling get_stats with for None data. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - # Call get_stats with no dcids. result = dc.get_stats(['geoId/00'], 'dc/0hyp6tkn18vcb') self.assertDictEqual({}, result) @@ -375,9 +349,6 @@ def test_no_data(self, urlopen): @mock.patch('six.moves.urllib.request.urlopen', side_effect=request_mock) def test_batch_request(self, mock_urlopen): """ Make multiple calls to REST API when number of geos exceeds the batch size. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - save_batch_size = dc.utils._QUERY_BATCH_SIZE dc.utils._QUERY_BATCH_SIZE = 1 diff --git a/datacommons/test/populations_test.py b/datacommons/test/populations_test.py index 1f6273cb..7054854c 100644 --- a/datacommons/test/populations_test.py +++ b/datacommons/test/populations_test.py @@ -11,7 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -""" Data Commons Python Client API unit tests. +""" Data Commons Python API unit tests. Unit tests for Population and Observation methods in the Data Commons Python Client API. @@ -47,10 +47,6 @@ def read(self): if req.data: data = json.loads(req.data) - api_key = req.get_header('X-api-key') - if api_key != 'TEST-API-KEY': - return urllib.error.HTTPError(None, 403, None, None, None) - constrained_props = [ { 'property': 'placeOfBirth', @@ -214,9 +210,6 @@ class TestGetPopulations(unittest.TestCase): @mock.patch('six.moves.urllib.request.urlopen', side_effect=request_mock) def test_multiple_dcids(self, urlopen): """ Calling get_populations with proper dcids returns valid results. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - # Call get_populations populations = dc.get_populations(['geoId/06085', 'geoId/4805000'], 'Person', constraining_properties=self._constraints) @@ -231,9 +224,6 @@ def test_bad_dcids(self, urlopen): """ Calling get_populations with dcids that do not exist returns empty results. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - # Call get_populations pops_1 = dc.get_populations(['geoId/06085', 'dc/MadDcid'], 'Person', constraining_properties=self._constraints) @@ -247,9 +237,6 @@ def test_bad_dcids(self, urlopen): @mock.patch('six.moves.urllib.request.urlopen', side_effect=request_mock) def test_no_dcids(self, urlopen): """ Calling get_populations with no dcids returns empty results. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - pops = dc.get_populations( [], 'Person', constraining_properties=self._constraints) self.assertDictEqual(pops, {}) @@ -260,9 +247,6 @@ class TestGetObservations(unittest.TestCase): @mock.patch('six.moves.urllib.request.urlopen', side_effect=request_mock) def test_multiple_dcids(self, urlopen): """ Calling get_observations with proper dcids returns valid results. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - dcids = ['dc/p/x6t44d8jd95rd', 'dc/p/lr52m1yr46r44', 'dc/p/fs929fynprzs'] expected = { 'dc/p/lr52m1yr46r44': 3075662.0, @@ -279,9 +263,6 @@ def test_bad_dcids(self, urlopen): """ Calling get_observations with dcids that do not exist returns empty results. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - # Get the input dcids_1 = ['dc/p/x6t44d8jd95rd', 'dc/MadDcid'] dcids_2 = ['dc/MadDcid', 'dc/MadderDcid'] @@ -301,9 +282,6 @@ def test_bad_dcids(self, urlopen): @mock.patch('six.moves.urllib.request.urlopen', side_effect=request_mock) def test_no_dcids(self, urlopen): """ Calling get_observations with no dcids returns empty results. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - actual = dc.get_observations([], 'count', 'measuredValue', '2018-12', observation_period='P1M', measurement_method='BLSSeasonallyAdjusted') @@ -316,9 +294,6 @@ class TestGetPopObs(unittest.TestCase): @mock.patch('six.moves.urllib.request.urlopen', side_effect=request_mock) def test_valid_dcid(self, urlopen): """ Calling get_pop_obs with valid dcid returns valid results. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - # Call get_pop_obs pop_obs = dc.get_pop_obs('geoId/06085') self.assertDictEqual(pop_obs, { @@ -361,9 +336,6 @@ class TestGetPlaceObs(unittest.TestCase): @mock.patch('six.moves.urllib.request.urlopen', side_effect=request_mock) def test_valid(self, urlopen): """ Calling get_place_obs with valid parameters returns a valid result. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - # Call get_place_obs pvs = { 'placeOfBirth': 'BornInOtherStateInTheUnitedStates', diff --git a/datacommons/test/query_test.py b/datacommons/test/query_test.py index f35209a5..3e61c2b2 100644 --- a/datacommons/test/query_test.py +++ b/datacommons/test/query_test.py @@ -11,7 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -""" Data Commons Python Client API unit tests. +""" Data Commons Python API unit tests. Unit tests for the SPARQL query wrapper. """ @@ -53,12 +53,6 @@ def read(self): req = args[0] data = json.loads(req.data) - # If the API key does not match, then return 403 Forbidden - api_key = req.get_header('X-api-key') - if api_key != 'TEST-API-KEY': - return urllib.error.HTTPError(None, 403, None, None, None) - - # Mock responses for urlopen requests to query. if req.full_url == utils._API_ROOT + utils._API_ENDPOINTS['query']\ and data['sparql'] == accepted_query: return MockResponse(json.dumps({ @@ -110,9 +104,6 @@ class TestQuery(unittest.TestCase): @mock.patch('six.moves.urllib.request.urlopen', side_effect=request_mock) def test_rows(self, urlopen): """ Sending a valid query returns the correct response. """ - # Set the API key - dc.set_api_key('TEST-API-KEY') - # Create the SPARQL query query_string = (''' SELECT ?name ?dcid diff --git a/datacommons/utils.py b/datacommons/utils.py index f7ed1b9c..ade2a2f5 100644 --- a/datacommons/utils.py +++ b/datacommons/utils.py @@ -11,9 +11,9 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -""" Data Commons utilities library +""" Data Commons Utilities Library. -Various functions that can aid in the extension of the DataCommons API. +Various functions that can aid in the extension of the Data Commons API. """ from __future__ import absolute_import @@ -24,6 +24,7 @@ import base64 import json +import logging import os import six.moves.urllib.error import six.moves.urllib.request @@ -57,27 +58,13 @@ # Batch size for heavyweight queries. _QUERY_BATCH_SIZE = 500 -# Environment variable names used by the package -_ENV_VAR_API_KEY = 'DC_API_KEY' # Name the API key variable - # --------------------------- API UTILITY FUNCTIONS --------------------------- def set_api_key(api_key): - """ Sets an environment variable :code:`"DC_API_KEY"` to given :code:`api_key`. - - An API key is required to use the Python Client API. This can be provided to - the API after importing the library, or set as an environment variable - :code:`"DC_API_KEY"`. - - For more details about how to get an API key and provide it to the Python - Client API, please visit :ref:`getting_started` - - Args: - api_key (:obj:`str`): The api key. - """ - os.environ[_ENV_VAR_API_KEY] = api_key + """DEPRECATED FUNCTION--API keys no longer required.""" + logging.warning('Data Commons has removed the API key requirement. This function will be removed by June 1st, 2020.') # ------------------------- INTERNAL HELPER FUNCTIONS ------------------------- @@ -89,14 +76,7 @@ def _send_request(req_url, req_json={}, compress=False, post=True): Returns: The payload returned by sending the POST/GET request formatted as a dict. """ - # Get the API key - if not os.environ.get(_ENV_VAR_API_KEY, None): - raise ValueError( - 'Request error: Must set an API key before using the API! You can ' - 'call datacommons.set_api_key or assign the key to an environment ' - 'variable named {}'.format(_ENV_VAR_API_KEY)) headers = { - 'x-api-key': os.environ[_ENV_VAR_API_KEY], 'Content-Type': 'application/json' } diff --git a/notebooks/README.md b/notebooks/README.md index 75ebfe4e..8d591aef 100644 --- a/notebooks/README.md +++ b/notebooks/README.md @@ -1,6 +1,6 @@ -# Python Client API Notebooks +# Python API Notebooks -This directory contains iPython notebooks that use the Python Client API to +This directory contains iPython notebooks that use the Python API to perform various statistical analyses on interesting datasets. You can click on each link to see a live colab version. diff --git a/notebooks/analyzing_census_data.ipynb b/notebooks/analyzing_census_data.ipynb index 9f23fe2a..c70df907 100644 --- a/notebooks/analyzing_census_data.ipynb +++ b/notebooks/analyzing_census_data.ipynb @@ -36,7 +36,7 @@ "source": [ "# Analyzing Census Data with Data Commons\n", "\n", - "Datacommons is intended for various data science tasks. This tutorial introduces the datacommons knowledge graph and discusses two tools to help integrate its data into your data science projects: (1) the [datacommons browser](https://browser.datacommons.org/) and (2) the [Python Client API](https://github.com/google/datacommons). Before getting started, we will need to install the Python API package. \n" + "Datacommons is intended for various data science tasks. This tutorial introduces the datacommons knowledge graph and discusses two tools to help integrate its data into your data science projects: (1) the [datacommons browser](https://browser.datacommons.org/) and (2) the [Python API](https://github.com/google/datacommons). Before getting started, we will need to install the Python API package. \n" ] }, { @@ -106,7 +106,7 @@ "source": [ "## Python API\n", "\n", - "The [Python Client API](https://github.com/datacommonsorg/api-python) provides functions for users to extract structured information from Data Commons programmatically and view them in different formats such as Python `dict`'s and [Pandas](https://pandas.pydata.org/) DataFrames. DataFrames allow access to all the data processing, analytical and visualization tools provided by packages such as Pandas, NumPy, SciPy, and Matplotlib.\n", + "The [Python API](https://github.com/datacommonsorg/api-python) provides functions for users to extract structured information from Data Commons programmatically and view them in different formats such as Python `dict`'s and [Pandas](https://pandas.pydata.org/) DataFrames. DataFrames allow access to all the data processing, analytical and visualization tools provided by packages such as Pandas, NumPy, SciPy, and Matplotlib.\n", "\n", "Every notebook begins by loading the dataCommons client as follows:\n" ] @@ -139,7 +139,7 @@ "colab_type": "text" }, "source": [ - "We will also need to provide an API key to access the Data Commons Python Client API. This notebook is setup to read from a `json` file stored at `key_path` in your Google Drive. This text file should have one line:\n", + "We will also need to provide an API key to access the Data Commons Python API. This notebook is setup to read from a `json` file stored at `key_path` in your Google Drive. This text file should have one line:\n", "\n", " ```\n", "{\n", @@ -147,7 +147,7 @@ "}\n", " ```\n", " \n", - " If you want to make a copy of this notebook, make sure to replace `key_path` with the path to a file containing your API key. For more detail, visit the [Creating an API Key](https://datacommons.readthedocs.io/en/latest/started.html#creating-an-api-key) page of the Python Client API documentation.\n", + " If you want to make a copy of this notebook, make sure to replace `key_path` with the path to a file containing your API key. For more detail, visit the [Creating an API Key](https://datacommons.readthedocs.io/en/latest/started.html#creating-an-api-key) page of the Python API documentation.\n", "\n" ] }, diff --git a/notebooks/analyzing_education_achievement.ipynb b/notebooks/analyzing_education_achievement.ipynb index 906e50d3..ad2cbc5e 100644 --- a/notebooks/analyzing_education_achievement.ipynb +++ b/notebooks/analyzing_education_achievement.ipynb @@ -125,7 +125,7 @@ "colab_type": "text" }, "source": [ - "We will also need to assign an API key to the library. See the [Analyzing Statistics in Data Commons Using the Python Client API](https://colab.research.google.com/drive/1ZNXTHu3J0W3vo9Mg3kNUpk0hnD6Ce1u6#scrollTo=ijxoBhFHjo3Z) to see how to set this up for a Colab Notebook." + "We will also need to assign an API key to the library. See the [Analyzing Statistics in Data Commons Using the Python API](https://colab.research.google.com/drive/1ZNXTHu3J0W3vo9Mg3kNUpk0hnD6Ce1u6#scrollTo=ijxoBhFHjo3Z) to see how to set this up for a Colab Notebook." ] }, { diff --git a/notebooks/analyzing_income_distribution.ipynb b/notebooks/analyzing_income_distribution.ipynb index cb5e3f77..d360b826 100644 --- a/notebooks/analyzing_income_distribution.ipynb +++ b/notebooks/analyzing_income_distribution.ipynb @@ -97,7 +97,7 @@ "colab_type": "text" }, "source": [ - "We will also need to provide the API with an API key. See the [Analyzing Statistics in Data Commons Using the Python Client API](https://colab.research.google.com/drive/1ZNXTHu3J0W3vo9Mg3kNUpk0hnD6Ce1u6#scrollTo=ijxoBhFHjo3Z) to see how to set this up for a Colab Notebook." + "We will also need to provide the API with an API key. See the [Analyzing Statistics in Data Commons Using the Python API](https://colab.research.google.com/drive/1ZNXTHu3J0W3vo9Mg3kNUpk0hnD6Ce1u6#scrollTo=ijxoBhFHjo3Z) to see how to set this up for a Colab Notebook." ] }, { diff --git a/notebooks/analyzing_obesity_prevalence.ipynb b/notebooks/analyzing_obesity_prevalence.ipynb index 99266ed1..13ac21ff 100644 --- a/notebooks/analyzing_obesity_prevalence.ipynb +++ b/notebooks/analyzing_obesity_prevalence.ipynb @@ -104,7 +104,7 @@ "colab_type": "text" }, "source": [ - "We will also need to provide the API with an API key. See the [Analyzing Statistics in Data Commons Using the Python Client API](https://colab.research.google.com/drive/1ZNXTHu3J0W3vo9Mg3kNUpk0hnD6Ce1u6#scrollTo=ijxoBhFHjo3Z) to see how to set this up for a Colab Notebook." + "We will also need to provide the API with an API key. See the [Analyzing Statistics in Data Commons Using the Python API](https://colab.research.google.com/drive/1ZNXTHu3J0W3vo9Mg3kNUpk0hnD6Ce1u6#scrollTo=ijxoBhFHjo3Z) to see how to set this up for a Colab Notebook." ] }, { diff --git a/notebooks/getting_started.ipynb b/notebooks/getting_started.ipynb index fff4188b..47f27d36 100644 --- a/notebooks/getting_started.ipynb +++ b/notebooks/getting_started.ipynb @@ -3,7 +3,7 @@ "nbformat_minor": 0, "metadata": { "colab": { - "name": "Getting Started with the Python Client API", + "name": "Getting Started with the Python API", "version": "0.3.2", "provenance": [], "collapsed_sections": [] @@ -38,7 +38,7 @@ "\n", "- Sending an issue request to the [datacommons issues page](https://github.com/google/datacommons/issues). When creating an issue please mark the issue using the **api feedback** label!\n", "\n", - "**DISCLAIMER** this notebook uses an experimental version of the Data Commons Python Client API. The semantics and availability of this API may be subject to change without prior notice! " + "**DISCLAIMER** this notebook uses an experimental version of the Data Commons Python API. The semantics and availability of this API may be subject to change without prior notice! " ] }, { @@ -48,11 +48,11 @@ "colab_type": "text" }, "source": [ - "# Getting Started with the Python Client API\n", + "# Getting Started with the Python API\n", "\n", - "This tutorial introduces the Data Commons open knowledge graph and discusses how to programmtically access its data through the Python Client API. We will use the task of plotting employment data provided by the Bureau of Labor Statistics as an example to demonstrate various functionalities supported by the Python Client API.\n", + "This tutorial introduces the Data Commons open knowledge graph and discusses how to programmtically access its data through the Python API. We will use the task of plotting employment data provided by the Bureau of Labor Statistics as an example to demonstrate various functionalities supported by the Python API.\n", "\n", - "Before proceeding, we will need to install the Python Client API package." + "Before proceeding, we will need to install the Python API package." ] }, { @@ -106,7 +106,7 @@ "\n", "### The Data Commons Browser\n", "\n", - "Throughout this tutorial, we will be using the [Data Commons browser](https://browser.datacommons.org). The browser provides a human readable way of navigating nodes within the knowledge graph. This is particularly useful for discovering what parameters to pass into the Python Client API in order to correctly query for nodes in the graph. " + "Throughout this tutorial, we will be using the [Data Commons browser](https://browser.datacommons.org). The browser provides a human readable way of navigating nodes within the knowledge graph. This is particularly useful for discovering what parameters to pass into the Python API in order to correctly query for nodes in the graph. " ] }, { @@ -116,9 +116,9 @@ "colab_type": "text" }, "source": [ - "## The Python Client API\n", + "## The Python API\n", "\n", - "The Python Client API provides functions for users to programmatically access nodes in the Data Commons open knowledge graph. In this tutorial, we will be demonstrating how to use the API access nodes in the Data Commons graph and store their information in a [Pandas](https://pandas.pydata.org) Data Frame. For a discussion on how to use the API generally, please refer to the [API Documentation](https://datacommons.readthedocs.io/en/dev2/).\n", + "The Python API provides functions for users to programmatically access nodes in the Data Commons open knowledge graph. In this tutorial, we will be demonstrating how to use the API access nodes in the Data Commons graph and store their information in a [Pandas](https://pandas.pydata.org) Data Frame. For a discussion on how to use the API generally, please refer to the [API Documentation](https://datacommons.readthedocs.io/en/dev2/).\n", "\n", "Let's begin by importing the Python Client and other helpful libraries.\n", "\n" @@ -218,7 +218,7 @@ "source": [ "## Using the API To Plot Unemployment Data\n", "\n", - "The [Bureau of Labor Statistics](https://www.bls.gov) provides a monthly count for number of individuals who are employed at the State, County, and City level. This data is surfaced in the Data Commons; for example, one can find employment statistics associated with Santa Clara County [here](https://browser.datacommons.org/kg?dcid=dc/p/y6xm2mny8mck1&db=). Our task for this tutorial will be to extract employment data associated with counties in California from Data Commons using the Python Client API and view it in a Pandas DataFrame. We will focus on how functions such as\n", + "The [Bureau of Labor Statistics](https://www.bls.gov) provides a monthly count for number of individuals who are employed at the State, County, and City level. This data is surfaced in the Data Commons; for example, one can find employment statistics associated with Santa Clara County [here](https://browser.datacommons.org/kg?dcid=dc/p/y6xm2mny8mck1&db=). Our task for this tutorial will be to extract employment data associated with counties in California from Data Commons using the Python API and view it in a Pandas DataFrame. We will focus on how functions such as\n", "\n", "- `get_property_values`\n", "- `get_places_in`\n", @@ -754,7 +754,7 @@ "\n", "There are two other properties defined: `numConstraints` and `employment`. These two properties help us describe entities contained in this statistical population. Properties used to describe the entities captured by a StatisticalPopulation are called *constraining properties*. In the example above, `employment=BLS_Employed` is a constraining property that tells us the Statistical Population captures employed persons. `numConstraints` denotes how many constraining properties there are, and in the example above, `numConstraints=1` tells us that `employment` is the only constraining property.\n", "\n", - "To query for `StatisticalPopulation`s using the Data Commons Python Client API, we call **`get_populations`**. The function accepts the following parameters.\n", + "To query for `StatisticalPopulation`s using the Data Commons Python API, we call **`get_populations`**. The function accepts the following parameters.\n", "\n", "- **`dcids`** - A list or Pandas Series of dcids denoting the locations of populations to query for.\n", "- **`population_type`** - The `populationType` of the `StatisticalPopulation`\n", @@ -961,7 +961,7 @@ "\n", "The final property of interest is **`measuredValue`**. This property tells us that the raw value observed by the observation (whose value is 1,015,129) in this case. The `measuredValue` is also a *statistic type* associated with the observation. For a single observation, there could be many statistics that describe it. One would be the raw value represented by `measuredValue`, while others include `meanValue`, `medianValue`, `marginOfError`, and more.\n", "\n", - "These parameters are useful for deciding what values to provide to the API. To query for `Observation`s using the Python Client API we call **`get_observations`** which accepts the following parameters.\n", + "These parameters are useful for deciding what values to provide to the API. To query for `Observation`s using the Python API we call **`get_observations`** which accepts the following parameters.\n", "\n", "- **`dcids`** - A list or Pandas Series of dcids of nodes that are observed by observations being queried for.\n", "- **`measured_property`** - The `measuredProperty` of the observation.\n", @@ -1218,7 +1218,7 @@ "colab_type": "text" }, "source": [ - "This wraps up our tutorial on how to use the Data Commons Python Client API to access statistics in the knowledge graph and view it in a Pandas Data Frame. From this tutorial we should now know\n", + "This wraps up our tutorial on how to use the Data Commons Python API to access statistics in the knowledge graph and view it in a Pandas Data Frame. From this tutorial we should now know\n", "\n", "- How statistics are modeled in the graph\n", "- What API methods are available for accessing these statistics\n", diff --git a/setup.py b/setup.py index a7db4358..b3720138 100644 --- a/setup.py +++ b/setup.py @@ -20,7 +20,7 @@ # Package metadata. NAME = 'datacommons' -DESCRIPTION = 'A library to access Data Commons Python Client API.' +DESCRIPTION = 'A library to access Data Commons Python API.' URL = 'https://github.com/datacommonsorg/api-python' EMAIL = 'support@datacommons.org' AUTHOR = 'datacommons.org' From 95558091c92166d03f00deb05769f49000be33ca Mon Sep 17 00:00:00 2001 From: tjann <18621425+tjann@users.noreply.github.com> Date: Tue, 21 Jul 2020 18:47:34 -0700 Subject: [PATCH 3/4] Restore set_api_key to __init__ so old clients don't fail. --- datacommons/__init__.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/datacommons/__init__.py b/datacommons/__init__.py index 1bba1698..a109c69b 100644 --- a/datacommons/__init__.py +++ b/datacommons/__init__.py @@ -19,3 +19,6 @@ from datacommons.core import get_property_labels, get_property_values, get_triples from datacommons.places import get_places_in, get_related_places, get_stats from datacommons.populations import get_populations, get_observations, get_pop_obs, get_place_obs + +# Other utilities +from .utils import set_api_key \ No newline at end of file From 96afd30c61b883e9785a7ef8fb5d27e0f19eca1b Mon Sep 17 00:00:00 2001 From: tjann <18621425+tjann@users.noreply.github.com> Date: Tue, 21 Jul 2020 18:49:37 -0700 Subject: [PATCH 4/4] tjann has totally lost track of time... --- datacommons/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datacommons/utils.py b/datacommons/utils.py index ade2a2f5..e6cd9080 100644 --- a/datacommons/utils.py +++ b/datacommons/utils.py @@ -64,7 +64,7 @@ def set_api_key(api_key): """DEPRECATED FUNCTION--API keys no longer required.""" - logging.warning('Data Commons has removed the API key requirement. This function will be removed by June 1st, 2020.') + logging.warning('Data Commons has removed the API key requirement. This function will be removed by Dec 1st, 2020.') # ------------------------- INTERNAL HELPER FUNCTIONS -------------------------