diff --git a/sprint-challenge/Pipfile b/sprint-challenge/Pipfile new file mode 100644 index 00000000..2f3efb24 --- /dev/null +++ b/sprint-challenge/Pipfile @@ -0,0 +1,16 @@ +[[source]] +name = "pypi" +url = "https://pypi.org/simple" +verify_ssl = true + +[dev-packages] + +[packages] +flask = "*" +flask-sqlalchemy = "*" +requests = "*" +python-decouple = "*" +python-dateutil = "*" + +[requires] +python_version = "3.7" diff --git a/sprint-challenge/Pipfile.lock b/sprint-challenge/Pipfile.lock new file mode 100644 index 00000000..375d6513 --- /dev/null +++ b/sprint-challenge/Pipfile.lock @@ -0,0 +1,162 @@ +{ + "_meta": { + "hash": { + "sha256": "e6f7f344115de9b054e6bb960cbacdcd090c61deabfb393bcb041e0a817f4cf6" + }, + "pipfile-spec": 6, + "requires": { + "python_version": "3.7" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "certifi": { + "hashes": [ + "sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3", + "sha256:25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f" + ], + "version": "==2019.11.28" + }, + "chardet": { + "hashes": [ + "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", + "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" + ], + "version": "==3.0.4" + }, + "click": { + "hashes": [ + "sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13", + "sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7" + ], + "version": "==7.0" + }, + "flask": { + "hashes": [ + "sha256:13f9f196f330c7c2c5d7a5cf91af894110ca0215ac051b5844701f2bfd934d52", + "sha256:45eb5a6fd193d6cf7e0cf5d8a5b31f83d5faae0293695626f539a823e93b13f6" + ], + "index": "pypi", + "version": "==1.1.1" + }, + "flask-sqlalchemy": { + "hashes": [ + "sha256:0078d8663330dc05a74bc72b3b6ddc441b9a744e2f56fe60af1a5bfc81334327", + "sha256:6974785d913666587949f7c2946f7001e4fa2cb2d19f4e69ead02e4b8f50b33d" + ], + "index": "pypi", + "version": "==2.4.1" + }, + "idna": { + "hashes": [ + "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407", + "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c" + ], + "version": "==2.8" + }, + "itsdangerous": { + "hashes": [ + "sha256:321b033d07f2a4136d3ec762eac9f16a10ccd60f53c0c91af90217ace7ba1f19", + "sha256:b12271b2047cb23eeb98c8b5622e2e5c5e9abd9784a153e9d8ef9cb4dd09d749" + ], + "version": "==1.1.0" + }, + "jinja2": { + "hashes": [ + "sha256:74320bb91f31270f9551d46522e33af46a80c3d619f4a4bf42b3164d30b5911f", + "sha256:9fe95f19286cfefaa917656583d020be14e7859c6b0252588391e47db34527de" + ], + "version": "==2.10.3" + }, + "markupsafe": { + "hashes": [ + "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473", + "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161", + "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235", + "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5", + "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff", + "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b", + "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1", + "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e", + "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183", + "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66", + "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1", + "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1", + "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e", + "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b", + "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905", + "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735", + "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d", + "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e", + "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d", + "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c", + "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21", + "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2", + "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5", + "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b", + "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6", + "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f", + "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f", + "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7" + ], + "version": "==1.1.1" + }, + "python-dateutil": { + "hashes": [ + "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c", + "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a" + ], + "index": "pypi", + "version": "==2.8.1" + }, + "python-decouple": { + "hashes": [ + "sha256:55c546b85b0c47a15a47a4312d451a437f7344a9be3e001660bccd93b637de95" + ], + "index": "pypi", + "version": "==3.3" + }, + "requests": { + "hashes": [ + "sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4", + "sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31" + ], + "index": "pypi", + "version": "==2.22.0" + }, + "six": { + "hashes": [ + "sha256:1f1b7d42e254082a9db6279deae68afb421ceba6158efa6131de7b3003ee93fd", + "sha256:30f610279e8b2578cab6db20741130331735c781b56053c59c4076da27f06b66" + ], + "version": "==1.13.0" + }, + "sqlalchemy": { + "hashes": [ + "sha256:afa5541e9dea8ad0014251bc9d56171ca3d8b130c9627c6cb3681cff30be3f8a" + ], + "version": "==1.3.11" + }, + "urllib3": { + "hashes": [ + "sha256:a8a318824cc77d1fd4b2bec2ded92646630d7fe8619497b142c84a9e6f5a7293", + "sha256:f3c5fd51747d450d4dcf6f923c81f78f811aab8205fda64b0aba34a4e48b0745" + ], + "version": "==1.25.7" + }, + "werkzeug": { + "hashes": [ + "sha256:7280924747b5733b246fe23972186c6b348f9ae29724135a6dfc1e53cea433e7", + "sha256:e5f4a1f98b52b18a93da705a7458e55afb26f32bff83ff5d19189f92462d65c4" + ], + "version": "==0.16.0" + } + }, + "develop": {} +} diff --git a/sprint-challenge/app/Screen Shot 2019-12-16 at 1.36.13 AM.png b/sprint-challenge/app/Screen Shot 2019-12-16 at 1.36.13 AM.png new file mode 100644 index 00000000..302782a1 Binary files /dev/null and b/sprint-challenge/app/Screen Shot 2019-12-16 at 1.36.13 AM.png differ diff --git a/sprint-challenge/app/Screen Shot 2019-12-16 at 1.36.18 AM.png b/sprint-challenge/app/Screen Shot 2019-12-16 at 1.36.18 AM.png new file mode 100644 index 00000000..9258a133 Binary files /dev/null and b/sprint-challenge/app/Screen Shot 2019-12-16 at 1.36.18 AM.png differ diff --git a/sprint-challenge/app/__init__.py b/sprint-challenge/app/__init__.py new file mode 100644 index 00000000..683e6e43 --- /dev/null +++ b/sprint-challenge/app/__init__.py @@ -0,0 +1,8 @@ +from flask import Flask + +app = Flask(__name__) + +from app import aq_dashboard + + +app.run(debug=True) diff --git a/sprint-challenge/app/aq_dashboard.py b/sprint-challenge/app/aq_dashboard.py new file mode 100644 index 00000000..595a15d9 --- /dev/null +++ b/sprint-challenge/app/aq_dashboard.py @@ -0,0 +1,70 @@ +"""OpenAQ Air Quality Dashboard with Flask.""" +# imports +import openaq +from app import app +from flask import Flask, jsonify +from flask_sqlalchemy import SQLAlchemy +from decouple import config +import requests + +# app = Flask(__name__) +app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.sqlite3' + +DB = SQLAlchemy(app) +api = openaq.OpenAQ() + + +def utc_values(city='Los Angeles', parameter='pm25'): + """Takes in air quality measurements and returns list of utc and values""" + status, body = api.measurements(city='Los Angeles', parameter='pm25') + big_dict = body['results'] + date = [] + for i in big_dict: + for x, y in i.items(): + if x == 'date': + date.append(y) + utc = [] + for b in date: + for c, d in b.items(): + if c == 'utc': + utc.append(d) + + value = [] + for p in big_dict: + for q, r in p.items(): + if q == 'value': + value.append(r) + + list_of_zipped_items = list(zip(utc, value)) + return list_of_zipped_items + + +@app.route('/') +def root(): + """Returns values greater than 10""" + risky = Record.query.filter(Record.value >= 10).all() + return str(risky) + + +class Record(DB.Model): + id = DB.Column(DB.Integer, primary_key=True) + datetime = DB.Column(DB.String(25)) + value = DB.Column(DB.Float, nullable=False) + + def __repr__(self): + return '< Date-time: {} - Value: {} >'.format(self.datetime, + self.value) + + +@app.route('/refresh') +def refresh(): + """Pull fresh data from Open AQ and replace existing data.""" + DB.drop_all() + DB.create_all() + la = utc_values(city='Los Angeles', parameter='pm25') + for v in la: + tupl = Record(datetime=v[0], value=v[1]) + DB.session.add(tupl) + + DB.session.commit() + return 'Data refreshed!' diff --git a/sprint-challenge/app/openaq.py b/sprint-challenge/app/openaq.py new file mode 100644 index 00000000..cc51c4c2 --- /dev/null +++ b/sprint-challenge/app/openaq.py @@ -0,0 +1,538 @@ +"""Simple openaq to only depend on json, math, and requests (no dfs/plots).""" +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import json +import requests +import math + + +class ApiError(Exception): + pass + +class API(object): + """Generic API wrapper object. + """ + def __init__(self, **kwargs): + self._key = kwargs.pop('key', '') + self._pswd = kwargs.pop('pswd', '') + self._version = kwargs.pop('version', None) + self._baseurl = kwargs.pop('baseurl', None) + self._headers = {'content-type': 'application/json'} + + def _make_url(self, endpoint, **kwargs): + """Internal method to create a url from an endpoint. + :param endpoint: Endpoint for an API call + :type endpoint: string + :returns: url + """ + endpoint = "{}/{}/{}".format(self._baseurl, self._version, endpoint) + + extra = [] + for key, value in kwargs.items(): + if isinstance(value, list) or isinstance(value, tuple): + #value = ','.join(value) + for v in value: + extra.append("{}={}".format(key, v)) + else: + extra.append("{}={}".format(key, value)) + + if len(extra) > 0: + endpoint = '?'.join([endpoint, '&'.join(extra)]) + + return endpoint + + def _send(self, endpoint, method='GET', **kwargs): + """Make an API call of any method + + :param endpoint: API endpoint + :param method: API call type. Options are PUT, POST, GET, DELETE + + :type endpoint: string + :type method: string + + :returns: (status_code, json_response) + + :raises ApiError: raises an exception + """ + auth = (self._key, self._pswd) + url = self._make_url(endpoint, **kwargs) + + if method == 'GET': + resp = requests.get(url, auth=auth, headers=self._headers) + else: + raise ApiError("Invalid Method") + + if resp.status_code != 200: + raise ApiError("A bad request was made: {}".format(resp.status_code)) + + res = resp.json() + + # Add a 'pages' attribute to the meta data + try: + res['meta']['pages'] = math.ceil(res['meta']['found'] / res['meta']['limit']) + except: + pass + + return resp.status_code, res + + def _get(self, url, **kwargs): + return self._send(url, 'GET', **kwargs) + +class OpenAQ(API): + """Create an instance of the OpenAQ API + + """ + def __init__(self, version='v1', **kwargs): + """Initialize the OpenAQ instance. + + :param version: API version. + :param kwargs: API options. + + :type version: string + :type kwargs: dictionary + + """ + self._baseurl = 'https://api.openaq.org' + + super(OpenAQ, self).__init__(version=version, baseurl=self._baseurl) + + def cities(self, **kwargs): + """Returns a listing of cities within the platform. + + :param country: limit results by a certain country + :param limit: limit results in the query. Default is 100. Max is 10000. + :param page: paginate through the results. Default is 1. + :param order_by: order by one or more fields (ex. order_by=['country', 'locations']). Default value is 'country' + :param sort: define the sort order for one or more fields (ex. sort='desc') + + :return: dictionary containing the *city*, *country*, *count*, and number of *locations* + + :type country: 2-digit ISO code + :type limit: number + :type order_by: string or list of strings + :type sort: string + :type page: number + :type country: string or array of strings + :type df: bool + :type index: string + + :Example: + + >>> import openaq + >>> api = openaq.OpenAQ() + >>> status, resp = api.cities() + >>> resp['results'] + [ + { + "city": "Amsterdam", + "country": "NL", + "count": 21301, + "locations": 14 + }, + { + "city": "Badhoevedorp", + "country": "NL", + "count": 2326, + "locations": 1 + }, + ... + ] + """ + return self._get('cities', **kwargs) + + def countries(self, **kwargs): + """Returns a listing of all countries within the platform + + :param order_by: order by one or more fields (ex. order_by=['cities', 'locations']). Default value is 'country' + :param sort: define the sort order for one or more fields (ex. sort='desc') + :param limit: change the number of results returned. Max is 10000. Default is 100. + :param page: paginate through results. Default is 1. + + :type order_by: string or list + :type sort: string + :type limit: int + :type page: int + :type df: bool + :type index: string + + :return: dictionary containing the *code*, *name*, *count*, *cities*, and number of *locations*. + + :Example: + + >>> import openaq + >>> api = openaq.OpenAQ() + >>> status, resp = api.countries() + >>> resp['results'] + [ + { + "cities": 174, + "code": "AT", + "count": 121987, + "locations": 174, + "name": "Austria" + }, + { + "cities": 28, + "code": "AU", + "count": 1066179, + "locations": 28, + "name": "Australia", + }, + ... + ] + """ + return self._get('countries', **kwargs) + + def latest(self, **kwargs): + """Provides the latest value of each parameter for each location + + :param city: limit results by a certain city. Defaults to ``None``. + :param country: limit results by a certain country. Should be a 2-digit + ISO country code. Defaults to ``None``. + :param location: limit results by a city. Defaults to ``None``. + :param parameter: limit results by a specific parameter. Options include [ + pm25, pm10, so2, co, no2, o3, bc] + :param has_geo: filter items that do or do not have geographic information. + :param coordinates: center point (`lat`, `long`) used to get measurements within a + certain area. (Ex: coordinates=40.23,34.17) + :param radius: radius (in meters) used to get measurements. Must be used with coordinates. + Default value is 2500. + :param limit: change the number of results returned. Max is 10000. Default is 100. + :param page: paginate through the results. + + :type city: string + :type country: string + :type location: string + :type parameter: string + :type has_geo: bool + :type coordinates: string + :type radius: int + :type limit: int + :type page: int + :type df: bool + :type index: string + + :return: dictionary containing the *location*, *country*, *city*, and number of *measurements* + + :Example: + + >>> import openaq + >>> api = openaq.OpenAQ() + >>> status, resp = api.latest() + >>> resp['results'] + [ + { + "location": "Punjabi Bagh", + "city": "Delhi", + "country": "IN", + "measurements": [ + { + "parameter": "so2", + "value": 7.8, + "unit": "ug/m3", + "lastUpdated": "2015-07-24T11:30:00.000Z" + }, + { + "parameter": "co", + "value": 1.3, + "unit": "mg/m3", + "lastUpdated": "2015-07-24T11:30:00.000Z" + }, + ... + ] + ... + } + ] + """ + return self._get('latest', **kwargs) + + def locations(self, **kwargs): + """Provides metadata about distinct measurement locations + + :param city: Limit results by one or more cities. Defaults to ``None``. Can define as a single city + (ex. city='Delhi'), a list of cities (ex. city=['Delhi', 'Mumbai']), or as a tuple + (ex. city=('Delhi', 'Mumbai')). + :param country: Limit results by one or more countries. Should be a 2-digit + ISO country code as a string, a list, or a tuple. See `city` for details. + :param location: Limit results by one or more locations. + :param parameter: Limit results by one or more parameters. Options include [ + pm25, pm10, so2, co, no2, o3, bc] + :param has_geo: Filter items that do or do not have geographic information. + :param coordinates: center point (`lat`, `long`) used to get measurements within a + certain area. (Ex: coordinates=40.23,34.17) + :param nearest: get the X nearest number of locations to `coordinates`. Must be used + with coordinates. Wins over `radius` if both are present. Will add the + `distance` property to locations. + :param radius: radius (in meters) used to get measurements. Must be used with coordinates. + Default value is 2500. + :param order_by: order by one or more fields (ex. order_by=['country', 'count']). Default value is 'location' + :param sort: define the sort order for one or more fields (ex. sort='desc') + :param limit: change the number of results returned. Max is 10000. Default is 100. + :param page: paginate through the results. + + :type city: string, array, or tuple + :type country: string, array, or tuple + :type location: string, array, or tuple + :type parameter: string, array, or tuple + :type has_geo: bool + :type coordinates: string + :type nearest: int + :type radius: int + :type order_by: string or list + :type sort: string + :type limit: int + :type page: int + :type df: bool + :type index: string + + :return: a dictionary containing the *location*, *country*, *city*, *count*, *distance*, + *sourceName*, *sourceNames*, *firstUpdated*, *lastUpdated*, *parameters*, and *coordinates* + + :Example: + + >>> import openaq + >>> api = openaq.OpenAQ() + >>> status, resp = api.locations() + >>> resp['results'] + [ + { + "count": 4242, + "sourceName": "Australia - New South Wales", + "firstUpdated": "2015-07-24T11:30:00.000Z", + "lastUpdated": "2015-07-24T11:30:00.000Z", + "parameters": [ + "pm25", + "pm10", + "so2", + "co", + "no2", + "o3" + ], + "country": "AU", + "city": "Central Coast", + "location": "wyong" + }, + ... + ] + """ + return self._get('locations', **kwargs) + + def measurements(self, **kwargs): + """Provides data about individual measurements + + :param city: Limit results by a certain city. Defaults to ``None``. + :param country: Limit results by a certain country. Should be a 2-digit + ISO country code. Defaults to ``None``. + :param location: Limit results by a city. Defaults to ``None``. + :param parameter: Limit results by one or more parameters. Options include [ + pm25, pm10, so2, co, no2, o3, bc] + :param has_geo: Filter items that do or do not have geographic information. + :param coordinates: center point (`lat`, `long`) used to get measurements within a + certain area. (Ex: coordinates=40.23,34.17) + :param radius: radius (in meters) used to get measurements. Must be used with `coordinates`. + Default value is 2500. + :param value_from: Show results above a value threshold. Must be used with `parameter`. + :param value_to: Show results below a value threshold. Must be used with `parameter`. + :param date_from: Show results after a certain date. Format should be ``Y-M-D``. + :param date_to: Show results before a certain date. Format should be ``Y-M-D``. + :param sort: The sort order (``asc`` or ``desc``). Must be used with `order_by`. + :param order_by: Field to sort by. Must be used with **sort**. + :param include_fields: Include additional fields in the output. Allowed values are: *attribution*, + *averagingPeriod*, and *sourceName*. + :param limit: Change the number of results returned. Max is 10000 and default is 100. + :param page: Paginate through the results + + :type city: string + :type country: string + :type location: string + :type parameter: string, array, or tuple + :type has_geo: bool + :type coordinates: string + :type radius: int + :type value_from: number + :type value_to: number + :type date_from: date + :type date_to: date + :type sort: string + :type order_by: string + :type include_fields: array + :type limit: number + :type page: number + :type df: bool + :type index: string + + :return: a dictionary containing the *date*, *parameter*, *value*, *unit*, + *location*, *country*, *city*, *coordinates*, and *sourceName*. + + :Example: + + >>> import openaq + >>> api = openaq.OpenAQ() + >>> status, resp = api.measurements(city = 'Delhi') + >>> resp['results'] + { + "parameter": "Ammonia", + "date": { + "utc": "2015-07-16T20:30:00.000Z", + 'local': "2015-07-16T18:30:00.000-02:00" + }, + "value": "72.9", + "unit": "ug/m3", + "location": "Anand Vihar", + "country": "IN", + "city": "Delhi", + "coordinates": { + "latitude": 43.34, + "longitude": 23.04 + }, + "attribution": { + "name": "SINCA", + "url": "http://sinca.mma.gob.cl/" + }, + { + "name": "Ministerio del Medio Ambiente" + } + ... + } + """ + return self._get('measurements', **kwargs) + + def fetches(self, **kwargs): + """Provides data about individual fetch operations that are used to populate + data in the platform. + + :param order_by: order by one or more fields (ex. order_by=['timeEnded', 'count']). Default value is 'country' + :param sort: define the sort order for one or more fields (ex. sort='desc') + :param limit: change the number of results returned. Max is 10000. Default is 100. + :param page: paginate through the results. Default is 1. + + :type order_by: string or list + :type sort: string + :type limit: int + :type page: int + + :return: dictionary containing the *timeStarted*, *timeEnded*, *count*, and *results* + + :Example: + + >>> import openaq + >>> api = openaq.OpenAQ() + >>> status, resp = api.fetches() + >>> resp + { + "meta": { + "name": "openaq-api", + "license": + "website": + "page": 1, + "limit": 100, + "found": 3, + "pages": 1 + }, + "results": [ + { + "count": 0, + "results": [ + { + "message": "New measurements inserted for Mandir Marg: 1", + "failures": {}, + "count": 0, + "duration": 0.153, + "sourceName": "Mandir Marg" + }, + { + "message": "New measurements inserted for Sao Paulo: 1898", + "failures": {}, + "count": 1898, + "duration": 16.918, + "sourceName": "Sao Paulo" + }, + ... + ], + "timeStarted": "2016-02-07T15:25:04.603Z", + "timeEnded": "2016-02-07T15:25:04.793Z", + } + ] + } + """ + return self._get('fetches', **kwargs) + + def parameters(self, **kwargs): + """ + Provides a simple listing of parameters within the platform. + + :param order_by: order by one or more fields (ex. order_by=['preferredUnit', 'id']). Default value is 'country' + :param sort: define the sort order for one or more fields (ex. sort='desc') + + :type order_by: string or list + :type sort: string + + :return: a dictionary containing the *id*, *name*, *description*, and + *preferredUnit*. + + :Example: + + >>> import openaq + >>> api = openaq.OpenAQ() + >>> status, resp = api.parameters() + >>> resp['results'] + [ + { + "id": "pm25", + "name": "PM2.5", + "description": "Particulate matter less than 2.5 micrometers in diameter", + "preferredUnit": "ug/m3" + } + ... + ] + """ + return self._get('parameters', **kwargs) + + def sources(self, **kwargs): + """ + Provides a list of data sources. + + :param order_by: order by one or more fields (ex. order_by=['active', 'country']). Default value is 'country' + :param sort: define the sort order for one or more fields (ex. sort='desc') + :param limit: Change the number of results returned. + :param page: Paginate through the results + + :type limit: number + :type page: number + :type df: bool + :type index: string + :type order_by: string or list + :type sort: string + + :return: a dictionary containing the *url*, *adapter*, *name*, *city*, + *country*, *description*, *resolution*, *sourceURL*, *contacts*, and *active*. + + :Example: + + >>> import openaq + >>> api = openaq.OpenAQ() + >>> status, resp = api.sources() + >>> resp['results'] + [ + { + "url": "http://airquality.environment.nsw.gov.au/aquisnetnswphp/getPage.php?reportid=2", + "adapter": "nsw", + "name": "Australia - New South Wales", + "city": "", + "country": "AU", + "description": "Measurements from the Office of Environment & Heritage of the New South Wales government.", + "resolution": "1 hr", + "sourceURL": "http://www.environment.nsw.gov.au/AQMS/hourlydata.htm", + "contacts": [ + "olaf@developmentseed.org" + ] + } + ... + ] + """ + + return self._get('sources', **kwargs) + + def __repr__(self): + return "OpenAQ API"