{"id":13500201,"url":"https://github.com/daleal/symmetric","last_synced_at":"2025-03-29T05:33:16.511Z","repository":{"id":54393493,"uuid":"242027997","full_name":"daleal/symmetric","owner":"daleal","description":"A powerful tool to enable super fast module-to-API transformations. Learn in minutes, implement in seconds. Batteries included.","archived":true,"fork":false,"pushed_at":"2021-02-21T04:27:34.000Z","size":430,"stargazers_count":64,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-22T11:46:26.550Z","etag":null,"topics":["api","flask","openapi","pip","poetry","python","redoc"],"latest_commit_sha":null,"homepage":"https://symmetric.daleal.dev/","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/daleal.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":"2020-02-21T01:24:28.000Z","updated_at":"2025-02-02T09:55:13.000Z","dependencies_parsed_at":"2022-08-13T14:20:30.200Z","dependency_job_id":null,"html_url":"https://github.com/daleal/symmetric","commit_stats":null,"previous_names":[],"tags_count":23,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/daleal%2Fsymmetric","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/daleal%2Fsymmetric/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/daleal%2Fsymmetric/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/daleal%2Fsymmetric/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/daleal","download_url":"https://codeload.github.com/daleal/symmetric/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246145012,"owners_count":20730494,"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","flask","openapi","pip","poetry","python","redoc"],"created_at":"2024-07-31T22:00:53.107Z","updated_at":"2025-03-29T05:33:11.499Z","avatar_url":"https://github.com/daleal.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"# Symmetric\n\n![PyPI - Version](https://img.shields.io/pypi/v/symmetric?style=for-the-badge\u0026logo=python\u0026color=306998\u0026logoColor=%23fff\u0026label=version)\n![PyPI - Downloads](https://img.shields.io/pypi/dm/symmetric?style=for-the-badge\u0026logo=python\u0026color=306998\u0026logoColor=%23fff)\n\nA powerful tool to enable super fast module-to-**[API](https://en.wikipedia.org/wiki/Web_API)** transformations. Learn in minutes, implement in seconds. Batteries included.\n\n![Tests Workflow](https://img.shields.io/github/workflow/status/daleal/symmetric/tests?label=tests\u0026logo=github\u0026style=for-the-badge)\n![Linters Workflow](https://img.shields.io/github/workflow/status/daleal/symmetric/linters?label=linters\u0026logo=github\u0026style=for-the-badge)\n\n## Disclaimer\n\n`symmetric` is **no longer being maintained**. But don't worry! Its spiritual successor, [`asymmetric`](https://github.com/daleal/asymmetric), has an **essentially identical API**, and is faster, better designed, and has a bunch of new _features_. The `symmetric` token is the only _feature_ present in `symmetric` that won't be part of `asymmetric`. Other than that, you can port your code performing a search and replace, replacing all the appearances of `symmetric` for `asymmetric`. Thank you for being a part of this project! Hope to see you around [`asymmetric`](https://github.com/daleal/asymmetric)!\n\n## Why Symmetric?\n\nRaw developing speed and ease of use, that's why. `symmetric` is based on **[Flask](https://github.com/pallets/flask)**! While `Flask` is a powerful tool to have, getting it to work from scratch can be a bit of a pain, especially if you have never used it before. The idea behind `symmetric` is to be able to take any module **already written** and transform it into a working API in a matter of minutes, instead of having to design the module ground-up to work with `Flask` (it can also be used to build an API from scratch really fast). With `symmetric`, you will also get some neat features, namely:\n\n- Auto logging.\n- Server-side error detection and exception handling.\n- Auto-generated `/docs` endpoint for your API with **interactive documentation**.\n- Native support for an authentication token on a per-endpoint basis.\n- Auto-generated [OpenAPI Specification](https://swagger.io/docs/specification/about/) and Markdown documentation files for your API.\n\nThe [complete documentation](https://symmetric.daleal.dev/docs/) is available on the [official website](https://symmetric.daleal.dev/).\n\n## Installing\n\nInstall using pip!\n\n```bash\npip install symmetric\n```\n\n## Usage\n\n### Running the development server\n\nTo start the development server, just run:\n\n```bash\nsymmetric run \u003cmodule\u003e\n```\n\nWhere `\u003cmodule\u003e` is your module name (in the examples, we will be writing in a file named `module.py`, so the module name will be just `module`). A `Flask` instance will be spawned immediately and can be reached at [http://127.0.0.1:5000](http://127.0.0.1:5000) by default. We don't have any endpoints yet, so we'll add some later. **Do not use this in production**. The `Flask` server is meant for development only. Instead, you can use any `WSGI` server to run the API. For example, to run the API using [gunicorn](https://gunicorn.org/), you just need to run `gunicorn module:symmetric` and a production ready server will be spawned.\n\n### Defining the API endpoints\n\nThe module consists of a main object called `symmetric`, which includes an important element: the `router` decorator. Let's analyze it:\n\n```py\nfrom symmetric import symmetric\n\n@symmetric.router(\"/some-route\", methods=[\"post\"], response_code=200, auth_token=False)\n```\n\nThe decorator recieves 4 arguments: the `route` argument (the endpoint of the API to which the decorated function will map), the `methods` argument (a list of the methods accepted to connect to that endpoint, defaults in only `POST` requests), the `response_code` argument (the response code of the endpoint if everything goes according to the plan. Defaults to `200`) and the `auth_token` argument (a boolean stating if the endpoint requires authentication using a `symmetric` token. Defaults to `False`).\n\nNow let's imagine that we have the following method:\n\n```py\ndef some_function():\n    \"\"\"Greets the world.\"\"\"\n    return \"Hello World!\"\n```\n\nTo transform that method into an API endpoint, all you need to do is add one line:\n\n```py\n@symmetric.router(\"/sample\", methods=[\"get\"])\ndef some_function():\n    \"\"\"Greets the world.\"\"\"\n    return \"Hello World!\"\n```\n\nRun `symmetric run module` and send a `GET` request to `http://127.0.0.1:5000/sample`. You should get a `Hello World!` in response! (To try it with a browser, make sure to run the above command and click [this link](http://127.0.0.1:5000/sample)).\n\nBut what about methods with arguments? Of course they can be API'd too! Let's now say that you have the following function:\n\n```py\ndef another_function(a, b=372):\n    \"\"\"\n    Adds :a and :b and returns the result of\n    that operation.\n    \"\"\"\n    return a + b\n```\n\nTo transform that method into an API endpoint, all you need to do, again, is add one line:\n\n```py\n@symmetric.router(\"/add\")\ndef another_function(a, b=372):\n    \"\"\"\n    Adds :a and :b and returns the result of\n    that operation.\n    \"\"\"\n    return a + b\n```\n\n### Querying API endpoints\n\nTo give parameters to a function, all we need to do is send a `json` body with the names of the parameters as keys. Let's see how! Run `symmetric run module` and send a `POST` request (the default `HTTP` method) to `http://127.0.0.1:5000/add`, now using the `requests` module.\n\n```python\nimport requests\n\npayload = {\n    \"a\": 48,\n    \"b\": 21\n}\nresponse = requests.post(\"http://127.0.0.1:5000/add\", json=payload)\nprint(response.json())\n```\n\nWe got a `69` response! (`48 + 21 = 69`). Of course, you can return dictionaries from your methods and those will get returned as a `json` body in the response object **automagically**!\n\nWith this in mind, you can transform any existing project into a usable API very quickly!\n\n## ReDoc Documentation\n\nBy default, you can `GET` the `/docs` endpoint (using a browser) to access to **interactive auto-generated documentation** about your API. It will include request bodies for each endpoint, response codes, authentication required, default values, and much more!\n\n**Tip**: Given that the [ReDoc Documentation](https://github.com/Redocly/redoc) is based on the OpenAPI standard, using **type annotations** in your code will result in a more detailed interactive documentation. Instead of the parameters being allowed to be any type, they will be forced into the type declared in your code. Cool, right?\n\n## Developing\n\nClone the repository:\n\n```bash\ngit clone https://github.com/daleal/symmetric.git\n\ncd symmetric\n```\n\nRecreate environment:\n\n```bash\n./environment.sh\n\n. .venv/bin/activate\n```\n\nTest install:\n\n```bash\npoetry install  # will also install the symmetric CLI\n```\n\nRun the tests:\n\n```bash\npython -m unittest\n```\n\n## Resources\n\n- [Official Website](https://symmetric.daleal.dev/)\n- [Issue Tracker](https://github.com/daleal/symmetric/issues/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdaleal%2Fsymmetric","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdaleal%2Fsymmetric","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdaleal%2Fsymmetric/lists"}