Skip to content
This repository has been archived by the owner on Oct 27, 2024. It is now read-only.

Commit

Permalink
Merge pull request #22 from exTerEX/feature-11
Browse files Browse the repository at this point in the history
Added tests and stuff, one commit due to error in other branch. Closes #11
  • Loading branch information
exTerEX authored Mar 19, 2022
2 parents 5bd1019 + 59494da commit 5144894
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 38 deletions.
8 changes: 7 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,13 @@ jobs:
with:
python-version: ${{ matrix.python-version }}

# TODO: Implement unittest and run
- name: Install module on ${{ matrix.python-version }}
run: |
python -m pip install .
- name: Run test on ${{ matrix.python-version }}
run: |
python tests/climate.py ${{ secrets.CDO_TOKEN }}
draft:
if: github.event_name != 'pull_request'
Expand Down
12 changes: 8 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ python -m pip install git+https://github.com/exTerEX/noaa/tarball/main
Below is a simple example on how to use this API. Get a token from [NOAA](https://www.ncdc.noaa.gov/cdo-web/token) and input it into where `<token>` in the example below.

```python
import noaa
from noaa.climate import API

noaaobj = noaa.NOAA("<token>")
noaaobj = API("<token>")

print(noaaobj.get_datasets())
print(noaaobj.get_data(
Expand All @@ -65,15 +65,19 @@ See [documentation](https://www.ncdc.noaa.gov/cdo-web/webservices/v2) for an in-

### Running tests

TODO: Not implemented yet.
Run the tests in the CMD using the line under, with a valid token.

```console
python tests/climate.py <token>
```

## Contributing

Please read [CONTRIBUTING](https://github.com/exTerEX/noaa/blob/main/.github/CONTRIBUTING.md) for details on our code of conduct, and the process for submitting pull requests to us.

## Versioning

This project use [Semantic Versioning](https://semver.org/) for versioning. For the versions available, see the [tags](https://github.com/exTerEX/noaa/tags) on this repository.
This project use [PEP440](https://peps.python.org/pep-0440/) for versioning. For the versions available, see the [tags](https://github.com/exTerEX/noaa/tags) on this repository.

## Authors

Expand Down
2 changes: 1 addition & 1 deletion docs/source/documentation.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
API Referance
================================

.. autoclass:: climate.api.NOAA
.. autoclass:: climate.API
:members:

TODO: Include more info on available input values for some fields.
36 changes: 5 additions & 31 deletions noaa/climate/api.py → noaa/climate.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,15 @@
"""
Source code for API implementation
MIT License
Copyright (c) 2022 Andreas Sagen
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
Expand All @@ -31,9 +26,8 @@
from typing import Optional, Union


class NOAA:
class API:
"""Class for interfacing with NOAA climate data API
:param key: Access token from NOAA
:type key: str
"""
Expand All @@ -58,7 +52,6 @@ def get_datasets(
offset: Optional[int] = 0
) -> dict:
"""Get list of available datasets in CDO or info on a specific dataset
:param dataset_id: Identification to dataset in CDO, defaults to None
:type dataset_id: str, optional
:param data_type_id: Identification to datatype(s) in CDO, defaults to None
Expand All @@ -79,9 +72,7 @@ def get_datasets(
:type limit: int, optional
:param offset: Offset first result in response from CDO, defaults to 0
:type offset: int, optional
:raises TypeError: If dataset_id is not string or None, raises an error.
:return: Return a object with data from response
:rtype: dict
"""
Expand Down Expand Up @@ -119,7 +110,6 @@ def get_data_categories(
offset: Optional[int] = 0
) -> dict:
"""Get list of available categories in CDO or info on a specific category
:param category_id: Identification to category in CDO, defaults to None
:type category_id: str, optional
:param dataset_id: Identification to dataset(s) in CDO, defaults to None
Expand All @@ -140,9 +130,7 @@ def get_data_categories(
:type limit: int, optional
:param offset: Offset first result in response from CDO, defaults to 0
:type offset: int, optional
:raises TypeError: If category_id is not string or None, raises an error.
:return: Return a object with data from response
:rtype: dict
"""
Expand Down Expand Up @@ -181,7 +169,6 @@ def get_data_types(
offset: Optional[int] = 0
) -> dict:
"""Get list of available datatypes in CDO or info on a specific datatype
:param type_id: Identification to type in CDO, defaults to None
:type type_id: str, optional
:param dataset_id: Identification to dataset(s) in CDO, defaults to None
Expand All @@ -204,9 +191,7 @@ def get_data_types(
:type limit: int, optional
:param offset: Offset first result in response from CDO, defaults to 0
:type offset: int, optional
:raises TypeError: If type_id is not string or None, raises an error.
:return: Return a object with data from response
:rtype: dict
"""
Expand Down Expand Up @@ -243,7 +228,6 @@ def get_location_categories(
offset: Optional[int] = 0
) -> dict:
"""Get list of available location categories in CDO or info on a specific location category
:param location_category_id: Identification to location category in CDO, defaults to None
:type location_category_id: str, optional
:param dataset_id: Identification to dataset(s) in CDO, defaults to None
Expand All @@ -260,9 +244,7 @@ def get_location_categories(
:type limit: int, optional
:param offset: Offset first result in response from CDO, defaults to 0
:type offset: int, optional
:raises TypeError: If location_category_id is not string or None, raises an error.
:return: Return a object with data from response
:rtype: dict
"""
Expand Down Expand Up @@ -299,7 +281,6 @@ def get_locations(
offset: Optional[int] = 0
) -> dict:
"""Get list of available locations in CDO or info on a specific location
:param location_id: Identification to location in CDO, defaults to None
:type location_id: str, optional
:param dataset_id: Identification to dataset(s) in CDO, defaults to None
Expand All @@ -320,9 +301,7 @@ def get_locations(
:type limit: int, optional
:param offset: Offset first result in response from CDO, defaults to 0
:type offset: int, optional
:raises TypeError: If location_id is not string or None, raises an error.
:return: Return a object with data from response
:rtype: dict
"""
Expand Down Expand Up @@ -362,7 +341,6 @@ def get_stations(
offset: Optional[int] = 0
) -> dict:
"""Get list of available stations in CDO or info on a specific station
:param station_id: Identification to station in CDO, defaults to None
:type station_id: str, optional
:param dataset_id: Identification to dataset(s) in CDO, defaults to None
Expand All @@ -387,9 +365,7 @@ def get_stations(
:type limit: int, optional
:param offset: Offset first result in response from CDO, defaults to 0
:type offset: int, optional
:raises TypeError: If station_id is not string or None, raises an error.
:return: Return a object with data from response
:rtype: dict
"""
Expand Down Expand Up @@ -431,7 +407,6 @@ def get_data(
include_metadata: Optional[bool] = False
) -> dict:
"""Get available data in CDO
:param dataset_id: Identification to dataset in CDO
:type dataset_id: str, datetime.datetime
:param start_date: Filter from time in ISO formatted date
Expand All @@ -456,7 +431,6 @@ def get_data(
:type offset: int, optional
:param include_metadata: Include or exclude metadata from CDO, defaults to False
:type include_metadata: bool, optional
:return: Return a object with data from response
:rtype: dict
"""
Expand All @@ -475,7 +449,7 @@ def get_data(
start_date=start_date,
station_id=station_id,
units=units,
__full_time=True
_full_time=True
)

def _call_api(
Expand All @@ -496,7 +470,7 @@ def _call_api(
sort_order: Optional[str] = "asc",
station_id: Optional[Union[str, list, tuple]] = None,
units: Optional[str] = "metric",
__full_time=False
_full_time: bool = False
) -> dict:
_ids_1 = [
dataset_id,
Expand Down Expand Up @@ -531,7 +505,7 @@ def _call_api(
raise ValueError(
"start_date has to be on ISO date format") from error

if __full_time:
if _full_time:
start_date = start_date.isoformat() + "T" + start_date.strftime("%H:%M:%S")
else:
start_date = start_date.isoformat()
Expand All @@ -547,7 +521,7 @@ def _call_api(
raise ValueError(
"end_date has to be on ISO date format") from error

if __full_time:
if _full_time:
end_date = end_date.isoformat() + "T" + end_date.strftime("%H:%M:%S")
else:
end_date = end_date.isoformat()
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pythonVersion = "3.7"
multi_line_output = 5

[tool.pylint.master]
ignore = ["__init__.py", "docs", "__pycache__"]
ignore = ["__init__.py", "docs", "tests", "__pycache__"]
jobs = 0
persistent = "yes"

Expand Down
77 changes: 77 additions & 0 deletions tests/climate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import unittest
import sys
from noaa.climate import API

if len(sys.argv) != 2:
sys.exit("ERROR: A command-line parameter must be supplied for these tests")


obj = API(sys.argv[1])


class TestClimateApi(unittest.TestCase):
def test_get_datasets(self):
result = obj.get_datasets("GSOM")

self.assertEqual(result["id"], "GSOM")
self.assertIsInstance(result, dict)
self.assertIsNotNone(result)

result = obj.get_datasets(limit=5)

result = obj.get_datasets(
start_date="1970-10-03",
end_date="2012-09-10"
)

self.assertIsInstance(result, dict)
self.assertIsNotNone(result)

result = obj.get_datasets(
start_date="1970-10-03H10:10:10",
end_date="2012-08-10H10:10:10"
)

self.assertIsInstance(result, dict)
self.assertIsNotNone(result)

self.assertLessEqual(len(result), 5)
self.assertIsNotNone(result)

def test_get_data_categories(self):
result = obj.get_data_categories("ANNAGR")

self.assertEqual(result["id"], "ANNAGR")
self.assertIsInstance(result, dict)
self.assertIsNotNone(result)

def test_get_data_types(self):
result = obj.get_data_types("ACMH")

self.assertEqual(result["id"], "ACMH")
self.assertIsInstance(result, dict)
self.assertIsNotNone(result)

def test_get_location_categories(self):
result = obj.get_location_categories("CITY")

def test_get_locations(self):
result = obj.get_locations("FIPS:37")

self.assertEqual(result["id"], "FIPS:37")
self.assertIsInstance(result, dict)
self.assertIsNotNone(result)

def test_get_stations(self):
result = obj.get_stations("COOP:010957")

self.assertEqual(result["id"], "COOP:010957")
self.assertIsInstance(result, dict)
self.assertIsNotNone(result)

def test_get_data(self):
pass


if __name__ == "__main__":
unittest.main(argv=["first-arg-is-ignored"], exit=False)

0 comments on commit 5144894

Please sign in to comment.