# fastapi-listing
Advanced items listing library that gives you freedom to design complex listing APIs that can be read by human.
[![.github/workflows/deploy.yml](https://github.com/danielhasan1/fastapi-listing/actions/workflows/deploy.yml/badge.svg)](https://github.com/danielhasan1/fastapi-listing/actions/workflows/deploy.yml)
[![.github/workflows/tests.yml](https://github.com/danielhasan1/fastapi-listing/actions/workflows/tests.yml/badge.svg)](https://github.com/danielhasan1/fastapi-listing/actions/workflows/tests.yml) ![PyPI - Programming Language](https://img.shields.io/pypi/pyversions/fastapi-listing.svg?color=%2334D058)
[![codecov](https://codecov.io/gh/danielhasan1/fastapi-listing/branch/dev/graph/badge.svg?token=U29ZRNAH8I)](https://codecov.io/gh/danielhasan1/fastapi-listing) [![Downloads](https://static.pepy.tech/badge/fastapi-listing)](https://pepy.tech/project/fastapi-listing)
➡️ Craft powerful Listing REST APIs designed to serve websites akin to Stack Overflow:
![](https://drive.google.com/uc?export=view&id=1sCkzxi7OirmtA9gGM0LlK9dryI1dlU4U)
Comes with:
- pre defined filters
- pre defined paginator
- pre defined sorter
## Advantage
- simplify the intricate process of designing and developing complex listing APIs
- Design components(USP) and plug them from anywhere
- Components can be **reusable**
- Best for fast changing needs
## Usage
➡️ With the New Compact Version(Older version was provided with a guide style which is supported by this version as well)
create your listing API in 2 easy steps 🥳
1️⃣ Create a Dao (Data Access Object) layer (a simple class)
```python
from fastapi_listing.dao import GenericDao
from app.model import Employee
# your dao (data access object) placed here for the sake of example
class EmployeeDao(GenericDao):
"""write your data layer access logic here. keep it raw!"""
name = "employee"
model = Employee # your sqlalchemy model, support for more orm is coming soon
```
2️⃣ Just call `FastapiListing`
```python
from fastapi import FastAPI, Depends
from sqlalchemy.orm import Session
# import fastapi-listing dependencies
from fastapi_listing.paginator import ListingPage # default pydantic page model, you can create/extend your own
from fastapi_listing import FastapiListing, MetaInfo
app = FastAPI() # create FastAPI app
def get_db() -> Session:
"""
replicating sessionmaker for any fastapi app.
anyone could be using a different way or opensource packages to produce sessions.
it all comes down to a single result that is yielding a session.
for the sake of simplicity and testing purpose I'm replicating this behaviour in this way.
:return: Session
"""
# your pydantic response class if you are using one
# Supports pydantic v2
class EmployeeListDetails(BaseModel):
emp_no: int = Field(alias="empid", title="Employee ID")
birth_date: date = Field(alias="bdt", title="Birth Date")
first_name: str = Field(alias="fnm", title="First Name")
last_name: str = Field(alias="lnm", title="Last Name")
gender: str = Field(alias="gdr", title="Gender")
hire_date: date = Field(alias="hdt", title="Hiring Date")
class Config:
orm_mode = True
allow_population_by_field_name = True
@app.get("/employees", response_model=ListingPage[EmployeeListDetails])
def get_employees(db=Depends(get_db)):
dao = EmployeeDao(read_db=db)
# passing pydantic serializer is optional, automatically generates a
# select query based on pydantic class fields for easy cases like columns of same table
return FastapiListing(dao=dao, pydantic_serializer=EmployeeListDetails
).get_response(MetaInfo(default_srt_on="emp_no"))
```
Voila 🎉 your very first listing response(that's even extensible user can manipulate default page structure)
![](https://drive.google.com/uc?export=view&id=1amgrAdGP7WvXfiNlCYJZPC9fz4_1CidE)
Your pydantic class contains some dynamic fields that you populate at runtime❓️
```python
@app.get("/employees", response_model=ListingPage[EmployeeListDetails])
def get_employees(db=Depends(get_db)):
dao = EmployeeDao(read_db=db)
return FastapiListing(dao=dao,
pydantic_serializer=EmployeeListDetails, # optional
custom_fields=True # just tell fastapi-listing that your model contains custom_fields
).get_response(MetaInfo(default_srt_on="emp_no"))
```
Auto generated query doesn't fulfil your use case❓️
```python
class EmployeeDao(GenericDao):
"""write your data layer access logic here. keep it raw!"""
name = "employee"
model = Employee
def get_default_read(self, fields_to_read: Optional[list]):
"""
Extend and return your query from here.
Use it when use cases are comparatively easier than complex.
Alternatively fastapi-listing provides a robust way to write performance packed queries
for complex APIs which we will look at later.
"""
query = self._read_db.query(Employee)
return query
```
```python
@app.get("/employees", response_model=ListingPage[EmployeeListDetails])
def get_employees(db=Depends(get_db)):
dao = EmployeeDao(read_db=db)
return FastapiListing(dao=dao).get_response(MetaInfo(default_srt_on="emp_no"))
```
## Thinking about adding filters???
Don't worry I've got you covered😎
➡️ Say you want to add filter on Employee for:
1. gender - return only **Employees** belonging to 'X' gender where X could be anything.
2. DOB - return **Employees** belonging to a specific range of DOB.
3. First Name - return **Employees** only starting with specific first names.
```python
from fastapi_listing.filters import generic_filters # collection of inbuilt filters
from fastapi_listing.factory import filter_factory # import filter_factory to register filter against a listing
# {"alias": ("<model.field>", "<filter_definition>")}
emp_filter_mapper = {
"gdr": ("Employee.gender", generic_filters.EqualityFilter),
"bdt": ("Employee.birth_date", generic_filters.MySqlNativeDateFormateRangeFilter),
"fnm": ("Employee.first_name", generic_filters.StringStartsWithFilter),
}
filter_factory.register_filter_mapper(emp_filter_mapper) # You just registered the number of filters allowed to client on this listing
@app.get("/employees", response_model=ListingPage[EmployeeListDetails])
def get_employees(request: Request, db=Depends(get_db)):
"""
request is optional to pass.
you can pass filter query_param or use request object.
make fastapi-listing adapt to your client existing query_param format
"""
dao = EmployeeDao(read_db=db)
return FastapiListing(request=request, dao=dao).get_response(
MetaInfo(default_srt_on="emp_no", filter_mapper=emp_filter_mapper))
```
Thinking about how fastapi-listing reads filter/sorter/paginator params❓️
```python
# Extend adapter to make fastapi-listing adapt your existing clients
# default implementation
from fastapi_listing.service.adapters import CoreListingParamsAdapter
class YourAdapterClass(CoreListingParamsAdapter): # Extend to add your behaviour
"""Utilise this adapter class to make your remote client site:
- filter,
- sorter,
- paginator.
query params adapt to fastapi listing library.
With this you can utilise same listing api to multiple remote client
even if it's a front end server or other backend server.
core service is always going to request one of the following fundamental key
- sort
- filter
- pagination
depending upon this return the appropriate transformed client param back to fastapi listing
supported formats for
filter:
simple filter - [{"field":"<key used in filter mapper>", "value":{"search":"<client param>"}}, ...]
if you are using a range filter -
[{"field":"<key used in filter mapper>", "value":{"start":"<start range>", "end": "<end range>"}}, ...]
if you are using a list filter i.e. search on given items
[{"field":"<key used in filter mapper>", "value":{"list":["<client params>"]}}, ...]
sort:
[{"field":<"key used in sort mapper>", "type":"asc or "dsc"}, ...]
by default single sort allowed you can change it by extending sort interceptor
pagination:
{"pageSize": <integer page size>, "page": <integer page number 1 based>}
"""
def get(self, key: Literal["sort", "filter", "pagination"]):
"""
@param key: Literal["sort", "filter", "pagination"]
@return: List[Optional[dict]] for filter/sort and dict for paginator
"""
return utils.dictify_query_params(self.dependency.get(key))
```
Pass request or extract feature(filter/sorter/paginator) params at router and pass them as kwargs
```python
@app.get("/employees", response_model=ListingPage[EmployeeListDetails])
def get_employees(request: Request, db=Depends(get_db)):
params = request.query_params
# filter, sort. pagination = params.get("filter"), params.get("sort"), params.get("paginator")
# you can pass above args as kwargs in MetaInfo
dao = EmployeeDao(read_db=db)
return FastapiListing(request=request, dao=dao).get_response(
MetaInfo(default_srt_on="emp_no", filter_mapper=emp_filter_mapper, feature_params_adapter=YourAdapterClass))
```
Check out [docs](https://fastapi-listing.readthedocs.io/en/latest/tutorials.html#adding-filters-to-your-listing-api) for supported list of filters.
Additionally, you can create **custom filters** as well.
## Thinking about adding Sorting???
I won't leave you hanging there as well😎
```python
@app.get("/employees", response_model=ListingPage[EmployeeListDetails])
def get_employees(request: Request, db=Depends(get_db)):
# define it here or anywhere
emp_sort_mapper = {
"cd": "Employee.emp_no",
"bdt": "Employee.birth_date"
}
dao = EmployeeDao(read_db=db)
return FastapiListing(request=request, dao=dao).get_response(
MetaInfo(default_srt_on="emp_no", filter_mapper=emp_filter_mapper, feature_params_adapter=YourAdapterClass,
sort_mapper=emp_sort_mapper))
```
## Provided features are not meeting your requirements???
It is customizable.😎
➡️ You can write custom:
* Query
* Filter
* Sorter
* Paginator
You can check out customisation section in docs after going through basics and tutorials.
Check out my other [repo](https://github.com/danielhasan1/test-fastapi-listing/blob/master/app/router/router.py) to see some examples
## Features and Readability hand in hand 🤝
- Easy-to-use API for listing and formatting data
- Built-in support for pagination, sorting and filtering
- Well defined interface for filter, sorter, paginator
- Support Dependency Injection for easy testing
- Room to adapt the existing remote client query param semantics
- Write standardise listing APIs that will be understood by generations of upcoming developers
- Write listing features which is easy on human mind to extend or understand
- Break down the most complex listing data APIs into digestible piece of code
With FastAPI Listing you won't end up like
<img src="https://drive.google.com/uc?export=view&id=1C2ZHltxpdyq4YmBsnbOu4HF9JGt6uMfQ" width="600" height="600"/>
# Documentation
View full documentation at: https://fastapi-listing.readthedocs.io ███▓▓░️░️░35%️░️░️░️
# Feedback, Questions?
Any form of feedback and questions are welcome! Please create an issue 💭
[here](https://github.com/danielhasan1/fastapi-listing/issues/new).
Raw data
{
"_id": null,
"home_page": "https://github.com/danielhasan1/fastapi-listing",
"name": "fastapi-listing",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.7",
"maintainer_email": "",
"keywords": "starlette,fastapi,pydantic,sqlalchemy",
"author": "Danish Hasan",
"author_email": "dh813030@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/49/de/8c96dcb1a60547e96867366f340b22015780c982ace074a569fd4b2cc725/fastapi-listing-0.3.2.tar.gz",
"platform": null,
"description": "# fastapi-listing\n\nAdvanced items listing library that gives you freedom to design complex listing APIs that can be read by human.\n\n[![.github/workflows/deploy.yml](https://github.com/danielhasan1/fastapi-listing/actions/workflows/deploy.yml/badge.svg)](https://github.com/danielhasan1/fastapi-listing/actions/workflows/deploy.yml)\n[![.github/workflows/tests.yml](https://github.com/danielhasan1/fastapi-listing/actions/workflows/tests.yml/badge.svg)](https://github.com/danielhasan1/fastapi-listing/actions/workflows/tests.yml) ![PyPI - Programming Language](https://img.shields.io/pypi/pyversions/fastapi-listing.svg?color=%2334D058)\n[![codecov](https://codecov.io/gh/danielhasan1/fastapi-listing/branch/dev/graph/badge.svg?token=U29ZRNAH8I)](https://codecov.io/gh/danielhasan1/fastapi-listing) [![Downloads](https://static.pepy.tech/badge/fastapi-listing)](https://pepy.tech/project/fastapi-listing)\n\n\u27a1\ufe0f Craft powerful Listing REST APIs designed to serve websites akin to Stack Overflow:\n\n![](https://drive.google.com/uc?export=view&id=1sCkzxi7OirmtA9gGM0LlK9dryI1dlU4U)\n\nComes with:\n- pre defined filters\n- pre defined paginator\n- pre defined sorter\n\n## Advantage\n- simplify the intricate process of designing and developing complex listing APIs\n- Design components(USP) and plug them from anywhere\n- Components can be **reusable**\n- Best for fast changing needs\n\n## Usage\n\n\u27a1\ufe0f With the New Compact Version(Older version was provided with a guide style which is supported by this version as well)\ncreate your listing API in 2 easy steps \ud83e\udd73\n\n1\ufe0f\u20e3 Create a Dao (Data Access Object) layer (a simple class)\n\n```python\nfrom fastapi_listing.dao import GenericDao\nfrom app.model import Employee\n\n\n# your dao (data access object) placed here for the sake of example\nclass EmployeeDao(GenericDao):\n \"\"\"write your data layer access logic here. keep it raw!\"\"\"\n name = \"employee\"\n model = Employee # your sqlalchemy model, support for more orm is coming soon\n```\n2\ufe0f\u20e3 Just call `FastapiListing`\n\n```python\nfrom fastapi import FastAPI, Depends\nfrom sqlalchemy.orm import Session\n\n# import fastapi-listing dependencies\nfrom fastapi_listing.paginator import ListingPage # default pydantic page model, you can create/extend your own\nfrom fastapi_listing import FastapiListing, MetaInfo\n\napp = FastAPI() # create FastAPI app\n\ndef get_db() -> Session:\n \"\"\"\n replicating sessionmaker for any fastapi app.\n anyone could be using a different way or opensource packages to produce sessions.\n it all comes down to a single result that is yielding a session.\n for the sake of simplicity and testing purpose I'm replicating this behaviour in this way.\n :return: Session\n \"\"\"\n\n\n\n# your pydantic response class if you are using one\n# Supports pydantic v2\nclass EmployeeListDetails(BaseModel):\n emp_no: int = Field(alias=\"empid\", title=\"Employee ID\")\n birth_date: date = Field(alias=\"bdt\", title=\"Birth Date\")\n first_name: str = Field(alias=\"fnm\", title=\"First Name\")\n last_name: str = Field(alias=\"lnm\", title=\"Last Name\")\n gender: str = Field(alias=\"gdr\", title=\"Gender\")\n hire_date: date = Field(alias=\"hdt\", title=\"Hiring Date\")\n\n class Config:\n orm_mode = True\n allow_population_by_field_name = True\n \n@app.get(\"/employees\", response_model=ListingPage[EmployeeListDetails])\ndef get_employees(db=Depends(get_db)):\n dao = EmployeeDao(read_db=db)\n # passing pydantic serializer is optional, automatically generates a\n # select query based on pydantic class fields for easy cases like columns of same table\n return FastapiListing(dao=dao, pydantic_serializer=EmployeeListDetails\n ).get_response(MetaInfo(default_srt_on=\"emp_no\")) \n```\n\nVoila \ud83c\udf89 your very first listing response(that's even extensible user can manipulate default page structure)\n\n![](https://drive.google.com/uc?export=view&id=1amgrAdGP7WvXfiNlCYJZPC9fz4_1CidE)\n\n\nYour pydantic class contains some dynamic fields that you populate at runtime\u2753\ufe0f\n\n```python\n@app.get(\"/employees\", response_model=ListingPage[EmployeeListDetails])\ndef get_employees(db=Depends(get_db)):\n dao = EmployeeDao(read_db=db)\n return FastapiListing(dao=dao,\n pydantic_serializer=EmployeeListDetails, # optional\n custom_fields=True # just tell fastapi-listing that your model contains custom_fields\n ).get_response(MetaInfo(default_srt_on=\"emp_no\"))\n```\n\nAuto generated query doesn't fulfil your use case\u2753\ufe0f\n\n```python\nclass EmployeeDao(GenericDao):\n \"\"\"write your data layer access logic here. keep it raw!\"\"\"\n name = \"employee\"\n model = Employee\n \n def get_default_read(self, fields_to_read: Optional[list]):\n \"\"\"\n Extend and return your query from here.\n Use it when use cases are comparatively easier than complex.\n Alternatively fastapi-listing provides a robust way to write performance packed queries \n for complex APIs which we will look at later.\n \"\"\"\n query = self._read_db.query(Employee)\n return query\n```\n\n```python\n@app.get(\"/employees\", response_model=ListingPage[EmployeeListDetails])\ndef get_employees(db=Depends(get_db)):\n dao = EmployeeDao(read_db=db)\n return FastapiListing(dao=dao).get_response(MetaInfo(default_srt_on=\"emp_no\"))\n```\n\n\n## Thinking about adding filters???\nDon't worry I've got you covered\ud83d\ude0e\n\n\u27a1\ufe0f Say you want to add filter on Employee for:\n1. gender - return only **Employees** belonging to 'X' gender where X could be anything.\n2. DOB - return **Employees** belonging to a specific range of DOB.\n3. First Name - return **Employees** only starting with specific first names.\n```python\nfrom fastapi_listing.filters import generic_filters # collection of inbuilt filters\nfrom fastapi_listing.factory import filter_factory # import filter_factory to register filter against a listing\n\n# {\"alias\": (\"<model.field>\", \"<filter_definition>\")}\nemp_filter_mapper = {\n \"gdr\": (\"Employee.gender\", generic_filters.EqualityFilter),\n \"bdt\": (\"Employee.birth_date\", generic_filters.MySqlNativeDateFormateRangeFilter),\n \"fnm\": (\"Employee.first_name\", generic_filters.StringStartsWithFilter),\n}\nfilter_factory.register_filter_mapper(emp_filter_mapper) # You just registered the number of filters allowed to client on this listing\n\n\n@app.get(\"/employees\", response_model=ListingPage[EmployeeListDetails])\ndef get_employees(request: Request, db=Depends(get_db)):\n \"\"\"\n request is optional to pass.\n you can pass filter query_param or use request object.\n make fastapi-listing adapt to your client existing query_param format\n \"\"\"\n dao = EmployeeDao(read_db=db)\n return FastapiListing(request=request, dao=dao).get_response(\n MetaInfo(default_srt_on=\"emp_no\", filter_mapper=emp_filter_mapper))\n \n```\n\nThinking about how fastapi-listing reads filter/sorter/paginator params\u2753\ufe0f\n\n```python\n# Extend adapter to make fastapi-listing adapt your existing clients\n\n# default implementation\n\nfrom fastapi_listing.service.adapters import CoreListingParamsAdapter\n\nclass YourAdapterClass(CoreListingParamsAdapter): # Extend to add your behaviour\n \"\"\"Utilise this adapter class to make your remote client site:\n - filter,\n - sorter,\n - paginator.\n query params adapt to fastapi listing library.\n With this you can utilise same listing api to multiple remote client\n even if it's a front end server or other backend server.\n\n core service is always going to request one of the following fundamental key\n - sort\n - filter\n - pagination\n depending upon this return the appropriate transformed client param back to fastapi listing\n supported formats for\n filter:\n simple filter - [{\"field\":\"<key used in filter mapper>\", \"value\":{\"search\":\"<client param>\"}}, ...]\n if you are using a range filter -\n [{\"field\":\"<key used in filter mapper>\", \"value\":{\"start\":\"<start range>\", \"end\": \"<end range>\"}}, ...]\n if you are using a list filter i.e. search on given items\n [{\"field\":\"<key used in filter mapper>\", \"value\":{\"list\":[\"<client params>\"]}}, ...]\n\n sort:\n [{\"field\":<\"key used in sort mapper>\", \"type\":\"asc or \"dsc\"}, ...]\n by default single sort allowed you can change it by extending sort interceptor\n\n pagination:\n {\"pageSize\": <integer page size>, \"page\": <integer page number 1 based>}\n \"\"\"\n \n def get(self, key: Literal[\"sort\", \"filter\", \"pagination\"]):\n \"\"\"\n @param key: Literal[\"sort\", \"filter\", \"pagination\"]\n @return: List[Optional[dict]] for filter/sort and dict for paginator\n \"\"\"\n return utils.dictify_query_params(self.dependency.get(key))\n\n```\nPass request or extract feature(filter/sorter/paginator) params at router and pass them as kwargs\n\n```python\n\n@app.get(\"/employees\", response_model=ListingPage[EmployeeListDetails])\ndef get_employees(request: Request, db=Depends(get_db)):\n params = request.query_params\n # filter, sort. pagination = params.get(\"filter\"), params.get(\"sort\"), params.get(\"paginator\")\n # you can pass above args as kwargs in MetaInfo\n dao = EmployeeDao(read_db=db)\n return FastapiListing(request=request, dao=dao).get_response(\n MetaInfo(default_srt_on=\"emp_no\", filter_mapper=emp_filter_mapper, feature_params_adapter=YourAdapterClass))\n \n```\n\nCheck out [docs](https://fastapi-listing.readthedocs.io/en/latest/tutorials.html#adding-filters-to-your-listing-api) for supported list of filters.\nAdditionally, you can create **custom filters** as well.\n\n## Thinking about adding Sorting???\nI won't leave you hanging there as well\ud83d\ude0e\n```python\n@app.get(\"/employees\", response_model=ListingPage[EmployeeListDetails])\ndef get_employees(request: Request, db=Depends(get_db)):\n # define it here or anywhere\n emp_sort_mapper = {\n \"cd\": \"Employee.emp_no\",\n \"bdt\": \"Employee.birth_date\"\n }\n dao = EmployeeDao(read_db=db)\n return FastapiListing(request=request, dao=dao).get_response(\n MetaInfo(default_srt_on=\"emp_no\", filter_mapper=emp_filter_mapper, feature_params_adapter=YourAdapterClass,\n sort_mapper=emp_sort_mapper))\n```\n\n## Provided features are not meeting your requirements???\n\nIt is customizable.\ud83d\ude0e\n\n\u27a1\ufe0f You can write custom:\n\n* Query\n* Filter\n* Sorter\n* Paginator\n\nYou can check out customisation section in docs after going through basics and tutorials.\n\nCheck out my other [repo](https://github.com/danielhasan1/test-fastapi-listing/blob/master/app/router/router.py) to see some examples\n\n## Features and Readability hand in hand \ud83e\udd1d\n\n - Easy-to-use API for listing and formatting data\n - Built-in support for pagination, sorting and filtering\n - Well defined interface for filter, sorter, paginator\n - Support Dependency Injection for easy testing\n - Room to adapt the existing remote client query param semantics\n - Write standardise listing APIs that will be understood by generations of upcoming developers\n - Write listing features which is easy on human mind to extend or understand\n - Break down the most complex listing data APIs into digestible piece of code \n\nWith FastAPI Listing you won't end up like\n\n<img src=\"https://drive.google.com/uc?export=view&id=1C2ZHltxpdyq4YmBsnbOu4HF9JGt6uMfQ\" width=\"600\" height=\"600\"/>\n\n# Documentation\nView full documentation at: https://fastapi-listing.readthedocs.io \u2588\u2588\u2588\u2593\u2593\u2591\ufe0f\u2591\ufe0f\u259135%\ufe0f\u2591\ufe0f\u2591\ufe0f\u2591\ufe0f\n\n\n\n# Feedback, Questions?\n\nAny form of feedback and questions are welcome! Please create an issue \ud83d\udcad\n[here](https://github.com/danielhasan1/fastapi-listing/issues/new).\n",
"bugtrack_url": null,
"license": "",
"summary": "Advaned Data Listing Library for FastAPI",
"version": "0.3.2",
"project_urls": {
"Homepage": "https://github.com/danielhasan1/fastapi-listing"
},
"split_keywords": [
"starlette",
"fastapi",
"pydantic",
"sqlalchemy"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "14c18a65c2f4ac6588bb4a761438ce5e69d19d1c4e94881f38767c3084dae140",
"md5": "aa3af02c7e4390306e4b8eb433b2d178",
"sha256": "6b2ddcbfc5b4a60877e9d8e3eda112d6bdd341fd4f35890d7d36caeecdb18780"
},
"downloads": -1,
"filename": "fastapi_listing-0.3.2-py3-none-any.whl",
"has_sig": false,
"md5_digest": "aa3af02c7e4390306e4b8eb433b2d178",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.7",
"size": 52040,
"upload_time": "2024-01-30T10:49:33",
"upload_time_iso_8601": "2024-01-30T10:49:33.872622Z",
"url": "https://files.pythonhosted.org/packages/14/c1/8a65c2f4ac6588bb4a761438ce5e69d19d1c4e94881f38767c3084dae140/fastapi_listing-0.3.2-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "49de8c96dcb1a60547e96867366f340b22015780c982ace074a569fd4b2cc725",
"md5": "f03c905c43ac94392587e2d58119facd",
"sha256": "5535a9aff110e38c1ca830ceac08d159330bb3a1bdb14bcd16bd3c9a9c4704ae"
},
"downloads": -1,
"filename": "fastapi-listing-0.3.2.tar.gz",
"has_sig": false,
"md5_digest": "f03c905c43ac94392587e2d58119facd",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.7",
"size": 40766,
"upload_time": "2024-01-30T10:49:35",
"upload_time_iso_8601": "2024-01-30T10:49:35.731193Z",
"url": "https://files.pythonhosted.org/packages/49/de/8c96dcb1a60547e96867366f340b22015780c982ace074a569fd4b2cc725/fastapi-listing-0.3.2.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-01-30 10:49:35",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "danielhasan1",
"github_project": "fastapi-listing",
"travis_ci": false,
"coveralls": true,
"github_actions": true,
"lcname": "fastapi-listing"
}