Skip to content

Commit 3513e02

Browse files
prez2307zachspar
andauthored
Feature/cli (#26)
* boilerplate cli * wrap sources cli * Feature/required args (#10) * create api decorator to check valid args * format files * add args validation for releases * add api arg validator for categories * update required args for categories namespace * add required args to tags namespace * add validate args to sources apis * add arg validation to series namespace * add required args for series apis * finish base implementation of all APIs, closes issue #4 * bump fred-py-api to 0.0.5 and update readme to point to wiki * Create dependabot.yml * Delete dependabot.yml * Feature/test suite (#11) * basic tests for categories namespace * add basic tests for tags api * add basic tests for sources api namespace * create basic tests for releases api namespace * add basic tests for series api namespace * create test for decorators * use src for tests * first full test-suite of basic API functionality, closes issue #8 * new CI for lint and test package * upgrade black in CI, use fred api key from GH secrets * reformat files * update CI only test for 3.9 & 3.10 * only run CI with python 3.10.x * run ci using coverage * add coverage upload * add new job skeleton to CI * upload to PyPI when publishing new release/prerelease * Feature/test suite (#14) * basic tests for categories namespace * add basic tests for tags api * add basic tests for sources api namespace * create basic tests for releases api namespace * add basic tests for series api namespace * create test for decorators * use src for tests * first full test-suite of basic API functionality, closes issue #8 * new CI for lint and test package * upgrade black in CI, use fred api key from GH secrets * reformat files * update CI only test for 3.9 & 3.10 * only run CI with python 3.10.x * run ci using coverage * add coverage upload * add new job skeleton to CI * upload to PyPI when publishing new release/prerelease * update readme * 0.0.7-Alpha (#16) * add FRED urls to python docstrings * update readme * bump lib * fix issue #15 by enforcing API length * check alnum * update tests * reformat file * rename top level packagename to fred * bump lib (#17) * Add support for XML `file_type` (#18) * add XML support, and associated test * bump lib version to v0.1.1 * move cli library * cli WIP * general idea of FRED cli, WIP * variadic api arguments and kwargs generator, import cleanups * re-organize internal util module * full CLI project skeleton with some working examples * json dump string in sources CLI * restructure tests module * adding dummy test case for codecov * adding dummy test case for codecov * reformat file * update ci to run coverage with src * add test for generate_api_kwargs cli utility * Added JSON CLI commands for each command * update tests module to use installed fred library * update local requirements * update cli code slightly * update pyproject.toml to include new deps and script entrypoints * update README to include CLI * update github ci workflow to include editable install * Fixed many issues in code review, still need 4 utility functions, few changes needed * update a few args, docstrings, and file format * Adding basic testing structure for sources cli * wip series test cases * refactor fred cli entry point * refactor common test case logic * refactor and fix existing api tests * fix api key mock for cli tests * update ci workflow * slight refactor to base fred client test setup * allow for more testing constraints in base framework * wip series cli tests * omit test * add all basic tests for releases namespace * add missing test to releases namespace * finish up all basic tests for series cli * add support for XML output in CLI * Added CLI test cases for sources, tags, categories * reformat files * fix up some broken tests * add new test for CLI entry point * optimize imports * update codecoverage omit files, and CI * fix CI * ignore unnecessary files in codecov * update pyproject.toml description Co-authored-by: Zachary Spar <[email protected]> Co-authored-by: Zachary Spar <[email protected]>
1 parent c15b84d commit 3513e02

32 files changed

+1624
-62
lines changed

.github/workflows/fred-py-api-package.yml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
1+
# This workflow will install Python dependencies, run tests and lint
2+
# On publish event, it will build and publish a package to PyPI
23

34
name: Lint, Test & Upload fred-py-api
45

@@ -20,6 +21,8 @@ jobs:
2021
python-version: ["3.10"]
2122
env:
2223
FRED_API_KEY: ${{ secrets.FRED_API_KEY }}
24+
TEST_FRED_API_KEY__API: ${{ secrets.TEST_FRED_API_KEY__API }}
25+
TEST_FRED_API_KEY__CLI: ${{ secrets.TEST_FRED_API_KEY__CLI }}
2326

2427
steps:
2528
- uses: actions/checkout@v3
@@ -31,14 +34,15 @@ jobs:
3134
run: |
3235
python -m pip install --upgrade pip
3336
python -m pip install requests coverage black==22.6.0
37+
python -m pip install -e .
3438
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
3539
- name: Lint with black
3640
run: |
3741
# Run black on all Python files
3842
black --line-length 120 --check ./
3943
- name: Test with coverage
4044
run: |
41-
coverage run -m unittest discover -s tests
45+
coverage run --source="src" --omit="src/fred/cli/__main__.py","src/fred/cli/__init__.py" -m unittest
4246
coverage report -m
4347
- name: Upload coverage report
4448
uses: codecov/codecov-action@v2

README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,11 @@
33
[![codecov](https://codecov.io/gh/zachspar/fred-py-api/branch/main/graph/badge.svg?token=BG1948D8Y7)](https://codecov.io/gh/zachspar/fred-py-api)
44

55
# Fred Python API
6-
A fully-featured FRED Python Wrapper.
6+
A fully-featured FRED Command Line Interface & Python API Wrapper.
77

88
## Documentation:
99
- [fred-py-api Wiki](https://github.com/zachspar/fred-py-api/wiki)
1010

1111
### FRED References:
1212
- [Create an API Key Here](https://fredaccount.stlouisfed.org/apikey)
1313
- [API Documentation](https://fred.stlouisfed.org/docs/api/fred/)
14-

pyproject.toml

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
[build-system]
2-
requires = ["setuptools>=61.0", "requests>=2.17.3",]
2+
requires = ["setuptools>=61.0",]
33
build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "fred-py-api"
7-
version = "1.0.1"
7+
version = "1.1.0"
88
authors = [
99
{ name="Zachary Spar", email="[email protected]" },
1010
{ name="Prasiddha Parthsarthy", email="[email protected]" },
1111
]
12-
description = "A fully featured FRED API client library for Python."
12+
description = "A fully featured FRED Command Line Interface & Python API client library."
1313
readme = "README.md"
1414
requires-python = ">=3.6"
1515
classifiers = [
@@ -27,8 +27,12 @@ classifiers = [
2727
]
2828
dependencies = [
2929
"requests>=2.17.3",
30+
"click>=7.0",
3031
]
3132

33+
[project.scripts]
34+
fred = "fred.cli:__main__.run_cli"
35+
3236
[project.urls]
3337
"Homepage" = "https://github.com/zachspar/fred_py_api"
3438
"Bug Tracker" = "https://github.com/zachspar/fred_py_api/issues"

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,5 @@ toml==0.10.2
2121
tomli==2.0.1
2222
tox==3.25.1
2323
typing_extensions==4.3.0
24-
urllib3==1.26.10
24+
urllib3==1.26.11
2525
virtualenv==20.15.1

src/fred/_util/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/usr/bin/env python3
2+
from .cli import *
3+
from .decorators import *

src/fred/_util/cli.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#!/usr/bin/env python3
2+
"""
3+
FRED CLI Utilities.
4+
"""
5+
from json import dumps
6+
from typing import Union
7+
from xml.etree import ElementTree as ET
8+
9+
10+
__all__ = [
11+
"generate_api_kwargs",
12+
"serialize",
13+
]
14+
15+
16+
def generate_api_kwargs(arguments: tuple) -> dict:
17+
"""Generate API keyword arguments from CLI variadic arguments."""
18+
api_kwargs = {}
19+
for arg in arguments:
20+
try:
21+
api_kwargs[arg.split("=")[0]] = arg.split("=")[1]
22+
except IndexError:
23+
pass
24+
return api_kwargs
25+
26+
27+
def serialize(response_obj: Union[dict, ET.Element]) -> str:
28+
"""Serialize a FRED response object to a string."""
29+
if isinstance(response_obj, dict):
30+
return dumps(response_obj, indent=4)
31+
elif isinstance(response_obj, ET.Element):
32+
return ET.tostring(response_obj, encoding="unicode", method="xml")
33+
else:
34+
raise TypeError("response_obj must be a dict or xml.etree.ElementTree.Element")

src/fred/_util/decorators.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
11
#!/usr/bin/env python3
2+
"""
3+
FRED API Decorators.
4+
"""
25
from functools import wraps
36

47

8+
__all__ = [
9+
"validate_api_args",
10+
]
11+
12+
513
def validate_api_args(*valid_args):
614
"""Class method decorator to validate API arguments."""
715

src/fred/api/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
"""
33
Fred API core.
44
"""
5+
from ._fred_client import JsonOrXml
56
from .categories import FredAPICategories
67
from .exceptions import BaseFredAPIError, FredAPIRequestError
7-
from ._fred_client import JsonOrXml
88
from .releases import FredAPIReleases
99
from .series import FredAPISeries
1010
from .sources import FredAPISources

src/fred/api/_fred_client.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,13 @@
33
Fred API Client.
44
"""
55
from http import HTTPStatus
6-
from os import environ
76
from typing import Optional, Dict, TypeVar
87
from xml.etree import ElementTree as ET
98

109
import requests
1110

1211
from .exceptions import FredAPIRequestError
1312

14-
1513
__all__ = [
1614
"FredClient",
1715
"JsonOrXml",
@@ -26,8 +24,6 @@ class FredClient(object):
2624

2725
def __init__(self, api_key: str = None, base_client: Optional["FredClient"] = None):
2826
"""Init client."""
29-
if not base_client and not api_key:
30-
api_key = environ.get("FRED_API_KEY", None)
3127

3228
assert api_key or base_client, "Fred API Client or API Key required to use FredAPI"
3329

src/fred/cli/__init__.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#!/usr/bin/env python3
2+
"""CLI Core."""
3+
import click
4+
from click import group
5+
6+
from fred import FredAPI
7+
from .categories import categories
8+
from .releases import releases
9+
from .series import series
10+
from .sources import sources
11+
from .tags import tags
12+
13+
__all__ = [
14+
"fred_cli",
15+
]
16+
17+
18+
@group()
19+
@click.option("--api-key", type=click.STRING, required=False, help="FRED API key.")
20+
@click.pass_context
21+
def fred_cli(ctx, api_key: str):
22+
"""CLI for the Federal Reserve Economic Data (FRED)."""
23+
ctx.ensure_object(dict)
24+
ctx.obj["api_key"] = api_key
25+
ctx.obj["client"] = FredAPI(api_key=api_key)
26+
27+
28+
# add each FRED command group
29+
fred_cli.add_command(categories)
30+
fred_cli.add_command(releases)
31+
fred_cli.add_command(series)
32+
fred_cli.add_command(sources)
33+
fred_cli.add_command(tags)

0 commit comments

Comments
 (0)