diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ee2af31..b15afbe 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,6 +3,7 @@ repos: rev: 'v0.941' # Use the sha / tag to point at specific version hooks: - id: mypy + additional_dependencies: ['types-requests', 'types-urllib3'] - repo: https://github.com/psf/black rev: '22.1.0' hooks: diff --git a/README.md b/README.md index ac27d6e..d8b9911 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,8 @@ I want to make it easy to get your hands on accurate air quality data for your p [License and TOS](#license-and-terms-of-service) +[Contributors](#contributors) + ## Install it here! ```sh @@ -67,6 +69,22 @@ data = o3.get_multiple_city_air([ARRAY OF CITY NAMES]) ![Gif of ozone.get_multiple_city_air()](/src/media/ozone_get_multiple_city_air_updated.gif) +### Air Quality Parameters + +Ozone can fetch the following parameters: + + * `aqi`: air quality index, a measurement of air quality that tells you how clean or polluted the air is + * `pm25`: fine particulate matter, a measure of 2.5 micrometers or smaller particles in the air + * `pm10`: respirable particulate matter, a measure of 10 micrometers or smaller particles in the air + * `o3`: a measure of ground level ozone concentrations in the air + * `co`: a measure of carbon monoxide concentrations in the air + * `no2`: a measure of nitrogen dioxide concentrations in the air + * `so2`: a measure of sulfur dioxide concentrations in the air + * `dew`: dew point, the temperature the air needs to be cooled to in order to reach 100% relative humidity + * `h`: relative humidity, a measure of moisture in the atmosphere + * `p`: atmospheric pressure, a measure of the weight of atoms and molecules that make up the layers in the atmosphere + * `t`: temperature, a measure of thermal energy in one or a combined substance at a given time + * `w`: wind speed, a measure of air in motion Sample output: blehblhe @@ -97,6 +115,14 @@ This package is a wrapper around an API provided by the World Air Quality Index 1. Ozone is licensed under the GNU GENERAL PUBLIC LICENSE v3.0, and so it cannot be used for closed-source software or for monetary gain. 2. The WAQI API, which Ozone uses to provide data, has it's own [Acceptable Usage Policy](https://aqicn.org/api/tos/). Please refer to it for more details. +## Contributors + +Contributions of any kind are welcome and these are our amazing contributors. + + + + + Enjoy using Ozone! 🥳 🍾 🚀 diff --git a/setup.cfg b/setup.cfg index 2b867a5..c14ce4b 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = ozon3 -version = 1.4.6 +version = 1.4.7 author = Milind Sharma author_email = milindsharma8@gmail.com description = A package to get air quality data using the WAQI API diff --git a/setup.py b/setup.py index c73c092..efb2ad0 100644 --- a/setup.py +++ b/setup.py @@ -9,8 +9,8 @@ description="A package to get air quality data using the WAQI API", license="GPLv3+", url="https://github.com/Milind220/Ozone", - version="1.4.6", - download_url="https://github.com/Milind220/Ozone/archive/refs/tags/v1.4.6.tar.gz", + version="1.4.7", + download_url="https://github.com/Milind220/Ozone/archive/refs/tags/v1.4.7.tar.gz", packages=setuptools.find_packages(), install_requires=[ "numpy; python_version>='3'", diff --git a/src/ozone/ozone.py b/src/ozone/ozone.py index ad62ca0..b16c634 100644 --- a/src/ozone/ozone.py +++ b/src/ozone/ozone.py @@ -8,7 +8,8 @@ Attributes (module level): CALLS (int=1000): The number of calls per second allowed by the WAQI API is 1000. - RATE_LIMIT (int=1): The time period in seconds for the max number of calls is 1 second. + RATE_LIMIT (int=1): The time period in seconds for the max number of calls is + 1 second. """ import pandas @@ -112,12 +113,15 @@ def reset_token(self, token: str) -> None: self._check_token_validity() def _format_output( - self, data_format: str = "df", df: pandas.DataFrame = pandas.DataFrame(), + self, + data_format: str = "df", + df: pandas.DataFrame = pandas.DataFrame(), ) -> pandas.DataFrame: """Format output data Args: - data_format (str): File format. Defaults to 'df'. Choose from 'csv', 'json', 'xlsx'. + data_format (str): File format. Defaults to 'df'. + Choose from 'csv', 'json', 'xlsx'. df (pandas.DataFrame,): Dataframe object of air quality data. Returns: @@ -133,7 +137,9 @@ def _format_output( df.to_json("air_quality_data.json") print("File saved to disk as air_quality_data.json") elif data_format == "xlsx": - df.to_excel("air_quality_data.xlsx",) + df.to_excel( + "air_quality_data.xlsx", + ) print("File saved to disk as air_quality_data.xlsx") else: raise Exception( @@ -147,7 +153,8 @@ def _parse_data( """Parse the data from the API response Args: - data_obj (JSON object returned by json.loads): The data from the API response. + data_obj (JSON object returned by json.loads): The data from the API's + response. city (str): The city name. params (List[str]): The parameters to parse. @@ -197,19 +204,35 @@ def _AQI_meaning(self, aqi: float) -> Tuple[str, str]: if 0 <= aqi <= 50: AQI_meaning = "Good" - AQI_health_implications = "Air quality is considered satisfactory, and air pollution poses little or no risk" + AQI_health_implications = ( + "Air quality is considered satisfactory, " + "and air pollution poses little or no risk" + ) elif 51 <= aqi <= 100: AQI_meaning = "Moderate" - AQI_health_implications = "Air quality is acceptable; however, for some pollutants there may be a moderate health concern for a very small number of people who are unusually sensitive to air pollution." + AQI_health_implications = ( + "Air quality is acceptable; however, for some pollutants " + "there may be a moderate health concern for a very small " + "number of people who are unusually sensitive to air pollution." + ) elif 101 <= aqi <= 150: AQI_meaning = "Unhealthy for sensitive group" - AQI_health_implications = "Members of sensitive groups may experience health effects. The general public is not likely to be affected." + AQI_health_implications = ( + "Members of sensitive groups may experience health effects. " + "The general public is not likely to be affected." + ) elif 151 <= aqi <= 200: AQI_meaning = "Unhealthy" - AQI_health_implications = "Everyone may begin to experience health effects; members of sensitive groups may experience more serious health effects." + AQI_health_implications = ( + "Everyone may begin to experience health effects; members of " + "sensitive groups may experience more serious health effects." + ) elif 201 <= aqi <= 300: AQI_meaning = "Very Unhealthy" - AQI_health_implications = "Health warnings of emergency conditions. The entire population is more likely to be affected." + AQI_health_implications = ( + "Health warnings of emergency conditions. " + "The entire population is more likely to be affected." + ) elif 301 <= aqi <= 500: AQI_meaning = "Hazardous" AQI_health_implications = ( @@ -217,7 +240,8 @@ def _AQI_meaning(self, aqi: float) -> Tuple[str, str]: ) else: raise Exception( - f"{aqi} is not valid air quality index value. Should be between 0 to 500." + f"{aqi} is not valid air quality index value. " + "Should be between 0 to 500." ) return AQI_meaning, AQI_health_implications @@ -269,8 +293,10 @@ def get_coordinate_air( Args: lat (float): Latitude lon (float): Longitude - data_format (str): File format for data. Defaults to 'df'. Choose from 'csv', 'json', 'xlsx'. - df (pandas.DataFrame, optional): An existing dataframe to append the data to. + data_format (str): File format for data. Defaults to 'df'. + Choose from 'csv', 'json', 'xlsx'. + df (pandas.DataFrame, optional): An existing dataframe to + append the data to. params (List[str], optional): A list of parameters to get data for. Gets all parameters by default. @@ -302,8 +328,10 @@ def get_city_air( Args: city (str): The city to get data for. - data_format (str): File format for data. Defaults to 'df'. Choose from 'csv', 'json', 'xlsx'. - df (pandas.DataFrame, optional): An existing dataframe to append the data to. + data_format (str): File format for data. Defaults to 'df'. + Choose from 'csv', 'json', 'xlsx'. + df (pandas.DataFrame, optional): An existing dataframe to + append the data to. params (List[str], optional): A list of parameters to get data for. Gets all parameters by default. @@ -326,7 +354,8 @@ def get_city_air( ) raise Exception( - f'There is a problem with city "{city}", the returned data: {data_obj}' + f'There is a problem with city "{city}", ' + "the returned data: {data_obj}" ) row = self._parse_data(data_obj, city, params) @@ -345,8 +374,10 @@ def get_multiple_coordinate_air( Args: locations (list): A list of pair (latitude,longitude) to get data for. - data_format (str): File format. Defaults to 'df'. Choose from 'csv', 'json', 'xlsx'. - df (pandas.DataFrame, optional): An existing dataframe to append the data to. + data_format (str): File format. Defaults to 'df'. + Choose from 'csv', 'json', 'xlsx'. + df (pandas.DataFrame, optional): An existing dataframe to + append the data to. params (List[str], optional): A list of parameters to get data for. Gets all parameters by default. @@ -355,7 +386,8 @@ def get_multiple_coordinate_air( selected another data format, this dataframe will be empty) """ for loc in locations: - # This just makes sure that it's always a returns a pd.DataFrame. Makes mypy happy. + # This just makes sure that it's always a returns a pandas.DataFrame. + # Makes mypy happy. df = pandas.DataFrame( self.get_coordinate_air(loc[0], loc[1], df=df, params=params) ) @@ -376,8 +408,10 @@ def get_range_coordinates_air( Args: lower_bound (tuple): start coordinate upper_bound (tuple): end coordinate - data_format (str): File format. Defaults to 'df'. Choose from 'csv', 'json', 'xlsx'. - df (pandas.DataFrame, optional): An existing dataframe to append the data to. + data_format (str): File format. Defaults to 'df'. + Choose from 'csv', 'json', 'xlsx'. + df (pandas.DataFrame, optional): An existing dataframe to + append the data to. params (List[str], optional): A list of parameters to get data for. Gets all parameters by default. @@ -403,23 +437,30 @@ def get_multiple_city_air( Args: cities (list): A list of cities to get data for. - data_format (str): File format. Defaults to 'df'. Choose from 'csv', 'json', 'xlsx'. + data_format (str): File format. Defaults to 'df'. + Choose from 'csv', 'json', 'xlsx'. params (List[str], optional): A list of parameters to get data for. Gets all parameters by default. - df (pandas.DataFrame, optional): An existing dataframe to append the data to. + df (pandas.DataFrame, optional): An existing dataframe to + append the data to. Returns: pandas.DataFrame: The dataframe containing the data. (If you selected another data format, this dataframe will be empty) """ for city in cities: - # This just makes sure that it's always a returns a pd.DataFrame. Makes mypy happy. + # This just makes sure that it's always a returns a pandas.DataFrame. + # Makes mypy happy. df = pandas.DataFrame(self.get_city_air(city=city, df=df, params=params)) df.reset_index(inplace=True, drop=True) return self._format_output(data_format, df) - def get_specific_parameter(self, city: str, air_param: str = "",) -> float: + def get_specific_parameter( + self, + city: str, + air_param: str = "", + ) -> float: """Get specific parameter as a float Args: