├── .github ├── ISSUE_TEMPLATE │ ├── bug.md │ └── feature_request.md ├── PULL_REQUEST_TEMPLATE │ ├── pull_request_template.md │ └── version_release.md └── workflows │ ├── publish-to-pypi.yml │ └── test.yml ├── .gitignore ├── .pre-commit-config.yaml ├── .readthedocs.yml ├── LICENSE ├── README.md ├── RELEASE.md ├── docs ├── index.md ├── references │ ├── CHANGELOG.md │ ├── CONTRIBUTING.md │ ├── base.md │ ├── category.md │ ├── maps.md │ ├── releases.md │ ├── series.md │ ├── series_collection.md │ ├── sources.md │ └── tags.md ├── requirements.txt └── tutorials │ ├── category.ipynb │ ├── maps.ipynb │ ├── releases.ipynb │ ├── series.ipynb │ ├── series_collection.ipynb │ ├── sources.ipynb │ └── tags.ipynb ├── mkdocs.yml ├── mypy.ini ├── pyfredapi ├── __about__.py ├── __init__.py ├── _base.py ├── category.py ├── exceptions │ ├── __init__.py │ └── exceptions.py ├── maps.py ├── py.typed ├── releases.py ├── series.py ├── series_collection.py ├── sources.py ├── tags.py └── utils │ ├── __init__.py │ ├── _common_type_hints.py │ ├── _convert_to_df.py │ └── enums.py ├── pyproject.toml ├── requirements.txt ├── tests ├── __init__.py ├── conftest.py ├── test_base.py ├── test_category.py ├── test_maps.py ├── test_release.py ├── test_series.py ├── test_series_collection.py ├── test_sources.py ├── test_tags.py └── vhs │ ├── test_category │ ├── test_get_category.yaml │ ├── test_get_category_children.yaml │ ├── test_get_category_related.yaml │ ├── test_get_category_related_tags[json].yaml │ ├── test_get_category_related_tags[pandas].yaml │ ├── test_get_category_series.yaml │ ├── test_get_category_tags[json].yaml │ └── test_get_category_tags[pandas].yaml │ ├── test_maps │ ├── test_get_geoseries[json].yaml │ ├── test_get_geoseries[pandas].yaml │ ├── test_get_geoseries_info.yaml │ └── test_get_shape_files.yaml │ ├── test_release │ ├── test_get_release.yaml │ ├── test_get_release_dates.yaml │ ├── test_get_release_related_tags.yaml │ ├── test_get_release_series.yaml │ ├── test_get_release_sources.yaml │ ├── test_get_release_tables.yaml │ ├── test_get_release_tags.yaml │ ├── test_get_releases.yaml │ └── test_get_releases_dates.yaml │ ├── test_series │ ├── test_get_series[json].yaml │ ├── test_get_series[pandas].yaml │ ├── test_get_series[polars].yaml │ ├── test_get_series_all_releases[json].yaml │ ├── test_get_series_all_releases[pandas].yaml │ ├── test_get_series_all_releases[polars].yaml │ ├── test_get_series_asof_date[json].yaml │ ├── test_get_series_asof_date[pandas].yaml │ ├── test_get_series_asof_date[polars].yaml │ ├── test_get_series_categories.yaml │ ├── test_get_series_info.yaml │ ├── test_get_series_initial_release[json].yaml │ ├── test_get_series_initial_release[pandas].yaml │ ├── test_get_series_initial_release[polars].yaml │ ├── test_get_series_releases.yaml │ ├── test_get_series_tags.yaml │ ├── test_get_series_updates.yaml │ ├── test_get_series_vintagedates.yaml │ ├── test_search_series[json].yaml │ ├── test_search_series[pandas].yaml │ ├── test_search_series[polars].yaml │ ├── test_search_series_related_tags[json].yaml │ ├── test_search_series_related_tags[pandas].yaml │ ├── test_search_series_related_tags[polars].yaml │ ├── test_search_series_tags[json].yaml │ ├── test_search_series_tags[pandas].yaml │ └── test_search_series_tags[polars].yaml │ ├── test_series_collection │ ├── test_list_methods_diff.yaml │ └── test_remove_series.yaml │ ├── test_sources │ ├── test_get_source.yaml │ ├── test_get_source_release.yaml │ └── test_get_sources.yaml │ └── test_tags │ ├── test_get_related_tags.yaml │ ├── test_get_tag_series.yaml │ └── test_get_tags.yaml └── tox.ini /.github/ISSUE_TEMPLATE/bug.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: 'bug' 6 | assignees: '' 7 | --- 8 | 9 | **Describe the bug** 10 | A clear and concise description of what the bug is. 11 | 12 | **To Reproduce** 13 | Steps to reproduce the behavior: 14 | 1. Go to '...' 15 | 2. Click on '....' 16 | 3. Scroll down to '....' 17 | 4. See error 18 | 19 | **Expected behavior** 20 | A clear and concise description of what you expected to happen. 21 | 22 | **Screenshots** 23 | If applicable, add screenshots to help explain your problem. 24 | 25 | **Version** 26 | - pyfredapi version [e.g. 0.5.0] 27 | - Python version [e.g. 3.9.7] 28 | 29 | **Additional context** 30 | Add any other context about the problem here. 31 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for pyfredapi 4 | title: '' 5 | labels: 'enhancement' 6 | assignees: '' 7 | --- 8 | 9 | **Is your feature request related to a problem? Please describe.** 10 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 11 | 12 | **Describe the solution you'd like** 13 | A clear and concise description of what you want to happen. 14 | 15 | **Describe alternatives you've considered** 16 | A clear and concise description of any alternative solutions or features you've considered. 17 | 18 | **Additional context** 19 | Add any other context or screenshots about the feature request here. 20 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE/pull_request_template.md: -------------------------------------------------------------------------------- 1 | # Description 2 | 3 | Please include a summary of the changes and the related issue. Please also include relevant motivation and context. List any dependencies that are required for this change. 4 | 5 | Fixes # (issue) 6 | 7 | # Type of change 8 | 9 | Please delete options that are not relevant. 10 | 11 | - [ ] Bug fix (non-breaking change which fixes an issue) 12 | - [ ] New feature (non-breaking change which adds functionality) 13 | - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) 14 | - [ ] This change requires a documentation update 15 | 16 | # Check List 17 | 18 | - [ ] I have added tests that prove my fix is effective or that my feature works 19 | - [ ] I have made corresponding changes to the documentation 20 | - [ ] I have performed a self-review of my code 21 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE/version_release.md: -------------------------------------------------------------------------------- 1 | # Release Version X.X.X 2 | 3 | Please include a summary of all the changes in this release. 4 | 5 | - Does this release contain any breaking changes? 6 | - Does this release contain any new features? 7 | - Does this release fix any bugs? 8 | 9 | ## Release checklist 10 | 11 | - [ ] Tests pass 12 | - [ ] Linting pass 13 | - [ ] Refresh documentation notebooks in `docs/tutorials` 14 | - [ ] Bump version in `pyproject.toml` 15 | - [ ] Ensure the Changelog is update to date 16 | - [ ] Ensure the readme is up to date 17 | -------------------------------------------------------------------------------- /.github/workflows/publish-to-pypi.yml: -------------------------------------------------------------------------------- 1 | name: Publish Python 🐍 distribution 📦 to PyPI and TestPyPI 2 | 3 | on: push 4 | 5 | jobs: 6 | build: 7 | name: Build distribution 📦 8 | runs-on: ubuntu-latest 9 | 10 | steps: 11 | - uses: actions/checkout@v4 12 | - name: Set up Python 13 | uses: actions/setup-python@v5 14 | with: 15 | python-version: "3.x" 16 | 17 | - name: Install pypa/build 18 | run: >- 19 | python3 -m 20 | pip install 21 | build 22 | --user 23 | - name: Build a binary wheel and a source tarball 24 | run: python3 -m build 25 | - name: Store the distribution packages 26 | uses: actions/upload-artifact@v4 27 | with: 28 | name: python-package-distributions 29 | path: dist/ 30 | 31 | publish-to-pypi: 32 | name: >- 33 | Publish Python 🐍 distribution 📦 to PyPI 34 | if: startsWith(github.ref, 'refs/tags/') # only publish to PyPI on tag pushes 35 | needs: 36 | - build 37 | runs-on: ubuntu-latest 38 | environment: 39 | name: pypi 40 | url: https://pypi.org/p/pyfredapi # Replace with your PyPI project name 41 | permissions: 42 | id-token: write # IMPORTANT: mandatory for trusted publishing 43 | 44 | steps: 45 | - name: Download all the dists 46 | uses: actions/download-artifact@v4 47 | with: 48 | name: python-package-distributions 49 | path: dist/ 50 | - name: Publish distribution 📦 to PyPI 51 | uses: pypa/gh-action-pypi-publish@release/v1 52 | 53 | publish-to-testpypi: 54 | name: Publish Python 🐍 distribution 📦 to TestPyPI 55 | needs: 56 | - build 57 | runs-on: ubuntu-latest 58 | 59 | environment: 60 | name: testpypi 61 | url: https://test.pypi.org/p/pyfredapi 62 | 63 | permissions: 64 | id-token: write # IMPORTANT: mandatory for trusted publishing 65 | 66 | steps: 67 | - name: Download all the dists 68 | uses: actions/download-artifact@v4 69 | with: 70 | name: python-package-distributions 71 | path: dist/ 72 | - name: Publish distribution 📦 to TestPyPI 73 | uses: pypa/gh-action-pypi-publish@release/v1 74 | with: 75 | repository-url: https://test.pypi.org/legacy/ 76 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Unit Tests 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | types: [opened, synchronize, reopened] 9 | branches: 10 | - main 11 | 12 | jobs: 13 | lint: 14 | name: Linter 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v3 19 | 20 | - name: Setup Python 21 | uses: actions/setup-python@v4 22 | with: 23 | python-version: "3.11" 24 | 25 | - name: Install dependencies 26 | run: | 27 | pip install '.[lint]' 28 | 29 | - name: black 30 | run: | 31 | black . --check 32 | 33 | - name: ruff 34 | run: | 35 | ruff check . 36 | 37 | - name: mypy 38 | run: | 39 | mypy pyfredapi 40 | 41 | test: 42 | name: Run pytest 43 | runs-on: ubuntu-latest 44 | env: 45 | FRED_API_KEY: ${{ secrets.FRED_API_KEY }} 46 | 47 | strategy: 48 | matrix: 49 | python-version: ["3.10", "3.11", "3.12"] 50 | 51 | steps: 52 | - uses: actions/checkout@v3 53 | - name: Set up Python ${{ matrix.python-version }} 54 | uses: actions/setup-python@v4 55 | with: 56 | python-version: ${{ matrix.python-version }} 57 | - name: Install dependencies 58 | run: | 59 | pip install '.[test]' 60 | - name: Test with pytest 61 | run: | 62 | pytest tests/ --record-mode=none --no-header -vv 63 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | Untitled.ipynb 80 | scratch.ipynb 81 | 82 | # IPython 83 | profile_default/ 84 | ipython_config.py 85 | 86 | # pyenv 87 | .python-version 88 | 89 | # pipenv 90 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 91 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 92 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 93 | # install all needed dependencies. 94 | #Pipfile.lock 95 | 96 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 97 | __pypackages__/ 98 | 99 | # Celery stuff 100 | celerybeat-schedule 101 | celerybeat.pid 102 | 103 | # SageMath parsed files 104 | *.sage.py 105 | 106 | # Environments 107 | .env 108 | .venv 109 | env/ 110 | venv/ 111 | ENV/ 112 | env.bak/ 113 | venv.bak/ 114 | 115 | # Spyder project settings 116 | .spyderproject 117 | .spyproject 118 | 119 | # Rope project settings 120 | .ropeproject 121 | 122 | # mkdocs documentation 123 | /site 124 | 125 | # mypy 126 | .mypy_cache/ 127 | .dmypy.json 128 | dmypy.json 129 | 130 | # ruff 131 | .ruff_cache/ 132 | 133 | # Pyre type checker 134 | .pyre/ 135 | 136 | # IDE 137 | .vscode/ 138 | .idea/ 139 | 140 | # docs in development 141 | dev_docs/ 142 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | exclude: ^docs/ 2 | 3 | repos: 4 | - repo: https://github.com/pre-commit/pre-commit-hooks 5 | rev: v4.4.0 6 | hooks: 7 | - id: end-of-file-fixer 8 | - id: trailing-whitespace 9 | - repo: https://github.com/psf/black 10 | rev: 24.8.0 11 | hooks: 12 | - id: black 13 | - repo: https://github.com/astral-sh/ruff-pre-commit 14 | rev: "v0.9.2" 15 | hooks: 16 | - id: ruff 17 | - repo: https://github.com/pre-commit/mirrors-mypy 18 | rev: "v1.14.1" 19 | hooks: 20 | - id: mypy 21 | additional_dependencies: 22 | - "types-requests" 23 | - "types-setuptools" 24 | - "pandas-stubs" 25 | - "pydantic" 26 | -------------------------------------------------------------------------------- /.readthedocs.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | build: 4 | os: ubuntu-24.04 5 | tools: 6 | python: "3" 7 | 8 | python: 9 | install: 10 | - requirements: docs/requirements.txt 11 | 12 | mkdocs: 13 | configuration: mkdocs.yml 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Greg Moore 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pyfredapi - Python library for the Federal Reserve Economic Data (FRED) API 2 | 3 |
4 | 5 | 6 | | | | 7 | | :--- | :--- | 8 | | CI/CD | [![CI - Test](https://github.com/gw-moore/pyfredapi/actions/workflows/test.yml/badge.svg)](https://github.com/gw-moore/pyfredapi/actions/workflows/test.yml)| 9 | | Docs | [![Documentation Status](https://readthedocs.org/projects/pyfredapi/badge/?version=latest)](https://pyfredapi.readthedocs.io/en/latest/?badge=latest) | 10 | | Package | [![PyPi Version](https://img.shields.io/pypi/v/pyfredapi.svg)](https://pypi.python.org/pypi/pyfredapi/) [![Supported Python Versions](https://img.shields.io/pypi/pyversions/pyfredapi)](https://pypi.python.org/pypi/pyfredapi) | 11 | | Meta | [![Hatch project](https://img.shields.io/badge/%F0%9F%A5%9A-Hatch-4051b5.svg)](https://github.com/pypa/hatch) [![linting - Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v0.json)](https://github.com/charliermarsh/ruff) [![code style - Black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) [![types - Mypy](https://img.shields.io/badge/types-Mypy-blue.svg)](https://github.com/python/mypy) [![License - MIT](https://img.shields.io/badge/license-MIT-9400d3.svg)](https://spdx.org/licenses/) | 12 | 13 |
14 | 15 | ----- 16 | 17 | `pyfredapi` is a full featured Python library that makes it is easy to retrieve data from the [Federal Reserve Economic Data](https://fred.stlouisfed.org/docs/api/fred/) (FRED) API web service. `pyfredapi` covers all the FRED api endpoints, and can retrieve data from [FRED](https://fred.stlouisfed.org/) and [ALFRED](https://alfred.stlouisfed.org). Data can be returned as a [pandas](https://pandas.pydata.org/) dataframe or json. Requests to the FRED API can be customized according to the parameters made available by the web service endpoints. 18 | 19 | ## Documentation 20 | 21 | The [documentation](https://pyfredapi.readthedocs.io/en/latest/) is made with [MkDocs](https://www.mkdocs.org/) and hosted on [Read the Docs](https://readthedocs.org/). 22 | 23 | ## Installation 24 | 25 | Install the latest version with pip: 26 | 27 | ```bash 28 | pip install pyfredapi 29 | ``` 30 | 31 | Install pyfredapi with all optional dependencies. 32 | 33 | ```bash 34 | pip install 'pyfredapi[all]' 35 | ``` 36 | 37 | You can also install a subset of all optional dependencies. 38 | 39 | ```bash 40 | pip install 'pyfredapi[polars]' 41 | ``` 42 | 43 | ## Quick Start 44 | 45 | ### FRED API Key 46 | 47 | Before using `pyfredapi` and must have an API key to the FRED API web service. You can apply for [one for free](https://fred.stlouisfed.org/docs/api/api_key.html) on the FRED website. 48 | 49 | You can set your API key in two ways: 50 | 51 | * set your API key to the environment variable `FRED_API_KEY` 52 | * pass it to the `api_key` parameter of the request function 53 | 54 | You can set the API key as an environment variable by adding the following line to your `~/.zshrc`, `~/.bashrc` file: 55 | 56 | ```bash 57 | export FRED_API_KEY="your_api_key" 58 | ``` 59 | 60 | ### Using pyfredapi 61 | 62 | Each of the FRED API endpoint namespaces is covered by a module in `pyfredapi`. For a deeper dive into each of the modules see the tutorials and API reference in the [documentation](https://pyfredapi.readthedocs.io/en/latest/). 63 | 64 | - `category` - covers the FRED Categories endpoints 65 | - `maps` - covers the FRED Maps endpoints 66 | - `release` - covers the FRED Releases endpoints 67 | - `series` - covers the FRED Series endpoints 68 | - `sources` - covers the FRED Sources endpoints 69 | - `tags` - covers the FRED Tags endpoints 70 | - `series_collection` - makes handling multiple series easier 71 | 72 | Quick start example: 73 | 74 | ```python 75 | import pyfredapi as pf 76 | 77 | # api key set as environment variable 78 | pf.get_series(series_id="GDP") 79 | 80 | # api key passed to the function 81 | pf.get_series(series_id="GDP", api_key="my_api_key") 82 | ``` 83 | 84 | ## Contributing 85 | 86 | Thank you for your interest in contributing to `pyfredapi`. Check out the [contributing guide](https://pyfredapi.readthedocs.io/en/latest/references/CONTRIBUTING.html) to get started. 87 | -------------------------------------------------------------------------------- /RELEASE.md: -------------------------------------------------------------------------------- 1 | # Release Process 2 | 3 | This document describes the process for preparing new version of the `pyfredapi` package. 4 | 5 | ## Pre-release PR Checklist 6 | 7 | Preform these tasks before opening a PR for the `main` branch. 8 | 9 | - [ ] Bump the version number. `pyfredapi` follow [semantic versioning](https://semver.org/spec/v2.0.0.html), and uses [hatch](https://hatch.pypa.io/latest/) to manage the version number. 10 | - Determine if this is a major, minor, or patch release based on the UNRELEASED section in changelog 11 | - Use [hatch to bump the package version number](https://hatch.pypa.io/latest/version/#updating) 12 | - [ ] Update the `CHANGELOG.md` file with the changes for the new release. Follow the [keepachangelog](https://keepachangelog.com/en/1.0.0/) guidelines. 13 | - [ ] Check that no updates are needed in `CONTRIBUTING.md` 14 | - [ ] Check that no updates are needed in `README.md` 15 | - [ ] Update the requirements.txt 16 | ```bash 17 | python -m piptools compile --upgrade -o requirements.txt pyproject.toml 18 | ``` 19 | - [ ] Run unit tests and make fresh vcr cassettes 20 | ```bash 21 | pytest tests/ --record-mode=all --runslow 22 | ``` 23 | - [ ] Make sure the `pyfredapi` package builds locally 24 | ```bash 25 | hatch build 26 | ``` 27 | 28 | ### Prepare the documentation 29 | 30 | When a commit is made to the `main` branch, the Read The Docs build will be triggered and the documentation will be updated. It is important to be sure the documentation is correct before merging into the main branch. 31 | 32 | - [ ] Update documentation dependencies for Read The Docs 33 | ```bash 34 | python -m piptools compile --upgrade --extra docs -o docs/requirements.txt pyproject.toml 35 | ``` 36 | - [ ] Test that the documentation builds locally 37 | ```bash 38 | mkdocs build 39 | open site/index.html 40 | ``` 41 | - [ ] Review the documentation site 42 | 43 | ## Open a PR 44 | 45 | When a PR is opened for the main branch, the GitHub actions pipeline will the test suite and lint the code. 46 | 47 | - [ ] Check that the CI/CD pipeline tasks have passed 48 | - [ ] Give the PR a descriptive title 49 | - [ ] Add a description of the changes 50 | 51 | ## Post PR merge tasks 52 | 53 | The package is published to PyPi via GitHub actions pipeline. The pipeline is triggered when a new version release is created in GitHub. Use the GitHub UI to create a new release. 54 | 55 | - [ ] Title the tag `pyfredapi-v`. The tag is used to trigger the GitHub actions pipeline to publish the package to PyPi. 56 | - [ ] Title the release `pyfredapi v` 57 | - [ ] Add the changelog release notes to the release description 58 | - [ ] Publish the release 59 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | # pyfredapi 2 | 3 | `pyfredapi` is a Python library that makes it is easy to retrieve data from the [FRED API web service](https://fred.stlouisfed.org/docs/api/fred). 4 | 5 | `pyfredapi` covers all the FRED API endpoints, and can retrieve data from [FRED](https://fred.stlouisfed.org/) and [ALFRED](https://alfred.stlouisfed.org/). 6 | Data can be returned as a [pandas](https://pandas.pydata.org/) dataframe or as [json](https://www.json.org/json-en.html). Requests to the FRED API can be customized according to 7 | the parameters made available by the web service endpoints. 8 | 9 | ## Installation 10 | 11 | `pyfredapi` can be installed via pip. 12 | 13 | ```bash 14 | pip install pyfredapi 15 | 16 | # install with plotting dependencies 17 | pip install 'pyfredapi[plot]' 18 | ``` 19 | 20 | ## FRED API Key 21 | 22 | Before you can use `pyfredapi` you must have an API key to the FRED API web service. You can [apply for one](https://fred.stlouisfed.org/docs/api/api_key.html) for free on the FRED website. 23 | 24 | You can set your API key in two ways: 25 | 26 | * set your API key to the environment variable :code:`FRED_API_KEY` 27 | * pass it to the :code:`api_key` parameter of the request function 28 | 29 | You can set the API key as an environment variable by adding the following line to your `~/.zshrc`, `~/.bashrc` file: 30 | 31 | ```bash 32 | export FRED_API_KEY="your_api_key" 33 | ``` 34 | 35 | ## Quick Start 36 | 37 | Each of the FRED API endpoint namespaces is covered by a module in `pyfredapi`. For a deeper dive into each of the 38 | modules see the tutorials and API documentation in the sidebar. 39 | 40 | - `category` - covers the FRED Categories endpoints 41 | - `maps` - covers the FRED Maps endpoints 42 | - `release` - covers the FRED Releases endpoints 43 | - `series` - covers the FRED Series endpoints 44 | - `sources` - covers the FRED Sources endpoints 45 | - `tags` - covers the FRED Tags endpoints 46 | - `series_collection` - makes handling multiple series easier 47 | 48 | Quick start example: 49 | 50 | ```python 51 | import pyfreadpi as pf 52 | 53 | # api key set as environment variable 54 | pf.get_series_info(series_id="GDP") 55 | 56 | # api key passed to function 57 | pf.get_series_info(series_id="GDP", api_key="my_api_key") 58 | ``` 59 | -------------------------------------------------------------------------------- /docs/references/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## Version 0.9.2 - 2024-11-03 4 | 5 | ### Added 6 | 7 | - Support for [polars](https://pola.rs/) as a return format. 8 | 9 | ### Changed 10 | 11 | - Updated optional dependencies. 12 | 13 | ## Version 0.9.1 - 2024-11-02 14 | 15 | ### Removed 16 | 17 | - Dependency on `frozendict` package. 18 | 19 | ## Version 0.9.0 - 2024-09-28 20 | 21 | ### Added 22 | 23 | - Added `.data` attribute to `SeriesCollection`. 24 | - Added `series_info_to_df()` method to `SeriesCollection`. 25 | - Official support for Python 3.12. 26 | 27 | ### Changed 28 | 29 | - Bumped `pydantic` version to >=2. 30 | - Updated `pandas` version to >=1.0.0,<3.0.0. 31 | - Updated `numpy` version to >=1.0.0,<2.0.0. 32 | 33 | ## Version 0.8.0 - 2023-04-27 34 | 35 | ### Changed 36 | 37 | - Make `series_id` a required parameter for `SeriesCollection()`. 38 | 39 | ## Version 0.7.1 - 2023-04-27 40 | 41 | ### Fixed 42 | 43 | - Import error in `SeriesCollection` when `plotly` is not installed. 44 | - Updated dev dependencies to include `plotly`. 45 | 46 | ## Version 0.7.0 - 2023-04-27 47 | 48 | ### Changed 49 | 50 | - Refactor `SeriesCollection`'s internal structure to represent a sequence. 51 | - Updated `__init__` to handle adding the initial set of series. 52 | - `SeriesCollection` is now iterable, indexable, and sized. 53 | - Renamed `add_series()` to `add()`. 54 | - Renamed `drop_series()` to `remove()`. 55 | - Updated the docstring for `api_key` parameter. 56 | - When data is converted to a pandas dataframe, the `created` attribute will be cast a date-type column. 57 | - Added `sleep` parameter to `SeriesCollection.add_series`. Defaults to 0.1 seconds. 58 | - Added upper bound to dependency versions. 59 | - Made `plotly` an optional dependency. 60 | 61 | ### Removed 62 | 63 | - Unnecessary type ignore comments. 64 | - .flake8 config file. 65 | 66 | ## Version 0.6.0 - 2023-04-22 67 | 68 | ### Changed 69 | 70 | - Switched to the [Hatch](https://github.com/pypa/hatch) build tool. 71 | - Bumped copyright year to 2023. 72 | - Renamed `APIKeyNotFoundError` exception to `APIKeyNotFound`. 73 | - Updated the bug report github issue template. 74 | 75 | ## Version 0.5.4 - 2022-04-16 76 | 77 | ### Changed 78 | 79 | - Loosened the dependency package versions to >= latest major version. 80 | 81 | ## Version 0.5.3 - 2022-04-02 82 | 83 | ### Changed 84 | 85 | - Added `@lru_cache` decorator to `_get_request` and `_get_api_key`. 86 | - Upgraded project to poetry 1.4.0. 87 | 88 | ## Version 0.5.2 - 2023-03-30 89 | 90 | ### Fixed 91 | 92 | - Typos and errors in the documentation. 93 | - Add timeouts to API requests. 94 | 95 | ### Changed 96 | 97 | - Updated dependencies to latest versions. 98 | - Updated the linting suite to [ruff](https://github.com/charliermarsh/ruff). 99 | 100 | ## Version 0.5.1 - 2022-11-05 101 | 102 | ### Added 103 | 104 | - Support for python 3.11. 105 | 106 | ### Removed 107 | 108 | - Github actions for building docs. 109 | 110 | ## Version 0.5.0 - 2022-10-26 111 | 112 | This release introduces breaking changes. The `pyfredapi` API has been refactored to use functions rather than class methods. 113 | 114 | ### Added 115 | 116 | - CONTRIBUTING.md. 117 | 118 | ### Changed 119 | 120 | - Refactored the API into functions. Each FRED API endpoint now has an associated function rather than being attached to a class. All tests and docs have been updated to reflect this change. 121 | - Moved `SeriesData` to the `SeriesCollection` module. `get_series` now only returns series data. To get both series data and series info in one object, use a `SeriesCollection`. 122 | 123 | ### Fixed 124 | 125 | - Broken formatting in the sphinx autodocs API reference. 126 | 127 | ## Version 0.4.1 - 2022-10-20 128 | 129 | ### Changed 130 | 131 | - Updated pydantic base model classes to accept extra parameters. 132 | - Updated `SeriesData.plot` x-axis label to include units. 133 | - Tweak docs formatting to adapt to sphinx_material theme. 134 | 135 | ## Version 0.4.0 - 2022-10-19 136 | 137 | ### Added 138 | 139 | - `SeriesCollection` class, test, and docs. 140 | - `plot` function to `SeriesData`. 141 | - Docstring to the top of all API modules. 142 | 143 | ### Changed 144 | 145 | - Sphinx docs theme to [sphinx_material](https://bashtage.github.io/sphinx-material/index.html). 146 | - Removed 'dev' install group to make dependencies DRY. 147 | - Sonarcloud config to generate main branch statistics. 148 | 149 | ## Version 0.3.0 - 2022-10-11 150 | 151 | ### Added 152 | 153 | - Methods and tests for `FredRelease`, `FredTags`, and `FredSource`. 154 | - py.typed file. 155 | - Pull request template. 156 | - GitHub actions workflows for sonarcloud, linting, and testing. 157 | 158 | ### Changed 159 | 160 | - Updates `SeriesInfo`'s `notes` field to be optional. 161 | - Added `sort_order` parameter to `SeriesSearchParameters`. 162 | - Updates to the README.md. 163 | - Updates to the documentation. 164 | 165 | ## Version 0.2.0 - 2022-09-27 166 | 167 | ### Added 168 | 169 | - `SeriesData` class for the `get_series` methods. `SeriesData` holds both the data and the metadata for a given series. 170 | - Unit tests for `FredSeries` method, 171 | - [vcr](https://vcrpy.readthedocs.io/en/latest/) pytest fixture to unit tests. vcr records the http interactions with the FRED API. Speeds up unit tests significantly and reduces the requests made to the FRED API. 172 | - `FredMaps` class and tests. 173 | 174 | ### Changed 175 | 176 | - Switch license to MIT. 177 | - Updates `FredCategory` & `FredSeries` method docstrings to fix typos, add missing parameters, and add links to the FRED endpoint documentation. 178 | - When returning data as a pandas dataframe, process the data so that date and numeric columns are the correct data type. 179 | - Renamed methods in `FredSeries` 180 | - `get_series_data` -> `get_series` 181 | - `get_series_data_all_releases` -> `get_series_all_releases` 182 | - `get_series_data_initial_release` -> `get_series_initial_release` 183 | - `get_series_data_asof_date` -> `get_series_asof_date` 184 | - Rename `BaseApiArgs` to `BaseApiParameters`. 185 | - Rename `CategoryArgs` to `CategoryApiParameters`. 186 | - Rename `SeriesArgs` to `SeriesApiParameters`. 187 | 188 | ### Fixed 189 | 190 | - Install instructions. 191 | - pydantic dependency. 192 | - `FredSeries.get_series_releases` endpoint. 193 | - Removed `series_id` from `SeriesArgs`. 194 | 195 | ## Version 0.1.0 - 2022-09-25 196 | 197 | **Note:** This version has been deleted from Python Package Index. 198 | 199 | Initial release of `pyfredapi` package. 200 | 201 | ### Added 202 | 203 | - `FredApi` class. 204 | - `FredCategory` class. 205 | - `FredSeries` class. 206 | - `FredMaps` stub. 207 | - `FredSources` stub. 208 | - `FredTags` stub. 209 | - Sphinx docs. 210 | -------------------------------------------------------------------------------- /docs/references/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to pyfredapi 2 | 3 | Thank you for your interest in contributing to pyfredapi! There are many ways you can help: 4 | 5 | - Reporting a bug 6 | - Submitting a fix 7 | - Adding/Proposing new features 8 | 9 | ## Report bugs 10 | 11 | Report a bug by [opening a new issue](https://github.com/gw-moore/pyfredapi/issues/new/choose). 12 | 13 | ## How to contribute to pyfredapi 14 | 15 | Before contributing to `pyfredapi` it a good idea to create an issue to discuss the changes you would like to make. This will help ensure that your changes are accepted and merged into the project. 16 | 17 | When you're ready contribute changes to `pyfredapi`, you will need to setup the project on your machine. The following steps will help you get started: 18 | 19 | 1. Set your FRED API key as an environment variable. The `pyfredapi` tests require a FRED API key to run. You can set the API key as an environment variable by adding the following line to your `~/.zshrc`, `~/.bashrc` file: 20 | 21 | ```bash 22 | export FRED_API_KEY="your_api_key" 23 | ``` 24 | 25 | 2. Fork the `pyfredapi` repo 26 | 3. Clone your fork of the repo to your local machine 27 | 4. Create a branch from `main`. Give your branch a descriptive name, e.g. `add-foo-feature` 28 | 29 | Once you have completed the above steps, you need to setup your development environment. The `pyfredapi` project uses [hatch](https://github.com/pypa/hatch) to build and publish the `pyfredapi` package, so it a good idea to use `hatch` to setup your development environment. 30 | 31 | 4. Follow the [hatch](https://hatch.pypa.io/latest/install/) install instructions. 32 | 5. This step is a personal preference. Update the hatch config.toml to setup a python virtual environment in the project's directory. Follow the [hatch config docs](https://hatch.pypa.io/latest/config/hatch/) 33 | 34 | 35 | 6. Create a virtual environment for the project and activate the environment 36 | 37 | ```bash 38 | hatch env create 39 | hatch shell 40 | ``` 41 | 42 | 7. Install the `pyfredapi` development dependencies 43 | 44 | ```bash 45 | pip install '.[dev]' 46 | ``` 47 | 48 | 8. Setup pre-commit 49 | 50 | ```bash 51 | pre-commit install 52 | ``` 53 | 54 | 9. Run the tests. Before making any changes it is a good to test that your environment is setup correctly. From the root of the project directory, run: 55 | 56 | With pytest: 57 | 58 | ```bash 59 | pytest tests/ 60 | ``` 61 | 62 | With tox: 63 | 64 | ```bash 65 | tox 66 | ``` 67 | 68 | 10. Make your changes. After making your changes: 69 | - Add or update tests 70 | - Add or update documentation 71 | 72 | 11. Ensure the test and lint suites pass with tox. From the root of the project directory, run: 73 | 74 | ```bash 75 | tox 76 | ``` 77 | 78 | 12. Ensure the documentation builds correctly. The documentation is built with sphinx. From the root of the project directory, run: 79 | 80 | ```bash 81 | make html -C docs/ 82 | ``` 83 | 84 | Then open the html docs with: 85 | 86 | ```bash 87 | open docs/_build/html/index.html 88 | ``` 89 | 90 | 13. Submit a pull request (PR) 91 | -------------------------------------------------------------------------------- /docs/references/base.md: -------------------------------------------------------------------------------- 1 | # `base` module 2 | 3 | ::: pyfredapi._base -------------------------------------------------------------------------------- /docs/references/category.md: -------------------------------------------------------------------------------- 1 | # `category` module 2 | 3 | ::: pyfredapi.category -------------------------------------------------------------------------------- /docs/references/maps.md: -------------------------------------------------------------------------------- 1 | # `maps` module 2 | 3 | ::: pyfredapi.maps -------------------------------------------------------------------------------- /docs/references/releases.md: -------------------------------------------------------------------------------- 1 | # `releases` module 2 | 3 | ::: pyfredapi.releases -------------------------------------------------------------------------------- /docs/references/series.md: -------------------------------------------------------------------------------- 1 | # `series` module 2 | 3 | ::: pyfredapi.series -------------------------------------------------------------------------------- /docs/references/series_collection.md: -------------------------------------------------------------------------------- 1 | # `series_collection` module 2 | 3 | ::: pyfredapi.series_collection -------------------------------------------------------------------------------- /docs/references/sources.md: -------------------------------------------------------------------------------- 1 | # `sources` module 2 | 3 | ::: pyfredapi.sources -------------------------------------------------------------------------------- /docs/references/tags.md: -------------------------------------------------------------------------------- 1 | # `tags` module 2 | 3 | ::: pyfredapi.tags -------------------------------------------------------------------------------- /docs/tutorials/category.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "attachments": {}, 5 | "cell_type": "markdown", 6 | "metadata": {}, 7 | "source": [ 8 | "# FRED Categories\n", 9 | "\n", 10 | "The `pyfredapi.category` module has functions for requesting data about [FRED Categories](https://fred.stlouisfed.org/categories).\n", 11 | "\n", 12 | "Each FRED category is associated a unique integer identifier. For example:\n", 13 | "\n", 14 | "- Money, Banking and Finance is category 32991\n", 15 | "- Population, Employment, & Labor Markets is category 10\n", 16 | "- Prices is category 32455\n", 17 | "\n", 18 | "Categories are organized in a hierarchical structure. All categories are children of the root category (category_id = 0).\n", 19 | "\n", 20 | "FRED series are assigned to categories. This allows users to query the category API to find all series associated with a given category. This tutorial will demonstrate how you can use the `pyfredapi.category` module to search through the FRED category hierarchy and find series associated with U.S unemployment." 21 | ] 22 | }, 23 | { 24 | "cell_type": "markdown", 25 | "metadata": {}, 26 | "source": [ 27 | "## Setup" 28 | ] 29 | }, 30 | { 31 | "cell_type": "code", 32 | "execution_count": 1, 33 | "metadata": { 34 | "tags": [] 35 | }, 36 | "outputs": [], 37 | "source": [ 38 | "import operator\n", 39 | "\n", 40 | "import matplotlib.pyplot as plt\n", 41 | "import seaborn as sns\n", 42 | "from rich.pretty import pprint\n", 43 | "\n", 44 | "import pyfredapi as pf" 45 | ] 46 | }, 47 | { 48 | "cell_type": "markdown", 49 | "metadata": {}, 50 | "source": [ 51 | "## get_series_categories\n", 52 | "\n", 53 | "When starting an analysis, you will often have a series in mind, but probably don't know the full scope of related series you're interested in. The `get_series_categories` function allows you to find the category or categories associated with a given series.\n", 54 | "\n", 55 | "As an example, if you're interested in analyzing unemployment you can start with the series id [`UNRATE`](https://fred.stlouisfed.org/series/UNRATE) and see what category the unemployment series is associated with. Below we see that `UNRATE` is associated with category 32447, which is the Unemployment Rate category." 56 | ] 57 | }, 58 | { 59 | "cell_type": "code", 60 | "execution_count": null, 61 | "metadata": { 62 | "tags": [] 63 | }, 64 | "outputs": [], 65 | "source": [ 66 | "pprint(pf.get_series_categories(series_id=\"UNRATE\"))" 67 | ] 68 | }, 69 | { 70 | "cell_type": "markdown", 71 | "metadata": {}, 72 | "source": [ 73 | "## get_category_series\n", 74 | "\n", 75 | "Next, with this information we can use the `get_category_series` function to find all series associated with the Unemployment Rate category. This will return a list of `SeriesInfo` objects containing all series in the Unemployment Rate category.\n", 76 | "\n", 77 | "The example code below shows that there are 820 series in the Unemployment Rate category." 78 | ] 79 | }, 80 | { 81 | "cell_type": "code", 82 | "execution_count": 3, 83 | "metadata": { 84 | "tags": [] 85 | }, 86 | "outputs": [], 87 | "source": [ 88 | "all_unemployment_series = pf.get_category_series(category_id=32447)" 89 | ] 90 | }, 91 | { 92 | "cell_type": "code", 93 | "execution_count": null, 94 | "metadata": { 95 | "tags": [] 96 | }, 97 | "outputs": [], 98 | "source": [ 99 | "print(f\"Number of series in Unemployment category: {len(all_unemployment_series)}\")" 100 | ] 101 | }, 102 | { 103 | "cell_type": "markdown", 104 | "metadata": {}, 105 | "source": [ 106 | "Now we have all the unemployment related series, but 820 series is a lot to look through. Let's narrow it down to just seasonally adjusted series with a popularity >= 20." 107 | ] 108 | }, 109 | { 110 | "cell_type": "code", 111 | "execution_count": 5, 112 | "metadata": { 113 | "tags": [] 114 | }, 115 | "outputs": [], 116 | "source": [ 117 | "seasonally_adjusted_unemployment_series = [\n", 118 | " series_info\n", 119 | " for series_info in all_unemployment_series.values()\n", 120 | " if series_info.seasonal_adjustment == \"Seasonally Adjusted\"\n", 121 | " and series_info.popularity >= 20\n", 122 | "]" 123 | ] 124 | }, 125 | { 126 | "cell_type": "markdown", 127 | "metadata": {}, 128 | "source": [ 129 | "Let's also sort the series by popularity. Then print the the series id and title." 130 | ] 131 | }, 132 | { 133 | "cell_type": "code", 134 | "execution_count": 6, 135 | "metadata": { 136 | "tags": [] 137 | }, 138 | "outputs": [], 139 | "source": [ 140 | "seasonally_adjusted_unemployment_series = sorted(\n", 141 | " seasonally_adjusted_unemployment_series,\n", 142 | " key=operator.attrgetter(\"popularity\"),\n", 143 | " reverse=True,\n", 144 | ")" 145 | ] 146 | }, 147 | { 148 | "cell_type": "code", 149 | "execution_count": null, 150 | "metadata": {}, 151 | "outputs": [], 152 | "source": [ 153 | "len(seasonally_adjusted_unemployment_series)" 154 | ] 155 | }, 156 | { 157 | "cell_type": "code", 158 | "execution_count": null, 159 | "metadata": { 160 | "tags": [] 161 | }, 162 | "outputs": [], 163 | "source": [ 164 | "for series_info in seasonally_adjusted_unemployment_series:\n", 165 | " print(f\"{series_info.id}: {series_info.title}\")" 166 | ] 167 | }, 168 | { 169 | "cell_type": "markdown", 170 | "metadata": {}, 171 | "source": [ 172 | "## Move to SeriesCollection\n", 173 | "\n", 174 | "Great! Now we have the 7 most popular unemployment series to work with. Next we can construct a `SeriesCollection` object to download the data for these series." 175 | ] 176 | }, 177 | { 178 | "cell_type": "code", 179 | "execution_count": 9, 180 | "metadata": { 181 | "tags": [] 182 | }, 183 | "outputs": [], 184 | "source": [ 185 | "series_id = [series.id for series in seasonally_adjusted_unemployment_series]" 186 | ] 187 | }, 188 | { 189 | "cell_type": "code", 190 | "execution_count": 10, 191 | "metadata": { 192 | "tags": [] 193 | }, 194 | "outputs": [], 195 | "source": [ 196 | "series_names = {\n", 197 | " series_info.id: series_info.title\n", 198 | " for series_info in seasonally_adjusted_unemployment_series\n", 199 | "}" 200 | ] 201 | }, 202 | { 203 | "cell_type": "code", 204 | "execution_count": null, 205 | "metadata": { 206 | "tags": [] 207 | }, 208 | "outputs": [], 209 | "source": [ 210 | "unemployment_sc = pf.SeriesCollection(series_id=series_id, rename=series_names)" 211 | ] 212 | }, 213 | { 214 | "cell_type": "markdown", 215 | "metadata": {}, 216 | "source": [ 217 | "## Plot the series\n", 218 | "\n", 219 | "Now that we have the data, we can plot the series." 220 | ] 221 | }, 222 | { 223 | "cell_type": "code", 224 | "execution_count": 12, 225 | "metadata": { 226 | "tags": [] 227 | }, 228 | "outputs": [], 229 | "source": [ 230 | "long_df = unemployment_sc.merge_long()\n", 231 | "min_date = min(long_df[\"date\"].dt.date)\n", 232 | "max_date = max(long_df[\"date\"].dt.date)" 233 | ] 234 | }, 235 | { 236 | "cell_type": "markdown", 237 | "metadata": {}, 238 | "source": [ 239 | "### Bar Chart" 240 | ] 241 | }, 242 | { 243 | "cell_type": "code", 244 | "execution_count": null, 245 | "metadata": {}, 246 | "outputs": [], 247 | "source": [ 248 | "sns.set(rc={\"figure.figsize\": (11.7, 8.27)})\n", 249 | "ax = sns.barplot(\n", 250 | " data=long_df[long_df[\"date\"] == max(long_df[\"date\"])],\n", 251 | " x=\"series\",\n", 252 | " y=\"value\",\n", 253 | " hue=\"series\",\n", 254 | ")\n", 255 | "plt.xticks(rotation=290)\n", 256 | "ax.set(\n", 257 | " xlabel=\"Series\",\n", 258 | " xticklabels=[],\n", 259 | " ylabel=\"Unemployment Rate\",\n", 260 | " title=f\"U.S. Unemployment Rate, Seasonally Adjusted, {max_date}\",\n", 261 | ")\n", 262 | "sns.move_legend(ax, \"best\")" 263 | ] 264 | }, 265 | { 266 | "cell_type": "markdown", 267 | "metadata": {}, 268 | "source": [ 269 | "### Time series plot" 270 | ] 271 | }, 272 | { 273 | "cell_type": "code", 274 | "execution_count": null, 275 | "metadata": {}, 276 | "outputs": [], 277 | "source": [ 278 | "sns.set(rc={\"figure.figsize\": (11.7, 8.27)})\n", 279 | "ax = sns.lineplot(data=long_df, x=\"date\", y=\"value\", hue=\"series\")\n", 280 | "ax.set(\n", 281 | " xlabel=\"Date\",\n", 282 | " ylabel=\"Unemployment Rate\",\n", 283 | " title=f\"U.S. Unemployment Rate, Seasonally Adjusted, {min_date} - {max_date}\",\n", 284 | ")\n", 285 | "sns.move_legend(ax, \"best\")" 286 | ] 287 | } 288 | ], 289 | "metadata": { 290 | "kernelspec": { 291 | "display_name": ".venv", 292 | "language": "python", 293 | "name": "python3" 294 | }, 295 | "language_info": { 296 | "codemirror_mode": { 297 | "name": "ipython", 298 | "version": 3 299 | }, 300 | "file_extension": ".py", 301 | "mimetype": "text/x-python", 302 | "name": "python", 303 | "nbconvert_exporter": "python", 304 | "pygments_lexer": "ipython3", 305 | "version": "3.12.2" 306 | } 307 | }, 308 | "nbformat": 4, 309 | "nbformat_minor": 4 310 | } 311 | -------------------------------------------------------------------------------- /docs/tutorials/sources.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# FRED Sources\n", 8 | "\n", 9 | "FRED sources endpoints provide information about the sources of data available via the FRED API." 10 | ] 11 | }, 12 | { 13 | "cell_type": "markdown", 14 | "metadata": {}, 15 | "source": [ 16 | "## Setup" 17 | ] 18 | }, 19 | { 20 | "cell_type": "code", 21 | "execution_count": 1, 22 | "metadata": {}, 23 | "outputs": [], 24 | "source": [ 25 | "import pyfredapi as pf" 26 | ] 27 | }, 28 | { 29 | "cell_type": "markdown", 30 | "metadata": {}, 31 | "source": [ 32 | "## Get all sources" 33 | ] 34 | }, 35 | { 36 | "cell_type": "code", 37 | "execution_count": 2, 38 | "metadata": {}, 39 | "outputs": [], 40 | "source": [ 41 | "sources = pf.get_sources()" 42 | ] 43 | }, 44 | { 45 | "cell_type": "code", 46 | "execution_count": 3, 47 | "metadata": {}, 48 | "outputs": [ 49 | { 50 | "data": { 51 | "text/plain": [ 52 | "114" 53 | ] 54 | }, 55 | "execution_count": 3, 56 | "metadata": {}, 57 | "output_type": "execute_result" 58 | } 59 | ], 60 | "source": [ 61 | "len(sources[\"sources\"])" 62 | ] 63 | }, 64 | { 65 | "cell_type": "code", 66 | "execution_count": 4, 67 | "metadata": {}, 68 | "outputs": [ 69 | { 70 | "data": { 71 | "text/plain": [ 72 | "[{'id': 1,\n", 73 | " 'realtime_start': '2024-04-05',\n", 74 | " 'realtime_end': '2024-04-05',\n", 75 | " 'name': 'Board of Governors of the Federal Reserve System (US)',\n", 76 | " 'link': 'http://www.federalreserve.gov/'},\n", 77 | " {'id': 3,\n", 78 | " 'realtime_start': '2024-04-05',\n", 79 | " 'realtime_end': '2024-04-05',\n", 80 | " 'name': 'Federal Reserve Bank of Philadelphia',\n", 81 | " 'link': 'https://www.philadelphiafed.org/'},\n", 82 | " {'id': 4,\n", 83 | " 'realtime_start': '2024-04-05',\n", 84 | " 'realtime_end': '2024-04-05',\n", 85 | " 'name': 'Federal Reserve Bank of St. Louis',\n", 86 | " 'link': 'http://www.stlouisfed.org/'}]" 87 | ] 88 | }, 89 | "execution_count": 4, 90 | "metadata": {}, 91 | "output_type": "execute_result" 92 | } 93 | ], 94 | "source": [ 95 | "sources[\"sources\"][0:3]" 96 | ] 97 | } 98 | ], 99 | "metadata": { 100 | "kernelspec": { 101 | "display_name": ".venv", 102 | "language": "python", 103 | "name": "python3" 104 | }, 105 | "language_info": { 106 | "codemirror_mode": { 107 | "name": "ipython", 108 | "version": 3 109 | }, 110 | "file_extension": ".py", 111 | "mimetype": "text/x-python", 112 | "name": "python", 113 | "nbconvert_exporter": "python", 114 | "pygments_lexer": "ipython3", 115 | "version": "3.11.7" 116 | }, 117 | "orig_nbformat": 4 118 | }, 119 | "nbformat": 4, 120 | "nbformat_minor": 2 121 | } 122 | -------------------------------------------------------------------------------- /docs/tutorials/tags.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# FRED Tags\n", 8 | "\n" 9 | ] 10 | }, 11 | { 12 | "cell_type": "markdown", 13 | "metadata": {}, 14 | "source": [ 15 | "## Setup" 16 | ] 17 | }, 18 | { 19 | "cell_type": "code", 20 | "execution_count": 1, 21 | "metadata": {}, 22 | "outputs": [], 23 | "source": [ 24 | "import pyfredapi as pf" 25 | ] 26 | }, 27 | { 28 | "cell_type": "markdown", 29 | "metadata": {}, 30 | "source": [ 31 | "## Get all tags" 32 | ] 33 | }, 34 | { 35 | "cell_type": "code", 36 | "execution_count": 2, 37 | "metadata": {}, 38 | "outputs": [], 39 | "source": [ 40 | "tags = pf.get_tags()" 41 | ] 42 | }, 43 | { 44 | "cell_type": "code", 45 | "execution_count": 3, 46 | "metadata": {}, 47 | "outputs": [ 48 | { 49 | "data": { 50 | "text/plain": [ 51 | "[{'name': 'nsa',\n", 52 | " 'group_id': 'seas',\n", 53 | " 'notes': 'Not Seasonally Adjusted',\n", 54 | " 'created': '2012-02-27 10:18:19-06',\n", 55 | " 'popularity': 100,\n", 56 | " 'series_count': 728472},\n", 57 | " {'name': 'usa',\n", 58 | " 'group_id': 'geo',\n", 59 | " 'notes': 'United States of America',\n", 60 | " 'created': '2012-02-27 10:18:19-06',\n", 61 | " 'popularity': 100,\n", 62 | " 'series_count': 658320},\n", 63 | " {'name': 'public domain: citation requested',\n", 64 | " 'group_id': 'cc',\n", 65 | " 'notes': None,\n", 66 | " 'created': '2018-12-17 23:33:13-06',\n", 67 | " 'popularity': 99,\n", 68 | " 'series_count': 612154}]" 69 | ] 70 | }, 71 | "execution_count": 3, 72 | "metadata": {}, 73 | "output_type": "execute_result" 74 | } 75 | ], 76 | "source": [ 77 | "tags[\"tags\"][0:3]" 78 | ] 79 | }, 80 | { 81 | "cell_type": "markdown", 82 | "metadata": {}, 83 | "source": [ 84 | "## Get all series with matching tags\n", 85 | "\n", 86 | "If you want to find all series with certain tag you can use `get_series_matching_tags`.\n", 87 | "\n", 88 | "For example, you can find series that are published monthly." 89 | ] 90 | }, 91 | { 92 | "cell_type": "code", 93 | "execution_count": 4, 94 | "metadata": {}, 95 | "outputs": [], 96 | "source": [ 97 | "monthly_series = pf.get_series_matching_tags(tag_names=\"monthly\")" 98 | ] 99 | }, 100 | { 101 | "cell_type": "code", 102 | "execution_count": 5, 103 | "metadata": {}, 104 | "outputs": [ 105 | { 106 | "data": { 107 | "text/plain": [ 108 | "1000" 109 | ] 110 | }, 111 | "execution_count": 5, 112 | "metadata": {}, 113 | "output_type": "execute_result" 114 | } 115 | ], 116 | "source": [ 117 | "len(monthly_series[\"seriess\"])" 118 | ] 119 | } 120 | ], 121 | "metadata": { 122 | "kernelspec": { 123 | "display_name": ".venv", 124 | "language": "python", 125 | "name": "python3" 126 | }, 127 | "language_info": { 128 | "codemirror_mode": { 129 | "name": "ipython", 130 | "version": 3 131 | }, 132 | "file_extension": ".py", 133 | "mimetype": "text/x-python", 134 | "name": "python", 135 | "nbconvert_exporter": "python", 136 | "pygments_lexer": "ipython3", 137 | "version": "3.11.7" 138 | }, 139 | "orig_nbformat": 4 140 | }, 141 | "nbformat": 4, 142 | "nbformat_minor": 2 143 | } 144 | -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: pyfredapi 2 | site_url: https://pyfredapi.readthedocs.io/en/latest/ 3 | repo_url: https://github.com/gw-moore/pyfredapi 4 | repo_name: "GitHub" 5 | 6 | nav: 7 | - Welcome to pyfedapi: index.md 8 | - Tutorials: 9 | - tutorials/category.ipynb 10 | # - tutorials/maps.ipynb 11 | - tutorials/releases.ipynb 12 | - tutorials/series_collection.ipynb 13 | - tutorials/series.ipynb 14 | - tutorials/sources.ipynb 15 | - tutorials/tags.ipynb 16 | - API Documentation: 17 | - references/base.md 18 | - references/category.md 19 | - references/maps.md 20 | - references/releases.md 21 | - references/series.md 22 | - references/series_collection.md 23 | - references/sources.md 24 | - references/tags.md 25 | - Changelog: references/CHANGELOG.md 26 | - Contributing: references/CONTRIBUTING.md 27 | 28 | theme: 29 | name: material 30 | icon: 31 | logo: material/chart-line 32 | palette: 33 | - media: "(prefers-color-scheme: light)" 34 | scheme: default 35 | primary: teal 36 | accent: teal 37 | toggle: 38 | icon: material/lightbulb-outline 39 | name: "Switch to dark mode" 40 | - media: "(prefers-color-scheme: dark)" 41 | scheme: slate 42 | primary: teal 43 | accent: teal 44 | toggle: 45 | icon: material/lightbulb 46 | name: "Switch to light mode" 47 | features: 48 | - search.suggest 49 | 50 | plugins: 51 | - mkdocs-jupyter 52 | - search 53 | - mkdocstrings: 54 | handlers: 55 | python: 56 | options: 57 | show_source: false 58 | show_root_heading: false 59 | show_if_no_docstring: false 60 | inherited_members: true 61 | member_order: alphabetical 62 | separate_signature: true 63 | unwrap_annotated: true 64 | merge_init_into_class: false 65 | show_signature_annotations: true 66 | signature_cross_refs: true 67 | show_symbol_type_heading: true 68 | show_symbol_type_toc: true 69 | docstring_style: numpy 70 | # rendering: 71 | # show_root_toc_entry: true 72 | # extensions: 73 | # - griffe_pydantic: 74 | # schema: true 75 | # - pymdownx.highlight: 76 | # anchor_linenums: true 77 | # line_spans: __span 78 | # pygments_lang_class: true 79 | # - pymdownx.inlinehilite 80 | # - pymdownx.snippets 81 | # - pymdownx.superfences 82 | -------------------------------------------------------------------------------- /mypy.ini: -------------------------------------------------------------------------------- 1 | [mypy] 2 | plugins = pydantic.mypy 3 | ignore_missing_imports = True 4 | -------------------------------------------------------------------------------- /pyfredapi/__about__.py: -------------------------------------------------------------------------------- 1 | """Define the package metadata.""" 2 | 3 | __version__ = "0.9.2.dev3" 4 | -------------------------------------------------------------------------------- /pyfredapi/__init__.py: -------------------------------------------------------------------------------- 1 | """pyfredapi - Python client for the Federal Reserve Economic Data (FRED) API 2 | ==============================================================================. 3 | 4 | **pyfredapi** is a Python client for the FRED API web service (https://fred.stlouisfed.org/docs/api/fred/). 5 | `pyfredapi` covers all the FRED API endpoints and can return data as a pandas (https://pandas.pydata.org/) 6 | dataframe or json. Checkout the [docs](https://pyfredapi.readthedocs.io/en/latest/) to learn more. 7 | """ 8 | 9 | from importlib.metadata import version as _version 10 | 11 | __version__ = _version("pyfredapi") 12 | 13 | from .category import ( 14 | CategoryApiParameters, 15 | get_category, 16 | get_category_children, 17 | get_category_related, 18 | get_category_related_tags, 19 | get_category_series, 20 | get_category_tags, 21 | ) 22 | from .maps import MapApiParameters, get_geoseries, get_geoseries_info, get_shape_files 23 | from .releases import ( 24 | ReleaseApiParameters, 25 | get_release, 26 | get_release_dates, 27 | get_release_related_tags, 28 | get_release_series, 29 | get_release_sources, 30 | get_release_tables, 31 | get_release_tags, 32 | get_releases, 33 | get_releases_dates, 34 | ) 35 | from .series import ( 36 | SeriesApiParameters, 37 | SeriesInfo, 38 | SeriesSearchParameters, 39 | get_series, 40 | get_series_all_releases, 41 | get_series_asof_date, 42 | get_series_categories, 43 | get_series_info, 44 | get_series_initial_release, 45 | get_series_releases, 46 | get_series_tags, 47 | get_series_updates, 48 | get_series_vintagedates, 49 | search_series, 50 | search_series_related_tags, 51 | search_series_tags, 52 | ) 53 | from .series_collection import SeriesCollection, SeriesData 54 | from .sources import SourceApiParameters, get_source, get_source_release, get_sources 55 | from .tags import ( 56 | TagsApiParameters, 57 | get_related_tags, 58 | get_series_matching_tags, 59 | get_tags, 60 | ) 61 | -------------------------------------------------------------------------------- /pyfredapi/_base.py: -------------------------------------------------------------------------------- 1 | """The `_base` module contains the get request functions used in the pyfredapi modules. 2 | 3 | The `_base` module is not intended to be used directly by the user. It is used by the other 4 | functions in pyfredapi. 5 | """ 6 | 7 | from functools import lru_cache 8 | from http import HTTPStatus 9 | from os import environ 10 | from typing import Union 11 | 12 | import requests 13 | from pydantic import BaseModel, ConfigDict 14 | 15 | from .exceptions import APIKeyNotFound, FredAPIRequestError, InvalidAPIKey 16 | from .utils._common_type_hints import JsonType 17 | 18 | 19 | class BaseApiParameters(BaseModel): 20 | """Represents the parameters accepted by all FRED Series endpoints.""" 21 | 22 | model_config = ConfigDict(extra="forbid") 23 | 24 | api_key: str 25 | file_type: str = "json" 26 | 27 | 28 | @lru_cache 29 | def _get_api_key(api_key: Union[str, None] = None) -> str: 30 | """Get FRED_API_KEY from the environment. 31 | 32 | api_key : str | None 33 | FRED API key. Defaults to None. If None, will check for FRED_API_KEY in the environment. 34 | 35 | Returns 36 | ------- 37 | str 38 | The FRED API key. 39 | 40 | Raises 41 | ------ 42 | APIKeyNotFound 43 | If the api_key is None and FRED_API_KEY is not in the environment. 44 | 45 | """ 46 | if api_key is None: 47 | api_key = environ.get("FRED_API_KEY", None) 48 | 49 | if api_key is None: 50 | raise APIKeyNotFound() 51 | elif not api_key.isalnum() or len(api_key) != 32: 52 | raise InvalidAPIKey() 53 | 54 | return api_key 55 | 56 | 57 | @lru_cache 58 | def _get_request( 59 | endpoint: str, 60 | api_key: Union[str, None] = None, 61 | params: Union[frozenset, None] = None, 62 | base_url: str = "https://api.stlouisfed.org/fred", 63 | ) -> JsonType: 64 | """Make a get request to a FRED web service endpoint and return the response as Json. 65 | 66 | Base get request that child class methods utilize. 67 | 68 | Parameters 69 | ---------- 70 | endpoint : str 71 | The FRED API endpoint. 72 | api_key : str | None, optional 73 | FRED API key. Defaults to None. If None, will check for FRED_API_KEY in the environment. 74 | params : Dict[str, Any] | None, optional 75 | Dictionary of query parameters. Defaults to None. 76 | base_url : str, optional 77 | Base fred url. Defaults to https://api.stlouisfed.org/fred. 78 | 79 | Returns 80 | ------- 81 | A dictionary representing the json response. 82 | 83 | Raises 84 | ------ 85 | FredAPIRequestError 86 | If the request fails. 87 | 88 | """ 89 | api_key = _get_api_key(api_key) 90 | _base_params = BaseApiParameters(api_key=api_key) 91 | 92 | if not params: 93 | params = frozenset({}.items()) 94 | 95 | fparams = dict(params) 96 | 97 | try: 98 | response = requests.get( 99 | f"{base_url}/{endpoint}", 100 | params={**_base_params.model_dump(), **fparams}, 101 | timeout=30, 102 | ) 103 | except requests.exceptions.RequestException as e: 104 | raise FredAPIRequestError( 105 | message=f"Error invoking Fred API: {e}", status_code=None 106 | ) from e 107 | if response.status_code != HTTPStatus.OK: 108 | raise FredAPIRequestError( 109 | message=response.json()["error_message"], 110 | status_code=response.status_code, 111 | ) 112 | 113 | return response.json() 114 | -------------------------------------------------------------------------------- /pyfredapi/category.py: -------------------------------------------------------------------------------- 1 | """The category module provides functions to request data from the [FRED API Categories endpoints](https://fred.stlouisfed.org/docs/api/fred/#Categories).""" 2 | 3 | from __future__ import annotations 4 | 5 | from typing import Dict, Literal, Optional 6 | 7 | from pydantic import BaseModel, ConfigDict, PositiveInt 8 | 9 | from ._base import _get_request 10 | from .series import SeriesInfo 11 | from .utils import _convert_pydantic_model_to_frozenset 12 | from .utils._common_type_hints import ( 13 | ApiKeyType, 14 | JsonType, 15 | KwargsType, 16 | ReturnFormats, 17 | ReturnTypes, 18 | ) 19 | from .utils._convert_to_df import _convert_to_pandas, _convert_to_polars 20 | from .utils.enums import ReturnFormat 21 | 22 | 23 | class CategoryApiParameters(BaseModel): 24 | """Represents the parameters accepted by the FRED Category endpoints.""" 25 | 26 | model_config = ConfigDict(extra="allow") 27 | 28 | category_id: Optional[int] = None 29 | realtime_start: Optional[str] = None 30 | realtime_end: Optional[str] = None 31 | limit: Optional[int] = None 32 | offset: Optional[PositiveInt] = None 33 | order_by: Optional[ 34 | Literal[ 35 | "series_id", 36 | "title", 37 | "units", 38 | "frequency", 39 | "seasonal_adjustment", 40 | "realtime_start", 41 | "realtime_end", 42 | "last_updated", 43 | "observation_start", 44 | "observation_end", 45 | "popularity", 46 | "group_popularity", 47 | ] 48 | ] = None 49 | sort_order: Optional[Literal["acs", "desc"]] = None 50 | filter_variable: Optional[Literal["frequency", "units", "seasonal_adjustment"]] = ( 51 | None 52 | ) 53 | filter_value: Optional[str] = None 54 | tag_names: Optional[str] = None 55 | exclude_tag_names: Optional[str] = None 56 | 57 | 58 | def get_category( 59 | category_id: Optional[int] = None, api_key: ApiKeyType = None, **kwargs: KwargsType 60 | ) -> JsonType: 61 | """Get category by ID. [Endpoint documentation](https://fred.stlouisfed.org/docs/api/fred/category.html). 62 | 63 | Parameters 64 | ---------- 65 | category_id : str | None 66 | Category id of interest. 67 | api_key : str | None, optional 68 | FRED API key. Defaults to None. If None, will search for FRED_API_KEY in environment variables. 69 | **kwargs: Dict[str, str], optional 70 | Additional parameters to FRED API ``category/`` endpoint. Refer to the FRED documentation for a list of all possible parameters. 71 | 72 | Returns 73 | ------- 74 | dict 75 | Dictionary representing the json response. 76 | 77 | Examples 78 | -------- 79 | >>> import pyfredapi as pf 80 | >>> pf.get_category(category_id=125) 81 | 82 | """ 83 | params = _convert_pydantic_model_to_frozenset( 84 | CategoryApiParameters(category_id=category_id, **kwargs) 85 | ) 86 | 87 | return _get_request( 88 | api_key=api_key, 89 | endpoint="category", 90 | params=params, 91 | ) 92 | 93 | 94 | def get_category_children( 95 | category_id: Optional[int] = None, api_key: ApiKeyType = None, **kwargs: KwargsType 96 | ) -> JsonType: 97 | """Get category children by category ID. [Endpoint documentation](https://fred.stlouisfed.org/docs/api/fred/category_children.html). 98 | 99 | Parameters 100 | ---------- 101 | category_id : str | None 102 | Category id of interest. 103 | api_key : str | None, optional 104 | FRED API key. Defaults to None. If None, will search for FRED_API_KEY in environment variables. 105 | **kwargs : dict, optional 106 | Additional parameters to FRED API ``category/children`` endpoint. Refer to the FRED documentation for a list of all possible parameters. 107 | 108 | Returns 109 | ------- 110 | dict 111 | Dictionary representing the json response. 112 | 113 | Examples 114 | -------- 115 | >>> import pyfredapi as pf 116 | >>> pf.get_category_children(category_id=13) 117 | 118 | """ 119 | params = _convert_pydantic_model_to_frozenset( 120 | CategoryApiParameters(category_id=category_id, **kwargs) 121 | ) 122 | return _get_request( 123 | endpoint="category/children", 124 | api_key=api_key, 125 | params=params, 126 | ) 127 | 128 | 129 | def get_category_related( 130 | category_id: int, api_key: ApiKeyType = None, **kwargs: KwargsType 131 | ) -> JsonType: 132 | """Get related categories by category ID. [Endpoint documentation](https://fred.stlouisfed.org/docs/api/fred/category_related.html). 133 | 134 | Parameters 135 | ---------- 136 | category_id : str 137 | Category id of interest. 138 | api_key : str | None, optional 139 | FRED API key. Defaults to None. If None, will search for FRED_API_KEY in environment variables. 140 | **kwargs : dict, optional 141 | Additional parameters to FRED API ``category/children`` endpoint. Refer to the FRED documentation for a list of all possible parameters. 142 | 143 | 144 | Returns 145 | ------- 146 | dict 147 | Dictionary representing the json response. 148 | 149 | """ 150 | params = _convert_pydantic_model_to_frozenset( 151 | CategoryApiParameters(category_id=category_id, **kwargs) 152 | ) 153 | return _get_request( 154 | api_key=api_key, 155 | endpoint="category/related", 156 | params=params, 157 | ) 158 | 159 | 160 | def get_category_series( 161 | category_id: int, api_key: ApiKeyType = None, **kwargs: KwargsType 162 | ) -> Dict[str, SeriesInfo]: 163 | """Get the series info for each series in a category by category ID. [Endpoint documentation](https://fred.stlouisfed.org/docs/api/fred/category_series.html). 164 | 165 | Parameters 166 | ---------- 167 | category_id : str 168 | Category id of interest. 169 | api_key : str | None, optional 170 | FRED API key. Defaults to None. If None, will search for FRED_API_KEY in environment variables. 171 | **kwargs : dict, optional 172 | Additional parameters to FRED API ``category/children`` endpoint. Refer to the FRED documentation for a list of all possible parameters. 173 | 174 | Returns 175 | ------- 176 | dict 177 | A dictionary where the keys are series ids and the values for SeriesInfo objects. 178 | 179 | """ 180 | params = _convert_pydantic_model_to_frozenset( 181 | CategoryApiParameters(category_id=category_id, **kwargs) 182 | ) 183 | response = _get_request( 184 | api_key=api_key, 185 | endpoint="category/series", 186 | params=params, 187 | ) 188 | 189 | return {series["id"]: SeriesInfo(**series) for series in response["seriess"]} 190 | 191 | 192 | def get_category_tags( 193 | category_id: Optional[int] = None, 194 | api_key: ApiKeyType = None, 195 | return_format: ReturnFormats = "json", 196 | **kwargs: KwargsType, 197 | ) -> ReturnTypes: 198 | """Get the FRED tags for a category by category ID. [Endpoint documentation](https://fred.stlouisfed.org/docs/api/fred/category_tags.html). 199 | 200 | Parameters 201 | ---------- 202 | category_id : str | None 203 | Category id of interest. 204 | api_key : str | None, optional 205 | FRED API key. Defaults to None. If None, will search for FRED_API_KEY in environment variables. 206 | return_format : str | ReturnFormat 207 | Define how to return the response. Must be either 'json' or 'pandas'. 208 | **kwargs : dict, optional 209 | Additional parameters to FRED API ``category/children`` endpoint. Refer to the FRED documentation for a list of all possible parameters. 210 | 211 | Returns 212 | ------- 213 | dict | pd.DataFrame | pl.DataFrame 214 | 215 | """ 216 | return_format = ReturnFormat(return_format) 217 | 218 | params = _convert_pydantic_model_to_frozenset( 219 | CategoryApiParameters(category_id=category_id, **kwargs) 220 | ) 221 | response = _get_request( 222 | api_key=api_key, 223 | endpoint="category/tags", 224 | params=params, 225 | ) 226 | 227 | if return_format == ReturnFormat.pandas: 228 | return _convert_to_pandas(response["tags"]) 229 | if return_format == ReturnFormat.polars: 230 | return _convert_to_polars(response["tags"]) 231 | return response 232 | 233 | 234 | def get_category_related_tags( 235 | category_id: Optional[int] = None, 236 | api_key: ApiKeyType = None, 237 | return_format: ReturnFormats = "json", 238 | **kwargs: KwargsType, 239 | ) -> ReturnTypes: 240 | """Get the related FRED tags for a category by category ID. [Endpoint documentation](https://fred.stlouisfed.org/docs/api/fred/category_related_tags.html). 241 | 242 | Parameters 243 | ---------- 244 | category_id : str | None 245 | Category id of interest. 246 | api_key : str | None, optional 247 | FRED API key. Defaults to None. If None, will search for FRED_API_KEY in environment variables. 248 | return_format : str | ReturnFormat 249 | Define how to return the response. Must be either 'json' or 'pandas'. 250 | **kwargs : dict, optional 251 | Additional parameters to FRED API ``category/children`` endpoint. Refer to the FRED documentation for a list of all possible parameters. 252 | 253 | Returns 254 | ------- 255 | dict | pd.DataFrame | pl.DataFrame 256 | 257 | """ 258 | return_format = ReturnFormat(return_format) 259 | 260 | params = _convert_pydantic_model_to_frozenset( 261 | CategoryApiParameters(category_id=category_id, **kwargs) 262 | ) 263 | response = _get_request( 264 | api_key=api_key, 265 | endpoint="category/related_tags", 266 | params=params, 267 | ) 268 | 269 | if return_format == ReturnFormat.pandas: 270 | return _convert_to_pandas(response["tags"]) 271 | if return_format == ReturnFormat.polars: 272 | return _convert_to_polars(response["tags"]) 273 | return response 274 | -------------------------------------------------------------------------------- /pyfredapi/exceptions/__init__.py: -------------------------------------------------------------------------------- 1 | """The exceptions module provides the exceptions for pyfredapi.""" 2 | 3 | from .exceptions import APIKeyNotFound, FredAPIRequestError, InvalidAPIKey 4 | -------------------------------------------------------------------------------- /pyfredapi/exceptions/exceptions.py: -------------------------------------------------------------------------------- 1 | """The exceptions module contains the custom exceptions for pyfredapi.""" 2 | 3 | 4 | class BaseFredAPIError(Exception): 5 | def __init__(self, message): 6 | """Base class for all API errors.""" # noqa: D401 7 | self.message = message 8 | 9 | def __str__(self): 10 | return self.message 11 | 12 | 13 | class InvalidAPIKey(BaseFredAPIError): 14 | def __init__(self): 15 | """Error raised when the API Key is invalid.""" 16 | super().__init__( 17 | "API key must be a 32 character lower-cased alpha-numeric string." 18 | ) 19 | 20 | 21 | class APIKeyNotFound(BaseFredAPIError): 22 | def __init__(self): 23 | """Error raised when FRED_API_KEY not found in the environment.""" 24 | super().__init__( 25 | """API key not found. Either set a FRED_API_KEY environment variable or pass your API key to the `api_key` parameter.""" 26 | ) 27 | 28 | 29 | class FredAPIRequestError(BaseFredAPIError): 30 | def __init__(self, message, status_code): 31 | """Error raised when a request to the FRED API fails.""" 32 | super().__init__(message) 33 | self.status_code = status_code 34 | 35 | def __str__(self): 36 | return f"HTTP response code: {self.status_code} - {self.message}" 37 | -------------------------------------------------------------------------------- /pyfredapi/maps.py: -------------------------------------------------------------------------------- 1 | """The `maps` module provides functions to request data from the [FRED API Maps endpoints](https://fred.stlouisfed.org/docs/api/fred/#Maps). 2 | 3 | The FRED Maps API is a web service that allows developers to write programs and build applications to harvest data and shape files of series available on the maps found 4 | in the FRED website hosted by the Economic Research Division of the Federal Reserve Bank of St. Louis. Not all series that are in FRED have geographical data. 5 | """ 6 | 7 | from typing import Any, Dict, List, Literal, Optional, Union 8 | 9 | import pandas as pd 10 | from pydantic import BaseModel, ConfigDict 11 | 12 | from ._base import _get_request 13 | from .utils import _convert_pydantic_model_to_frozenset 14 | from .utils._common_type_hints import ApiKeyType, JsonType, ReturnFormats 15 | from .utils.enums import ReturnFormat 16 | 17 | _geo_fred_url = "https://api.stlouisfed.org/geofred/" 18 | 19 | 20 | class MapApiParameters(BaseModel): 21 | """Represents the parameters accepted by the FRED Maps endpoints.""" 22 | 23 | model_config = ConfigDict(extra="allow") 24 | 25 | shape: Optional[ 26 | Literal[ 27 | "bea", 28 | "msa", 29 | "frb", 30 | "necta", 31 | "state", 32 | "country", 33 | "county", 34 | "censusregion", 35 | "censusdivision", 36 | ] 37 | ] = None 38 | series_id: Optional[str] = None 39 | date: Optional[str] = None 40 | start_date: Optional[str] = None 41 | 42 | 43 | class GeoseriesInfo(BaseModel): 44 | """Represents geo series information. [Endpoint documentation](https://fred.stlouisfed.org/docs/api/geofred/series_group.html).""" 45 | 46 | model_config = ConfigDict(extra="allow") 47 | 48 | title: str 49 | region_type: str 50 | series_group: str 51 | season: str 52 | units: str 53 | frequency: str 54 | min_date: str 55 | max_date: str 56 | 57 | 58 | class GeoseriesData(BaseModel): 59 | """Represents metadata about an economics data series. [Endpoint documentation](https://fred.stlouisfed.org/docs/api/fred/series.html).""" 60 | 61 | model_config = ConfigDict(arbitrary_types_allowed=True) 62 | 63 | info: GeoseriesInfo 64 | data: Union[Dict[str, List[Dict[str, Any]]], pd.DataFrame] 65 | 66 | 67 | def get_geoseries_info(series_id: str, api_key: ApiKeyType = None) -> GeoseriesInfo: 68 | """Request the metadata for a given geo series id. [Endpoint documentation](https://fred.stlouisfed.org/docs/api/geofred/series_group.html). 69 | 70 | Parameters 71 | ---------- 72 | series_id : str 73 | Series id of interest. 74 | api_key : str | None, optional 75 | FRED API key. Defaults to None. If None, will search for FRED_API_KEY in environment variables. 76 | 77 | Returns 78 | ------- 79 | GeoseriesInfo 80 | An instance of GeoseriesInfo. 81 | 82 | """ 83 | params = _convert_pydantic_model_to_frozenset(MapApiParameters(series_id=series_id)) 84 | response = _get_request( 85 | base_url=_geo_fred_url, 86 | endpoint="series/group", 87 | api_key=api_key, 88 | params=params, 89 | ) 90 | return GeoseriesInfo(**response["series_group"]) 91 | 92 | 93 | def get_shape_files( 94 | shape: Literal[ 95 | "bea", 96 | "msa", 97 | "frb", 98 | "necta", 99 | "state", 100 | "country", 101 | "county", 102 | "censusregion", 103 | "censusdivision", 104 | ], 105 | api_key: ApiKeyType = None, 106 | ) -> JsonType: 107 | """Request shape files from FRED in Well-known text (WKT) format. 108 | 109 | Parameters 110 | ---------- 111 | shape : One of "bea", "msa", "frb", "necta", "state", "country", "county", "censusregion", "censusdivision" 112 | Define the shape of Well-known text (WKT) data. 113 | api_key : str | None, optional 114 | FRED API key. Defaults to None. If None, will search for FRED_API_KEY in environment variables. 115 | 116 | Returns 117 | ------- 118 | dict 119 | Dictionary representing the json response. 120 | 121 | """ 122 | params = _convert_pydantic_model_to_frozenset(MapApiParameters(shape=shape)) 123 | return _get_request( 124 | base_url=_geo_fred_url, 125 | endpoint="shapes/file", 126 | api_key=api_key, 127 | params=params, 128 | ) 129 | 130 | 131 | def get_geoseries( 132 | series_id: str, 133 | api_key: ApiKeyType = None, 134 | start_date: Optional[str] = None, 135 | end_date: Optional[str] = None, 136 | return_format: ReturnFormats = "pandas", 137 | ) -> GeoseriesData: 138 | """Request a cross section of regional data for a specified release date. If no date is specified, the most recent data available are returned. 139 | 140 | For example, you can request Per Capita Personal Income by State (series_id: WIPCPI) over a specific time period. 141 | [Endpoint documentation](https://fred.stlouisfed.org/docs/api/geofred/series_data.html). 142 | 143 | Parameters 144 | ---------- 145 | series_id : str 146 | Series id of interest. Not all series that are in FRED have geographical data. 147 | api_key : str | None, optional 148 | FRED API key. Defaults to None. If None, will search for FRED_API_KEY in environment variables. 149 | start_date : str, optional 150 | Define start date. YYYY-MM-DD formatted string. 151 | end_date : str, optional 152 | Define the end date. YYYY-MM-DD formatted string. 153 | return_format : Literal[json, pandas] | ReturnFormat 154 | Define how to return the response. Must be either 'json' or 'pandas'. Defaults to 'pandas'. 155 | 156 | Returns 157 | ------- 158 | GeoseriesData 159 | GeoseriesData object containing the geoseries data and metadata. 160 | 161 | """ 162 | params = _convert_pydantic_model_to_frozenset( 163 | MapApiParameters(series_id=series_id, date=end_date, start_date=start_date) 164 | ) 165 | response = _get_request( 166 | endpoint="series/data", 167 | api_key=api_key, 168 | params=params, 169 | base_url=_geo_fred_url, 170 | ) 171 | 172 | geoseries_info = get_geoseries_info(series_id=series_id) 173 | 174 | if return_format == ReturnFormat.pandas: 175 | dfs = [] 176 | for date, data in response["meta"]["data"].items(): 177 | t = pd.DataFrame.from_dict(data) 178 | t["date"] = date 179 | t["date"] = pd.to_datetime(t["date"]) 180 | dfs.append(t) 181 | 182 | return GeoseriesData(info=geoseries_info, data=pd.concat(dfs)) 183 | else: 184 | return GeoseriesData(info=geoseries_info, data=response["meta"]["data"]) 185 | -------------------------------------------------------------------------------- /pyfredapi/py.typed: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gw-moore/pyfredapi/6c77e94c176c9583a97aa5704c265ffe9914546a/pyfredapi/py.typed -------------------------------------------------------------------------------- /pyfredapi/sources.py: -------------------------------------------------------------------------------- 1 | """The `sources` module provides functions to request data from the [FRED API Sources endpoints](https://fred.stlouisfed.org/docs/api/fred/#Sources). 2 | 3 | The FRED database contains many sources of data. The sources module provides functions to query the FRED database for information about the available sources. 4 | """ 5 | 6 | from typing import Literal, Optional 7 | 8 | from pydantic import BaseModel, ConfigDict, PositiveInt 9 | 10 | from ._base import _get_request 11 | from .utils import _convert_pydantic_model_to_frozenset 12 | from .utils._common_type_hints import ApiKeyType, JsonType, KwargsType 13 | 14 | 15 | class SourceApiParameters(BaseModel): 16 | """Represents the parameters accepted by the FRED Sources endpoints.""" 17 | 18 | model_config = ConfigDict(extra="allow") 19 | 20 | source_id: Optional[PositiveInt] = None 21 | realtime_start: Optional[str] = None 22 | realtime_end: Optional[str] = None 23 | limit: Optional[int] = None 24 | offset: Optional[PositiveInt] = None 25 | order_by: Optional[ 26 | Literal["source_id", "name", "realtime_start", "realtime_end"] 27 | ] = None 28 | sort_order: Optional[Literal["asc", "desc"]] = None 29 | 30 | 31 | def get_sources(api_key: ApiKeyType = None, **kwargs: KwargsType) -> JsonType: 32 | """Get all sources of economic data. [Endpoint documentation](https://fred.stlouisfed.org/docs/api/fred/sources.html). 33 | 34 | Parameters 35 | ---------- 36 | api_key : str | None, optional 37 | FRED API key. Defaults to None. If None, will search for FRED_API_KEY in environment variables. 38 | **kwargs : dict, optional 39 | Additional parameters to FRED API ``sources/`` endpoint. Refer to the FRED documentation for a list of all possible parameters. 40 | 41 | Returns 42 | ------- 43 | Dictionary representing the Json response 44 | 45 | """ 46 | params = _convert_pydantic_model_to_frozenset(SourceApiParameters(**kwargs)) 47 | return _get_request( 48 | endpoint="sources", 49 | api_key=api_key, 50 | params=params, 51 | ) 52 | 53 | 54 | def get_source( 55 | source_id: int, api_key: ApiKeyType = None, **kwargs: KwargsType 56 | ) -> JsonType: 57 | """Get a source of economic data. https://fred.stlouisfed.org/docs/api/fred/source.html. 58 | 59 | Parameters 60 | ---------- 61 | source_id : int 62 | Source id of interest. 63 | api_key : str | None, optional 64 | FRED API key. Defaults to None. If None, will search for FRED_API_KEY in environment variables. 65 | **kwargs : dict, optional 66 | Additional parameters to FRED API ``source/`` endpoint. Refer to the FRED documentation for a list of all possible parameters. 67 | 68 | Returns 69 | ------- 70 | Dictionary representing the Json response 71 | 72 | """ 73 | params = _convert_pydantic_model_to_frozenset( 74 | SourceApiParameters(source_id=source_id, **kwargs) 75 | ) 76 | return _get_request( 77 | endpoint="source", 78 | api_key=api_key, 79 | params=params, 80 | ) 81 | 82 | 83 | def get_source_release( 84 | source_id: int, api_key: ApiKeyType = None, **kwargs: KwargsType 85 | ): 86 | """Get the releases for a source. [Endpoint documentation](https://fred.stlouisfed.org/docs/api/fred/source.html). 87 | 88 | Parameters 89 | ---------- 90 | source_id : int 91 | Source id of interest. 92 | api_key : str | None, optional 93 | FRED API key. Defaults to None. If None, will search for FRED_API_KEY in environment variables. 94 | **kwargs : dict, optional 95 | Additional parameters to FRED API ``source/releases`` endpoint. 96 | Refer to the FRED documentation for a list of all possible parameters. 97 | 98 | Returns 99 | ------- 100 | Dictionary representing the Json response 101 | 102 | """ 103 | params = _convert_pydantic_model_to_frozenset( 104 | SourceApiParameters(source_id=source_id, **kwargs) 105 | ) 106 | return _get_request( 107 | endpoint="source/releases", 108 | api_key=api_key, 109 | params=params, 110 | ) 111 | -------------------------------------------------------------------------------- /pyfredapi/tags.py: -------------------------------------------------------------------------------- 1 | """The `tags` module provides functions to request data from the [FRED API Tags endpoints](https://fred.stlouisfed.org/docs/api/fred/#Tags). 2 | 3 | FRED tags are assigned to series. Tags define a characteristic about the series. Each tag is a unique character identifier. For example: 4 | 5 | - Gross Domestic Product has the tag id 'gdp' 6 | - Not Seasonally Adjusted has the tag id 'nsa' 7 | - Monthly has the tag id `monthly` 8 | 9 | Categories are organized in a hierarchical structure where parent categories contain children categories. All categories are children of the root category (category_id = 0). 10 | """ 11 | 12 | from typing import Literal, Optional 13 | 14 | from pydantic import BaseModel, ConfigDict, PositiveInt 15 | 16 | from ._base import _get_request 17 | from .utils import _convert_pydantic_model_to_dict, _convert_pydantic_model_to_frozenset 18 | from .utils._common_type_hints import ApiKeyType, JsonType, KwargsType 19 | 20 | 21 | class TagsApiParameters(BaseModel): 22 | """Represents the parameters accepted by the FRED Tags endpoints.""" 23 | 24 | model_config = ConfigDict(extra="allow") 25 | 26 | realtime_start: Optional[str] = None 27 | realtime_end: Optional[str] = None 28 | tag_names: Optional[str] = None 29 | tag_group_id: Optional[ 30 | Literal["freq", "gen", "geo", "geot", "rls", "seas", "src", "cc"] 31 | ] = None 32 | search_text: Optional[str] = None 33 | limit: Optional[int] = None 34 | offset: Optional[PositiveInt] = None 35 | order_by: Optional[ 36 | Literal["series_count", "popularity", "created", "name", "group_id"] 37 | ] = None 38 | sort_order: Optional[Literal["acs", "desc"]] = None 39 | exclude_tag_names: Optional[str] = None 40 | 41 | 42 | def get_tags(api_key: ApiKeyType = None, **kwargs: KwargsType) -> JsonType: 43 | """Get FRED tags.[Endpoint documentation](https://fred.stlouisfed.org/docs/api/fred/tags.html). 44 | 45 | Parameters 46 | ---------- 47 | api_key : str | None, optional 48 | FRED API key. Defaults to None. If None, will search for FRED_API_KEY in environment variables. 49 | **kwargs : dict, optional 50 | Additional parameters to FRED API ``tags/`` endpoint. Refer to the FRED documentation for a list of all possible parameters. 51 | 52 | Returns 53 | ------- 54 | dict 55 | A dictionary representing the json response. 56 | 57 | """ 58 | params = _convert_pydantic_model_to_frozenset(TagsApiParameters(**kwargs)) 59 | return _get_request( 60 | endpoint="tags", 61 | api_key=api_key, 62 | params=params, 63 | ) 64 | 65 | 66 | def get_related_tags( 67 | tag_names: str, api_key: ApiKeyType = None, **kwargs: KwargsType 68 | ) -> JsonType: 69 | """Get related FRED tags for one or more FRED tags. [Endpoint documentation](https://fred.stlouisfed.org/docs/api/fred/related_tags.html). 70 | 71 | Parameters 72 | ---------- 73 | tag_names : str 74 | A semicolon delimited list of tag names that series match all of. 75 | api_key : str | None, optional 76 | FRED API key. Defaults to None. If None, will search for FRED_API_KEY in the environment. 77 | **kwargs : dict, optional 78 | Additional parameters to FRED API ``related_tags/`` endpoint. Refer to the FRED documentation for a list of all possible parameters. 79 | 80 | Returns 81 | ------- 82 | dict 83 | A dictionary representing the json response. 84 | 85 | """ 86 | params = _convert_pydantic_model_to_frozenset( 87 | TagsApiParameters(tag_names=tag_names, **kwargs) 88 | ) 89 | return _get_request( 90 | endpoint="related_tags", 91 | api_key=api_key, 92 | params=params, 93 | ) 94 | 95 | 96 | def get_series_matching_tags( 97 | tag_names: str, api_key: ApiKeyType = None, **kwargs: KwargsType 98 | ) -> JsonType: 99 | """Get the series matching all tags in the tag_names parameter. [Endpoint documentation](https://fred.stlouisfed.org/docs/api/fred/tags_series.html). 100 | 101 | Parameters 102 | ---------- 103 | tag_names : str 104 | A semicolon delimited list of tag names that series match all of. 105 | api_key : str | None, optional 106 | FRED API key. Defaults to None. If None, will search for FRED_API_KEY in environment variables. 107 | **kwargs : dict, optional 108 | Additional parameters to FRED API ``tags/series`` endpoint. Refer to the FRED documentation for a list of all possible parameters. 109 | 110 | Returns 111 | ------- 112 | dict 113 | A dictionary representing the json response. 114 | 115 | """ 116 | params = _convert_pydantic_model_to_dict(TagsApiParameters(**kwargs)) 117 | fparams = frozenset( 118 | { 119 | "tag_names": tag_names, 120 | **params, 121 | }.items() 122 | ) 123 | 124 | return _get_request( 125 | endpoint="tags/series", 126 | api_key=api_key, 127 | params=fparams, 128 | ) 129 | -------------------------------------------------------------------------------- /pyfredapi/utils/__init__.py: -------------------------------------------------------------------------------- 1 | """Utilities module.""" 2 | 3 | from pydantic import BaseModel 4 | 5 | 6 | def _convert_pydantic_model_to_frozenset(model: BaseModel) -> frozenset: 7 | return frozenset(model.model_dump(exclude_none=True).items()) 8 | 9 | 10 | def _convert_pydantic_model_to_dict(model: BaseModel) -> dict: 11 | return model.model_dump(exclude_none=True) 12 | -------------------------------------------------------------------------------- /pyfredapi/utils/_common_type_hints.py: -------------------------------------------------------------------------------- 1 | """Module for defining common type hints used across modules.""" 2 | 3 | from __future__ import annotations 4 | 5 | from typing import Any, Dict, Literal, Union 6 | 7 | from pandas import DataFrame as PdDataFrame 8 | 9 | from pyfredapi.utils.enums import ReturnFormat 10 | 11 | try: 12 | from polars import DataFrame as PlDataFrame 13 | except ImportError: 14 | pass 15 | 16 | 17 | ApiKeyType = Union[str, None] 18 | JsonType = Dict[str, Any] 19 | ReturnTypes = Union[Dict, PdDataFrame, "PlDataFrame"] 20 | ReturnFormats = Union[Literal["json", "pandas", "polars"], ReturnFormat] 21 | KwargsType = Dict[str, Union[int, str, None]] 22 | -------------------------------------------------------------------------------- /pyfredapi/utils/_convert_to_df.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import pandas as pd 4 | 5 | try: 6 | import polars as pl 7 | from polars.exceptions import InvalidOperationError 8 | 9 | MISSING_POLARS = False 10 | except ImportError: 11 | MISSING_POLARS = True 12 | 13 | 14 | # ! Excluding realtime_start & realtime_end because pandas can't convert the max/min dates in FRED 15 | # ! I'm not sure this is a good idea. Feels hacky, fragile, and I don't like overwriting the source data when converting 16 | # ! But I would like to convert all columns to the correct data type 17 | # ! and pandas does not accept the realtime dates as-is from FRED 18 | # ! A check could be made against the realtime columns, and if the date is out of bounds, the value is overwritten to the min/max that pandas accepts 19 | # ! The overwrite will allow pd.to_datetime to work 20 | # ! The minimum date pandas accepts is 1677-09-21 21 | # ! The maximum date pandas accepts is 2262-04-11 22 | # ! code snippet for converting to valid date: 23 | # for c in date_cols: 24 | # df.loc[(df[c] < "1677-09-21"), c] = "1677-09-21" 25 | # df.loc[(df[c] > "2262-04-11"), c] = "2262-04-11" 26 | 27 | FRED_DATE_COLS = ["date", "created", "realtime_start", "realtime_end"] 28 | FRED_NUM_COLS = ["value"] 29 | 30 | 31 | def _convert_to_pandas(data: list[dict]) -> pd.DataFrame: 32 | """Convert a FRED response dictionary to a pandas dataframe. 33 | 34 | Parameters 35 | ---------- 36 | data : Dict[str, Any] 37 | Response from FRED api endpoint. 38 | 39 | Returns 40 | ------- 41 | Pandas dataframe. 42 | 43 | """ 44 | df = pd.DataFrame(data) 45 | date_cols = [c for c in list(df.columns) if c in FRED_DATE_COLS] 46 | for c in date_cols: 47 | df[c] = pd.to_datetime(df[c], errors="coerce") 48 | 49 | num_cols = [c for c in list(df.columns) if c in FRED_NUM_COLS] 50 | for c in num_cols: 51 | df[c] = pd.to_numeric(df[c], errors="coerce") 52 | 53 | return df 54 | 55 | 56 | def _convert_to_polars(data: list[dict]) -> pl.DataFrame: 57 | """Convert a FRED response dictionary to a pandas dataframe. 58 | 59 | Parameters 60 | ---------- 61 | data : Dict[str, Any] 62 | Response from FRED api endpoint. 63 | 64 | Returns 65 | ------- 66 | Polars DataFrame. 67 | 68 | """ 69 | if MISSING_POLARS: 70 | raise ImportError( 71 | "Unable to import polars. Ensure you have the polars package installed." 72 | ) 73 | 74 | df = pl.DataFrame(data) 75 | 76 | date_cols = [c for c in list(df.columns) if c in FRED_DATE_COLS] 77 | for col in date_cols: 78 | try: 79 | df = df.cast({col: pl.Date}) 80 | except InvalidOperationError: 81 | pass 82 | 83 | num_cols = [c for c in list(df.columns) if c in FRED_NUM_COLS] 84 | for col in num_cols: 85 | df = df.filter(pl.col(col) != ".") 86 | df = df.cast({col: pl.Float64}) 87 | 88 | return df 89 | -------------------------------------------------------------------------------- /pyfredapi/utils/enums.py: -------------------------------------------------------------------------------- 1 | """The enum module contains enum definitions.""" 2 | 3 | from enum import Enum 4 | 5 | 6 | class ReturnFormat(str, Enum): 7 | """Defines how to format the data returned from the FRED endpoint.""" 8 | 9 | pandas = "pandas" 10 | polars = "polars" 11 | json = "json" 12 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["hatchling>=1.14.0"] 3 | build-backend = "hatchling.build" 4 | 5 | [project] 6 | name = "pyfredapi" 7 | description = "A full featured API client for the FRED API web service." 8 | authors = [{ name = "Greg Moore", email = "gwmoore.career@gmail.com" }] 9 | readme = "README.md" 10 | license = "MIT" 11 | requires-python = ">=3.8" 12 | keywords = [ 13 | "federal reserve", 14 | "fred", 15 | "economic data", 16 | "economic indicators", 17 | "economic statistics", 18 | "economic time series", 19 | "economic data api", 20 | "economic data api client", 21 | "economics", 22 | ] 23 | classifiers = [ 24 | "Development Status :: 4 - Beta", 25 | "License :: OSI Approved :: MIT License", 26 | "Operating System :: OS Independent", 27 | "Intended Audience :: Developers", 28 | "Intended Audience :: Financial and Insurance Industry", 29 | "Intended Audience :: Science/Research", 30 | "Programming Language :: Python :: 3.8", 31 | "Programming Language :: Python :: 3.9", 32 | "Programming Language :: Python :: 3.10", 33 | "Programming Language :: Python :: 3.11", 34 | "Programming Language :: Python :: 3.12", 35 | ] 36 | dependencies = [ 37 | "numpy>=1.0.0,<2.0.0", 38 | "pandas>=1.0.0,<3.0.0", 39 | "pydantic>=2.0.0,<3.0.0", 40 | "requests>=2.0.0,<3.0.0", 41 | "rich>=13.0.0,<14.0.0", 42 | ] 43 | dynamic = ["version"] 44 | 45 | [project.optional-dependencies] 46 | polars = ["polars>=1.0.0,<2.0.0"] 47 | plotly = ["plotly>=5.0.0,<6.0.0"] 48 | all = [ 49 | "pyfredapi[polars]", 50 | "pyfredapi[plotly]", 51 | ] 52 | 53 | docs = [ 54 | "mkdocs==1.6.1", 55 | "jupyter==1.1.1", 56 | "plotly==5.18", 57 | "seaborn==0.12.2", 58 | "mkdocstrings-python==1.13.0", 59 | "mkdocs-material==9.5.50", 60 | "mkdocs-jupyter==0.25.1", 61 | ] 62 | 63 | lint = [ 64 | "black[jupyter]==24.8.0", 65 | "mypy==1.14.1", 66 | "pandas-stubs==2.2.1.240316", 67 | "pre-commit==3.7.0", 68 | "ruff==0.9.2", 69 | "types-frozendict==2.0.9", 70 | "types-requests==2.31.0.20240403", 71 | "types-setuptools==69.2.0.20240317", 72 | ] 73 | 74 | test = [ 75 | "pyfredapi[all]", 76 | "coverage==7.4.4", 77 | "pytest==8.1.1", 78 | "pytest-cov==5.0.0", 79 | "pytest-recording==0.13.0", 80 | "tox==4.14.2", 81 | ] 82 | 83 | dev = [ 84 | "hatch==1.10.0", 85 | "pip-tools==7.4.1", 86 | "pyfredapi[all]", 87 | "pyfredapi[docs]", 88 | "pyfredapi[lint]", 89 | "pyfredapi[test]", 90 | ] 91 | 92 | [tool.hatch.version] 93 | path = "pyfredapi/__about__.py" 94 | 95 | 96 | [project.urls] 97 | Homepage = "https://pyfredapi.readthedocs.io/en/latest/" 98 | Source = "https://github.com/gw-moore/pyfredapi" 99 | 100 | 101 | [tool.black] 102 | exclude = ''' 103 | /( 104 | \.git 105 | | \.hg 106 | | \.mypy_cache 107 | | \.tox 108 | | \.nox 109 | | \.venv 110 | | \.ipynb_checkpoints 111 | | _build 112 | | buck-out 113 | | build 114 | | dist 115 | )/ 116 | ''' 117 | 118 | [tool.ruff] 119 | lint.select = [ 120 | "B", # flake8-bugbear 121 | "D", # pydocstyle 122 | "E", # pycodestyle 123 | "F", # Pyflakes 124 | "I", # isort 125 | "S", # flake8-bandit 126 | ] 127 | 128 | lint.ignore = [ 129 | "D101", # Missing docstring in public class 130 | "D105", # Missing docstring in magic method 131 | "D106", # Missing docstring in public nested class 132 | "D203", # 1 blank line required before class docstring 133 | "D213", # Multi-line docstring summary should start at the second line 134 | "E501", # Line too long 135 | ] 136 | 137 | # Allow autofix for all enabled rules (when `--fix`) is provided. 138 | lint.fixable = [ 139 | "A", 140 | "B", 141 | "C", 142 | "D", 143 | "E", 144 | "F", 145 | "G", 146 | "I", 147 | "N", 148 | "Q", 149 | "S", 150 | "T", 151 | "W", 152 | "ANN", 153 | "ARG", 154 | "BLE", 155 | "COM", 156 | "DJ", 157 | "DTZ", 158 | "EM", 159 | "ERA", 160 | "EXE", 161 | "FBT", 162 | "ICN", 163 | "INP", 164 | "ISC", 165 | "NPY", 166 | "PD", 167 | "PGH", 168 | "PIE", 169 | "PL", 170 | "PT", 171 | "PTH", 172 | "PYI", 173 | "RET", 174 | "RSE", 175 | "RUF", 176 | "SIM", 177 | "SLF", 178 | "TCH", 179 | "TID", 180 | "TRY", 181 | "UP", 182 | "YTT", 183 | ] 184 | 185 | lint.unfixable = [] 186 | 187 | # Exclude a variety of commonly ignored directories. 188 | exclude = [ 189 | ".bzr", 190 | ".direnv", 191 | ".eggs", 192 | ".git", 193 | ".hg", 194 | ".mypy_cache", 195 | ".nox", 196 | ".pants.d", 197 | ".pytype", 198 | ".ruff_cache", 199 | ".svn", 200 | ".tox", 201 | ".venv", 202 | "__pypackages__", 203 | "_build", 204 | "buck-out", 205 | "build", 206 | "dist", 207 | "node_modules", 208 | "venv", 209 | ] 210 | 211 | # Same as Black. 212 | line-length = 88 213 | 214 | # Allow unused variables when underscore-prefixed. 215 | lint.dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" 216 | 217 | # Assume Python 3.11 218 | target-version = "py311" 219 | 220 | [tool.ruff.lint.mccabe] 221 | max-complexity = 10 222 | 223 | [tool.ruff.lint.per-file-ignores] 224 | "__init__.py" = ["E402", "D105", "F401", "D205"] 225 | "tests/*" = ["S101", "D103", "D100"] 226 | "exceptions.py" = ["D101", "D105", "D107"] 227 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | # 2 | # This file is autogenerated by pip-compile with Python 3.12 3 | # by the following command: 4 | # 5 | # pip-compile --output-file=requirements.txt pyproject.toml 6 | # 7 | annotated-types==0.7.0 8 | # via pydantic 9 | certifi==2024.12.14 10 | # via requests 11 | charset-normalizer==3.4.1 12 | # via requests 13 | idna==3.10 14 | # via requests 15 | markdown-it-py==3.0.0 16 | # via rich 17 | mdurl==0.1.2 18 | # via markdown-it-py 19 | numpy==1.26.4 20 | # via 21 | # pandas 22 | # pyfredapi (pyproject.toml) 23 | pandas==2.2.3 24 | # via pyfredapi (pyproject.toml) 25 | pydantic==2.10.5 26 | # via pyfredapi (pyproject.toml) 27 | pydantic-core==2.27.2 28 | # via pydantic 29 | pygments==2.19.1 30 | # via rich 31 | python-dateutil==2.9.0.post0 32 | # via pandas 33 | pytz==2024.2 34 | # via pandas 35 | requests==2.32.3 36 | # via pyfredapi (pyproject.toml) 37 | rich==13.9.4 38 | # via pyfredapi (pyproject.toml) 39 | six==1.17.0 40 | # via python-dateutil 41 | typing-extensions==4.12.2 42 | # via 43 | # pydantic 44 | # pydantic-core 45 | tzdata==2024.2 46 | # via pandas 47 | urllib3==2.3.0 48 | # via requests 49 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | """Testing module.""" 2 | -------------------------------------------------------------------------------- /tests/conftest.py: -------------------------------------------------------------------------------- 1 | import os 2 | import time 3 | from typing import Dict, Optional 4 | 5 | import pytest 6 | import requests 7 | 8 | api_key = os.environ.get("FRED_API_KEY") 9 | 10 | if api_key is None: 11 | raise ValueError("Must set FRED_API_KEY in environment before running tests.") 12 | 13 | base_params = { 14 | "api_key": api_key, 15 | "file_type": "json", 16 | } 17 | BASE_FRED_URL = "https://api.stlouisfed.org/fred" 18 | 19 | 20 | def pytest_addoption(parser): 21 | parser.addoption( 22 | "--runslow", 23 | action="store_true", 24 | default=False, 25 | help="Slow down tests to not overload the FRED API. (Y/N)", 26 | ) 27 | 28 | 29 | def pytest_configure(config): 30 | config.addinivalue_line("markers", "slow: mark test as slow to run") 31 | 32 | 33 | @pytest.fixture(scope="session") 34 | def runslow(request): 35 | return request.config.getoption("--runslow") 36 | 37 | 38 | @pytest.fixture(autouse=True) 39 | def slow_down_tests(runslow): 40 | yield 41 | 42 | if runslow: 43 | time.sleep(0.5) 44 | 45 | 46 | def get_request( 47 | endpoint: str, 48 | extra_params: Optional[Dict[str, str]] = None, 49 | base_params: Dict[str, str] = base_params, 50 | ): 51 | if extra_params is None: 52 | extra_params = {} 53 | 54 | return requests.get( 55 | f"{BASE_FRED_URL}/{endpoint}", 56 | params={**base_params, **extra_params}, 57 | timeout=30, 58 | ) 59 | 60 | 61 | @pytest.fixture(scope="module") 62 | def vcr_config(): 63 | return { 64 | # Exclude the api_key from the url request 65 | "filter_query_parameters": ["api_key"], 66 | } 67 | 68 | 69 | @pytest.fixture(scope="module") 70 | def vcr_cassette_dir(request): 71 | # Put all cassettes in vhs/{module}/{test}.yaml 72 | return os.path.join("tests/vhs", request.module.__name__.split(".")[-1]) 73 | -------------------------------------------------------------------------------- /tests/test_base.py: -------------------------------------------------------------------------------- 1 | import os 2 | from unittest import mock 3 | 4 | import pytest 5 | 6 | from pyfredapi._base import _get_api_key, _get_request 7 | from pyfredapi.exceptions import APIKeyNotFound, FredAPIRequestError, InvalidAPIKey 8 | 9 | 10 | def test_get_api_kay(): 11 | assert _get_api_key() == os.environ.get("FRED_API_KEY") 12 | 13 | 14 | def test_invalid_api_key_err(): 15 | with pytest.raises(InvalidAPIKey): 16 | _get_api_key(api_key="foobar") 17 | 18 | 19 | def test_api_key_not_found_err(): 20 | _get_api_key.cache_clear() 21 | with mock.patch.dict(os.environ, {}, clear=True): 22 | with pytest.raises(APIKeyNotFound): 23 | _ = _get_api_key() 24 | 25 | 26 | def test_fredapi_request_err(): 27 | with pytest.raises(FredAPIRequestError): 28 | _get_request(endpoint="not-a-real-endpoint") 29 | -------------------------------------------------------------------------------- /tests/test_category.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import pytest 3 | 4 | from pyfredapi.category import ( 5 | get_category, 6 | get_category_children, 7 | get_category_related, 8 | get_category_related_tags, 9 | get_category_series, 10 | get_category_tags, 11 | ) 12 | from pyfredapi.series import SeriesInfo 13 | from pyfredapi.utils._convert_to_df import _convert_to_pandas 14 | 15 | from .conftest import get_request as category_request 16 | 17 | category_params = { 18 | "category_id": 125, 19 | } 20 | 21 | 22 | @pytest.mark.vcr() 23 | def test_get_category(): 24 | actual = get_category(category_params["category_id"]) 25 | assert actual is not None 26 | assert isinstance(actual, dict) 27 | assert isinstance(actual["categories"], list) 28 | 29 | expected = category_request( 30 | endpoint="category", extra_params=category_params 31 | ).json() 32 | assert expected == actual 33 | 34 | 35 | @pytest.mark.vcr() 36 | def test_get_category_children(): 37 | actual = get_category_children(category_params["category_id"]) 38 | assert actual is not None 39 | assert isinstance(actual, dict) 40 | assert isinstance(actual["categories"], list) 41 | 42 | expected = category_request( 43 | endpoint="category/children", extra_params=category_params 44 | ).json() 45 | assert expected == actual 46 | 47 | 48 | @pytest.mark.vcr() 49 | def test_get_category_related(): 50 | actual = get_category_related(category_params["category_id"]) 51 | assert actual is not None 52 | assert isinstance(actual, dict) 53 | assert isinstance(actual["categories"], list) 54 | 55 | expected = category_request( 56 | endpoint="category/related", extra_params=category_params 57 | ).json() 58 | assert expected == actual 59 | 60 | 61 | @pytest.mark.vcr() 62 | def test_get_category_series(): 63 | actual = get_category_series(category_id=category_params["category_id"]) 64 | expected = category_request( 65 | endpoint="category/series", extra_params=category_params 66 | ).json() 67 | 68 | expected = {series["id"]: SeriesInfo(**series) for series in expected["seriess"]} 69 | 70 | assert isinstance(actual, dict) 71 | for series_info in actual.values(): 72 | assert isinstance(series_info, SeriesInfo) 73 | assert actual == expected 74 | 75 | 76 | @pytest.mark.vcr() 77 | @pytest.mark.parametrize("return_type", ["json", "pandas"]) 78 | def test_get_category_tags(return_type): 79 | actual = get_category_tags( 80 | category_id=category_params["category_id"], 81 | return_format=return_type, 82 | ) 83 | expected = category_request( 84 | endpoint="category/tags", extra_params=category_params 85 | ).json() 86 | 87 | if return_type == "json": 88 | assert isinstance(actual, dict) 89 | assert "tags" in actual 90 | assert expected == actual 91 | elif return_type == "pandas": 92 | assert isinstance(actual, pd.DataFrame) 93 | pd.testing.assert_frame_equal(_convert_to_pandas(expected["tags"]), actual) 94 | 95 | 96 | @pytest.mark.vcr() 97 | @pytest.mark.parametrize("return_type", ["json", "pandas"]) 98 | def test_get_category_related_tags(return_type): 99 | actual = get_category_related_tags( 100 | category_id=category_params["category_id"], 101 | return_format=return_type, 102 | **{"tag_names": "balance"}, 103 | ) 104 | 105 | expected = category_request( 106 | endpoint="category/related_tags", 107 | extra_params={**category_params, "tag_names": "balance"}, 108 | ).json() 109 | 110 | if return_type == "json": 111 | assert isinstance(actual, dict) 112 | assert "tags" in actual 113 | assert expected == actual 114 | elif return_type == "pandas": 115 | assert isinstance(actual, pd.DataFrame) 116 | pd.testing.assert_frame_equal(_convert_to_pandas(expected["tags"]), actual) 117 | -------------------------------------------------------------------------------- /tests/test_maps.py: -------------------------------------------------------------------------------- 1 | import os 2 | from typing import Dict, Optional 3 | 4 | import pandas as pd 5 | import pytest 6 | import requests 7 | 8 | from pyfredapi.maps import ( 9 | GeoseriesData, 10 | GeoseriesInfo, 11 | get_geoseries, 12 | get_geoseries_info, 13 | get_shape_files, 14 | ) 15 | 16 | BASE_FRED_URL = "https://api.stlouisfed.org/geofred/" 17 | 18 | base_params = { 19 | "api_key": os.environ.get("FRED_API_KEY", None), 20 | "file_type": "json", 21 | } 22 | 23 | 24 | def maps_get_request(endpoint: str, extra_params: Optional[Dict[str, str]] = None): 25 | if extra_params is None: 26 | extra_params = {} 27 | 28 | return requests.get( 29 | f"{BASE_FRED_URL}/{endpoint}", 30 | params={**base_params, **extra_params}, 31 | timeout=30, 32 | ) 33 | 34 | 35 | @pytest.mark.vcr("cassettes/maps/") 36 | def test_get_geoseries_info(): 37 | actual = get_geoseries_info(series_id="WIPCPI") 38 | response = maps_get_request( 39 | "series/group", extra_params={"series_id": "WIPCPI"} 40 | ).json() 41 | expected = GeoseriesInfo(**response["series_group"]) 42 | assert isinstance(actual, GeoseriesInfo) 43 | assert expected == actual 44 | 45 | 46 | @pytest.mark.vcr() 47 | def test_get_shape_files(): 48 | actual = get_shape_files(shape="bea") 49 | expected = maps_get_request("shapes/file", extra_params={"shape": "bea"}).json() 50 | assert isinstance(actual, dict) 51 | assert expected == actual 52 | 53 | 54 | @pytest.mark.vcr() 55 | @pytest.mark.parametrize("return_type", ["json", "pandas"]) 56 | def test_get_geoseries(return_type): 57 | actual = get_geoseries( 58 | series_id="WIPCPI", 59 | start_date="2019-01-01", 60 | end_date="2021-01-01", 61 | return_format=return_type, 62 | ) 63 | assert isinstance(actual, GeoseriesData) 64 | assert isinstance(actual.info, GeoseriesInfo) 65 | 66 | expected = maps_get_request( 67 | "series/data", 68 | extra_params={ 69 | "series_id": "WIPCPI", 70 | "start_date": "2019-01-01", 71 | "date": "2021-01-01", 72 | "return_format": "json", 73 | }, 74 | ).json() 75 | 76 | if return_type == "json": 77 | assert isinstance(actual.data, dict) 78 | assert expected["meta"]["data"] == actual.data 79 | elif return_type == "pandas": 80 | dfs = [] 81 | for date, data in expected["meta"]["data"].items(): 82 | t = pd.DataFrame.from_dict(data) 83 | t["date"] = date 84 | t["date"] = pd.to_datetime(t["date"]) 85 | dfs.append(t) 86 | 87 | assert isinstance(actual.data, pd.DataFrame) 88 | pd.testing.assert_frame_equal(pd.concat(dfs), actual.data) 89 | -------------------------------------------------------------------------------- /tests/test_release.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import pytest 4 | 5 | from pyfredapi.releases import ( 6 | get_release, 7 | get_release_dates, 8 | get_release_related_tags, 9 | get_release_series, 10 | get_release_sources, 11 | get_release_tables, 12 | get_release_tags, 13 | get_releases, 14 | get_releases_dates, 15 | ) 16 | 17 | from .conftest import get_request 18 | 19 | base_params = { 20 | "api_key": os.environ.get("FRED_API_KEY", None), 21 | "file_type": "json", 22 | "release_id": 10, 23 | } 24 | 25 | 26 | @pytest.mark.vcr() 27 | def test_get_releases(): 28 | actual = get_releases() 29 | expected = get_request(endpoint="releases").json() 30 | 31 | assert actual == expected 32 | 33 | 34 | @pytest.mark.vcr() 35 | def test_get_releases_dates(): 36 | actual = get_releases_dates() 37 | expected = get_request(endpoint="releases/dates").json() 38 | 39 | assert actual == expected 40 | 41 | 42 | @pytest.mark.vcr() 43 | def test_get_release(): 44 | actual = get_release(release_id=base_params["release_id"]) 45 | expected = get_request( 46 | endpoint="release", 47 | extra_params={"release_id": base_params["release_id"]}, 48 | ).json() 49 | 50 | assert actual == expected 51 | 52 | 53 | @pytest.mark.vcr() 54 | def test_get_release_dates(): 55 | actual = get_release_dates(release_id=base_params["release_id"]) 56 | expected = get_request( 57 | endpoint="release/dates", 58 | extra_params={"release_id": base_params["release_id"]}, 59 | ).json() 60 | 61 | assert actual == expected 62 | 63 | 64 | @pytest.mark.vcr() 65 | def test_get_release_series(): 66 | actual = get_release_series(release_id=base_params["release_id"]) 67 | expected = get_request( 68 | endpoint="release/series", 69 | extra_params={"release_id": base_params["release_id"]}, 70 | ).json() 71 | 72 | assert actual == expected 73 | 74 | 75 | @pytest.mark.vcr() 76 | def test_get_release_sources(): 77 | actual = get_release_sources(release_id=base_params["release_id"]) 78 | expected = get_request( 79 | endpoint="release/sources", 80 | extra_params={"release_id": base_params["release_id"]}, 81 | ).json() 82 | 83 | assert actual == expected 84 | 85 | 86 | @pytest.mark.vcr() 87 | def test_get_release_tags(): 88 | actual = get_release_tags(release_id=base_params["release_id"]) 89 | expected = get_request( 90 | endpoint="release/tags", 91 | extra_params={"release_id": base_params["release_id"]}, 92 | ).json() 93 | 94 | assert actual == expected 95 | 96 | 97 | @pytest.mark.vcr() 98 | def test_get_release_related_tags(): 99 | actual = get_release_related_tags( 100 | release_id=base_params["release_id"], tag_names="sa;foreign" 101 | ) 102 | expected = get_request( 103 | endpoint="release/related_tags", 104 | extra_params={ 105 | "release_id": base_params["release_id"], 106 | "tag_names": "sa;foreign", 107 | }, 108 | ).json() 109 | 110 | assert actual == expected 111 | 112 | 113 | @pytest.mark.vcr() 114 | def test_get_release_tables(): 115 | actual = get_release_tables(release_id=base_params["release_id"]) 116 | expected = get_request( 117 | endpoint="release/tables", 118 | extra_params={"release_id": base_params["release_id"]}, 119 | ).json() 120 | 121 | assert actual == expected 122 | -------------------------------------------------------------------------------- /tests/test_series.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import polars as pl 3 | import pytest 4 | from polars.testing import assert_frame_equal 5 | 6 | from pyfredapi.series import ( 7 | SeriesInfo, 8 | get_series, 9 | get_series_all_releases, 10 | get_series_asof_date, 11 | get_series_categories, 12 | get_series_info, 13 | get_series_initial_release, 14 | get_series_releases, 15 | get_series_tags, 16 | get_series_updates, 17 | get_series_vintagedates, 18 | search_series, 19 | search_series_related_tags, 20 | search_series_tags, 21 | ) 22 | from pyfredapi.utils._convert_to_df import _convert_to_pandas, _convert_to_polars 23 | 24 | from .conftest import get_request 25 | 26 | series_params = { 27 | "series_id": "GDP", 28 | } 29 | 30 | test_search_text = "monetary+service+index" 31 | series_obv_endpoint = "series/observations" 32 | 33 | return_type_mark = pytest.mark.parametrize("return_type", ["json", "pandas", "polars"]) 34 | 35 | 36 | @pytest.mark.vcr() 37 | def test_get_series_info(): 38 | actual = get_series_info(series_params["series_id"]) 39 | assert isinstance(actual, SeriesInfo) 40 | 41 | 42 | @pytest.mark.vcr() 43 | def test_get_series_categories(): 44 | actual = get_series_categories(series_id=series_params["series_id"]) 45 | expected = get_request( 46 | endpoint="series/categories", 47 | extra_params=series_params, 48 | ).json() 49 | assert isinstance(actual, dict) 50 | assert expected == actual 51 | 52 | 53 | @pytest.mark.vcr() 54 | @return_type_mark 55 | def test_get_series(return_type): 56 | actual = get_series(series_id=series_params["series_id"], return_format=return_type) 57 | expected = get_request( 58 | endpoint=series_obv_endpoint, extra_params=series_params 59 | ).json()["observations"] 60 | 61 | if return_type == "json": 62 | assert isinstance(actual, list) 63 | assert expected == actual 64 | elif return_type == "pandas": 65 | assert isinstance(actual, pd.DataFrame) 66 | pd.testing.assert_frame_equal(_convert_to_pandas(expected), actual) 67 | 68 | 69 | @pytest.mark.vcr() 70 | def test_get_series_releases(): 71 | actual = get_series_releases(series_id=series_params["series_id"]) 72 | expected = get_request( 73 | endpoint="series/release", 74 | extra_params=series_params, 75 | ).json() 76 | assert isinstance(actual, dict) 77 | assert expected == actual 78 | 79 | 80 | @pytest.mark.vcr() 81 | def test_get_series_tags(): 82 | actual = get_series_tags(series_id=series_params["series_id"]) 83 | expected = get_request( 84 | endpoint="series/tags", 85 | extra_params=series_params, 86 | ).json() 87 | assert isinstance(actual, dict) 88 | assert expected == actual 89 | 90 | 91 | @pytest.mark.vcr() 92 | def test_get_series_updates(): 93 | actual = get_series_updates(series_id=series_params["series_id"]) 94 | expected = get_request( 95 | endpoint="series/updates", 96 | extra_params=series_params, 97 | ).json() 98 | assert isinstance(actual, dict) 99 | assert expected == actual 100 | 101 | 102 | @pytest.mark.vcr() 103 | def test_get_series_vintagedates(): 104 | actual = get_series_vintagedates(series_id=series_params["series_id"]) 105 | expected = get_request( 106 | endpoint="series/vintagedates", 107 | extra_params=series_params, 108 | ).json()["vintage_dates"] 109 | assert isinstance(actual, list) 110 | assert expected == actual 111 | 112 | 113 | @pytest.mark.vcr() 114 | @return_type_mark 115 | def test_get_series_all_releases(return_type): 116 | actual = get_series_all_releases( 117 | series_id=series_params["series_id"], return_format=return_type 118 | ) 119 | 120 | expected = get_request( 121 | endpoint=series_obv_endpoint, 122 | extra_params={ 123 | "realtime_start": "1776-07-04", 124 | "realtime_end": "9999-12-31", 125 | "series_id": series_params["series_id"], 126 | }, 127 | ).json()["observations"] 128 | 129 | if return_type == "json": 130 | assert isinstance(actual, list) 131 | assert expected == actual 132 | elif return_type == "pandas": 133 | assert isinstance(actual, pd.DataFrame) 134 | pd.testing.assert_frame_equal(_convert_to_pandas(expected), actual) 135 | 136 | 137 | @pytest.mark.vcr() 138 | @return_type_mark 139 | def test_get_series_initial_release(return_type): 140 | actual = get_series_initial_release( 141 | series_id=series_params["series_id"], return_format=return_type 142 | ) 143 | 144 | expected = get_request( 145 | endpoint=series_obv_endpoint, 146 | extra_params={ 147 | "realtime_start": "1776-07-04", 148 | "output_type": "4", 149 | "series_id": series_params["series_id"], 150 | }, 151 | ).json()["observations"] 152 | 153 | if return_type == "json": 154 | assert isinstance(actual, list) 155 | assert expected == actual 156 | elif return_type == "pandas": 157 | assert isinstance(actual, pd.DataFrame) 158 | pd.testing.assert_frame_equal(_convert_to_pandas(expected), actual) 159 | elif return_type == "polars": 160 | assert isinstance(actual, pl.DataFrame) 161 | assert_frame_equal(_convert_to_polars(expected), actual) 162 | 163 | 164 | @pytest.mark.vcr() 165 | @return_type_mark 166 | def test_get_series_asof_date(return_type): 167 | actual = get_series_asof_date( 168 | series_id=series_params["series_id"], 169 | date="2019-01-01", 170 | return_format=return_type, 171 | ) 172 | 173 | expected = get_request( 174 | endpoint=series_obv_endpoint, 175 | extra_params={ 176 | "realtime_start": "1776-07-04", 177 | "realtime_end": "2019-01-01", 178 | "series_id": series_params["series_id"], 179 | }, 180 | ).json()["observations"] 181 | 182 | if return_type == "json": 183 | assert isinstance(actual, list) 184 | assert expected == actual 185 | elif return_type == "pandas": 186 | assert isinstance(actual, pd.DataFrame) 187 | pd.testing.assert_frame_equal(_convert_to_pandas(expected), actual) 188 | elif return_type == "polars": 189 | assert isinstance(actual, pl.DataFrame) 190 | assert_frame_equal(_convert_to_polars(expected), actual) 191 | 192 | 193 | @pytest.mark.vcr() 194 | @return_type_mark 195 | def test_search_series(return_type): 196 | actual = search_series( 197 | search_text=test_search_text, 198 | return_format=return_type, 199 | ) 200 | expected = get_request( 201 | endpoint="series/search", 202 | extra_params={ 203 | "search_text": test_search_text, 204 | "search_type": "full_text", 205 | }, 206 | ).json() 207 | 208 | if return_type == "json": 209 | assert isinstance(actual, dict) 210 | assert "seriess" in actual 211 | assert expected == actual 212 | elif return_type == "pandas": 213 | assert isinstance(actual, pd.DataFrame) 214 | pd.testing.assert_frame_equal(_convert_to_pandas(expected["seriess"]), actual) 215 | elif return_type == "polars": 216 | assert isinstance(actual, pl.DataFrame) 217 | assert_frame_equal(_convert_to_polars(expected["seriess"]), actual) 218 | 219 | 220 | @pytest.mark.vcr() 221 | @return_type_mark 222 | def test_search_series_tags(return_type): 223 | actual = search_series_tags( 224 | search_text=test_search_text, 225 | return_format=return_type, 226 | ) 227 | expected = get_request( 228 | endpoint="series/search/tags", 229 | extra_params={"series_search_text": test_search_text}, 230 | ).json() 231 | 232 | if return_type == "json": 233 | assert isinstance(actual, dict) 234 | assert "tags" in actual 235 | assert expected == actual 236 | elif return_type == "pandas": 237 | assert isinstance(actual, pd.DataFrame) 238 | pd.testing.assert_frame_equal(_convert_to_pandas(expected["tags"]), actual) 239 | elif return_type == "polars": 240 | assert isinstance(actual, pl.DataFrame) 241 | assert_frame_equal(_convert_to_polars(expected["tags"]), actual) 242 | 243 | 244 | @pytest.mark.vcr() 245 | @return_type_mark 246 | def test_search_series_related_tags(return_type): 247 | actual = search_series_related_tags( 248 | search_text=test_search_text, 249 | tag_names="30-year;frb", 250 | return_format=return_type, 251 | ) 252 | expected = get_request( 253 | endpoint="series/search/related_tags", 254 | extra_params={ 255 | "series_search_text": test_search_text, 256 | "tag_names": "30-year;frb", 257 | }, 258 | ).json() 259 | 260 | if return_type == "json": 261 | assert isinstance(actual, dict) 262 | assert "tags" in actual 263 | assert expected == actual 264 | elif return_type == "pandas": 265 | assert isinstance(actual, pd.DataFrame) 266 | pd.testing.assert_frame_equal(_convert_to_pandas(expected["tags"]), actual) 267 | elif return_type == "polars": 268 | assert isinstance(actual, pl.DataFrame) 269 | assert_frame_equal(_convert_to_polars(expected["tags"]), actual) 270 | -------------------------------------------------------------------------------- /tests/test_series_collection.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import pytest 3 | 4 | from pyfredapi.series_collection import SeriesCollection, SeriesData 5 | 6 | 7 | def test_init(): 8 | sc = SeriesCollection(series_id="CPIAUCSL") 9 | assert isinstance(sc, SeriesCollection) 10 | 11 | 12 | @pytest.mark.vcr() 13 | def test_add_series(): 14 | sc = SeriesCollection(series_id=["CPIAUCSL"]) 15 | sc.add("CPIAUCSL") 16 | assert hasattr(sc, "CPIAUCSL") 17 | assert isinstance(sc.CPIAUCSL, SeriesData) 18 | 19 | 20 | @pytest.mark.vcr() 21 | def test_remove_series(): 22 | sc = SeriesCollection(series_id=["CPIAUCSL", "CPILFESL"]) 23 | assert hasattr(sc, "CPIAUCSL") 24 | assert hasattr(sc, "CPILFESL") 25 | sc.remove("CPIAUCSL") 26 | assert not hasattr(sc, "CPIAUCSL") 27 | assert hasattr(sc, "CPILFESL") 28 | 29 | 30 | def test_drop_series_err(): 31 | with pytest.raises(ValueError): 32 | sc = SeriesCollection(series_id=["CPIAUCSL"]) 33 | sc.remove("foobar") 34 | 35 | 36 | @pytest.mark.vcr() 37 | def test_keep_realtime_cols(): 38 | sc = SeriesCollection(series_id="CPIAUCSL", drop_realtime=False) 39 | df_cols = set(sc.CPIAUCSL.df.columns.to_list()) 40 | assert set(("date", "CPIAUCSL", "realtime_start", "realtime_end")) == df_cols 41 | 42 | 43 | def parse_cpi_title(title: str) -> str: 44 | """Parse CPI series title into a readable label.""" 45 | return ( 46 | title.lower() 47 | .replace("consumer price index", "cpi ") 48 | .replace(" for all urban consumers: ", "") 49 | .replace(" in u.s. city average", "") 50 | .replace(" ", "_") 51 | # .capitalize() 52 | ) 53 | 54 | 55 | @pytest.mark.vcr() 56 | @pytest.mark.parametrize( 57 | "rename", [{"CPIAUCSL": "cpi_all_items"}, parse_cpi_title], ids=["dict", "func"] 58 | ) 59 | def test_rename_on_add(rename): 60 | sc = SeriesCollection(series_id="CPIAUCSL", rename=rename) 61 | df_cols = set(sc.CPIAUCSL.df.columns.to_list()) 62 | assert set(("date", "cpi_all_items")) == df_cols 63 | 64 | 65 | @pytest.mark.vcr() 66 | def test_rename_err(): 67 | with pytest.raises(TypeError): 68 | _ = SeriesCollection(series_id=["CPIAUCSL"], rename="foobar") 69 | 70 | 71 | @pytest.mark.vcr() 72 | @pytest.mark.parametrize( 73 | "rename", [{"CPIAUCSL": "cpi_all_items"}, parse_cpi_title], ids=["dict", "func"] 74 | ) 75 | def test_rename_after_add(rename): 76 | sc = SeriesCollection(series_id=["CPIAUCSL"]) 77 | sc.rename_series(rename=rename) 78 | df_cols = set(sc.CPIAUCSL.df.columns.to_list()) 79 | assert set(("date", "cpi_all_items")) == df_cols 80 | 81 | 82 | @pytest.mark.vcr() 83 | def test_rename_partial(): 84 | rename = {"CPIAUCSL": "cpi_all_items"} 85 | sc = SeriesCollection(series_id=["CPIAUCSL", "CPILFESL"]) 86 | sc.rename_series(rename=rename) 87 | assert set(("date", "cpi_all_items")) == set(sc.CPIAUCSL.df.columns.to_list()) 88 | assert set(("date", "CPILFESL")) == set(sc.CPILFESL.df.columns.to_list()) 89 | 90 | 91 | @pytest.mark.vcr() 92 | def test_merge_long(): 93 | series = ["CPIAUCSL", "CPILFESL"] 94 | sc = SeriesCollection(series_id=series) 95 | long_df = sc.merge_long() 96 | assert isinstance(long_df, pd.DataFrame) 97 | cols = set(long_df.columns.to_list()) 98 | assert set(("date", "value", "series")) == cols 99 | assert set(series) == set(long_df.series.tolist()) 100 | 101 | 102 | @pytest.mark.vcr() 103 | def test_merge_asof(): 104 | series = ["CPIAUCSL", "CPILFESL"] 105 | sc = SeriesCollection(series_id=series) 106 | asof_df = sc.merge_asof(base_series_id="CPIAUCSL") 107 | assert isinstance(asof_df, pd.DataFrame) 108 | cols = set(asof_df.columns.to_list()) 109 | assert set(["date"] + series) == cols 110 | assert set(series) == set([c for c in asof_df.columns.tolist() if c != "date"]) 111 | 112 | 113 | @pytest.mark.vcr() 114 | def test_merge_wide(): 115 | series = ["CPIAUCSL", "CPILFESL"] 116 | sc = SeriesCollection(series_id=series) 117 | wide_df = sc.merge_wide() 118 | assert isinstance(wide_df, pd.DataFrame) 119 | cols = set(wide_df.columns.to_list()) 120 | assert set(["date"] + series) == cols 121 | assert set(series) == set([c for c in wide_df.columns.tolist() if c != "date"]) 122 | 123 | 124 | @pytest.mark.vcr() 125 | def test_list_methods_same(): 126 | sc = SeriesCollection(series_id="CPIAUCSL") 127 | sc.list_series() 128 | sc.list_end_date() 129 | sc.list_frequency() 130 | sc.list_seasonality() 131 | sc.list_start_date() 132 | sc.list_units() 133 | 134 | 135 | @pytest.mark.vcr() 136 | def test_list_methods_diff(): 137 | sc = SeriesCollection(series_id=["CPIAUCSL", "WGS10YR"]) 138 | sc.list_series() 139 | sc.list_end_date() 140 | sc.list_frequency() 141 | sc.list_seasonality() 142 | sc.list_start_date() 143 | sc.list_units() 144 | -------------------------------------------------------------------------------- /tests/test_sources.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from pyfredapi.sources import get_source, get_source_release, get_sources 4 | 5 | from .conftest import get_request 6 | 7 | 8 | @pytest.mark.vcr() 9 | def test_get_sources(): 10 | actual = get_sources() 11 | expected = get_request(endpoint="sources").json() 12 | 13 | assert actual == expected 14 | 15 | 16 | @pytest.mark.vcr() 17 | def test_get_source(): 18 | actual = get_source(source_id=1) 19 | expected = get_request(endpoint="source", extra_params={"source_id": 1}).json() 20 | 21 | assert actual == expected 22 | 23 | 24 | @pytest.mark.vcr() 25 | def test_get_source_release(): 26 | actual = get_source_release(source_id=1) 27 | expected = get_request( 28 | endpoint="source/releases", extra_params={"source_id": 1} 29 | ).json() 30 | 31 | assert actual == expected 32 | -------------------------------------------------------------------------------- /tests/test_tags.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from pyfredapi.tags import get_related_tags, get_series_matching_tags, get_tags 4 | 5 | from .conftest import get_request 6 | 7 | 8 | @pytest.mark.vcr() 9 | def test_get_tags(): 10 | actual = get_tags() 11 | expected = get_request(endpoint="tags").json() 12 | 13 | assert actual == expected 14 | 15 | 16 | @pytest.mark.vcr() 17 | def test_get_related_tags(): 18 | actual = get_related_tags(tag_names="nation") 19 | expected = get_request( 20 | endpoint="related_tags", extra_params={"tag_names": "nation"} 21 | ).json() 22 | 23 | assert actual == expected 24 | 25 | 26 | @pytest.mark.vcr() 27 | def test_get_tag_series(): 28 | actual = get_series_matching_tags(tag_names="slovenia;food;oecd") 29 | expected = get_request( 30 | endpoint="tags/series", extra_params={"tag_names": "slovenia;food;oecd"} 31 | ).json() 32 | 33 | assert actual == expected 34 | -------------------------------------------------------------------------------- /tests/vhs/test_category/test_get_category.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: null 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate, zstd 9 | Connection: 10 | - keep-alive 11 | User-Agent: 12 | - python-requests/2.32.3 13 | method: GET 14 | uri: https://api.stlouisfed.org/fred/category?category_id=125&file_type=json 15 | response: 16 | body: 17 | string: '{"categories":[{"id":125,"name":"Trade Balance","parent_id":13}]}' 18 | headers: 19 | Cache-Control: 20 | - max-age=0, no-cache 21 | Connection: 22 | - keep-alive 23 | Content-Encoding: 24 | - gzip 25 | Content-Length: 26 | - '82' 27 | Content-Type: 28 | - application/json; charset=UTF-8 29 | Date: 30 | - Sun, 03 Nov 2024 14:33:04 GMT 31 | Expires: 32 | - Sun, 03 Nov 2024 14:33:04 GMT 33 | Last-Modified: 34 | - Sun, 03 Nov 2024 14:33:04 GMT 35 | Pragma: 36 | - no-cache 37 | Server: 38 | - Apache 39 | Strict-Transport-Security: 40 | - max-age=86400 41 | Vary: 42 | - Accept-Encoding 43 | status: 44 | code: 200 45 | message: OK 46 | - request: 47 | body: null 48 | headers: 49 | Accept: 50 | - '*/*' 51 | Accept-Encoding: 52 | - gzip, deflate, zstd 53 | Connection: 54 | - keep-alive 55 | User-Agent: 56 | - python-requests/2.32.3 57 | method: GET 58 | uri: https://api.stlouisfed.org/fred/category?category_id=125&file_type=json 59 | response: 60 | body: 61 | string: '{"categories":[{"id":125,"name":"Trade Balance","parent_id":13}]}' 62 | headers: 63 | Cache-Control: 64 | - max-age=0, no-cache 65 | Connection: 66 | - keep-alive 67 | Content-Encoding: 68 | - gzip 69 | Content-Length: 70 | - '82' 71 | Content-Type: 72 | - application/json; charset=UTF-8 73 | Date: 74 | - Sun, 03 Nov 2024 14:33:04 GMT 75 | Expires: 76 | - Sun, 03 Nov 2024 14:33:04 GMT 77 | Last-Modified: 78 | - Sun, 03 Nov 2024 14:33:04 GMT 79 | Pragma: 80 | - no-cache 81 | Server: 82 | - Apache 83 | Strict-Transport-Security: 84 | - max-age=86400 85 | Vary: 86 | - Accept-Encoding 87 | status: 88 | code: 200 89 | message: OK 90 | - request: 91 | body: null 92 | headers: 93 | Accept: 94 | - '*/*' 95 | Accept-Encoding: 96 | - gzip, deflate, zstd 97 | Connection: 98 | - keep-alive 99 | User-Agent: 100 | - python-requests/2.32.3 101 | method: GET 102 | uri: https://api.stlouisfed.org/fred/category?category_id=125&file_type=json 103 | response: 104 | body: 105 | string: '{"categories":[{"id":125,"name":"Trade Balance","parent_id":13}]}' 106 | headers: 107 | Cache-Control: 108 | - max-age=0, no-cache 109 | Connection: 110 | - keep-alive 111 | Content-Encoding: 112 | - gzip 113 | Content-Length: 114 | - '82' 115 | Content-Type: 116 | - application/json; charset=UTF-8 117 | Date: 118 | - Mon, 20 Jan 2025 14:55:48 GMT 119 | Expires: 120 | - Mon, 20 Jan 2025 14:55:48 GMT 121 | Last-Modified: 122 | - Mon, 20 Jan 2025 14:55:48 GMT 123 | Pragma: 124 | - no-cache 125 | Server: 126 | - Apache 127 | Strict-Transport-Security: 128 | - max-age=86400 129 | Vary: 130 | - Accept-Encoding 131 | status: 132 | code: 200 133 | message: OK 134 | - request: 135 | body: null 136 | headers: 137 | Accept: 138 | - '*/*' 139 | Accept-Encoding: 140 | - gzip, deflate, zstd 141 | Connection: 142 | - keep-alive 143 | User-Agent: 144 | - python-requests/2.32.3 145 | method: GET 146 | uri: https://api.stlouisfed.org/fred/category?category_id=125&file_type=json 147 | response: 148 | body: 149 | string: '{"categories":[{"id":125,"name":"Trade Balance","parent_id":13}]}' 150 | headers: 151 | Cache-Control: 152 | - max-age=0, no-cache 153 | Connection: 154 | - keep-alive 155 | Content-Encoding: 156 | - gzip 157 | Content-Length: 158 | - '82' 159 | Content-Type: 160 | - application/json; charset=UTF-8 161 | Date: 162 | - Mon, 20 Jan 2025 14:55:48 GMT 163 | Expires: 164 | - Mon, 20 Jan 2025 14:55:48 GMT 165 | Last-Modified: 166 | - Mon, 20 Jan 2025 14:55:48 GMT 167 | Pragma: 168 | - no-cache 169 | Server: 170 | - Apache 171 | Strict-Transport-Security: 172 | - max-age=86400 173 | Vary: 174 | - Accept-Encoding 175 | status: 176 | code: 200 177 | message: OK 178 | version: 1 179 | -------------------------------------------------------------------------------- /tests/vhs/test_category/test_get_category_children.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: null 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate, zstd 9 | Connection: 10 | - keep-alive 11 | User-Agent: 12 | - python-requests/2.32.3 13 | method: GET 14 | uri: https://api.stlouisfed.org/fred/category/children?category_id=125&file_type=json 15 | response: 16 | body: 17 | string: '{"categories":[]}' 18 | headers: 19 | Cache-Control: 20 | - max-age=0, no-cache 21 | Connection: 22 | - keep-alive 23 | Content-Length: 24 | - '17' 25 | Content-Type: 26 | - application/json; charset=UTF-8 27 | Date: 28 | - Sun, 03 Nov 2024 14:33:05 GMT 29 | Expires: 30 | - Sun, 03 Nov 2024 14:33:05 GMT 31 | Last-Modified: 32 | - Sun, 03 Nov 2024 14:33:05 GMT 33 | Pragma: 34 | - no-cache 35 | Server: 36 | - Apache 37 | Strict-Transport-Security: 38 | - max-age=86400 39 | status: 40 | code: 200 41 | message: OK 42 | - request: 43 | body: null 44 | headers: 45 | Accept: 46 | - '*/*' 47 | Accept-Encoding: 48 | - gzip, deflate, zstd 49 | Connection: 50 | - keep-alive 51 | User-Agent: 52 | - python-requests/2.32.3 53 | method: GET 54 | uri: https://api.stlouisfed.org/fred/category/children?category_id=125&file_type=json 55 | response: 56 | body: 57 | string: '{"categories":[]}' 58 | headers: 59 | Cache-Control: 60 | - max-age=0, no-cache 61 | Connection: 62 | - keep-alive 63 | Content-Length: 64 | - '17' 65 | Content-Type: 66 | - application/json; charset=UTF-8 67 | Date: 68 | - Sun, 03 Nov 2024 14:33:05 GMT 69 | Expires: 70 | - Sun, 03 Nov 2024 14:33:05 GMT 71 | Last-Modified: 72 | - Sun, 03 Nov 2024 14:33:05 GMT 73 | Pragma: 74 | - no-cache 75 | Server: 76 | - Apache 77 | Strict-Transport-Security: 78 | - max-age=86400 79 | status: 80 | code: 200 81 | message: OK 82 | - request: 83 | body: null 84 | headers: 85 | Accept: 86 | - '*/*' 87 | Accept-Encoding: 88 | - gzip, deflate, zstd 89 | Connection: 90 | - keep-alive 91 | User-Agent: 92 | - python-requests/2.32.3 93 | method: GET 94 | uri: https://api.stlouisfed.org/fred/category/children?category_id=125&file_type=json 95 | response: 96 | body: 97 | string: '{"categories":[]}' 98 | headers: 99 | Cache-Control: 100 | - max-age=0, no-cache 101 | Connection: 102 | - keep-alive 103 | Content-Length: 104 | - '17' 105 | Content-Type: 106 | - application/json; charset=UTF-8 107 | Date: 108 | - Mon, 20 Jan 2025 14:55:49 GMT 109 | Expires: 110 | - Mon, 20 Jan 2025 14:55:49 GMT 111 | Last-Modified: 112 | - Mon, 20 Jan 2025 14:55:49 GMT 113 | Pragma: 114 | - no-cache 115 | Server: 116 | - Apache 117 | Strict-Transport-Security: 118 | - max-age=86400 119 | status: 120 | code: 200 121 | message: OK 122 | - request: 123 | body: null 124 | headers: 125 | Accept: 126 | - '*/*' 127 | Accept-Encoding: 128 | - gzip, deflate, zstd 129 | Connection: 130 | - keep-alive 131 | User-Agent: 132 | - python-requests/2.32.3 133 | method: GET 134 | uri: https://api.stlouisfed.org/fred/category/children?category_id=125&file_type=json 135 | response: 136 | body: 137 | string: '{"categories":[]}' 138 | headers: 139 | Cache-Control: 140 | - max-age=0, no-cache 141 | Connection: 142 | - keep-alive 143 | Content-Length: 144 | - '17' 145 | Content-Type: 146 | - application/json; charset=UTF-8 147 | Date: 148 | - Mon, 20 Jan 2025 14:55:49 GMT 149 | Expires: 150 | - Mon, 20 Jan 2025 14:55:49 GMT 151 | Last-Modified: 152 | - Mon, 20 Jan 2025 14:55:49 GMT 153 | Pragma: 154 | - no-cache 155 | Server: 156 | - Apache 157 | Strict-Transport-Security: 158 | - max-age=86400 159 | status: 160 | code: 200 161 | message: OK 162 | version: 1 163 | -------------------------------------------------------------------------------- /tests/vhs/test_category/test_get_category_related.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: null 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate, zstd 9 | Connection: 10 | - keep-alive 11 | User-Agent: 12 | - python-requests/2.32.3 13 | method: GET 14 | uri: https://api.stlouisfed.org/fred/category/related?category_id=125&file_type=json 15 | response: 16 | body: 17 | string: '{"categories":[]}' 18 | headers: 19 | Cache-Control: 20 | - max-age=0, no-cache 21 | Connection: 22 | - keep-alive 23 | Content-Length: 24 | - '17' 25 | Content-Type: 26 | - application/json; charset=UTF-8 27 | Date: 28 | - Sun, 03 Nov 2024 14:33:06 GMT 29 | Expires: 30 | - Sun, 03 Nov 2024 14:33:06 GMT 31 | Last-Modified: 32 | - Sat, 02 Nov 2024 15:53:41 GMT 33 | Pragma: 34 | - no-cache 35 | Server: 36 | - Apache 37 | Strict-Transport-Security: 38 | - max-age=86400 39 | status: 40 | code: 200 41 | message: OK 42 | - request: 43 | body: null 44 | headers: 45 | Accept: 46 | - '*/*' 47 | Accept-Encoding: 48 | - gzip, deflate, zstd 49 | Connection: 50 | - keep-alive 51 | User-Agent: 52 | - python-requests/2.32.3 53 | method: GET 54 | uri: https://api.stlouisfed.org/fred/category/related?category_id=125&file_type=json 55 | response: 56 | body: 57 | string: '{"categories":[]}' 58 | headers: 59 | Cache-Control: 60 | - max-age=0, no-cache 61 | Connection: 62 | - keep-alive 63 | Content-Length: 64 | - '17' 65 | Content-Type: 66 | - application/json; charset=UTF-8 67 | Date: 68 | - Sun, 03 Nov 2024 14:33:06 GMT 69 | Expires: 70 | - Sun, 03 Nov 2024 14:33:06 GMT 71 | Last-Modified: 72 | - Sat, 02 Nov 2024 15:53:41 GMT 73 | Pragma: 74 | - no-cache 75 | Server: 76 | - Apache 77 | Strict-Transport-Security: 78 | - max-age=86400 79 | status: 80 | code: 200 81 | message: OK 82 | - request: 83 | body: null 84 | headers: 85 | Accept: 86 | - '*/*' 87 | Accept-Encoding: 88 | - gzip, deflate, zstd 89 | Connection: 90 | - keep-alive 91 | User-Agent: 92 | - python-requests/2.32.3 93 | method: GET 94 | uri: https://api.stlouisfed.org/fred/category/related?category_id=125&file_type=json 95 | response: 96 | body: 97 | string: '{"categories":[]}' 98 | headers: 99 | Cache-Control: 100 | - max-age=0, no-cache 101 | Connection: 102 | - keep-alive 103 | Content-Length: 104 | - '17' 105 | Content-Type: 106 | - application/json; charset=UTF-8 107 | Date: 108 | - Mon, 20 Jan 2025 14:55:50 GMT 109 | Expires: 110 | - Mon, 20 Jan 2025 14:55:50 GMT 111 | Last-Modified: 112 | - Mon, 20 Jan 2025 14:55:50 GMT 113 | Pragma: 114 | - no-cache 115 | Server: 116 | - Apache 117 | Strict-Transport-Security: 118 | - max-age=86400 119 | status: 120 | code: 200 121 | message: OK 122 | - request: 123 | body: null 124 | headers: 125 | Accept: 126 | - '*/*' 127 | Accept-Encoding: 128 | - gzip, deflate, zstd 129 | Connection: 130 | - keep-alive 131 | User-Agent: 132 | - python-requests/2.32.3 133 | method: GET 134 | uri: https://api.stlouisfed.org/fred/category/related?category_id=125&file_type=json 135 | response: 136 | body: 137 | string: '{"categories":[]}' 138 | headers: 139 | Cache-Control: 140 | - max-age=0, no-cache 141 | Connection: 142 | - keep-alive 143 | Content-Length: 144 | - '17' 145 | Content-Type: 146 | - application/json; charset=UTF-8 147 | Date: 148 | - Mon, 20 Jan 2025 14:55:50 GMT 149 | Expires: 150 | - Mon, 20 Jan 2025 14:55:50 GMT 151 | Last-Modified: 152 | - Mon, 20 Jan 2025 14:55:50 GMT 153 | Pragma: 154 | - no-cache 155 | Server: 156 | - Apache 157 | Strict-Transport-Security: 158 | - max-age=86400 159 | status: 160 | code: 200 161 | message: OK 162 | version: 1 163 | -------------------------------------------------------------------------------- /tests/vhs/test_category/test_get_category_related_tags[pandas].yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: null 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate, zstd 9 | Connection: 10 | - keep-alive 11 | User-Agent: 12 | - python-requests/2.32.3 13 | method: GET 14 | uri: https://api.stlouisfed.org/fred/category/related_tags?category_id=125&file_type=json&tag_names=balance 15 | response: 16 | body: 17 | string: '{"realtime_start":"2024-11-02","realtime_end":"2024-11-02","order_by":"series_count","sort_order":"desc","count":22,"offset":0,"limit":1000,"tags":[{"name":"bea","group_id":"src","notes":"Bureau 18 | of Economic Analysis","created":"2012-02-27 10:18:19-06","popularity":78,"series_count":48},{"name":"nation","group_id":"geot","notes":"","created":"2012-02-27 19 | 10:18:19-06","popularity":96,"series_count":48},{"name":"public domain: citation 20 | requested","group_id":"cc","notes":null,"created":"2018-12-17 23:33:13-06","popularity":99,"series_count":48},{"name":"usa","group_id":"geo","notes":"United 21 | States of America","created":"2012-02-27 10:18:19-06","popularity":100,"series_count":48},{"name":"nsa","group_id":"seas","notes":"Not 22 | Seasonally Adjusted","created":"2012-02-27 10:18:19-06","popularity":100,"series_count":32},{"name":"quarterly","group_id":"freq","notes":"","created":"2012-02-27 23 | 10:18:19-06","popularity":83,"series_count":28},{"name":"annual","group_id":"freq","notes":"","created":"2012-02-27 24 | 10:18:19-06","popularity":92,"series_count":18},{"name":"sa","group_id":"seas","notes":"Seasonally 25 | Adjusted","created":"2012-02-27 10:18:19-06","popularity":86,"series_count":16},{"name":"bop","group_id":"gen","notes":"Balance 26 | of Payments","created":"2013-01-28 14:10:13-06","popularity":45,"series_count":14},{"name":"goods","group_id":"gen","notes":"","created":"2012-02-27 27 | 10:18:19-06","popularity":67,"series_count":14},{"name":"services","group_id":"gen","notes":"","created":"2012-02-27 28 | 10:18:19-06","popularity":68,"series_count":14},{"name":"discontinued","group_id":"gen","notes":"","created":"2012-02-27 29 | 10:18:19-06","popularity":65,"series_count":12},{"name":"income","group_id":"gen","notes":"","created":"2012-02-27 30 | 10:18:19-06","popularity":70,"series_count":12},{"name":"capital account","group_id":"gen","notes":"","created":"2012-02-27 31 | 10:18:19-06","popularity":24,"series_count":6},{"name":"current account","group_id":"gen","notes":"","created":"2012-02-27 32 | 10:18:19-06","popularity":36,"series_count":6},{"name":"secondary","group_id":"gen","notes":"","created":"2012-02-27 33 | 10:18:19-06","popularity":45,"series_count":6},{"name":"trade","group_id":"gen","notes":"","created":"2012-02-27 34 | 10:18:19-06","popularity":54,"series_count":6},{"name":"merchandise","group_id":"gen","notes":"","created":"2013-11-13 35 | 16:08:31-06","popularity":22,"series_count":4},{"name":"primary","group_id":"gen","notes":"","created":"2012-02-27 36 | 10:18:19-06","popularity":47,"series_count":4},{"name":"census","group_id":"src","notes":"Census","created":"2012-02-27 37 | 10:18:19-06","popularity":86,"series_count":2},{"name":"investment","group_id":"gen","notes":"","created":"2012-02-27 38 | 10:18:19-06","popularity":54,"series_count":2},{"name":"monthly","group_id":"freq","notes":"","created":"2012-02-27 39 | 10:18:19-06","popularity":92,"series_count":2}]}' 40 | headers: 41 | Cache-Control: 42 | - max-age=0, no-cache 43 | Connection: 44 | - keep-alive 45 | Content-Encoding: 46 | - gzip 47 | Content-Length: 48 | - '805' 49 | Content-Type: 50 | - application/json; charset=UTF-8 51 | Date: 52 | - Sun, 03 Nov 2024 14:33:11 GMT 53 | Expires: 54 | - Sun, 03 Nov 2024 14:33:11 GMT 55 | Last-Modified: 56 | - Sat, 02 Nov 2024 15:53:45 GMT 57 | Pragma: 58 | - no-cache 59 | Server: 60 | - Apache 61 | Strict-Transport-Security: 62 | - max-age=86400 63 | Vary: 64 | - Accept-Encoding 65 | status: 66 | code: 200 67 | message: OK 68 | - request: 69 | body: null 70 | headers: 71 | Accept: 72 | - '*/*' 73 | Accept-Encoding: 74 | - gzip, deflate, zstd 75 | Connection: 76 | - keep-alive 77 | User-Agent: 78 | - python-requests/2.32.3 79 | method: GET 80 | uri: https://api.stlouisfed.org/fred/category/related_tags?category_id=125&file_type=json&tag_names=balance 81 | response: 82 | body: 83 | string: '{"realtime_start":"2025-01-20","realtime_end":"2025-01-20","order_by":"series_count","sort_order":"desc","count":22,"offset":0,"limit":1000,"tags":[{"name":"nation","group_id":"geot","notes":"","created":"2012-02-27 84 | 10:18:19-06","popularity":96,"series_count":32},{"name":"public domain: citation 85 | requested","group_id":"cc","notes":null,"created":"2018-12-17 23:33:13-06","popularity":99,"series_count":32},{"name":"usa","group_id":"geo","notes":"United 86 | States of America","created":"2012-02-27 10:18:19-06","popularity":100,"series_count":32},{"name":"bea","group_id":"src","notes":"Bureau 87 | of Economic Analysis","created":"2012-02-27 10:18:19-06","popularity":78,"series_count":30},{"name":"nsa","group_id":"seas","notes":"Not 88 | Seasonally Adjusted","created":"2012-02-27 10:18:19-06","popularity":100,"series_count":24},{"name":"quarterly","group_id":"freq","notes":"","created":"2012-02-27 89 | 10:18:19-06","popularity":83,"series_count":16},{"name":"annual","group_id":"freq","notes":"","created":"2012-02-27 90 | 10:18:19-06","popularity":92,"series_count":12},{"name":"discontinued","group_id":"gen","notes":"","created":"2012-02-27 91 | 10:18:19-06","popularity":65,"series_count":12},{"name":"services","group_id":"gen","notes":"","created":"2012-02-27 92 | 10:18:19-06","popularity":68,"series_count":12},{"name":"income","group_id":"gen","notes":"","created":"2012-02-27 93 | 10:18:19-06","popularity":70,"series_count":10},{"name":"sa","group_id":"seas","notes":"Seasonally 94 | Adjusted","created":"2012-02-27 10:18:19-06","popularity":86,"series_count":8},{"name":"goods","group_id":"gen","notes":"","created":"2012-02-27 95 | 10:18:19-06","popularity":67,"series_count":6},{"name":"secondary","group_id":"gen","notes":"","created":"2012-02-27 96 | 10:18:19-06","popularity":45,"series_count":6},{"name":"trade","group_id":"gen","notes":"","created":"2012-02-27 97 | 10:18:19-06","popularity":54,"series_count":6},{"name":"bop","group_id":"gen","notes":"Balance 98 | of Payments","created":"2013-01-28 14:10:13-06","popularity":45,"series_count":4},{"name":"census","group_id":"src","notes":"Census","created":"2012-02-27 99 | 10:18:19-06","popularity":86,"series_count":4},{"name":"current account","group_id":"gen","notes":"","created":"2012-02-27 100 | 10:18:19-06","popularity":36,"series_count":4},{"name":"monthly","group_id":"freq","notes":"","created":"2012-02-27 101 | 10:18:19-06","popularity":92,"series_count":4},{"name":"investment","group_id":"gen","notes":"","created":"2012-02-27 102 | 10:18:19-06","popularity":54,"series_count":2},{"name":"merchandise","group_id":"gen","notes":"","created":"2013-11-13 103 | 16:08:31-06","popularity":22,"series_count":2},{"name":"payments","group_id":"gen","notes":"","created":"2012-02-27 104 | 10:18:19-06","popularity":39,"series_count":2},{"name":"primary","group_id":"gen","notes":"","created":"2012-02-27 105 | 10:18:19-06","popularity":47,"series_count":2}]}' 106 | headers: 107 | Cache-Control: 108 | - max-age=0, no-cache 109 | Connection: 110 | - keep-alive 111 | Content-Encoding: 112 | - gzip 113 | Content-Length: 114 | - '804' 115 | Content-Type: 116 | - application/json; charset=UTF-8 117 | Date: 118 | - Mon, 20 Jan 2025 14:55:54 GMT 119 | Expires: 120 | - Mon, 20 Jan 2025 14:55:54 GMT 121 | Last-Modified: 122 | - Mon, 20 Jan 2025 14:55:53 GMT 123 | Pragma: 124 | - no-cache 125 | Server: 126 | - Apache 127 | Strict-Transport-Security: 128 | - max-age=86400 129 | Vary: 130 | - Accept-Encoding 131 | status: 132 | code: 200 133 | message: OK 134 | version: 1 135 | -------------------------------------------------------------------------------- /tests/vhs/test_category/test_get_category_tags[pandas].yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: null 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate, zstd 9 | Connection: 10 | - keep-alive 11 | User-Agent: 12 | - python-requests/2.32.3 13 | method: GET 14 | uri: https://api.stlouisfed.org/fred/category/tags?category_id=125&file_type=json 15 | response: 16 | body: 17 | string: '{"realtime_start":"2024-11-02","realtime_end":"2024-11-02","order_by":"series_count","sort_order":"desc","count":24,"offset":0,"limit":1000,"tags":[{"name":"bea","group_id":"src","notes":"Bureau 18 | of Economic Analysis","created":"2012-02-27 10:18:19-06","popularity":78,"series_count":54},{"name":"nation","group_id":"geot","notes":"","created":"2012-02-27 19 | 10:18:19-06","popularity":96,"series_count":54},{"name":"public domain: citation 20 | requested","group_id":"cc","notes":null,"created":"2018-12-17 23:33:13-06","popularity":99,"series_count":54},{"name":"usa","group_id":"geo","notes":"United 21 | States of America","created":"2012-02-27 10:18:19-06","popularity":100,"series_count":54},{"name":"balance","group_id":"gen","notes":"","created":"2012-02-27 22 | 10:18:19-06","popularity":49,"series_count":50},{"name":"quarterly","group_id":"freq","notes":"","created":"2012-02-27 23 | 10:18:19-06","popularity":83,"series_count":34},{"name":"nsa","group_id":"seas","notes":"Not 24 | Seasonally Adjusted","created":"2012-02-27 10:18:19-06","popularity":100,"series_count":32},{"name":"sa","group_id":"seas","notes":"Seasonally 25 | Adjusted","created":"2012-02-27 10:18:19-06","popularity":86,"series_count":22},{"name":"annual","group_id":"freq","notes":"","created":"2012-02-27 26 | 10:18:19-06","popularity":92,"series_count":18},{"name":"discontinued","group_id":"gen","notes":"","created":"2012-02-27 27 | 10:18:19-06","popularity":65,"series_count":18},{"name":"bop","group_id":"gen","notes":"Balance 28 | of Payments","created":"2013-01-28 14:10:13-06","popularity":45,"series_count":16},{"name":"goods","group_id":"gen","notes":"","created":"2012-02-27 29 | 10:18:19-06","popularity":67,"series_count":16},{"name":"services","group_id":"gen","notes":"","created":"2012-02-27 30 | 10:18:19-06","popularity":68,"series_count":16},{"name":"income","group_id":"gen","notes":"","created":"2012-02-27 31 | 10:18:19-06","popularity":70,"series_count":10},{"name":"capital account","group_id":"gen","notes":"","created":"2012-02-27 32 | 10:18:19-06","popularity":24,"series_count":8},{"name":"trade","group_id":"gen","notes":"","created":"2012-02-27 33 | 10:18:19-06","popularity":54,"series_count":8},{"name":"current account","group_id":"gen","notes":"","created":"2012-02-27 34 | 10:18:19-06","popularity":36,"series_count":6},{"name":"merchandise","group_id":"gen","notes":"","created":"2013-11-13 35 | 16:08:31-06","popularity":22,"series_count":6},{"name":"secondary","group_id":"gen","notes":"","created":"2012-02-27 36 | 10:18:19-06","popularity":45,"series_count":6},{"name":"net","group_id":"gen","notes":"","created":"2012-02-27 37 | 10:18:19-06","popularity":60,"series_count":4},{"name":"primary","group_id":"gen","notes":"","created":"2012-02-27 38 | 10:18:19-06","popularity":47,"series_count":4},{"name":"census","group_id":"src","notes":"Census","created":"2012-02-27 39 | 10:18:19-06","popularity":86,"series_count":2},{"name":"monthly","group_id":"freq","notes":"","created":"2012-02-27 40 | 10:18:19-06","popularity":92,"series_count":2},{"name":"transfers","group_id":"gen","notes":"","created":"2012-02-27 41 | 10:18:19-06","popularity":30,"series_count":2}]}' 42 | headers: 43 | Cache-Control: 44 | - max-age=0, no-cache 45 | Connection: 46 | - keep-alive 47 | Content-Encoding: 48 | - gzip 49 | Content-Length: 50 | - '835' 51 | Content-Type: 52 | - application/json; charset=UTF-8 53 | Date: 54 | - Sun, 03 Nov 2024 14:33:09 GMT 55 | Expires: 56 | - Sun, 03 Nov 2024 14:33:09 GMT 57 | Last-Modified: 58 | - Sat, 02 Nov 2024 15:53:43 GMT 59 | Pragma: 60 | - no-cache 61 | Server: 62 | - Apache 63 | Strict-Transport-Security: 64 | - max-age=86400 65 | Vary: 66 | - Accept-Encoding 67 | status: 68 | code: 200 69 | message: OK 70 | - request: 71 | body: null 72 | headers: 73 | Accept: 74 | - '*/*' 75 | Accept-Encoding: 76 | - gzip, deflate, zstd 77 | Connection: 78 | - keep-alive 79 | User-Agent: 80 | - python-requests/2.32.3 81 | method: GET 82 | uri: https://api.stlouisfed.org/fred/category/tags?category_id=125&file_type=json 83 | response: 84 | body: 85 | string: '{"realtime_start":"2025-01-20","realtime_end":"2025-01-20","order_by":"series_count","sort_order":"desc","count":25,"offset":0,"limit":1000,"tags":[{"name":"nation","group_id":"geot","notes":"","created":"2012-02-27 86 | 10:18:19-06","popularity":96,"series_count":50},{"name":"public domain: citation 87 | requested","group_id":"cc","notes":null,"created":"2018-12-17 23:33:13-06","popularity":99,"series_count":50},{"name":"usa","group_id":"geo","notes":"United 88 | States of America","created":"2012-02-27 10:18:19-06","popularity":100,"series_count":50},{"name":"bea","group_id":"src","notes":"Bureau 89 | of Economic Analysis","created":"2012-02-27 10:18:19-06","popularity":78,"series_count":48},{"name":"balance","group_id":"gen","notes":"","created":"2012-02-27 90 | 10:18:19-06","popularity":49,"series_count":46},{"name":"quarterly","group_id":"freq","notes":"","created":"2012-02-27 91 | 10:18:19-06","popularity":83,"series_count":32},{"name":"nsa","group_id":"seas","notes":"Not 92 | Seasonally Adjusted","created":"2012-02-27 10:18:19-06","popularity":100,"series_count":30},{"name":"discontinued","group_id":"gen","notes":"","created":"2012-02-27 93 | 10:18:19-06","popularity":65,"series_count":22},{"name":"goods","group_id":"gen","notes":"","created":"2012-02-27 94 | 10:18:19-06","popularity":67,"series_count":20},{"name":"sa","group_id":"seas","notes":"Seasonally 95 | Adjusted","created":"2012-02-27 10:18:19-06","popularity":86,"series_count":20},{"name":"bop","group_id":"gen","notes":"Balance 96 | of Payments","created":"2013-01-28 14:10:13-06","popularity":45,"series_count":16},{"name":"services","group_id":"gen","notes":"","created":"2012-02-27 97 | 10:18:19-06","popularity":68,"series_count":16},{"name":"annual","group_id":"freq","notes":"","created":"2012-02-27 98 | 10:18:19-06","popularity":92,"series_count":14},{"name":"current account","group_id":"gen","notes":"","created":"2012-02-27 99 | 10:18:19-06","popularity":36,"series_count":8},{"name":"trade","group_id":"gen","notes":"","created":"2012-02-27 100 | 10:18:19-06","popularity":54,"series_count":8},{"name":"capital account","group_id":"gen","notes":"","created":"2012-02-27 101 | 10:18:19-06","popularity":24,"series_count":6},{"name":"income","group_id":"gen","notes":"","created":"2012-02-27 102 | 10:18:19-06","popularity":70,"series_count":6},{"name":"census","group_id":"src","notes":"Census","created":"2012-02-27 103 | 10:18:19-06","popularity":86,"series_count":4},{"name":"investment","group_id":"gen","notes":"","created":"2012-02-27 104 | 10:18:19-06","popularity":54,"series_count":4},{"name":"merchandise","group_id":"gen","notes":"","created":"2013-11-13 105 | 16:08:31-06","popularity":22,"series_count":4},{"name":"monthly","group_id":"freq","notes":"","created":"2012-02-27 106 | 10:18:19-06","popularity":92,"series_count":4},{"name":"net","group_id":"gen","notes":"","created":"2012-02-27 107 | 10:18:19-06","popularity":60,"series_count":4},{"name":"headline figure","group_id":"gen","notes":"","created":"2013-11-19 108 | 13:55:53-06","popularity":50,"series_count":2},{"name":"primary","group_id":"gen","notes":"","created":"2012-02-27 109 | 10:18:19-06","popularity":47,"series_count":2},{"name":"transfers","group_id":"gen","notes":"","created":"2012-02-27 110 | 10:18:19-06","popularity":30,"series_count":2}]}' 111 | headers: 112 | Cache-Control: 113 | - max-age=0, no-cache 114 | Connection: 115 | - keep-alive 116 | Content-Encoding: 117 | - gzip 118 | Content-Length: 119 | - '882' 120 | Content-Type: 121 | - application/json; charset=UTF-8 122 | Date: 123 | - Mon, 20 Jan 2025 14:55:53 GMT 124 | Expires: 125 | - Mon, 20 Jan 2025 14:55:53 GMT 126 | Last-Modified: 127 | - Mon, 20 Jan 2025 14:55:52 GMT 128 | Pragma: 129 | - no-cache 130 | Server: 131 | - Apache 132 | Strict-Transport-Security: 133 | - max-age=86400 134 | Vary: 135 | - Accept-Encoding 136 | status: 137 | code: 200 138 | message: OK 139 | version: 1 140 | -------------------------------------------------------------------------------- /tests/vhs/test_maps/test_get_geoseries_info.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: null 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate, zstd 9 | Connection: 10 | - keep-alive 11 | User-Agent: 12 | - python-requests/2.32.3 13 | method: GET 14 | uri: https://api.stlouisfed.org/geofred//series/group?file_type=json&series_id=WIPCPI 15 | response: 16 | body: 17 | string: '{"series_group":{"title":"Per Capita Personal Income","region_type":"state","series_group":"882","season":"NSA","units":"Dollars","frequency":"Annual","min_date":"1929-01-01","max_date":"2023-01-01"}}' 18 | headers: 19 | Cache-Control: 20 | - max-age=0, no-cache 21 | Connection: 22 | - keep-alive 23 | Content-Encoding: 24 | - gzip 25 | Content-Length: 26 | - '190' 27 | Content-Type: 28 | - application/json; charset=UTF-8 29 | Date: 30 | - Sun, 03 Nov 2024 14:33:12 GMT 31 | Expires: 32 | - Sun, 03 Nov 2024 14:33:12 GMT 33 | Last-Modified: 34 | - Sat, 02 Nov 2024 15:53:47 GMT 35 | Pragma: 36 | - no-cache 37 | Server: 38 | - Apache 39 | Strict-Transport-Security: 40 | - max-age=86400 41 | Vary: 42 | - Accept-Encoding 43 | status: 44 | code: 200 45 | message: OK 46 | - request: 47 | body: null 48 | headers: 49 | Accept: 50 | - '*/*' 51 | Accept-Encoding: 52 | - gzip, deflate, zstd 53 | Connection: 54 | - keep-alive 55 | User-Agent: 56 | - python-requests/2.32.3 57 | method: GET 58 | uri: https://api.stlouisfed.org/geofred//series/group?file_type=json&series_id=WIPCPI 59 | response: 60 | body: 61 | string: '{"series_group":{"title":"Per Capita Personal Income","region_type":"state","series_group":"882","season":"NSA","units":"Dollars","frequency":"Annual","min_date":"1929-01-01","max_date":"2023-01-01"}}' 62 | headers: 63 | Cache-Control: 64 | - max-age=0, no-cache 65 | Connection: 66 | - keep-alive 67 | Content-Encoding: 68 | - gzip 69 | Content-Length: 70 | - '190' 71 | Content-Type: 72 | - application/json; charset=UTF-8 73 | Date: 74 | - Sun, 03 Nov 2024 14:33:12 GMT 75 | Expires: 76 | - Sun, 03 Nov 2024 14:33:12 GMT 77 | Last-Modified: 78 | - Sat, 02 Nov 2024 15:53:47 GMT 79 | Pragma: 80 | - no-cache 81 | Server: 82 | - Apache 83 | Strict-Transport-Security: 84 | - max-age=86400 85 | Vary: 86 | - Accept-Encoding 87 | status: 88 | code: 200 89 | message: OK 90 | - request: 91 | body: null 92 | headers: 93 | Accept: 94 | - '*/*' 95 | Accept-Encoding: 96 | - gzip, deflate, zstd 97 | Connection: 98 | - keep-alive 99 | User-Agent: 100 | - python-requests/2.32.3 101 | method: GET 102 | uri: https://api.stlouisfed.org/geofred//series/group?file_type=json&series_id=WIPCPI 103 | response: 104 | body: 105 | string: '{"series_group":{"title":"Per Capita Personal Income","region_type":"state","series_group":"882","season":"NSA","units":"Dollars","frequency":"Annual","min_date":"1929-01-01","max_date":"2023-01-01"}}' 106 | headers: 107 | Cache-Control: 108 | - max-age=0, no-cache 109 | Connection: 110 | - keep-alive 111 | Content-Encoding: 112 | - gzip 113 | Content-Length: 114 | - '190' 115 | Content-Type: 116 | - application/json; charset=UTF-8 117 | Date: 118 | - Mon, 20 Jan 2025 14:55:55 GMT 119 | Expires: 120 | - Mon, 20 Jan 2025 14:55:55 GMT 121 | Last-Modified: 122 | - Mon, 20 Jan 2025 14:55:55 GMT 123 | Pragma: 124 | - no-cache 125 | Server: 126 | - Apache 127 | Strict-Transport-Security: 128 | - max-age=86400 129 | Vary: 130 | - Accept-Encoding 131 | status: 132 | code: 200 133 | message: OK 134 | - request: 135 | body: null 136 | headers: 137 | Accept: 138 | - '*/*' 139 | Accept-Encoding: 140 | - gzip, deflate, zstd 141 | Connection: 142 | - keep-alive 143 | User-Agent: 144 | - python-requests/2.32.3 145 | method: GET 146 | uri: https://api.stlouisfed.org/geofred//series/group?file_type=json&series_id=WIPCPI 147 | response: 148 | body: 149 | string: '{"series_group":{"title":"Per Capita Personal Income","region_type":"state","series_group":"882","season":"NSA","units":"Dollars","frequency":"Annual","min_date":"1929-01-01","max_date":"2023-01-01"}}' 150 | headers: 151 | Cache-Control: 152 | - max-age=0, no-cache 153 | Connection: 154 | - keep-alive 155 | Content-Encoding: 156 | - gzip 157 | Content-Length: 158 | - '190' 159 | Content-Type: 160 | - application/json; charset=UTF-8 161 | Date: 162 | - Mon, 20 Jan 2025 14:55:55 GMT 163 | Expires: 164 | - Mon, 20 Jan 2025 14:55:55 GMT 165 | Last-Modified: 166 | - Mon, 20 Jan 2025 14:55:55 GMT 167 | Pragma: 168 | - no-cache 169 | Server: 170 | - Apache 171 | Strict-Transport-Security: 172 | - max-age=86400 173 | Vary: 174 | - Accept-Encoding 175 | status: 176 | code: 200 177 | message: OK 178 | version: 1 179 | -------------------------------------------------------------------------------- /tests/vhs/test_release/test_get_release.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: null 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate, zstd 9 | Connection: 10 | - keep-alive 11 | User-Agent: 12 | - python-requests/2.32.3 13 | method: GET 14 | uri: https://api.stlouisfed.org/fred/release?file_type=json&release_id=10 15 | response: 16 | body: 17 | string: '{"realtime_start":"2024-11-02","realtime_end":"2024-11-02","releases":[{"id":10,"realtime_start":"2024-11-02","realtime_end":"2024-11-02","name":"Consumer 18 | Price Index","press_release":true,"link":"http:\/\/www.bls.gov\/cpi\/"}]}' 19 | headers: 20 | Cache-Control: 21 | - max-age=0, no-cache 22 | Connection: 23 | - keep-alive 24 | Content-Encoding: 25 | - gzip 26 | Content-Length: 27 | - '167' 28 | Content-Type: 29 | - application/json; charset=UTF-8 30 | Date: 31 | - Sun, 03 Nov 2024 14:33:20 GMT 32 | Expires: 33 | - Sun, 03 Nov 2024 14:33:20 GMT 34 | Last-Modified: 35 | - Sat, 02 Nov 2024 15:54:25 GMT 36 | Pragma: 37 | - no-cache 38 | Server: 39 | - Apache 40 | Strict-Transport-Security: 41 | - max-age=86400 42 | Vary: 43 | - Accept-Encoding 44 | status: 45 | code: 200 46 | message: OK 47 | - request: 48 | body: null 49 | headers: 50 | Accept: 51 | - '*/*' 52 | Accept-Encoding: 53 | - gzip, deflate, zstd 54 | Connection: 55 | - keep-alive 56 | User-Agent: 57 | - python-requests/2.32.3 58 | method: GET 59 | uri: https://api.stlouisfed.org/fred/release?file_type=json&release_id=10 60 | response: 61 | body: 62 | string: '{"realtime_start":"2024-11-02","realtime_end":"2024-11-02","releases":[{"id":10,"realtime_start":"2024-11-02","realtime_end":"2024-11-02","name":"Consumer 63 | Price Index","press_release":true,"link":"http:\/\/www.bls.gov\/cpi\/"}]}' 64 | headers: 65 | Cache-Control: 66 | - max-age=0, no-cache 67 | Connection: 68 | - keep-alive 69 | Content-Encoding: 70 | - gzip 71 | Content-Length: 72 | - '167' 73 | Content-Type: 74 | - application/json; charset=UTF-8 75 | Date: 76 | - Sun, 03 Nov 2024 14:33:21 GMT 77 | Expires: 78 | - Sun, 03 Nov 2024 14:33:21 GMT 79 | Last-Modified: 80 | - Sat, 02 Nov 2024 15:54:25 GMT 81 | Pragma: 82 | - no-cache 83 | Server: 84 | - Apache 85 | Strict-Transport-Security: 86 | - max-age=86400 87 | Vary: 88 | - Accept-Encoding 89 | status: 90 | code: 200 91 | message: OK 92 | - request: 93 | body: null 94 | headers: 95 | Accept: 96 | - '*/*' 97 | Accept-Encoding: 98 | - gzip, deflate, zstd 99 | Connection: 100 | - keep-alive 101 | User-Agent: 102 | - python-requests/2.32.3 103 | method: GET 104 | uri: https://api.stlouisfed.org/fred/release?file_type=json&release_id=10 105 | response: 106 | body: 107 | string: '{"realtime_start":"2025-01-20","realtime_end":"2025-01-20","releases":[{"id":10,"realtime_start":"2025-01-20","realtime_end":"2025-01-20","name":"Consumer 108 | Price Index","press_release":true,"link":"http:\/\/www.bls.gov\/cpi\/"}]}' 109 | headers: 110 | Cache-Control: 111 | - max-age=0, no-cache 112 | Connection: 113 | - keep-alive 114 | Content-Encoding: 115 | - gzip 116 | Content-Length: 117 | - '167' 118 | Content-Type: 119 | - application/json; charset=UTF-8 120 | Date: 121 | - Mon, 20 Jan 2025 14:56:01 GMT 122 | Expires: 123 | - Mon, 20 Jan 2025 14:56:01 GMT 124 | Last-Modified: 125 | - Mon, 20 Jan 2025 14:56:01 GMT 126 | Pragma: 127 | - no-cache 128 | Server: 129 | - Apache 130 | Strict-Transport-Security: 131 | - max-age=86400 132 | Vary: 133 | - Accept-Encoding 134 | status: 135 | code: 200 136 | message: OK 137 | - request: 138 | body: null 139 | headers: 140 | Accept: 141 | - '*/*' 142 | Accept-Encoding: 143 | - gzip, deflate, zstd 144 | Connection: 145 | - keep-alive 146 | User-Agent: 147 | - python-requests/2.32.3 148 | method: GET 149 | uri: https://api.stlouisfed.org/fred/release?file_type=json&release_id=10 150 | response: 151 | body: 152 | string: '{"realtime_start":"2025-01-20","realtime_end":"2025-01-20","releases":[{"id":10,"realtime_start":"2025-01-20","realtime_end":"2025-01-20","name":"Consumer 153 | Price Index","press_release":true,"link":"http:\/\/www.bls.gov\/cpi\/"}]}' 154 | headers: 155 | Cache-Control: 156 | - max-age=0, no-cache 157 | Connection: 158 | - keep-alive 159 | Content-Encoding: 160 | - gzip 161 | Content-Length: 162 | - '167' 163 | Content-Type: 164 | - application/json; charset=UTF-8 165 | Date: 166 | - Mon, 20 Jan 2025 14:56:01 GMT 167 | Expires: 168 | - Mon, 20 Jan 2025 14:56:01 GMT 169 | Last-Modified: 170 | - Mon, 20 Jan 2025 14:56:01 GMT 171 | Pragma: 172 | - no-cache 173 | Server: 174 | - Apache 175 | Strict-Transport-Security: 176 | - max-age=86400 177 | Vary: 178 | - Accept-Encoding 179 | status: 180 | code: 200 181 | message: OK 182 | version: 1 183 | -------------------------------------------------------------------------------- /tests/vhs/test_release/test_get_release_related_tags.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: null 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate, zstd 9 | Connection: 10 | - keep-alive 11 | User-Agent: 12 | - python-requests/2.32.3 13 | method: GET 14 | uri: https://api.stlouisfed.org/fred/release/related_tags?file_type=json&release_id=10&tag_names=sa%3Bforeign 15 | response: 16 | body: 17 | string: '{"realtime_start":"2024-11-02","realtime_end":"2024-11-02","order_by":"series_count","sort_order":"desc","count":0,"offset":0,"limit":1000,"tags":[]}' 18 | headers: 19 | Cache-Control: 20 | - max-age=0, no-cache 21 | Connection: 22 | - keep-alive 23 | Content-Encoding: 24 | - gzip 25 | Content-Length: 26 | - '138' 27 | Content-Type: 28 | - application/json; charset=UTF-8 29 | Date: 30 | - Sun, 03 Nov 2024 14:33:25 GMT 31 | Expires: 32 | - Sun, 03 Nov 2024 14:33:25 GMT 33 | Last-Modified: 34 | - Sat, 02 Nov 2024 15:54:30 GMT 35 | Pragma: 36 | - no-cache 37 | Server: 38 | - Apache 39 | Strict-Transport-Security: 40 | - max-age=86400 41 | Vary: 42 | - Accept-Encoding 43 | status: 44 | code: 200 45 | message: OK 46 | - request: 47 | body: null 48 | headers: 49 | Accept: 50 | - '*/*' 51 | Accept-Encoding: 52 | - gzip, deflate, zstd 53 | Connection: 54 | - keep-alive 55 | User-Agent: 56 | - python-requests/2.32.3 57 | method: GET 58 | uri: https://api.stlouisfed.org/fred/release/related_tags?file_type=json&release_id=10&tag_names=sa%3Bforeign 59 | response: 60 | body: 61 | string: '{"realtime_start":"2024-11-02","realtime_end":"2024-11-02","order_by":"series_count","sort_order":"desc","count":0,"offset":0,"limit":1000,"tags":[]}' 62 | headers: 63 | Cache-Control: 64 | - max-age=0, no-cache 65 | Connection: 66 | - keep-alive 67 | Content-Encoding: 68 | - gzip 69 | Content-Length: 70 | - '138' 71 | Content-Type: 72 | - application/json; charset=UTF-8 73 | Date: 74 | - Sun, 03 Nov 2024 14:33:26 GMT 75 | Expires: 76 | - Sun, 03 Nov 2024 14:33:26 GMT 77 | Last-Modified: 78 | - Sat, 02 Nov 2024 15:54:30 GMT 79 | Pragma: 80 | - no-cache 81 | Server: 82 | - Apache 83 | Strict-Transport-Security: 84 | - max-age=86400 85 | Vary: 86 | - Accept-Encoding 87 | status: 88 | code: 200 89 | message: OK 90 | - request: 91 | body: null 92 | headers: 93 | Accept: 94 | - '*/*' 95 | Accept-Encoding: 96 | - gzip, deflate, zstd 97 | Connection: 98 | - keep-alive 99 | User-Agent: 100 | - python-requests/2.32.3 101 | method: GET 102 | uri: https://api.stlouisfed.org/fred/release/related_tags?file_type=json&release_id=10&tag_names=sa%3Bforeign 103 | response: 104 | body: 105 | string: '{"realtime_start":"2025-01-20","realtime_end":"2025-01-20","order_by":"series_count","sort_order":"desc","count":0,"offset":0,"limit":1000,"tags":[]}' 106 | headers: 107 | Cache-Control: 108 | - max-age=0, no-cache 109 | Connection: 110 | - keep-alive 111 | Content-Encoding: 112 | - gzip 113 | Content-Length: 114 | - '138' 115 | Content-Type: 116 | - application/json; charset=UTF-8 117 | Date: 118 | - Mon, 20 Jan 2025 14:56:06 GMT 119 | Expires: 120 | - Mon, 20 Jan 2025 14:56:06 GMT 121 | Last-Modified: 122 | - Mon, 20 Jan 2025 14:56:06 GMT 123 | Pragma: 124 | - no-cache 125 | Server: 126 | - Apache 127 | Strict-Transport-Security: 128 | - max-age=86400 129 | Vary: 130 | - Accept-Encoding 131 | status: 132 | code: 200 133 | message: OK 134 | - request: 135 | body: null 136 | headers: 137 | Accept: 138 | - '*/*' 139 | Accept-Encoding: 140 | - gzip, deflate, zstd 141 | Connection: 142 | - keep-alive 143 | User-Agent: 144 | - python-requests/2.32.3 145 | method: GET 146 | uri: https://api.stlouisfed.org/fred/release/related_tags?file_type=json&release_id=10&tag_names=sa%3Bforeign 147 | response: 148 | body: 149 | string: '{"realtime_start":"2025-01-20","realtime_end":"2025-01-20","order_by":"series_count","sort_order":"desc","count":0,"offset":0,"limit":1000,"tags":[]}' 150 | headers: 151 | Cache-Control: 152 | - max-age=0, no-cache 153 | Connection: 154 | - keep-alive 155 | Content-Encoding: 156 | - gzip 157 | Content-Length: 158 | - '138' 159 | Content-Type: 160 | - application/json; charset=UTF-8 161 | Date: 162 | - Mon, 20 Jan 2025 14:56:06 GMT 163 | Expires: 164 | - Mon, 20 Jan 2025 14:56:06 GMT 165 | Last-Modified: 166 | - Mon, 20 Jan 2025 14:56:06 GMT 167 | Pragma: 168 | - no-cache 169 | Server: 170 | - Apache 171 | Strict-Transport-Security: 172 | - max-age=86400 173 | Vary: 174 | - Accept-Encoding 175 | status: 176 | code: 200 177 | message: OK 178 | version: 1 179 | -------------------------------------------------------------------------------- /tests/vhs/test_release/test_get_release_sources.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: null 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate, zstd 9 | Connection: 10 | - keep-alive 11 | User-Agent: 12 | - python-requests/2.32.3 13 | method: GET 14 | uri: https://api.stlouisfed.org/fred/release/sources?file_type=json&release_id=10 15 | response: 16 | body: 17 | string: '{"realtime_start":"2024-11-02","realtime_end":"2024-11-02","sources":[{"id":22,"realtime_start":"2024-11-02","realtime_end":"2024-11-02","name":"U.S. 18 | Bureau of Labor Statistics","link":"https:\/\/www.bls.gov\/"}]}' 19 | headers: 20 | Cache-Control: 21 | - max-age=0, no-cache 22 | Connection: 23 | - keep-alive 24 | Content-Encoding: 25 | - gzip 26 | Content-Length: 27 | - '156' 28 | Content-Type: 29 | - application/json; charset=UTF-8 30 | Date: 31 | - Sun, 03 Nov 2024 14:33:23 GMT 32 | Expires: 33 | - Sun, 03 Nov 2024 14:33:23 GMT 34 | Last-Modified: 35 | - Sun, 03 Nov 2024 00:33:00 GMT 36 | Pragma: 37 | - no-cache 38 | Server: 39 | - Apache 40 | Strict-Transport-Security: 41 | - max-age=86400 42 | Vary: 43 | - Accept-Encoding 44 | status: 45 | code: 200 46 | message: OK 47 | - request: 48 | body: null 49 | headers: 50 | Accept: 51 | - '*/*' 52 | Accept-Encoding: 53 | - gzip, deflate, zstd 54 | Connection: 55 | - keep-alive 56 | User-Agent: 57 | - python-requests/2.32.3 58 | method: GET 59 | uri: https://api.stlouisfed.org/fred/release/sources?file_type=json&release_id=10 60 | response: 61 | body: 62 | string: '{"realtime_start":"2024-11-02","realtime_end":"2024-11-02","sources":[{"id":22,"realtime_start":"2024-11-02","realtime_end":"2024-11-02","name":"U.S. 63 | Bureau of Labor Statistics","link":"https:\/\/www.bls.gov\/"}]}' 64 | headers: 65 | Cache-Control: 66 | - max-age=0, no-cache 67 | Connection: 68 | - keep-alive 69 | Content-Encoding: 70 | - gzip 71 | Content-Length: 72 | - '156' 73 | Content-Type: 74 | - application/json; charset=UTF-8 75 | Date: 76 | - Sun, 03 Nov 2024 14:33:24 GMT 77 | Expires: 78 | - Sun, 03 Nov 2024 14:33:24 GMT 79 | Last-Modified: 80 | - Sun, 03 Nov 2024 00:33:00 GMT 81 | Pragma: 82 | - no-cache 83 | Server: 84 | - Apache 85 | Strict-Transport-Security: 86 | - max-age=86400 87 | Vary: 88 | - Accept-Encoding 89 | status: 90 | code: 200 91 | message: OK 92 | - request: 93 | body: null 94 | headers: 95 | Accept: 96 | - '*/*' 97 | Accept-Encoding: 98 | - gzip, deflate, zstd 99 | Connection: 100 | - keep-alive 101 | User-Agent: 102 | - python-requests/2.32.3 103 | method: GET 104 | uri: https://api.stlouisfed.org/fred/release/sources?file_type=json&release_id=10 105 | response: 106 | body: 107 | string: '{"realtime_start":"2025-01-20","realtime_end":"2025-01-20","sources":[{"id":22,"realtime_start":"2025-01-20","realtime_end":"2025-01-20","name":"U.S. 108 | Bureau of Labor Statistics","link":"https:\/\/www.bls.gov\/"}]}' 109 | headers: 110 | Cache-Control: 111 | - max-age=0, no-cache 112 | Connection: 113 | - keep-alive 114 | Content-Encoding: 115 | - gzip 116 | Content-Length: 117 | - '156' 118 | Content-Type: 119 | - application/json; charset=UTF-8 120 | Date: 121 | - Mon, 20 Jan 2025 14:56:04 GMT 122 | Expires: 123 | - Mon, 20 Jan 2025 14:56:04 GMT 124 | Last-Modified: 125 | - Mon, 20 Jan 2025 14:56:04 GMT 126 | Pragma: 127 | - no-cache 128 | Server: 129 | - Apache 130 | Strict-Transport-Security: 131 | - max-age=86400 132 | Vary: 133 | - Accept-Encoding 134 | status: 135 | code: 200 136 | message: OK 137 | - request: 138 | body: null 139 | headers: 140 | Accept: 141 | - '*/*' 142 | Accept-Encoding: 143 | - gzip, deflate, zstd 144 | Connection: 145 | - keep-alive 146 | User-Agent: 147 | - python-requests/2.32.3 148 | method: GET 149 | uri: https://api.stlouisfed.org/fred/release/sources?file_type=json&release_id=10 150 | response: 151 | body: 152 | string: '{"realtime_start":"2025-01-20","realtime_end":"2025-01-20","sources":[{"id":22,"realtime_start":"2025-01-20","realtime_end":"2025-01-20","name":"U.S. 153 | Bureau of Labor Statistics","link":"https:\/\/www.bls.gov\/"}]}' 154 | headers: 155 | Cache-Control: 156 | - max-age=0, no-cache 157 | Connection: 158 | - keep-alive 159 | Content-Encoding: 160 | - gzip 161 | Content-Length: 162 | - '156' 163 | Content-Type: 164 | - application/json; charset=UTF-8 165 | Date: 166 | - Mon, 20 Jan 2025 14:56:04 GMT 167 | Expires: 168 | - Mon, 20 Jan 2025 14:56:04 GMT 169 | Last-Modified: 170 | - Mon, 20 Jan 2025 14:56:04 GMT 171 | Pragma: 172 | - no-cache 173 | Server: 174 | - Apache 175 | Strict-Transport-Security: 176 | - max-age=86400 177 | Vary: 178 | - Accept-Encoding 179 | status: 180 | code: 200 181 | message: OK 182 | version: 1 183 | -------------------------------------------------------------------------------- /tests/vhs/test_release/test_get_release_tables.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: null 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate, zstd 9 | Connection: 10 | - keep-alive 11 | User-Agent: 12 | - python-requests/2.32.3 13 | method: GET 14 | uri: https://api.stlouisfed.org/fred/release/tables?file_type=json&release_id=10 15 | response: 16 | body: 17 | string: '{"release_id":"10","elements":{"34481":{"element_id":34481,"release_id":10,"series_id":null,"parent_id":null,"line":null,"type":"section","name":"Consumer 18 | Price Index by Expenditure Category","level":"0","children":[]},"36712":{"element_id":36712,"release_id":10,"series_id":null,"parent_id":null,"line":null,"type":"section","name":"Consumer 19 | Price Index Special Aggregate Indices","level":"0","children":[]}}}' 20 | headers: 21 | Cache-Control: 22 | - max-age=0, no-cache 23 | Connection: 24 | - keep-alive 25 | Content-Encoding: 26 | - gzip 27 | Content-Length: 28 | - '235' 29 | Content-Type: 30 | - application/json; charset=UTF-8 31 | Date: 32 | - Sun, 03 Nov 2024 14:33:27 GMT 33 | Expires: 34 | - Sun, 03 Nov 2024 14:33:27 GMT 35 | Last-Modified: 36 | - Sun, 03 Nov 2024 14:33:26 GMT 37 | Pragma: 38 | - no-cache 39 | Server: 40 | - Apache 41 | Strict-Transport-Security: 42 | - max-age=86400 43 | Vary: 44 | - Accept-Encoding 45 | status: 46 | code: 200 47 | message: OK 48 | - request: 49 | body: null 50 | headers: 51 | Accept: 52 | - '*/*' 53 | Accept-Encoding: 54 | - gzip, deflate, zstd 55 | Connection: 56 | - keep-alive 57 | User-Agent: 58 | - python-requests/2.32.3 59 | method: GET 60 | uri: https://api.stlouisfed.org/fred/release/tables?file_type=json&release_id=10 61 | response: 62 | body: 63 | string: '{"release_id":"10","elements":{"34481":{"element_id":34481,"release_id":10,"series_id":null,"parent_id":null,"line":null,"type":"section","name":"Consumer 64 | Price Index by Expenditure Category","level":"0","children":[]},"36712":{"element_id":36712,"release_id":10,"series_id":null,"parent_id":null,"line":null,"type":"section","name":"Consumer 65 | Price Index Special Aggregate Indices","level":"0","children":[]}}}' 66 | headers: 67 | Cache-Control: 68 | - max-age=0, no-cache 69 | Connection: 70 | - keep-alive 71 | Content-Encoding: 72 | - gzip 73 | Content-Length: 74 | - '235' 75 | Content-Type: 76 | - application/json; charset=UTF-8 77 | Date: 78 | - Sun, 03 Nov 2024 14:33:27 GMT 79 | Expires: 80 | - Sun, 03 Nov 2024 14:33:27 GMT 81 | Last-Modified: 82 | - Sun, 03 Nov 2024 14:33:26 GMT 83 | Pragma: 84 | - no-cache 85 | Server: 86 | - Apache 87 | Strict-Transport-Security: 88 | - max-age=86400 89 | Vary: 90 | - Accept-Encoding 91 | status: 92 | code: 200 93 | message: OK 94 | - request: 95 | body: null 96 | headers: 97 | Accept: 98 | - '*/*' 99 | Accept-Encoding: 100 | - gzip, deflate, zstd 101 | Connection: 102 | - keep-alive 103 | User-Agent: 104 | - python-requests/2.32.3 105 | method: GET 106 | uri: https://api.stlouisfed.org/fred/release/tables?file_type=json&release_id=10 107 | response: 108 | body: 109 | string: '{"release_id":"10","elements":{"34481":{"element_id":34481,"release_id":10,"series_id":null,"parent_id":null,"line":null,"type":"section","name":"Consumer 110 | Price Index by Expenditure Category","level":"0","children":[]},"36712":{"element_id":36712,"release_id":10,"series_id":null,"parent_id":null,"line":null,"type":"section","name":"Consumer 111 | Price Index Special Aggregate Indices","level":"0","children":[]}}}' 112 | headers: 113 | Cache-Control: 114 | - max-age=0, no-cache 115 | Connection: 116 | - keep-alive 117 | Content-Encoding: 118 | - gzip 119 | Content-Length: 120 | - '235' 121 | Content-Type: 122 | - application/json; charset=UTF-8 123 | Date: 124 | - Mon, 20 Jan 2025 14:56:07 GMT 125 | Expires: 126 | - Mon, 20 Jan 2025 14:56:07 GMT 127 | Last-Modified: 128 | - Mon, 20 Jan 2025 14:56:07 GMT 129 | Pragma: 130 | - no-cache 131 | Server: 132 | - Apache 133 | Strict-Transport-Security: 134 | - max-age=86400 135 | Vary: 136 | - Accept-Encoding 137 | status: 138 | code: 200 139 | message: OK 140 | - request: 141 | body: null 142 | headers: 143 | Accept: 144 | - '*/*' 145 | Accept-Encoding: 146 | - gzip, deflate, zstd 147 | Connection: 148 | - keep-alive 149 | User-Agent: 150 | - python-requests/2.32.3 151 | method: GET 152 | uri: https://api.stlouisfed.org/fred/release/tables?file_type=json&release_id=10 153 | response: 154 | body: 155 | string: '{"release_id":"10","elements":{"34481":{"element_id":34481,"release_id":10,"series_id":null,"parent_id":null,"line":null,"type":"section","name":"Consumer 156 | Price Index by Expenditure Category","level":"0","children":[]},"36712":{"element_id":36712,"release_id":10,"series_id":null,"parent_id":null,"line":null,"type":"section","name":"Consumer 157 | Price Index Special Aggregate Indices","level":"0","children":[]}}}' 158 | headers: 159 | Cache-Control: 160 | - max-age=0, no-cache 161 | Connection: 162 | - keep-alive 163 | Content-Encoding: 164 | - gzip 165 | Content-Length: 166 | - '235' 167 | Content-Type: 168 | - application/json; charset=UTF-8 169 | Date: 170 | - Mon, 20 Jan 2025 14:56:07 GMT 171 | Expires: 172 | - Mon, 20 Jan 2025 14:56:07 GMT 173 | Last-Modified: 174 | - Mon, 20 Jan 2025 14:56:07 GMT 175 | Pragma: 176 | - no-cache 177 | Server: 178 | - Apache 179 | Strict-Transport-Security: 180 | - max-age=86400 181 | Vary: 182 | - Accept-Encoding 183 | status: 184 | code: 200 185 | message: OK 186 | version: 1 187 | -------------------------------------------------------------------------------- /tests/vhs/test_series/test_get_series_categories.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: null 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate, zstd 9 | Connection: 10 | - keep-alive 11 | User-Agent: 12 | - python-requests/2.32.3 13 | method: GET 14 | uri: https://api.stlouisfed.org/fred/series/categories?file_type=json&series_id=GDP 15 | response: 16 | body: 17 | string: '{"categories":[{"id":106,"name":"GDP\/GNP","parent_id":18}]}' 18 | headers: 19 | Cache-Control: 20 | - max-age=0, no-cache 21 | Connection: 22 | - keep-alive 23 | Content-Encoding: 24 | - gzip 25 | Content-Length: 26 | - '77' 27 | Content-Type: 28 | - application/json; charset=UTF-8 29 | Date: 30 | - Sun, 03 Nov 2024 14:33:28 GMT 31 | Expires: 32 | - Sun, 03 Nov 2024 14:33:28 GMT 33 | Last-Modified: 34 | - Sat, 02 Nov 2024 15:54:33 GMT 35 | Pragma: 36 | - no-cache 37 | Server: 38 | - Apache 39 | Strict-Transport-Security: 40 | - max-age=86400 41 | Vary: 42 | - Accept-Encoding 43 | status: 44 | code: 200 45 | message: OK 46 | - request: 47 | body: null 48 | headers: 49 | Accept: 50 | - '*/*' 51 | Accept-Encoding: 52 | - gzip, deflate, zstd 53 | Connection: 54 | - keep-alive 55 | User-Agent: 56 | - python-requests/2.32.3 57 | method: GET 58 | uri: https://api.stlouisfed.org/fred/series/categories?file_type=json&series_id=GDP 59 | response: 60 | body: 61 | string: '{"categories":[{"id":106,"name":"GDP\/GNP","parent_id":18}]}' 62 | headers: 63 | Cache-Control: 64 | - max-age=0, no-cache 65 | Connection: 66 | - keep-alive 67 | Content-Encoding: 68 | - gzip 69 | Content-Length: 70 | - '77' 71 | Content-Type: 72 | - application/json; charset=UTF-8 73 | Date: 74 | - Sun, 03 Nov 2024 14:33:29 GMT 75 | Expires: 76 | - Sun, 03 Nov 2024 14:33:29 GMT 77 | Last-Modified: 78 | - Sat, 02 Nov 2024 15:54:33 GMT 79 | Pragma: 80 | - no-cache 81 | Server: 82 | - Apache 83 | Strict-Transport-Security: 84 | - max-age=86400 85 | Vary: 86 | - Accept-Encoding 87 | status: 88 | code: 200 89 | message: OK 90 | - request: 91 | body: null 92 | headers: 93 | Accept: 94 | - '*/*' 95 | Accept-Encoding: 96 | - gzip, deflate, zstd 97 | Connection: 98 | - keep-alive 99 | User-Agent: 100 | - python-requests/2.32.3 101 | method: GET 102 | uri: https://api.stlouisfed.org/fred/series/categories?file_type=json&series_id=GDP 103 | response: 104 | body: 105 | string: '{"categories":[{"id":106,"name":"GDP\/GNP","parent_id":18}]}' 106 | headers: 107 | Cache-Control: 108 | - max-age=0, no-cache 109 | Connection: 110 | - keep-alive 111 | Content-Encoding: 112 | - gzip 113 | Content-Length: 114 | - '77' 115 | Content-Type: 116 | - application/json; charset=UTF-8 117 | Date: 118 | - Mon, 20 Jan 2025 14:56:09 GMT 119 | Expires: 120 | - Mon, 20 Jan 2025 14:56:09 GMT 121 | Last-Modified: 122 | - Mon, 20 Jan 2025 14:56:09 GMT 123 | Pragma: 124 | - no-cache 125 | Server: 126 | - Apache 127 | Strict-Transport-Security: 128 | - max-age=86400 129 | Vary: 130 | - Accept-Encoding 131 | status: 132 | code: 200 133 | message: OK 134 | - request: 135 | body: null 136 | headers: 137 | Accept: 138 | - '*/*' 139 | Accept-Encoding: 140 | - gzip, deflate, zstd 141 | Connection: 142 | - keep-alive 143 | User-Agent: 144 | - python-requests/2.32.3 145 | method: GET 146 | uri: https://api.stlouisfed.org/fred/series/categories?file_type=json&series_id=GDP 147 | response: 148 | body: 149 | string: '{"categories":[{"id":106,"name":"GDP\/GNP","parent_id":18}]}' 150 | headers: 151 | Cache-Control: 152 | - max-age=0, no-cache 153 | Connection: 154 | - keep-alive 155 | Content-Encoding: 156 | - gzip 157 | Content-Length: 158 | - '77' 159 | Content-Type: 160 | - application/json; charset=UTF-8 161 | Date: 162 | - Mon, 20 Jan 2025 14:56:09 GMT 163 | Expires: 164 | - Mon, 20 Jan 2025 14:56:09 GMT 165 | Last-Modified: 166 | - Mon, 20 Jan 2025 14:56:09 GMT 167 | Pragma: 168 | - no-cache 169 | Server: 170 | - Apache 171 | Strict-Transport-Security: 172 | - max-age=86400 173 | Vary: 174 | - Accept-Encoding 175 | status: 176 | code: 200 177 | message: OK 178 | version: 1 179 | -------------------------------------------------------------------------------- /tests/vhs/test_series/test_get_series_info.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: null 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate, zstd 9 | Connection: 10 | - keep-alive 11 | User-Agent: 12 | - python-requests/2.32.3 13 | method: GET 14 | uri: https://api.stlouisfed.org/fred/series?file_type=json&series_id=GDP 15 | response: 16 | body: 17 | string: '{"realtime_start":"2024-10-30","realtime_end":"2024-10-30","seriess":[{"id":"GDP","realtime_start":"2024-10-30","realtime_end":"2024-10-30","title":"Gross 18 | Domestic Product","observation_start":"1947-01-01","observation_end":"2024-07-01","frequency":"Quarterly","frequency_short":"Q","units":"Billions 19 | of Dollars","units_short":"Bil. of $","seasonal_adjustment":"Seasonally Adjusted 20 | Annual Rate","seasonal_adjustment_short":"SAAR","last_updated":"2024-10-30 21 | 07:54:01-05","popularity":93,"notes":"BEA Account Code: A191RC\n\nGross domestic 22 | product (GDP), the featured measure of U.S. output, is the market value of 23 | the goods and services produced by labor and property located in the United 24 | States.For more information, see the Guide to the National Income and Product 25 | Accounts of the United States (NIPA) and the Bureau of Economic Analysis (http:\/\/www.bea.gov\/national\/pdf\/nipaguid.pdf)."}]}' 26 | headers: 27 | Cache-Control: 28 | - max-age=0, no-cache 29 | Connection: 30 | - keep-alive 31 | Content-Encoding: 32 | - gzip 33 | Content-Length: 34 | - '640' 35 | Content-Type: 36 | - application/json; charset=UTF-8 37 | Date: 38 | - Sun, 03 Nov 2024 14:33:28 GMT 39 | Expires: 40 | - Sun, 03 Nov 2024 14:33:28 GMT 41 | Last-Modified: 42 | - Wed, 30 Oct 2024 12:54:01 GMT 43 | Pragma: 44 | - no-cache 45 | Server: 46 | - Apache 47 | Strict-Transport-Security: 48 | - max-age=86400 49 | Vary: 50 | - Accept-Encoding 51 | status: 52 | code: 200 53 | message: OK 54 | - request: 55 | body: null 56 | headers: 57 | Accept: 58 | - '*/*' 59 | Accept-Encoding: 60 | - gzip, deflate, zstd 61 | Connection: 62 | - keep-alive 63 | User-Agent: 64 | - python-requests/2.32.3 65 | method: GET 66 | uri: https://api.stlouisfed.org/fred/series?file_type=json&series_id=GDP 67 | response: 68 | body: 69 | string: '{"realtime_start":"2024-12-19","realtime_end":"2024-12-19","seriess":[{"id":"GDP","realtime_start":"2024-12-19","realtime_end":"2024-12-19","title":"Gross 70 | Domestic Product","observation_start":"1947-01-01","observation_end":"2024-07-01","frequency":"Quarterly","frequency_short":"Q","units":"Billions 71 | of Dollars","units_short":"Bil. of $","seasonal_adjustment":"Seasonally Adjusted 72 | Annual Rate","seasonal_adjustment_short":"SAAR","last_updated":"2024-12-19 73 | 07:55:01-06","popularity":93,"notes":"BEA Account Code: A191RC\n\nGross domestic 74 | product (GDP), the featured measure of U.S. output, is the market value of 75 | the goods and services produced by labor and property located in the United 76 | States.For more information, see the Guide to the National Income and Product 77 | Accounts of the United States (NIPA) and the Bureau of Economic Analysis (http:\/\/www.bea.gov\/national\/pdf\/nipaguid.pdf)."}]}' 78 | headers: 79 | Cache-Control: 80 | - max-age=0, no-cache 81 | Connection: 82 | - keep-alive 83 | Content-Encoding: 84 | - gzip 85 | Content-Length: 86 | - '640' 87 | Content-Type: 88 | - application/json; charset=UTF-8 89 | Date: 90 | - Mon, 20 Jan 2025 14:56:08 GMT 91 | Expires: 92 | - Mon, 20 Jan 2025 14:56:08 GMT 93 | Last-Modified: 94 | - Thu, 19 Dec 2024 13:55:01 GMT 95 | Pragma: 96 | - no-cache 97 | Server: 98 | - Apache 99 | Strict-Transport-Security: 100 | - max-age=86400 101 | Vary: 102 | - Accept-Encoding 103 | status: 104 | code: 200 105 | message: OK 106 | version: 1 107 | -------------------------------------------------------------------------------- /tests/vhs/test_series/test_get_series_releases.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: null 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate, zstd 9 | Connection: 10 | - keep-alive 11 | User-Agent: 12 | - python-requests/2.32.3 13 | method: GET 14 | uri: https://api.stlouisfed.org/fred/series/release?file_type=json&series_id=GDP 15 | response: 16 | body: 17 | string: '{"realtime_start":"2024-11-03","realtime_end":"2024-11-03","releases":[{"id":53,"realtime_start":"2024-11-03","realtime_end":"2024-11-03","name":"Gross 18 | Domestic Product","press_release":true,"link":"https:\/\/www.bea.gov\/data\/gdp\/gross-domestic-product"}]}' 19 | headers: 20 | Cache-Control: 21 | - max-age=0, no-cache 22 | Connection: 23 | - keep-alive 24 | Content-Encoding: 25 | - gzip 26 | Content-Length: 27 | - '186' 28 | Content-Type: 29 | - application/json; charset=UTF-8 30 | Date: 31 | - Sun, 03 Nov 2024 14:33:32 GMT 32 | Expires: 33 | - Sun, 03 Nov 2024 14:33:32 GMT 34 | Last-Modified: 35 | - Sun, 03 Nov 2024 13:36:55 GMT 36 | Pragma: 37 | - no-cache 38 | Server: 39 | - Apache 40 | Strict-Transport-Security: 41 | - max-age=86400 42 | Vary: 43 | - Accept-Encoding 44 | status: 45 | code: 200 46 | message: OK 47 | - request: 48 | body: null 49 | headers: 50 | Accept: 51 | - '*/*' 52 | Accept-Encoding: 53 | - gzip, deflate, zstd 54 | Connection: 55 | - keep-alive 56 | User-Agent: 57 | - python-requests/2.32.3 58 | method: GET 59 | uri: https://api.stlouisfed.org/fred/series/release?file_type=json&series_id=GDP 60 | response: 61 | body: 62 | string: '{"realtime_start":"2024-11-03","realtime_end":"2024-11-03","releases":[{"id":53,"realtime_start":"2024-11-03","realtime_end":"2024-11-03","name":"Gross 63 | Domestic Product","press_release":true,"link":"https:\/\/www.bea.gov\/data\/gdp\/gross-domestic-product"}]}' 64 | headers: 65 | Cache-Control: 66 | - max-age=0, no-cache 67 | Connection: 68 | - keep-alive 69 | Content-Encoding: 70 | - gzip 71 | Content-Length: 72 | - '186' 73 | Content-Type: 74 | - application/json; charset=UTF-8 75 | Date: 76 | - Sun, 03 Nov 2024 14:33:32 GMT 77 | Expires: 78 | - Sun, 03 Nov 2024 14:33:32 GMT 79 | Last-Modified: 80 | - Sun, 03 Nov 2024 13:36:55 GMT 81 | Pragma: 82 | - no-cache 83 | Server: 84 | - Apache 85 | Strict-Transport-Security: 86 | - max-age=86400 87 | Vary: 88 | - Accept-Encoding 89 | status: 90 | code: 200 91 | message: OK 92 | - request: 93 | body: null 94 | headers: 95 | Accept: 96 | - '*/*' 97 | Accept-Encoding: 98 | - gzip, deflate, zstd 99 | Connection: 100 | - keep-alive 101 | User-Agent: 102 | - python-requests/2.32.3 103 | method: GET 104 | uri: https://api.stlouisfed.org/fred/series/release?file_type=json&series_id=GDP 105 | response: 106 | body: 107 | string: '{"realtime_start":"2025-01-20","realtime_end":"2025-01-20","releases":[{"id":53,"realtime_start":"2025-01-20","realtime_end":"2025-01-20","name":"Gross 108 | Domestic Product","press_release":true,"link":"https:\/\/www.bea.gov\/data\/gdp\/gross-domestic-product"}]}' 109 | headers: 110 | Cache-Control: 111 | - max-age=0, no-cache 112 | Connection: 113 | - keep-alive 114 | Content-Encoding: 115 | - gzip 116 | Content-Length: 117 | - '186' 118 | Content-Type: 119 | - application/json; charset=UTF-8 120 | Date: 121 | - Mon, 20 Jan 2025 14:56:13 GMT 122 | Expires: 123 | - Mon, 20 Jan 2025 14:56:13 GMT 124 | Last-Modified: 125 | - Mon, 20 Jan 2025 14:56:13 GMT 126 | Pragma: 127 | - no-cache 128 | Server: 129 | - Apache 130 | Strict-Transport-Security: 131 | - max-age=86400 132 | Vary: 133 | - Accept-Encoding 134 | status: 135 | code: 200 136 | message: OK 137 | - request: 138 | body: null 139 | headers: 140 | Accept: 141 | - '*/*' 142 | Accept-Encoding: 143 | - gzip, deflate, zstd 144 | Connection: 145 | - keep-alive 146 | User-Agent: 147 | - python-requests/2.32.3 148 | method: GET 149 | uri: https://api.stlouisfed.org/fred/series/release?file_type=json&series_id=GDP 150 | response: 151 | body: 152 | string: '{"realtime_start":"2025-01-20","realtime_end":"2025-01-20","releases":[{"id":53,"realtime_start":"2025-01-20","realtime_end":"2025-01-20","name":"Gross 153 | Domestic Product","press_release":true,"link":"https:\/\/www.bea.gov\/data\/gdp\/gross-domestic-product"}]}' 154 | headers: 155 | Cache-Control: 156 | - max-age=0, no-cache 157 | Connection: 158 | - keep-alive 159 | Content-Encoding: 160 | - gzip 161 | Content-Length: 162 | - '186' 163 | Content-Type: 164 | - application/json; charset=UTF-8 165 | Date: 166 | - Mon, 20 Jan 2025 14:56:13 GMT 167 | Expires: 168 | - Mon, 20 Jan 2025 14:56:13 GMT 169 | Last-Modified: 170 | - Mon, 20 Jan 2025 14:56:13 GMT 171 | Pragma: 172 | - no-cache 173 | Server: 174 | - Apache 175 | Strict-Transport-Security: 176 | - max-age=86400 177 | Vary: 178 | - Accept-Encoding 179 | status: 180 | code: 200 181 | message: OK 182 | version: 1 183 | -------------------------------------------------------------------------------- /tests/vhs/test_series/test_get_series_tags.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: null 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate, zstd 9 | Connection: 10 | - keep-alive 11 | User-Agent: 12 | - python-requests/2.32.3 13 | method: GET 14 | uri: https://api.stlouisfed.org/fred/series/tags?file_type=json&series_id=GDP 15 | response: 16 | body: 17 | string: '{"realtime_start":"2024-11-02","realtime_end":"2024-11-02","order_by":"series_count","sort_order":"asc","count":8,"offset":0,"limit":1000,"tags":[{"name":"nipa","group_id":"rls","notes":"National 18 | Income and Product Accounts","created":"2012-08-16 15:21:17-05","popularity":68,"series_count":12664},{"name":"gdp","group_id":"gen","notes":"Gross 19 | Domestic Product","created":"2012-02-27 10:18:19-06","popularity":79,"series_count":74396},{"name":"bea","group_id":"src","notes":"Bureau 20 | of Economic Analysis","created":"2012-02-27 10:18:19-06","popularity":78,"series_count":78784},{"name":"sa","group_id":"seas","notes":"Seasonally 21 | Adjusted","created":"2012-02-27 10:18:19-06","popularity":86,"series_count":94640},{"name":"quarterly","group_id":"freq","notes":"","created":"2012-02-27 22 | 10:18:19-06","popularity":83,"series_count":110452},{"name":"nation","group_id":"geot","notes":"","created":"2012-02-27 23 | 10:18:19-06","popularity":96,"series_count":266792},{"name":"public domain: 24 | citation requested","group_id":"cc","notes":null,"created":"2018-12-17 23:33:13-06","popularity":99,"series_count":613476},{"name":"usa","group_id":"geo","notes":"United 25 | States of America","created":"2012-02-27 10:18:19-06","popularity":100,"series_count":660206}]}' 26 | headers: 27 | Cache-Control: 28 | - max-age=0, no-cache 29 | Connection: 30 | - keep-alive 31 | Content-Encoding: 32 | - gzip 33 | Content-Length: 34 | - '614' 35 | Content-Type: 36 | - application/json; charset=UTF-8 37 | Date: 38 | - Sun, 03 Nov 2024 14:33:33 GMT 39 | Expires: 40 | - Sun, 03 Nov 2024 14:33:33 GMT 41 | Last-Modified: 42 | - Sat, 02 Nov 2024 15:52:56 GMT 43 | Pragma: 44 | - no-cache 45 | Server: 46 | - Apache 47 | Strict-Transport-Security: 48 | - max-age=86400 49 | Vary: 50 | - Accept-Encoding 51 | status: 52 | code: 200 53 | message: OK 54 | - request: 55 | body: null 56 | headers: 57 | Accept: 58 | - '*/*' 59 | Accept-Encoding: 60 | - gzip, deflate, zstd 61 | Connection: 62 | - keep-alive 63 | User-Agent: 64 | - python-requests/2.32.3 65 | method: GET 66 | uri: https://api.stlouisfed.org/fred/series/tags?file_type=json&series_id=GDP 67 | response: 68 | body: 69 | string: '{"realtime_start":"2024-11-02","realtime_end":"2024-11-02","order_by":"series_count","sort_order":"asc","count":8,"offset":0,"limit":1000,"tags":[{"name":"nipa","group_id":"rls","notes":"National 70 | Income and Product Accounts","created":"2012-08-16 15:21:17-05","popularity":68,"series_count":12664},{"name":"gdp","group_id":"gen","notes":"Gross 71 | Domestic Product","created":"2012-02-27 10:18:19-06","popularity":79,"series_count":74396},{"name":"bea","group_id":"src","notes":"Bureau 72 | of Economic Analysis","created":"2012-02-27 10:18:19-06","popularity":78,"series_count":78784},{"name":"sa","group_id":"seas","notes":"Seasonally 73 | Adjusted","created":"2012-02-27 10:18:19-06","popularity":86,"series_count":94640},{"name":"quarterly","group_id":"freq","notes":"","created":"2012-02-27 74 | 10:18:19-06","popularity":83,"series_count":110452},{"name":"nation","group_id":"geot","notes":"","created":"2012-02-27 75 | 10:18:19-06","popularity":96,"series_count":266792},{"name":"public domain: 76 | citation requested","group_id":"cc","notes":null,"created":"2018-12-17 23:33:13-06","popularity":99,"series_count":613476},{"name":"usa","group_id":"geo","notes":"United 77 | States of America","created":"2012-02-27 10:18:19-06","popularity":100,"series_count":660206}]}' 78 | headers: 79 | Cache-Control: 80 | - max-age=0, no-cache 81 | Connection: 82 | - keep-alive 83 | Content-Encoding: 84 | - gzip 85 | Content-Length: 86 | - '614' 87 | Content-Type: 88 | - application/json; charset=UTF-8 89 | Date: 90 | - Sun, 03 Nov 2024 14:33:33 GMT 91 | Expires: 92 | - Sun, 03 Nov 2024 14:33:33 GMT 93 | Last-Modified: 94 | - Sat, 02 Nov 2024 15:52:56 GMT 95 | Pragma: 96 | - no-cache 97 | Server: 98 | - Apache 99 | Strict-Transport-Security: 100 | - max-age=86400 101 | Vary: 102 | - Accept-Encoding 103 | status: 104 | code: 200 105 | message: OK 106 | - request: 107 | body: null 108 | headers: 109 | Accept: 110 | - '*/*' 111 | Accept-Encoding: 112 | - gzip, deflate, zstd 113 | Connection: 114 | - keep-alive 115 | User-Agent: 116 | - python-requests/2.32.3 117 | method: GET 118 | uri: https://api.stlouisfed.org/fred/series/tags?file_type=json&series_id=GDP 119 | response: 120 | body: 121 | string: '{"realtime_start":"2025-01-20","realtime_end":"2025-01-20","order_by":"series_count","sort_order":"asc","count":8,"offset":0,"limit":1000,"tags":[{"name":"nipa","group_id":"rls","notes":"National 122 | Income and Product Accounts","created":"2012-08-16 15:21:17-05","popularity":68,"series_count":12662},{"name":"gdp","group_id":"gen","notes":"Gross 123 | Domestic Product","created":"2012-02-27 10:18:19-06","popularity":79,"series_count":74564},{"name":"bea","group_id":"src","notes":"Bureau 124 | of Economic Analysis","created":"2012-02-27 10:18:19-06","popularity":78,"series_count":78298},{"name":"sa","group_id":"seas","notes":"Seasonally 125 | Adjusted","created":"2012-02-27 10:18:19-06","popularity":86,"series_count":94474},{"name":"quarterly","group_id":"freq","notes":"","created":"2012-02-27 126 | 10:18:19-06","popularity":83,"series_count":110530},{"name":"nation","group_id":"geot","notes":"","created":"2012-02-27 127 | 10:18:19-06","popularity":96,"series_count":269020},{"name":"public domain: 128 | citation requested","group_id":"cc","notes":null,"created":"2018-12-17 23:33:13-06","popularity":99,"series_count":612536},{"name":"usa","group_id":"geo","notes":"United 129 | States of America","created":"2012-02-27 10:18:19-06","popularity":100,"series_count":660740}]}' 130 | headers: 131 | Cache-Control: 132 | - max-age=0, no-cache 133 | Connection: 134 | - keep-alive 135 | Content-Encoding: 136 | - gzip 137 | Content-Length: 138 | - '615' 139 | Content-Type: 140 | - application/json; charset=UTF-8 141 | Date: 142 | - Mon, 20 Jan 2025 14:56:14 GMT 143 | Expires: 144 | - Mon, 20 Jan 2025 14:56:14 GMT 145 | Last-Modified: 146 | - Mon, 20 Jan 2025 14:56:14 GMT 147 | Pragma: 148 | - no-cache 149 | Server: 150 | - Apache 151 | Strict-Transport-Security: 152 | - max-age=86400 153 | Vary: 154 | - Accept-Encoding 155 | status: 156 | code: 200 157 | message: OK 158 | - request: 159 | body: null 160 | headers: 161 | Accept: 162 | - '*/*' 163 | Accept-Encoding: 164 | - gzip, deflate, zstd 165 | Connection: 166 | - keep-alive 167 | User-Agent: 168 | - python-requests/2.32.3 169 | method: GET 170 | uri: https://api.stlouisfed.org/fred/series/tags?file_type=json&series_id=GDP 171 | response: 172 | body: 173 | string: '{"realtime_start":"2025-01-20","realtime_end":"2025-01-20","order_by":"series_count","sort_order":"asc","count":8,"offset":0,"limit":1000,"tags":[{"name":"nipa","group_id":"rls","notes":"National 174 | Income and Product Accounts","created":"2012-08-16 15:21:17-05","popularity":68,"series_count":12662},{"name":"gdp","group_id":"gen","notes":"Gross 175 | Domestic Product","created":"2012-02-27 10:18:19-06","popularity":79,"series_count":74564},{"name":"bea","group_id":"src","notes":"Bureau 176 | of Economic Analysis","created":"2012-02-27 10:18:19-06","popularity":78,"series_count":78298},{"name":"sa","group_id":"seas","notes":"Seasonally 177 | Adjusted","created":"2012-02-27 10:18:19-06","popularity":86,"series_count":94474},{"name":"quarterly","group_id":"freq","notes":"","created":"2012-02-27 178 | 10:18:19-06","popularity":83,"series_count":110530},{"name":"nation","group_id":"geot","notes":"","created":"2012-02-27 179 | 10:18:19-06","popularity":96,"series_count":269020},{"name":"public domain: 180 | citation requested","group_id":"cc","notes":null,"created":"2018-12-17 23:33:13-06","popularity":99,"series_count":612536},{"name":"usa","group_id":"geo","notes":"United 181 | States of America","created":"2012-02-27 10:18:19-06","popularity":100,"series_count":660740}]}' 182 | headers: 183 | Cache-Control: 184 | - max-age=0, no-cache 185 | Connection: 186 | - keep-alive 187 | Content-Encoding: 188 | - gzip 189 | Content-Length: 190 | - '615' 191 | Content-Type: 192 | - application/json; charset=UTF-8 193 | Date: 194 | - Mon, 20 Jan 2025 14:56:14 GMT 195 | Expires: 196 | - Mon, 20 Jan 2025 14:56:14 GMT 197 | Last-Modified: 198 | - Mon, 20 Jan 2025 14:56:14 GMT 199 | Pragma: 200 | - no-cache 201 | Server: 202 | - Apache 203 | Strict-Transport-Security: 204 | - max-age=86400 205 | Vary: 206 | - Accept-Encoding 207 | status: 208 | code: 200 209 | message: OK 210 | version: 1 211 | -------------------------------------------------------------------------------- /tests/vhs/test_series/test_search_series_related_tags[json].yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: null 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate, zstd 9 | Connection: 10 | - keep-alive 11 | User-Agent: 12 | - python-requests/2.32.3 13 | method: GET 14 | uri: https://api.stlouisfed.org/fred/series/search/related_tags?file_type=json&series_search_text=monetary%2Bservice%2Bindex&tag_names=30-year%3Bfrb 15 | response: 16 | body: 17 | string: '{"realtime_start":"2024-11-02","realtime_end":"2024-11-02","order_by":"series_count","sort_order":"desc","count":0,"offset":0,"limit":1000,"tags":[]}' 18 | headers: 19 | Cache-Control: 20 | - max-age=0, no-cache 21 | Connection: 22 | - keep-alive 23 | Content-Encoding: 24 | - gzip 25 | Content-Length: 26 | - '138' 27 | Content-Type: 28 | - application/json; charset=UTF-8 29 | Date: 30 | - Sun, 03 Nov 2024 14:33:50 GMT 31 | Expires: 32 | - Sun, 03 Nov 2024 14:33:50 GMT 33 | Last-Modified: 34 | - Sat, 02 Nov 2024 15:54:50 GMT 35 | Pragma: 36 | - no-cache 37 | Server: 38 | - Apache 39 | Strict-Transport-Security: 40 | - max-age=86400 41 | Vary: 42 | - Accept-Encoding 43 | status: 44 | code: 200 45 | message: OK 46 | - request: 47 | body: null 48 | headers: 49 | Accept: 50 | - '*/*' 51 | Accept-Encoding: 52 | - gzip, deflate, zstd 53 | Connection: 54 | - keep-alive 55 | User-Agent: 56 | - python-requests/2.32.3 57 | method: GET 58 | uri: https://api.stlouisfed.org/fred/series/search/related_tags?file_type=json&series_search_text=monetary%2Bservice%2Bindex&tag_names=30-year%3Bfrb 59 | response: 60 | body: 61 | string: '{"realtime_start":"2024-11-02","realtime_end":"2024-11-02","order_by":"series_count","sort_order":"desc","count":0,"offset":0,"limit":1000,"tags":[]}' 62 | headers: 63 | Cache-Control: 64 | - max-age=0, no-cache 65 | Connection: 66 | - keep-alive 67 | Content-Encoding: 68 | - gzip 69 | Content-Length: 70 | - '138' 71 | Content-Type: 72 | - application/json; charset=UTF-8 73 | Date: 74 | - Sun, 03 Nov 2024 14:33:51 GMT 75 | Expires: 76 | - Sun, 03 Nov 2024 14:33:51 GMT 77 | Last-Modified: 78 | - Sat, 02 Nov 2024 15:54:50 GMT 79 | Pragma: 80 | - no-cache 81 | Server: 82 | - Apache 83 | Strict-Transport-Security: 84 | - max-age=86400 85 | Vary: 86 | - Accept-Encoding 87 | status: 88 | code: 200 89 | message: OK 90 | - request: 91 | body: null 92 | headers: 93 | Accept: 94 | - '*/*' 95 | Accept-Encoding: 96 | - gzip, deflate, zstd 97 | Connection: 98 | - keep-alive 99 | User-Agent: 100 | - python-requests/2.32.3 101 | method: GET 102 | uri: https://api.stlouisfed.org/fred/series/search/related_tags?file_type=json&series_search_text=monetary%2Bservice%2Bindex&tag_names=30-year%3Bfrb 103 | response: 104 | body: 105 | string: '{"realtime_start":"2025-01-20","realtime_end":"2025-01-20","order_by":"series_count","sort_order":"desc","count":0,"offset":0,"limit":1000,"tags":[]}' 106 | headers: 107 | Cache-Control: 108 | - max-age=0, no-cache 109 | Connection: 110 | - keep-alive 111 | Content-Encoding: 112 | - gzip 113 | Content-Length: 114 | - '138' 115 | Content-Type: 116 | - application/json; charset=UTF-8 117 | Date: 118 | - Mon, 20 Jan 2025 14:56:31 GMT 119 | Expires: 120 | - Mon, 20 Jan 2025 14:56:31 GMT 121 | Last-Modified: 122 | - Mon, 20 Jan 2025 14:56:30 GMT 123 | Pragma: 124 | - no-cache 125 | Server: 126 | - Apache 127 | Strict-Transport-Security: 128 | - max-age=86400 129 | Vary: 130 | - Accept-Encoding 131 | status: 132 | code: 200 133 | message: OK 134 | - request: 135 | body: null 136 | headers: 137 | Accept: 138 | - '*/*' 139 | Accept-Encoding: 140 | - gzip, deflate, zstd 141 | Connection: 142 | - keep-alive 143 | User-Agent: 144 | - python-requests/2.32.3 145 | method: GET 146 | uri: https://api.stlouisfed.org/fred/series/search/related_tags?file_type=json&series_search_text=monetary%2Bservice%2Bindex&tag_names=30-year%3Bfrb 147 | response: 148 | body: 149 | string: '{"realtime_start":"2025-01-20","realtime_end":"2025-01-20","order_by":"series_count","sort_order":"desc","count":0,"offset":0,"limit":1000,"tags":[]}' 150 | headers: 151 | Cache-Control: 152 | - max-age=0, no-cache 153 | Connection: 154 | - keep-alive 155 | Content-Encoding: 156 | - gzip 157 | Content-Length: 158 | - '138' 159 | Content-Type: 160 | - application/json; charset=UTF-8 161 | Date: 162 | - Mon, 20 Jan 2025 14:56:31 GMT 163 | Expires: 164 | - Mon, 20 Jan 2025 14:56:31 GMT 165 | Last-Modified: 166 | - Mon, 20 Jan 2025 14:56:30 GMT 167 | Pragma: 168 | - no-cache 169 | Server: 170 | - Apache 171 | Strict-Transport-Security: 172 | - max-age=86400 173 | Vary: 174 | - Accept-Encoding 175 | status: 176 | code: 200 177 | message: OK 178 | version: 1 179 | -------------------------------------------------------------------------------- /tests/vhs/test_series/test_search_series_related_tags[pandas].yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: null 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate, zstd 9 | Connection: 10 | - keep-alive 11 | User-Agent: 12 | - python-requests/2.32.3 13 | method: GET 14 | uri: https://api.stlouisfed.org/fred/series/search/related_tags?file_type=json&series_search_text=monetary%2Bservice%2Bindex&tag_names=30-year%3Bfrb 15 | response: 16 | body: 17 | string: '{"realtime_start":"2024-11-02","realtime_end":"2024-11-02","order_by":"series_count","sort_order":"desc","count":0,"offset":0,"limit":1000,"tags":[]}' 18 | headers: 19 | Cache-Control: 20 | - max-age=0, no-cache 21 | Connection: 22 | - keep-alive 23 | Content-Encoding: 24 | - gzip 25 | Content-Length: 26 | - '138' 27 | Content-Type: 28 | - application/json; charset=UTF-8 29 | Date: 30 | - Sun, 03 Nov 2024 14:33:51 GMT 31 | Expires: 32 | - Sun, 03 Nov 2024 14:33:51 GMT 33 | Last-Modified: 34 | - Sat, 02 Nov 2024 15:54:50 GMT 35 | Pragma: 36 | - no-cache 37 | Server: 38 | - Apache 39 | Strict-Transport-Security: 40 | - max-age=86400 41 | Vary: 42 | - Accept-Encoding 43 | status: 44 | code: 200 45 | message: OK 46 | - request: 47 | body: null 48 | headers: 49 | Accept: 50 | - '*/*' 51 | Accept-Encoding: 52 | - gzip, deflate, zstd 53 | Connection: 54 | - keep-alive 55 | User-Agent: 56 | - python-requests/2.32.3 57 | method: GET 58 | uri: https://api.stlouisfed.org/fred/series/search/related_tags?file_type=json&series_search_text=monetary%2Bservice%2Bindex&tag_names=30-year%3Bfrb 59 | response: 60 | body: 61 | string: '{"realtime_start":"2025-01-20","realtime_end":"2025-01-20","order_by":"series_count","sort_order":"desc","count":0,"offset":0,"limit":1000,"tags":[]}' 62 | headers: 63 | Cache-Control: 64 | - max-age=0, no-cache 65 | Connection: 66 | - keep-alive 67 | Content-Encoding: 68 | - gzip 69 | Content-Length: 70 | - '138' 71 | Content-Type: 72 | - application/json; charset=UTF-8 73 | Date: 74 | - Mon, 20 Jan 2025 14:56:32 GMT 75 | Expires: 76 | - Mon, 20 Jan 2025 14:56:32 GMT 77 | Last-Modified: 78 | - Mon, 20 Jan 2025 14:56:30 GMT 79 | Pragma: 80 | - no-cache 81 | Server: 82 | - Apache 83 | Strict-Transport-Security: 84 | - max-age=86400 85 | Vary: 86 | - Accept-Encoding 87 | status: 88 | code: 200 89 | message: OK 90 | version: 1 91 | -------------------------------------------------------------------------------- /tests/vhs/test_series/test_search_series_related_tags[polars].yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: null 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate, zstd 9 | Connection: 10 | - keep-alive 11 | User-Agent: 12 | - python-requests/2.32.3 13 | method: GET 14 | uri: https://api.stlouisfed.org/fred/series/search/related_tags?file_type=json&series_search_text=monetary%2Bservice%2Bindex&tag_names=30-year%3Bfrb 15 | response: 16 | body: 17 | string: '{"realtime_start":"2024-11-02","realtime_end":"2024-11-02","order_by":"series_count","sort_order":"desc","count":0,"offset":0,"limit":1000,"tags":[]}' 18 | headers: 19 | Cache-Control: 20 | - max-age=0, no-cache 21 | Connection: 22 | - keep-alive 23 | Content-Encoding: 24 | - gzip 25 | Content-Length: 26 | - '138' 27 | Content-Type: 28 | - application/json; charset=UTF-8 29 | Date: 30 | - Sun, 03 Nov 2024 14:33:52 GMT 31 | Expires: 32 | - Sun, 03 Nov 2024 14:33:52 GMT 33 | Last-Modified: 34 | - Sat, 02 Nov 2024 15:54:50 GMT 35 | Pragma: 36 | - no-cache 37 | Server: 38 | - Apache 39 | Strict-Transport-Security: 40 | - max-age=86400 41 | Vary: 42 | - Accept-Encoding 43 | status: 44 | code: 200 45 | message: OK 46 | - request: 47 | body: null 48 | headers: 49 | Accept: 50 | - '*/*' 51 | Accept-Encoding: 52 | - gzip, deflate, zstd 53 | Connection: 54 | - keep-alive 55 | User-Agent: 56 | - python-requests/2.32.3 57 | method: GET 58 | uri: https://api.stlouisfed.org/fred/series/search/related_tags?file_type=json&series_search_text=monetary%2Bservice%2Bindex&tag_names=30-year%3Bfrb 59 | response: 60 | body: 61 | string: '{"realtime_start":"2025-01-20","realtime_end":"2025-01-20","order_by":"series_count","sort_order":"desc","count":0,"offset":0,"limit":1000,"tags":[]}' 62 | headers: 63 | Cache-Control: 64 | - max-age=0, no-cache 65 | Connection: 66 | - keep-alive 67 | Content-Encoding: 68 | - gzip 69 | Content-Length: 70 | - '138' 71 | Content-Type: 72 | - application/json; charset=UTF-8 73 | Date: 74 | - Mon, 20 Jan 2025 14:56:32 GMT 75 | Expires: 76 | - Mon, 20 Jan 2025 14:56:32 GMT 77 | Last-Modified: 78 | - Mon, 20 Jan 2025 14:56:30 GMT 79 | Pragma: 80 | - no-cache 81 | Server: 82 | - Apache 83 | Strict-Transport-Security: 84 | - max-age=86400 85 | Vary: 86 | - Accept-Encoding 87 | status: 88 | code: 200 89 | message: OK 90 | version: 1 91 | -------------------------------------------------------------------------------- /tests/vhs/test_sources/test_get_source.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: null 4 | headers: 5 | Accept: 6 | - '*/*' 7 | Accept-Encoding: 8 | - gzip, deflate, zstd 9 | Connection: 10 | - keep-alive 11 | User-Agent: 12 | - python-requests/2.32.3 13 | method: GET 14 | uri: https://api.stlouisfed.org/fred/source?file_type=json&source_id=1 15 | response: 16 | body: 17 | string: '{"realtime_start":"2024-11-02","realtime_end":"2024-11-02","sources":[{"id":1,"realtime_start":"2024-11-02","realtime_end":"2024-11-02","name":"Board 18 | of Governors of the Federal Reserve System (US)","link":"http:\/\/www.federalreserve.gov\/"}]}' 19 | headers: 20 | Cache-Control: 21 | - max-age=0, no-cache 22 | Connection: 23 | - keep-alive 24 | Content-Encoding: 25 | - gzip 26 | Content-Length: 27 | - '177' 28 | Content-Type: 29 | - application/json; charset=UTF-8 30 | Date: 31 | - Sun, 03 Nov 2024 14:34:07 GMT 32 | Expires: 33 | - Sun, 03 Nov 2024 14:34:07 GMT 34 | Last-Modified: 35 | - Sat, 02 Nov 2024 15:55:07 GMT 36 | Pragma: 37 | - no-cache 38 | Server: 39 | - Apache 40 | Strict-Transport-Security: 41 | - max-age=86400 42 | Vary: 43 | - Accept-Encoding 44 | status: 45 | code: 200 46 | message: OK 47 | - request: 48 | body: null 49 | headers: 50 | Accept: 51 | - '*/*' 52 | Accept-Encoding: 53 | - gzip, deflate, zstd 54 | Connection: 55 | - keep-alive 56 | User-Agent: 57 | - python-requests/2.32.3 58 | method: GET 59 | uri: https://api.stlouisfed.org/fred/source?file_type=json&source_id=1 60 | response: 61 | body: 62 | string: '{"realtime_start":"2024-11-02","realtime_end":"2024-11-02","sources":[{"id":1,"realtime_start":"2024-11-02","realtime_end":"2024-11-02","name":"Board 63 | of Governors of the Federal Reserve System (US)","link":"http:\/\/www.federalreserve.gov\/"}]}' 64 | headers: 65 | Cache-Control: 66 | - max-age=0, no-cache 67 | Connection: 68 | - keep-alive 69 | Content-Encoding: 70 | - gzip 71 | Content-Length: 72 | - '177' 73 | Content-Type: 74 | - application/json; charset=UTF-8 75 | Date: 76 | - Sun, 03 Nov 2024 14:34:07 GMT 77 | Expires: 78 | - Sun, 03 Nov 2024 14:34:07 GMT 79 | Last-Modified: 80 | - Sat, 02 Nov 2024 15:55:07 GMT 81 | Pragma: 82 | - no-cache 83 | Server: 84 | - Apache 85 | Strict-Transport-Security: 86 | - max-age=86400 87 | Vary: 88 | - Accept-Encoding 89 | status: 90 | code: 200 91 | message: OK 92 | - request: 93 | body: null 94 | headers: 95 | Accept: 96 | - '*/*' 97 | Accept-Encoding: 98 | - gzip, deflate, zstd 99 | Connection: 100 | - keep-alive 101 | User-Agent: 102 | - python-requests/2.32.3 103 | method: GET 104 | uri: https://api.stlouisfed.org/fred/source?file_type=json&source_id=1 105 | response: 106 | body: 107 | string: '{"realtime_start":"2025-01-20","realtime_end":"2025-01-20","sources":[{"id":1,"realtime_start":"2025-01-20","realtime_end":"2025-01-20","name":"Board 108 | of Governors of the Federal Reserve System (US)","link":"http:\/\/www.federalreserve.gov\/"}]}' 109 | headers: 110 | Cache-Control: 111 | - max-age=0, no-cache 112 | Connection: 113 | - keep-alive 114 | Content-Encoding: 115 | - gzip 116 | Content-Length: 117 | - '177' 118 | Content-Type: 119 | - application/json; charset=UTF-8 120 | Date: 121 | - Mon, 20 Jan 2025 14:56:46 GMT 122 | Expires: 123 | - Mon, 20 Jan 2025 14:56:46 GMT 124 | Last-Modified: 125 | - Mon, 20 Jan 2025 14:56:46 GMT 126 | Pragma: 127 | - no-cache 128 | Server: 129 | - Apache 130 | Strict-Transport-Security: 131 | - max-age=86400 132 | Vary: 133 | - Accept-Encoding 134 | status: 135 | code: 200 136 | message: OK 137 | - request: 138 | body: null 139 | headers: 140 | Accept: 141 | - '*/*' 142 | Accept-Encoding: 143 | - gzip, deflate, zstd 144 | Connection: 145 | - keep-alive 146 | User-Agent: 147 | - python-requests/2.32.3 148 | method: GET 149 | uri: https://api.stlouisfed.org/fred/source?file_type=json&source_id=1 150 | response: 151 | body: 152 | string: '{"realtime_start":"2025-01-20","realtime_end":"2025-01-20","sources":[{"id":1,"realtime_start":"2025-01-20","realtime_end":"2025-01-20","name":"Board 153 | of Governors of the Federal Reserve System (US)","link":"http:\/\/www.federalreserve.gov\/"}]}' 154 | headers: 155 | Cache-Control: 156 | - max-age=0, no-cache 157 | Connection: 158 | - keep-alive 159 | Content-Encoding: 160 | - gzip 161 | Content-Length: 162 | - '177' 163 | Content-Type: 164 | - application/json; charset=UTF-8 165 | Date: 166 | - Mon, 20 Jan 2025 14:56:47 GMT 167 | Expires: 168 | - Mon, 20 Jan 2025 14:56:47 GMT 169 | Last-Modified: 170 | - Mon, 20 Jan 2025 14:56:46 GMT 171 | Pragma: 172 | - no-cache 173 | Server: 174 | - Apache 175 | Strict-Transport-Security: 176 | - max-age=86400 177 | Vary: 178 | - Accept-Encoding 179 | status: 180 | code: 200 181 | message: OK 182 | version: 1 183 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | isolated_build = True 3 | envlist = py{38,39,310,311,312}, lint, pytest-cov 4 | 5 | [tox:.package] 6 | basepython = python3 7 | 8 | [testenv] 9 | deps = . 10 | extras = test 11 | usedevelop = True 12 | passenv = PYTHON_VERSION, FRED_API_KEY 13 | commands = 14 | pytest tests/ --record-mode=none --no-header 15 | 16 | [testenv:pytest-cov] 17 | basepython = python3.11 18 | deps = . 19 | extras = test 20 | usedevelop = True 21 | passenv = PYTHON_VERSION, FRED_API_KEY 22 | commands = 23 | pytest --cov=pyfredapi tests/ --record-mode=none --cov-report=html --cov-report=xml --cov-report=term 24 | 25 | [testenv:lint] 26 | basepython = python3.11 27 | deps = . 28 | extras = lint 29 | usedevelop = True 30 | 31 | commands = 32 | ruff check . 33 | black . 34 | mypy pyfredapi 35 | --------------------------------------------------------------------------------