esuls 0.1.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
esuls-0.1.1/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 IperGiove
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
esuls-0.1.1/PKG-INFO ADDED
@@ -0,0 +1,290 @@
1
+ Metadata-Version: 2.4
2
+ Name: esuls
3
+ Version: 0.1.1
4
+ Summary: Utility library for async database operations, HTTP requests, and parallel execution
5
+ Author-email: IperGiove <ipergiove@gmail.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/ipergiove/esuls
8
+ Project-URL: Repository, https://github.com/ipergiove/esuls
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Operating System :: OS Independent
12
+ Requires-Python: >=3.14
13
+ Description-Content-Type: text/markdown
14
+ License-File: LICENSE
15
+ Requires-Dist: aiosqlite>=0.21.0
16
+ Requires-Dist: curl-cffi>=0.13.0
17
+ Requires-Dist: fake-useragent>=2.2.0
18
+ Requires-Dist: httpx>=0.28.1
19
+ Requires-Dist: loguru>=0.7.3
20
+ Dynamic: license-file
21
+
22
+ # esuls
23
+
24
+ A Python utility library for async database operations, HTTP requests, and parallel execution utilities.
25
+
26
+ ## Features
27
+
28
+ - **AsyncDB** - Type-safe async SQLite with dataclass schemas
29
+ - **Async HTTP client** - High-performance HTTP client with retry logic and connection pooling
30
+ - **Parallel utilities** - Async parallel execution with concurrency control
31
+ - **CloudFlare bypass** - curl-cffi integration for bypassing protections
32
+
33
+ ## Installation
34
+
35
+ ```bash
36
+ # With pip
37
+ pip install esuls
38
+
39
+ # With uv
40
+ uv pip install esuls
41
+ ```
42
+
43
+ ## Usage
44
+
45
+ ### Parallel Execution
46
+
47
+ ```python
48
+ import asyncio
49
+ from esuls import run_parallel
50
+
51
+ async def fetch_data(id):
52
+ await asyncio.sleep(1)
53
+ return f"Data {id}"
54
+
55
+ async def main():
56
+ # Run multiple async functions in parallel with concurrency limit
57
+ results = await run_parallel(
58
+ lambda: fetch_data(1),
59
+ lambda: fetch_data(2),
60
+ lambda: fetch_data(3),
61
+ limit=20 # Max concurrent tasks
62
+ )
63
+ print(results)
64
+
65
+ asyncio.run(main())
66
+ ```
67
+
68
+ ### Database Client (AsyncDB)
69
+
70
+ ```python
71
+ import asyncio
72
+ from dataclasses import dataclass, field
73
+ from esuls import AsyncDB, BaseModel
74
+
75
+ # Define your schema
76
+ @dataclass
77
+ class User(BaseModel):
78
+ name: str = field(metadata={"index": True})
79
+ email: str = field(metadata={"unique": True})
80
+ age: int = 0
81
+
82
+ async def main():
83
+ # Initialize database
84
+ db = AsyncDB(db_path="users.db", table_name="users", schema_class=User)
85
+
86
+ # Save data
87
+ user = User(name="Alice", email="alice@example.com", age=30)
88
+ await db.save(user)
89
+
90
+ # Save multiple items
91
+ users = [
92
+ User(name="Bob", email="bob@example.com", age=25),
93
+ User(name="Charlie", email="charlie@example.com", age=35)
94
+ ]
95
+ await db.save_batch(users)
96
+
97
+ # Query data
98
+ results = await db.find(name="Alice")
99
+ print(results)
100
+
101
+ # Query with filters
102
+ adults = await db.find(age__gte=18, order_by="-age")
103
+
104
+ # Count
105
+ count = await db.count(age__gte=18)
106
+
107
+ # Get by ID
108
+ user = await db.get_by_id(user_id)
109
+
110
+ # Delete
111
+ await db.delete(user_id)
112
+
113
+ asyncio.run(main())
114
+ ```
115
+
116
+ **Query Operators:**
117
+ - `field__eq` - Equal (default)
118
+ - `field__gt` - Greater than
119
+ - `field__gte` - Greater than or equal
120
+ - `field__lt` - Less than
121
+ - `field__lte` - Less than or equal
122
+ - `field__neq` - Not equal
123
+ - `field__like` - SQL LIKE
124
+ - `field__in` - IN operator (pass a list)
125
+
126
+ ### HTTP Request Client
127
+
128
+ ```python
129
+ import asyncio
130
+ from esuls import AsyncRequest, make_request
131
+
132
+ # Using context manager (recommended for multiple requests)
133
+ async def example1():
134
+ async with AsyncRequest() as client:
135
+ response = await client.request(
136
+ url="https://api.example.com/data",
137
+ method="GET",
138
+ add_user_agent=True,
139
+ max_attempt=3,
140
+ timeout_request=30
141
+ )
142
+ if response:
143
+ data = response.json()
144
+ print(data)
145
+
146
+ # Using standalone function (uses shared connection pool)
147
+ async def example2():
148
+ response = await make_request(
149
+ url="https://api.example.com/users",
150
+ method="POST",
151
+ json_data={"name": "Alice", "email": "alice@example.com"},
152
+ headers={"Authorization": "Bearer token"},
153
+ max_attempt=5,
154
+ force_response=True # Return response even on error
155
+ )
156
+ if response:
157
+ print(response.status_code)
158
+ print(response.text)
159
+
160
+ asyncio.run(example1())
161
+ ```
162
+
163
+ **Request Parameters:**
164
+ - `url` - Request URL
165
+ - `method` - HTTP method (GET, POST, PUT, DELETE, etc.)
166
+ - `headers` - Request headers
167
+ - `cookies` - Cookies dict
168
+ - `params` - URL parameters
169
+ - `json_data` - JSON body
170
+ - `files` - Multipart file upload
171
+ - `proxy` - Proxy URL
172
+ - `timeout_request` - Timeout in seconds (default: 60)
173
+ - `max_attempt` - Max retry attempts (default: 10)
174
+ - `force_response` - Return response even on error (default: False)
175
+ - `json_response` - Validate JSON response (default: False)
176
+ - `json_response_check` - Check for key in JSON response
177
+ - `skip_response` - Skip if text contains pattern(s)
178
+ - `exception_sleep` - Delay between retries in seconds (default: 10)
179
+ - `add_user_agent` - Add random User-Agent header (default: False)
180
+
181
+ ### CloudFlare Bypass
182
+
183
+ ```python
184
+ import asyncio
185
+ from esuls import make_request_cffi
186
+
187
+ async def fetch_protected_page():
188
+ html = await make_request_cffi("https://protected-site.com")
189
+ if html:
190
+ print(html)
191
+
192
+ asyncio.run(fetch_protected_page())
193
+ ```
194
+
195
+ ## Development
196
+
197
+ ### Project Structure
198
+
199
+ ```
200
+ utils/
201
+ ├── pyproject.toml
202
+ ├── README.md
203
+ ├── LICENSE
204
+ └── src/
205
+ └── esuls/
206
+ ├── __init__.py
207
+ ├── utils.py # Parallel execution utilities
208
+ ├── db_cli.py # AsyncDB with dataclass schemas
209
+ └── request_cli.py # Async HTTP client
210
+ ```
211
+
212
+ ### Local Development Installation
213
+
214
+ ```bash
215
+ # Navigate to the project
216
+ cd utils
217
+
218
+ # Install in editable mode with uv
219
+ uv pip install -e .
220
+
221
+ # Or with pip
222
+ pip install -e .
223
+ ```
224
+
225
+ ### Building and Publishing
226
+
227
+ ```bash
228
+ # With uv
229
+ uv build
230
+ twine upload dist/*
231
+
232
+ # Or with traditional tools
233
+ pip install build twine
234
+ python -m build
235
+ twine upload dist/*
236
+ ```
237
+
238
+ ## Advanced Features
239
+
240
+ ### AsyncDB Schema Definition
241
+
242
+ ```python
243
+ from dataclasses import dataclass, field
244
+ from esuls import BaseModel
245
+ from datetime import datetime
246
+ from typing import Optional, List
247
+ import enum
248
+
249
+ class Status(enum.Enum):
250
+ ACTIVE = "active"
251
+ INACTIVE = "inactive"
252
+
253
+ @dataclass
254
+ class User(BaseModel):
255
+ # BaseModel provides: id, created_at, updated_at
256
+
257
+ # Indexed field
258
+ email: str = field(metadata={"index": True, "unique": True})
259
+
260
+ # Simple fields
261
+ name: str = ""
262
+ age: int = 0
263
+
264
+ # Enum support
265
+ status: Status = Status.ACTIVE
266
+
267
+ # JSON-serialized complex types
268
+ tags: List[str] = field(default_factory=list)
269
+
270
+ # Optional fields
271
+ phone: Optional[str] = None
272
+
273
+ # Table constraints (optional)
274
+ __table_constraints__ = [
275
+ "CHECK (age >= 0)"
276
+ ]
277
+ ```
278
+
279
+ ### Connection Pooling & Performance
280
+
281
+ The HTTP client uses:
282
+ - Shared connection pool (prevents "too many open files" errors)
283
+ - Automatic retry with exponential backoff
284
+ - SSL optimization
285
+ - Random User-Agent rotation
286
+ - Cookie and header persistence
287
+
288
+ ## License
289
+
290
+ MIT License
esuls-0.1.1/README.md ADDED
@@ -0,0 +1,269 @@
1
+ # esuls
2
+
3
+ A Python utility library for async database operations, HTTP requests, and parallel execution utilities.
4
+
5
+ ## Features
6
+
7
+ - **AsyncDB** - Type-safe async SQLite with dataclass schemas
8
+ - **Async HTTP client** - High-performance HTTP client with retry logic and connection pooling
9
+ - **Parallel utilities** - Async parallel execution with concurrency control
10
+ - **CloudFlare bypass** - curl-cffi integration for bypassing protections
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ # With pip
16
+ pip install esuls
17
+
18
+ # With uv
19
+ uv pip install esuls
20
+ ```
21
+
22
+ ## Usage
23
+
24
+ ### Parallel Execution
25
+
26
+ ```python
27
+ import asyncio
28
+ from esuls import run_parallel
29
+
30
+ async def fetch_data(id):
31
+ await asyncio.sleep(1)
32
+ return f"Data {id}"
33
+
34
+ async def main():
35
+ # Run multiple async functions in parallel with concurrency limit
36
+ results = await run_parallel(
37
+ lambda: fetch_data(1),
38
+ lambda: fetch_data(2),
39
+ lambda: fetch_data(3),
40
+ limit=20 # Max concurrent tasks
41
+ )
42
+ print(results)
43
+
44
+ asyncio.run(main())
45
+ ```
46
+
47
+ ### Database Client (AsyncDB)
48
+
49
+ ```python
50
+ import asyncio
51
+ from dataclasses import dataclass, field
52
+ from esuls import AsyncDB, BaseModel
53
+
54
+ # Define your schema
55
+ @dataclass
56
+ class User(BaseModel):
57
+ name: str = field(metadata={"index": True})
58
+ email: str = field(metadata={"unique": True})
59
+ age: int = 0
60
+
61
+ async def main():
62
+ # Initialize database
63
+ db = AsyncDB(db_path="users.db", table_name="users", schema_class=User)
64
+
65
+ # Save data
66
+ user = User(name="Alice", email="alice@example.com", age=30)
67
+ await db.save(user)
68
+
69
+ # Save multiple items
70
+ users = [
71
+ User(name="Bob", email="bob@example.com", age=25),
72
+ User(name="Charlie", email="charlie@example.com", age=35)
73
+ ]
74
+ await db.save_batch(users)
75
+
76
+ # Query data
77
+ results = await db.find(name="Alice")
78
+ print(results)
79
+
80
+ # Query with filters
81
+ adults = await db.find(age__gte=18, order_by="-age")
82
+
83
+ # Count
84
+ count = await db.count(age__gte=18)
85
+
86
+ # Get by ID
87
+ user = await db.get_by_id(user_id)
88
+
89
+ # Delete
90
+ await db.delete(user_id)
91
+
92
+ asyncio.run(main())
93
+ ```
94
+
95
+ **Query Operators:**
96
+ - `field__eq` - Equal (default)
97
+ - `field__gt` - Greater than
98
+ - `field__gte` - Greater than or equal
99
+ - `field__lt` - Less than
100
+ - `field__lte` - Less than or equal
101
+ - `field__neq` - Not equal
102
+ - `field__like` - SQL LIKE
103
+ - `field__in` - IN operator (pass a list)
104
+
105
+ ### HTTP Request Client
106
+
107
+ ```python
108
+ import asyncio
109
+ from esuls import AsyncRequest, make_request
110
+
111
+ # Using context manager (recommended for multiple requests)
112
+ async def example1():
113
+ async with AsyncRequest() as client:
114
+ response = await client.request(
115
+ url="https://api.example.com/data",
116
+ method="GET",
117
+ add_user_agent=True,
118
+ max_attempt=3,
119
+ timeout_request=30
120
+ )
121
+ if response:
122
+ data = response.json()
123
+ print(data)
124
+
125
+ # Using standalone function (uses shared connection pool)
126
+ async def example2():
127
+ response = await make_request(
128
+ url="https://api.example.com/users",
129
+ method="POST",
130
+ json_data={"name": "Alice", "email": "alice@example.com"},
131
+ headers={"Authorization": "Bearer token"},
132
+ max_attempt=5,
133
+ force_response=True # Return response even on error
134
+ )
135
+ if response:
136
+ print(response.status_code)
137
+ print(response.text)
138
+
139
+ asyncio.run(example1())
140
+ ```
141
+
142
+ **Request Parameters:**
143
+ - `url` - Request URL
144
+ - `method` - HTTP method (GET, POST, PUT, DELETE, etc.)
145
+ - `headers` - Request headers
146
+ - `cookies` - Cookies dict
147
+ - `params` - URL parameters
148
+ - `json_data` - JSON body
149
+ - `files` - Multipart file upload
150
+ - `proxy` - Proxy URL
151
+ - `timeout_request` - Timeout in seconds (default: 60)
152
+ - `max_attempt` - Max retry attempts (default: 10)
153
+ - `force_response` - Return response even on error (default: False)
154
+ - `json_response` - Validate JSON response (default: False)
155
+ - `json_response_check` - Check for key in JSON response
156
+ - `skip_response` - Skip if text contains pattern(s)
157
+ - `exception_sleep` - Delay between retries in seconds (default: 10)
158
+ - `add_user_agent` - Add random User-Agent header (default: False)
159
+
160
+ ### CloudFlare Bypass
161
+
162
+ ```python
163
+ import asyncio
164
+ from esuls import make_request_cffi
165
+
166
+ async def fetch_protected_page():
167
+ html = await make_request_cffi("https://protected-site.com")
168
+ if html:
169
+ print(html)
170
+
171
+ asyncio.run(fetch_protected_page())
172
+ ```
173
+
174
+ ## Development
175
+
176
+ ### Project Structure
177
+
178
+ ```
179
+ utils/
180
+ ├── pyproject.toml
181
+ ├── README.md
182
+ ├── LICENSE
183
+ └── src/
184
+ └── esuls/
185
+ ├── __init__.py
186
+ ├── utils.py # Parallel execution utilities
187
+ ├── db_cli.py # AsyncDB with dataclass schemas
188
+ └── request_cli.py # Async HTTP client
189
+ ```
190
+
191
+ ### Local Development Installation
192
+
193
+ ```bash
194
+ # Navigate to the project
195
+ cd utils
196
+
197
+ # Install in editable mode with uv
198
+ uv pip install -e .
199
+
200
+ # Or with pip
201
+ pip install -e .
202
+ ```
203
+
204
+ ### Building and Publishing
205
+
206
+ ```bash
207
+ # With uv
208
+ uv build
209
+ twine upload dist/*
210
+
211
+ # Or with traditional tools
212
+ pip install build twine
213
+ python -m build
214
+ twine upload dist/*
215
+ ```
216
+
217
+ ## Advanced Features
218
+
219
+ ### AsyncDB Schema Definition
220
+
221
+ ```python
222
+ from dataclasses import dataclass, field
223
+ from esuls import BaseModel
224
+ from datetime import datetime
225
+ from typing import Optional, List
226
+ import enum
227
+
228
+ class Status(enum.Enum):
229
+ ACTIVE = "active"
230
+ INACTIVE = "inactive"
231
+
232
+ @dataclass
233
+ class User(BaseModel):
234
+ # BaseModel provides: id, created_at, updated_at
235
+
236
+ # Indexed field
237
+ email: str = field(metadata={"index": True, "unique": True})
238
+
239
+ # Simple fields
240
+ name: str = ""
241
+ age: int = 0
242
+
243
+ # Enum support
244
+ status: Status = Status.ACTIVE
245
+
246
+ # JSON-serialized complex types
247
+ tags: List[str] = field(default_factory=list)
248
+
249
+ # Optional fields
250
+ phone: Optional[str] = None
251
+
252
+ # Table constraints (optional)
253
+ __table_constraints__ = [
254
+ "CHECK (age >= 0)"
255
+ ]
256
+ ```
257
+
258
+ ### Connection Pooling & Performance
259
+
260
+ The HTTP client uses:
261
+ - Shared connection pool (prevents "too many open files" errors)
262
+ - Automatic retry with exponential backoff
263
+ - SSL optimization
264
+ - Random User-Agent rotation
265
+ - Cookie and header persistence
266
+
267
+ ## License
268
+
269
+ MIT License
@@ -0,0 +1,32 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "esuls"
7
+ version = "0.1.1"
8
+ description = "Utility library for async database operations, HTTP requests, and parallel execution"
9
+ readme = "README.md"
10
+ requires-python = ">=3.14"
11
+ authors = [
12
+ {name = "IperGiove", email = "ipergiove@gmail.com"}
13
+ ]
14
+ license = {text = "MIT"}
15
+ classifiers = [
16
+ "Programming Language :: Python :: 3",
17
+ "License :: OSI Approved :: MIT License",
18
+ "Operating System :: OS Independent",
19
+ ]
20
+
21
+ # All dependencies (always installed)
22
+ dependencies = [
23
+ "aiosqlite>=0.21.0",
24
+ "curl-cffi>=0.13.0",
25
+ "fake-useragent>=2.2.0",
26
+ "httpx>=0.28.1",
27
+ "loguru>=0.7.3",
28
+ ]
29
+
30
+ [project.urls]
31
+ Homepage = "https://github.com/ipergiove/esuls"
32
+ Repository = "https://github.com/ipergiove/esuls"
esuls-0.1.1/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,21 @@
1
+ """
2
+ esuls - Utility library for async database operations, HTTP requests, and parallel execution
3
+ """
4
+
5
+ __version__ = "0.1.0"
6
+
7
+ # Import all utilities
8
+ from .utils import run_parallel
9
+ from .db_cli import AsyncDB, BaseModel
10
+ from .request_cli import AsyncRequest, make_request, make_request_cffi, Response
11
+
12
+ __all__ = [
13
+ '__version__',
14
+ 'run_parallel',
15
+ 'AsyncDB',
16
+ 'BaseModel',
17
+ 'AsyncRequest',
18
+ 'make_request',
19
+ 'make_request_cffi',
20
+ 'Response',
21
+ ]