{"id":24573876,"url":"https://github.com/chrisk824/fastapi-g-context","last_synced_at":"2025-04-23T10:24:48.081Z","repository":{"id":255410471,"uuid":"849531631","full_name":"chrisK824/fastapi-g-context","owner":"chrisK824","description":"fastapi-g-context is a Python module that provides a simple mechanism for managing global variables with context isolation in FastAPI applications. It is designed to ensure that each request operates within its own isolated context, preventing data leakage between requests.","archived":false,"fork":false,"pushed_at":"2024-09-06T16:58:06.000Z","size":18,"stargazers_count":9,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-01-16T13:49:51.735Z","etag":null,"topics":["fastapi","flask"],"latest_commit_sha":null,"homepage":"","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/chrisK824.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-08-29T18:55:54.000Z","updated_at":"2025-01-15T19:43:39.000Z","dependencies_parsed_at":"2024-08-29T21:08:43.069Z","dependency_job_id":"604182e6-d6a3-4691-817b-507573beb05a","html_url":"https://github.com/chrisK824/fastapi-g-context","commit_stats":null,"previous_names":["chrisk824/fastapi-g","chrisk824/fastapi-g-context"],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chrisK824%2Ffastapi-g-context","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chrisK824%2Ffastapi-g-context/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chrisK824%2Ffastapi-g-context/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chrisK824%2Ffastapi-g-context/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chrisK824","download_url":"https://codeload.github.com/chrisK824/fastapi-g-context/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":235344471,"owners_count":18974920,"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":["fastapi","flask"],"created_at":"2025-01-23T20:22:38.191Z","updated_at":"2025-01-23T20:22:38.943Z","avatar_url":"https://github.com/chrisK824.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# fastapi-g-context\n\n`fastapi-g-context` is a Python module that provides a simple mechanism for managing global variables with context isolation in `FastAPI` applications. It is designed to ensure that each request operates within its own isolated context, preventing data leakage between requests.\n\nWhile this behaviour can be achieved in other ways as well, this module tries to mimic the `flask`'s global `g` object, so that `flask` users find it easier to migrate their logic when moving to `FastAPI`.\n\n\n## Features\n\n- **Context Isolation**: Each request operates in a fresh context, ensuring that global variables do not interfere with each other.\n- **Easy-to-Use** Interface: Get, set, and manage global variables with a simple and intuitive API, while resembling the usage of `flask`'s `g` object to make it easier for users that are switching to `FastAPI`.\n- **Middleware Integration**: Integrates seamlessly with FastAPI as a pure ASGI lightweight middleware.\n\n## Installation\n\nTo install `fastapi-g-context` simply use pip:\n\n`pip install fastapi-g-context`\n\n\n## Usage\nTo use `fastapi-g-context` in your FastAPI application, follow these simple steps:\n\n- Install the package: Ensure you have `fastapi-g-context` installed. You can add it to your requirements.txt or install it directly.\n- Import the necessary components from `fastapi_g_context`: \n    - `GlobalsMiddleware` \n    - `g` object (the global context manager) .\n- Add the GlobalsMiddleware to your FastAPI application. This middleware ensures that each request operates with a fresh context for global variables.\n- Set Global Variables: You can set and manipulate global variables using the g object. These variables are request-scoped and won't leak between requests.\n- Most usual use case would be to use that `g` object to set dependencies for your app's handlers via the `FastAPI`'s  dependency injection system.\n\n```python\nfrom fastapi import FastAPI, Depends\nfrom fastapi_g_context import GlobalsMiddleware, g\n\napp = FastAPI()\napp.add_middleware(GlobalsMiddleware)\n\nasync def set_globals() -\u003e None:\n    g.username = \"JohnDoe\"\n    g.request_id = \"123456\"\n    g.is_admin = True\n\n@app.get(\"/\", dependencies=[Depends(set_globals)])\nasync def info():\n    return {\"username\": g.username, \"request_id\": g.request_id, \"is_admin\": g.is_admin}\n\n```\n\n## API reference\n\nThe global object `g`  provides a mechanism to manage global variables with context isolation. Below are the methods and attributes available in this class:\n\n**`key in g`**  \n_Check whether an attribute is present in the global context._\n\n- **Parameters**: \n  - `key` (str): The name of the attribute to check.\n- **Return Type**: `bool`\n\n**`g.get(name, default=None)`**  \n_Get an attribute by name, or return a default value if the attribute is not present. This works similarly to `dict.get()`._\n\n- **Parameters**:\n  - `name` (str): Name of the attribute to retrieve.\n  - `default` (Any | None): Value to return if the attribute is not present (default is `None`).\n- **Return Type**: `Any`\n\n**`g.pop(name, default=None)`**  \n_Get and remove an attribute by name. This works similarly to `dict.pop()`._\n\n- **Parameters**:\n  - `name` (str): Name of the attribute to pop.\n  - `default` (Any | None): Value to return if the attribute is not present (default is `None`).\n- **Return Type**: `Any`\n\n**`g.keys()`**  \n_Return an iterator over the attribute names in the global context._\n\n- **Return Type**: `Iterator[str]`\n\n**`g.values()`**  \n_Return an iterator over the attribute values in the global context._\n\n- **Return Type**: `Iterator[Any]`\n\n**`g.items()`**  \n_Return an iterator over the attribute name-value pairs in the global context._\n\n- **Return Type**: `Iterator[tuple[str, Any]]`\n\n**`g.to_dict()`**  \n_Return all attributes and their current values as a dictionary._\n\n- **Return Type**: `Dict[str, Any]`\n\n**`g.clear()`**  \n_Clear all attributes from the global context._\n\n- **Return Type**: `None`\n\n**`g.__getattr__(name)`**  \n_Retrieve the value of an attribute by name. Raises an `AttributeError` if the attribute is not found._\n\n- **Parameters**:\n  - `name` (str): Name of the attribute to retrieve.\n- **Return Type**: `Any`\n\n**`g.__setattr__(name, value)`**  \n_Set the value of an attribute by name. Creates the attribute if it does not already exist._\n\n- **Parameters**:\n  - `name` (str): Name of the attribute to set.\n  - `value` (Any): Value to set for the attribute.\n- **Return Type**: `None`\n\n\n## Example\n\nTo demonstrate the capabilities of the fastapi_g_context module, here's an example FastAPI application.\n\n```python\nfrom fastapi import FastAPI, Depends\nfrom fastapi.responses import JSONResponse\nfrom fastapi_g_context import GlobalsMiddleware, g\nimport logging\n\nlogging.basicConfig(level=logging.INFO)\n\napp = FastAPI()\napp.add_middleware(GlobalsMiddleware)\n\n\nasync def set_globals() -\u003e None:\n    g.username = \"JohnDoe\"\n    g.request_id = \"123456\"\n    g.is_admin = True\n    g.to_pop = \"dispensable\"\n\n\n@app.get(\"/\", dependencies=[Depends(set_globals)])\nasync def info():\n    # Iterate over globals like a dictionary\n    for name, value in g.items():\n        logging.info(f\"Global variable '{name}' has value: {value}\")\n\n    # Check for attributes/variables existence in globals\n    logging.info(f\"'username' is present in globals: {'username' in g}\")\n    logging.info(f\"'password' is present in globals: {'password' in g}\")\n\n    # Usage of .get() with a default value or not\n    logging.info(f\"'non_existing_with_default' is present in globals: {'non_existing_with_default' in g}\")\n    non_existing_get_with_default = g.get(\"non_existing_with_default\", \"non_existing_default\")\n    logging.info(f\"'non_existing_with_default' key has value: {non_existing_get_with_default}\")\n\n    # Default value defaults to None if not provided\n    logging.info(f\"'non_existing_none' is present in globals: {'non_existing_none' in g}\")\n    non_existing_get = g.get(\"non_existing_none\")\n    logging.info(f\"'non_existing_none' key has value: {non_existing_get}\")\n\n    # Usage of .pop() with a default value or not\n    logging.info(f\"'non_existing_with_default' is present in globals: {'non_existing_with_default' in g}\")\n    non_existing_pop_with_default = g.pop(\"non_existing_with_default\", \"non_existing_default\")\n    logging.info(f\"'non_existing_with_default' key has value: {non_existing_pop_with_default}\")\n\n    # Default value defaults to None if not provided\n    logging.info(f\"'non_existing_none' is present in globals: {'non_existing_none' in g}\")\n    non_existing_pop = g.pop(\"non_existing_none\")\n    logging.info(f\"'non_existing_none' key has value: {non_existing_pop}\")\n\n    # Accessing a non-set variable directly like an attribute will lead to an AttributeError\n    try:\n        logging.info(f\"'not_existing' is present in globals: {'not_existing' in g}\")\n        logging.info(g.not_existing)\n    except AttributeError as e:\n        logging.exception(e)\n\n    # Retrieve an already set variable as an attribute\n    logging.info(f\"'username' key has value: {g.username}\")\n\n    # Set a new variable\n    logging.info(f\"'new_key' is present in globals: {'new_key' in g}\")\n    g.new_key = \"new_value\"\n    logging.info(f\"'new_key' is present in globals: {'new_key' in g}\")\n\n    # Pop an existing variable\n    logging.info(f\"'to_pop' is present in globals: {'to_pop' in g}\")\n    key_to_pop = g.pop(\"to_pop\")\n    logging.info(f\"'to_pop' key has value: {key_to_pop}\")\n    logging.info(f\"'to_pop' is present in globals: {'to_pop' in g}\")\n\n    # List all global variable names\n    globals_keys = list(g.keys())\n\n    # List all global variable values\n    globals_values = list(g.values())\n\n    # Get all global variables as a dictionary\n    global_dict = g.to_dict()\n\n    return JSONResponse(\n        content={\n            \"global_keys\": globals_keys,\n            \"global_values\": globals_values,\n            \"global_dict\": global_dict\n        }\n    )\n```\n\nAfter running this example app with `uvicorn example:app --host 0.0.0.0 --port 8080 --reload ` and requesting the only endpoint that it serves:\n\n- The logs that are printed out:\n\n```text\nINFO:root:Global variable 'username' has value: JohnDoe\nINFO:root:Global variable 'request_id' has value: 123456\nINFO:root:Global variable 'is_admin' has value: True\nINFO:root:Global variable 'to_pop' has value: dispensable\nINFO:root:'username' is present in globals: True\nINFO:root:'password' is present in globals: False\nINFO:root:'non_existing_with_default' is present in globals: False\nINFO:root:'non_existing_with_default' key has value: non_existing_default\nINFO:root:'non_existing_none' is present in globals: False\nINFO:root:'non_existing_none' key has value: None\nINFO:root:'non_existing_with_default' is present in globals: False\nINFO:root:'non_existing_with_default' key has value: non_existing_default\nINFO:root:'non_existing_none' is present in globals: False\nINFO:root:'non_existing_none' key has value: None\nINFO:root:'not_existing' is present in globals: False\nERROR:root:'not_existing' variable does not exist in globals, make sure to set it before trying to use it\nTraceback (most recent call last):\n  File \"/path/to/example.py\", line 53, in info\n    logging.info(g.not_existing)\n                 ^^^^^^^^^^^^^^\n  File \"/path/to/fastapi_g_context.py\", line 41, in __getattr__\n    raise AttributeError(\nAttributeError: 'not_existing' variable does not exist in globals, make sure to set it before trying to use it\nINFO:root:'username' key has value: JohnDoe\nINFO:root:'new_key' is present in globals: False\nINFO:root:'new_key' is present in globals: True\nINFO:root:'to_pop' is present in globals: True\nINFO:root:'to_pop' key has value: dispensable\nINFO:root:'to_pop' is present in globals: False\n```\n\n- The response returned:\n```json\n{\n    \"global_keys\": [\n        \"username\",\n        \"request_id\",\n        \"is_admin\",\n        \"new_key\"\n    ],\n    \"global_values\": [\n        \"JohnDoe\",\n        \"123456\",\n        true,\n        \"new_value\"\n    ],\n    \"global_dict\": {\n        \"username\": \"JohnDoe\",\n        \"request_id\": \"123456\",\n        \"is_admin\": true,\n        \"new_key\": \"new_value\"\n    }\n}\n\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchrisk824%2Ffastapi-g-context","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchrisk824%2Ffastapi-g-context","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchrisk824%2Ffastapi-g-context/lists"}