Skip to content

Commit 8e40593

Browse files
Add README.md with usage instructions, development guide, and simple API reference.
1 parent 05fc920 commit 8e40593

File tree

1 file changed

+227
-0
lines changed

1 file changed

+227
-0
lines changed

README.md

Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
# asgi-user-agents
2+
3+
[![CI](https://github.com/hasansezertasan/asgi-user-agents/actions/workflows/ci.yml/badge.svg)](https://github.com/hasansezertasan/asgi-user-agents/actions?query=event%3Apush+branch%3Amain+workflow%3ACI)
4+
[![Coverage](https://img.shields.io/codecov/c/github/hasansezertasan/asgi-user-agents)](https://codecov.io/gh/hasansezertasan/asgi-user-agents)
5+
[![PyPI - Version](https://img.shields.io/pypi/v/asgi-user-agents.svg)](https://pypi.org/project/asgi-user-agents)
6+
[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/asgi-user-agents.svg)](https://pypi.org/project/asgi-user-agents)
7+
[![License](https://img.shields.io/github/license/hasansezertasan/asgi-user-agents.svg)](https://github.com/hasansezertasan/asgi-user-agents/blob/main/LICENSE)
8+
[![Latest Commit](https://img.shields.io/github/last-commit/hasansezertasan/asgi-user-agents)](https://github.com/hasansezertasan/asgi-user-agents)
9+
10+
[![Downloads](https://pepy.tech/badge/asgi-user-agents)](https://pepy.tech/project/asgi-user-agents)
11+
[![Downloads/Month](https://pepy.tech/badge/asgi-user-agents/month)](https://pepy.tech/project/asgi-user-agents)
12+
[![Downloads/Week](https://pepy.tech/badge/asgi-user-agents/week)](https://pepy.tech/project/asgi-user-agents)
13+
14+
[User Agents][python-user-agents] integration for [ASGI](https://asgi.readthedocs.io/en/latest/) applications. Works with Starlette, FastAPI, Quart, Litestar -- or any other web framework supporting ASGI that exposes the ASGI `scope`.
15+
16+
-----
17+
18+
## Table of Contents
19+
20+
- [asgi-user-agents](#asgi-user-agents)
21+
- [Table of Contents](#table-of-contents)
22+
- [Installation](#installation)
23+
- [How does it work?](#how-does-it-work)
24+
- [Usage](#usage)
25+
- [API Reference](#api-reference)
26+
- [`UAMiddleware`](#uamiddleware)
27+
- [`UADetails`](#uadetails)
28+
- [`UARequest`](#uarequest)
29+
- [Development](#development)
30+
- [Author](#author)
31+
- [Credits](#credits)
32+
- [Analysis](#analysis)
33+
- [License](#license)
34+
35+
## Installation
36+
37+
**NOTE**: This is alpha software. Please be sure to pin your dependencies.
38+
39+
> Latest Release
40+
41+
```bash
42+
pip install asgi-user-agents
43+
```
44+
45+
> Development Version
46+
47+
```bash
48+
pip install git+https://github.com/hasansezertasan/asgi-user-agents.git
49+
```
50+
51+
## How does it work?
52+
53+
It simply adds a `ua` attribute to the request scope. This attribute is an instance of the `UADetails` class which abstracts the `UserAgent` class from the `user-agents` package 📄.
54+
55+
## Usage
56+
57+
It's pretty simple. Just add the middleware to your ASGI application and access the `ua` attribute from the request scope.
58+
59+
```python
60+
from asgi_user_agents import UAMiddleware
61+
from asgi_user_agents import UARequest as Request
62+
from fastapi.applications import FastAPI
63+
from starlette.middleware import Middleware
64+
from starlette.responses import JSONResponse, Response
65+
66+
67+
app = FastAPI(middleware=[Middleware(UAMiddleware)])
68+
69+
70+
@app.get("/")
71+
async def index(request: Request) -> Response:
72+
ua = request.scope["ua"]
73+
data = {
74+
"ua_string": ua.ua_string,
75+
"os": ua.os,
76+
"os.family": ua.os.family,
77+
"os.version": ua.os.version,
78+
"os.version_string": ua.os.version_string,
79+
"browser": ua.browser,
80+
"browser.family": ua.ua.browser.family,
81+
"browser.version": ua.ua.browser.version,
82+
"browser.version_string": ua.ua.browser.version_string,
83+
"device": ua.device,
84+
"device.family": ua.device.family,
85+
"device.brand": ua.device.brand,
86+
"device.model": ua.device.model,
87+
"is_provided": ua.is_provided,
88+
"is_tablet": ua.is_tablet,
89+
"is_mobile": ua.is_mobile,
90+
"is_touch_capable": ua.is_touch_capable,
91+
"is_pc": ua.is_pc,
92+
"is_bot": ua.is_bot,
93+
"is_email_client": ua.is_email_client,
94+
}
95+
return JSONResponse(data)
96+
97+
```
98+
99+
## API Reference
100+
101+
### `UAMiddleware`
102+
103+
An ASGI middleware that sets `scope["ua"]` to an instance of [`UADetails`](#uadetails) (`scope` refers to the ASGI scope).
104+
105+
```python
106+
app = UAMiddleware(app)
107+
```
108+
109+
### `UADetails`
110+
111+
A helper that provides shortcuts for accessing [`User-Agent` request header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent).
112+
113+
```python
114+
ua = UADetails(scope)
115+
```
116+
117+
- `ua: UserAgent` - The `UserAgent` instance from the `user-agents` package.
118+
- `ua_string: str` - The user agent string.
119+
- `is_provided: bool` - `True` if the user agent string is provided.
120+
- `os: OperatingSystem` - The operating system details of the user agent. It's a named tuple with the following fields:
121+
- `family: str` - The family of the operating system.
122+
- `version: str` - The version of the operating system.
123+
- `version_string: str` - The version of the operating system as a string.
124+
- `browser: Browser` - The browser details of the user agent. It's a named tuple with the following fields:
125+
- `family: str` - The family of the browser.
126+
- `version: str` - The version of the browser.
127+
- `version_string: str` - The version of the browser as a string.
128+
- `device: Device` - The device details of the user agent. It's a named tuple with the following fields:
129+
- `family: str` - The family of the device.
130+
- `brand: str` - The brand of the device.
131+
- `model: str` - The model of the device.
132+
- `is_tablet: bool` - `True` if the request was made by a tablet.
133+
- `is_mobile: bool` - `True` if the request was made by a mobile device.
134+
- `is_touch_capable: bool` - `True` if the request was made by a touch-capable device.
135+
- `is_pc: bool` - `True` if the request was made by a PC.
136+
- `is_bot: bool` - `True` if the request was made by a bot.
137+
- `is_email_client: bool` - `True` if the request was made by an email client.
138+
139+
### `UARequest`
140+
141+
For Starlette-based frameworks, use this instead of the standard `starlette.requests.Request` so that code editors understand that `request.scope["ua"]` contains an `UADetails` instance:
142+
143+
```python
144+
from asgi_user_agents import UARequest as Request
145+
146+
async def home(request: Request):
147+
reveal_type(request.scope["ua"]) # Revealed type is 'UADetails'
148+
```
149+
150+
## Development
151+
152+
Clone the repository and cd into the project directory:
153+
154+
```bash
155+
git clone https://github.com/hasansezertasan/asgi-user-agents
156+
cd asgi-user-agents
157+
```
158+
159+
Install hatch, you can follow the instructions [here](https://hatch.pypa.io/latest/install/), or simply run the following command:
160+
161+
```bash
162+
pipx install hatch
163+
```
164+
165+
Initialize the environment and install the dependencies:
166+
167+
```bash
168+
hatch shell
169+
```
170+
171+
Initialize pre-commit hooks by running the following command:
172+
173+
```bash
174+
pre-commit install
175+
```
176+
177+
Make your changes on a new branch and run the tests:
178+
179+
```bash
180+
hatch test -a
181+
```
182+
183+
Make sure that the code is typed, linted, and formatted correctly:
184+
185+
```bash
186+
hatch run types:all
187+
```
188+
189+
Stage your changes and commit them:
190+
191+
```bash
192+
git add .
193+
git commit -m "Your message"
194+
```
195+
196+
Push your changes to the repository:
197+
198+
```bash
199+
git push
200+
```
201+
202+
Create a pull request and wait for the review 🤓.
203+
204+
## Author
205+
206+
- [Hasan Sezer Taşan](https://www.github.com/hasansezertasan), It's me 👋.
207+
208+
## Credits
209+
210+
- This project wouldn't be possible without the [user-agents][python-user-agents] package 🙏.
211+
- The project structure is inspired by the [asgi-htmx](https://github.com/florimondmanca/asgi-htmx) 🚀 package and contains some code snippets from it 😅 (even this file).
212+
213+
## Analysis
214+
215+
- [Snyk Python Package Health Analysis](https://snyk.io/advisor/python/asgi-user-agents)
216+
- [Libraries.io - PyPI](https://libraries.io/pypi/asgi-user-agents)
217+
- [Safety DB](https://data.safetycli.com/packages/pypi/asgi-user-agents)
218+
- [PePy Download Stats](https://www.pepy.tech/projects/asgi-user-agents)
219+
- [PyPI Download Stats](https://pypistats.org/packages/asgi-user-agents)
220+
- [Pip Trends Download Stats](https://piptrends.com/package/asgi-user-agents)
221+
222+
## License
223+
224+
`asgi-user-agents` is distributed under the terms of the [MIT](https://spdx.org/licenses/MIT.html) license.
225+
226+
<!-- Links -->
227+
[python-user-agents]: https://github.com/selwin/python-user-agents

0 commit comments

Comments
 (0)