{"id":20636733,"url":"https://github.com/libcommon/api-manager-py","last_synced_at":"2026-04-22T06:07:14.312Z","repository":{"id":62575330,"uuid":"224098434","full_name":"libcommon/api-manager-py","owner":"libcommon","description":"Python library for managing requests to APIs with rate limits.","archived":false,"fork":false,"pushed_at":"2022-12-26T21:31:18.000Z","size":52,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-21T05:16:18.338Z","etag":null,"topics":["api","library","python"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/libcommon.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-11-26T03:57:30.000Z","updated_at":"2020-05-21T04:52:23.000Z","dependencies_parsed_at":"2023-01-31T01:45:48.042Z","dependency_job_id":null,"html_url":"https://github.com/libcommon/api-manager-py","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":"libcommon/template-repo-py","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/libcommon%2Fapi-manager-py","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/libcommon%2Fapi-manager-py/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/libcommon%2Fapi-manager-py/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/libcommon%2Fapi-manager-py/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/libcommon","download_url":"https://codeload.github.com/libcommon/api-manager-py/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":242656036,"owners_count":20164431,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","library","python"],"created_at":"2024-11-16T15:12:00.440Z","updated_at":"2026-04-22T06:07:13.659Z","avatar_url":"https://github.com/libcommon.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# api-manager-py\n\n## Overview\n\nMany APIs with rate limits push responsibility on API users to manage rate limiting, including those with SDKs.\n`api-manager-py` is a Python library that aims to abstract away the complexity of managing rate limits,\nallowing developers to focus on retrieving desired data without hacking together buggy, case-by-case solutions.\nThe API management functionality does not require using a specific library for interacting with an API, and will\nautomatically cache responses based on input parameters to reduce network IO. Simply implement a small API client\ninterface and start making requests.\n\n## Installation\n\n### Install from PyPi (preferred method)\n\n```bash\npip install lc-api-manager\n```\n\n### Install from GitHub with Pip\n\n```bash\npip install git+https://github.com/libcommon/api-manager-py.git@vx.x.x#egg=lc_api_manager\n```\n\nwhere `x.x.x` is the version you want to download.\n\n## Install by Manual Download\n\nTo download the source distribution and/or wheel files, navigate to\n`https://github.com/libcommon/api-manager-py/tree/releases/vx.x.x/dist`, where `x.x.x` is the version you want to install,\nand download either via the UI or with a tool like wget. Then to install run:\n\n```bash\npip install \u003cdownloaded file\u003e\n```\n\nDo _not_ change the name of the file after downloading, as Pip requires a specific naming convention for installation files.\n\n## Dependencies\n\n`api-manager-py` depends on the [lc-cache](https://pypi.org/project/lc-cache/) library for caching API responses. Only\nPython versions \u003e= 3.6 are officially supported.\n\n## Getting Started\n\nThe first step is to implement an `APIClient` and choose a library to make HTTP requests. One common choice is the\n[Requests](https://2.python-requests.org/en/master/) library, which we'll use to implement a client for the [GitHub REST API\nv3](https://developer.github.com/v3/). The domain for GitHub's API is `https://api.github.com`, so the client's `request` method\nonly needs the HTTP method (`GET`, `POST`, etc.), API endpoint (i.e., `/repos/\u003cusername\u003e/\u003crepo_name\u003e`), and optional `headers`,\n`params`, and `data` dictionaries (see: [Requests documentation](https://2.python-requests.org/en/master/user/quickstart/#make-a-request)).\n\n```python\nfrom hashlib import sha256\nfrom typing import Any, Dict, Optional\n\nimport requests\nfrom requests import Response\n\nfrom lc_api_manager import APIClient\n\nclass GitHubAPIClient(APIClient):\n    \"\"\"API client for GitHub Rest API v3.\"\"\"\n    __slots__ = (\"_headers\",)\n\n    def __init__(self, auth_token: Optional[str] = None) -\u003e None:\n        \"\"\"Initialize API client with optional GitHub API oauth token\n        see: https://developer.github.com/v3/#authentication.\n        \"\"\"\n        if auth_token:\n            self._headers = {\"Authorization\": \"token {}\".format(auth_token)}\n        else:\n            self._headers = dict()\n\n    def process_response_for_cache(self, response: Optional[Response]) -\u003e Optional[str]:\n        \"\"\"Return the SHA-256 hash of the API response if not None.\"\"\"\n        if response:\n            return sha256(response.text.encode(\"utf8\")).hexdigest()\n        return None\n\n    def request(http_method: str,\n                api_endpoint: str,\n                headers: Optional[Dict[str, Any]],\n                params: Optional[Dict[str, Any]],\n                data: Optional[Dict[Any, Any]]) -\u003e Response:\n        \"\"\"Make request to GitHub REST API endpoint with provided\n        headers, URL parameters, and data and return response.\"\"\"\n        # Merge authorization header with provided headers\n        merged_headers = self._headers\n        if headers:\n            merged_headers.update(headers)\n\n        # Construct full URL and make request\n        url = \"https://api.github.com/{}\".format(api_endpoint.lstrip(\"/\"))\n        response = requests.request(http_method.upper(), url, params=params, data=data, headers=merged_headers)\n\n        # Raise error if status code is 4XX or 5XX\n        response.raise_for_status()\n        return response\n```\n\nWith a functional `APIClient`, we can start making requests and caching them using the built-in `APIManager` class:\n\n```python\nfrom lc_api_manager import APIManager\nfrom lc_cache import HashmapCache\n\ndef main() -\u003e int:\n    \"\"\"Make 60 unauthenticated requests to an API endpoint in rapid succession.\"\"\"\n    api_manager = APIManager(3600, # GitHub API allows 60 unauthenticated requests per hour\n                             60,\n                             GitHubAPIClient(),\n                             HashmapCache())\n\n    # Make 60 requests to the same API endpoint\n    for _ in range(60):\n        # The API manager will make the request on first iteration,\n        # but will return cached response on the other 59\n        response = api_manager.request(\"GET\", \"repos/libcommon/api-manager-py\", params=dict(per_page=100))\n\n    # Check rate limit status, should be 59 requests remaining\n    # See: https://developer.github.com/v3/rate_limit/\n    response = api_manager.request(\"GET\", \"rate_limit\")\n    requests_remaining = response.json().get(\"resources\").get(\"core\").get(\"remaining\")\n    assert(requests_remaining == 59)\n\n    return 0\n\nif __name__ == \"__main__\":\n    main()\n```\n\nIf you are running multiple Python processes requesting data from the same API, and want to ensure that all of them\nrespect the rate limit requirements, you could override the `APIManager.update_state` method. The `APIManager` constructor\nhas a parameter called `updated_state_before_request`, which defaults to False. If you set this to `True`, the `update_state`\nmethod will be called before every API request, and thus can be used to sync rate limiting state across multiple processes.\nFor example, you could use the `/rate_limit` GitHub API endpoint to implement this method:\n\n```python\nfrom lc_api_manager import APIManager\n\n\ndef GitHubAPIManager(APIManager):\n    \"\"\"API manager for GitHub REST API v3 that syncs rate limiting state.\"\"\"\n    __slots__ = ()\n\n    def __init__(self, *args, **kwargs) -\u003e None:\n        if not kwargs.get(\"update_state_before_request\"):\n            kwargs[\"update_state_before_request\"] = True\n        super().__init__(*args, **kwargs)\n\n    def update_state(self) -\u003e None:\n        \"\"\"Make request to /rate_limit endpoint and update rate limit status.\"\"\"\n        response = self._client.request(\"GET\", \"rate_limit\")\n        requests_remaining = response.json().get(\"resources\").get(\"core\").get(\"remaining\")\n        self._count = self._threshold - requests_remaining\n```\n\n## Contributing/Suggestions\n\nContributions and suggestions are welcome! To make a feature request, report a bug, or otherwise comment on existing\nfunctionality, please file an issue. For contributions please submit a PR, but make sure to lint, type-check, and test\nyour code before doing so. Thanks in advance!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flibcommon%2Fapi-manager-py","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flibcommon%2Fapi-manager-py","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flibcommon%2Fapi-manager-py/lists"}