toolkitx 0.0.3__tar.gz → 0.0.4__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.
- {toolkitx-0.0.3 → toolkitx-0.0.4}/.github/workflows/python-publish.yml +0 -1
- toolkitx-0.0.4/PKG-INFO +150 -0
- toolkitx-0.0.4/README.md +131 -0
- toolkitx-0.0.4/makefile +5 -0
- {toolkitx-0.0.3 → toolkitx-0.0.4}/pyproject.toml +9 -9
- toolkitx-0.0.4/tests/test_task_utils.py +468 -0
- {toolkitx-0.0.3 → toolkitx-0.0.4}/toolkitx/__init__.py +0 -2
- {toolkitx-0.0.3 → toolkitx-0.0.4}/toolkitx/lab/translator.py +6 -7
- toolkitx-0.0.4/toolkitx/task_utils.py +389 -0
- {toolkitx-0.0.3 → toolkitx-0.0.4}/toolkitx/text_utils.py +0 -3
- toolkitx-0.0.4/uv.lock +444 -0
- toolkitx-0.0.3/PKG-INFO +0 -67
- toolkitx-0.0.3/README.md +0 -51
- toolkitx-0.0.3/toolkitx/hello.py +0 -2
- toolkitx-0.0.3/uv.lock +0 -270
- {toolkitx-0.0.3 → toolkitx-0.0.4}/.gitignore +0 -0
- {toolkitx-0.0.3 → toolkitx-0.0.4}/.python-version +0 -0
- {toolkitx-0.0.3 → toolkitx-0.0.4}/LICENSE +0 -0
- {toolkitx-0.0.3 → toolkitx-0.0.4}/tests/lab/test_translator.py +0 -0
- {toolkitx-0.0.3 → toolkitx-0.0.4}/tests/test_text_utils.py +0 -0
- {toolkitx-0.0.3 → toolkitx-0.0.4}/toolkitx/lab/__init__.py +0 -0
toolkitx-0.0.4/PKG-INFO
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: toolkitx
|
|
3
|
+
Version: 0.0.4
|
|
4
|
+
Summary: A personal Python toolkit for common tasks
|
|
5
|
+
Project-URL: Homepage, https://github.com/ider-zh/toolkitx
|
|
6
|
+
Project-URL: Bug Tracker, https://github.com/ider-zh/toolkitx/issues
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Requires-Python: >=3.12
|
|
9
|
+
Requires-Dist: diskcache>=5.6.3
|
|
10
|
+
Requires-Dist: httpx>=0.28.1
|
|
11
|
+
Requires-Dist: polars>=1.38.1
|
|
12
|
+
Requires-Dist: pydantic>=2.12.5
|
|
13
|
+
Requires-Dist: tencentcloud-sdk-python>=3.1.50
|
|
14
|
+
Requires-Dist: tqdm>=4.67.3
|
|
15
|
+
Provides-Extra: dev
|
|
16
|
+
Requires-Dist: pytest-dotenv>=0.5.2; extra == 'dev'
|
|
17
|
+
Requires-Dist: pytest>=9.0.2; extra == 'dev'
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
|
|
20
|
+
# toolkitx
|
|
21
|
+
|
|
22
|
+
A personal Python toolkit for common tasks. This package provides various utility functions to simplify common development workflows.
|
|
23
|
+
|
|
24
|
+
## Features
|
|
25
|
+
|
|
26
|
+
* **Text Utilities** (`toolkitx.text_utils`):
|
|
27
|
+
* `truncate_text_smart`: Smartly truncates text by characters or words, with options for suffix and tolerance, attempting to preserve sentence or word boundaries.
|
|
28
|
+
* `split_text_by_word_count`: Splits long text into overlapping chunks based on word count.
|
|
29
|
+
|
|
30
|
+
* **Task Utilities** (`toolkitx.task_utils`):
|
|
31
|
+
* `with_resilience`: A decorator for API resilience with rate limiting (QPS), exponential backoff retry, and jitter to prevent thundering herd.
|
|
32
|
+
* `PersistentTaskQueue`: A persistent task queue with SQLite backend, supporting concurrent processing, automatic retry, crash recovery, and graceful shutdown.
|
|
33
|
+
|
|
34
|
+
* **Experimental Translator** (`toolkitx.lab.translator`):
|
|
35
|
+
* `Translator`: A class providing translation capabilities using Baidu or Tencent translation APIs, with disk-based caching for performance. (Requires API credentials)
|
|
36
|
+
|
|
37
|
+
## Installation
|
|
38
|
+
|
|
39
|
+
1. Clone the repository:
|
|
40
|
+
```bash
|
|
41
|
+
git clone https://github.com/ider-zh/toolkitx.git
|
|
42
|
+
cd toolkitx
|
|
43
|
+
```
|
|
44
|
+
2. Install the package. For development, you can install it in editable mode with development dependencies:
|
|
45
|
+
```bash
|
|
46
|
+
pip install -e ".[dev]"
|
|
47
|
+
```
|
|
48
|
+
For regular installation:
|
|
49
|
+
```bash
|
|
50
|
+
pip install .
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Usage
|
|
54
|
+
|
|
55
|
+
### Text Utilities
|
|
56
|
+
|
|
57
|
+
```python
|
|
58
|
+
from toolkitx import truncate_text_smart, split_text_by_word_count
|
|
59
|
+
|
|
60
|
+
# Smart Truncation
|
|
61
|
+
text = "This is a very long sentence that needs to be truncated."
|
|
62
|
+
truncated_char = truncate_text_smart(text, limit=20, mode="char", suffix="...")
|
|
63
|
+
print(f"Char truncated: {truncated_char}")
|
|
64
|
+
|
|
65
|
+
truncated_word = truncate_text_smart(text, limit=5, mode="word", suffix="...")
|
|
66
|
+
print(f"Word truncated: {truncated_word}")
|
|
67
|
+
|
|
68
|
+
# Split Text
|
|
69
|
+
long_text = "This is a long piece of text that we want to split into several smaller chunks with some overlap between them for context."
|
|
70
|
+
chunks = split_text_by_word_count(long_text, max_words=10, overlap=2)
|
|
71
|
+
for i, chunk in enumerate(chunks):
|
|
72
|
+
print(f"Chunk {i+1}: {chunk}")
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Task Utilities
|
|
76
|
+
|
|
77
|
+
#### with_resilience Decorator
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
from toolkitx.task_utils import with_resilience
|
|
81
|
+
import requests
|
|
82
|
+
|
|
83
|
+
@with_resilience(qps=5.0, max_retries=3, base_delay=1.0, max_delay=60.0)
|
|
84
|
+
def call_api_with_retry(url: str) -> dict:
|
|
85
|
+
"""Call API with automatic retry and rate limiting"""
|
|
86
|
+
response = requests.get(url, timeout=10)
|
|
87
|
+
response.raise_for_status()
|
|
88
|
+
return response.json()
|
|
89
|
+
|
|
90
|
+
# The decorator will automatically:
|
|
91
|
+
# - Limit requests to 5 per second (QPS)
|
|
92
|
+
# - Retry up to 3 times on failure with exponential backoff
|
|
93
|
+
# - Add random jitter to prevent thundering herd
|
|
94
|
+
result = call_api_with_retry("https://api.example.com/data")
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
#### PersistentTaskQueue
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
import polars as pl
|
|
101
|
+
from pydantic import BaseModel
|
|
102
|
+
from toolkitx.task_utils import PersistentTaskQueue
|
|
103
|
+
import tempfile
|
|
104
|
+
|
|
105
|
+
# Define your data model
|
|
106
|
+
class EntityModel(BaseModel):
|
|
107
|
+
name: str
|
|
108
|
+
is_company: bool
|
|
109
|
+
|
|
110
|
+
# Define your processing function
|
|
111
|
+
def extract_entity(text: str) -> EntityModel:
|
|
112
|
+
"""Extract entity information from text"""
|
|
113
|
+
# Your processing logic here
|
|
114
|
+
return EntityModel(name=text.split()[0], is_company=True)
|
|
115
|
+
|
|
116
|
+
# Prepare data
|
|
117
|
+
df = pl.DataFrame({
|
|
118
|
+
"batch_id": ["batch1", "batch1", "batch2"],
|
|
119
|
+
"input_text": ["Apple Inc.", "Google Corp.", "Microsoft"]
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
# Initialize queue with temporary database
|
|
123
|
+
with tempfile.NamedTemporaryFile(suffix=".db", delete=False) as f:
|
|
124
|
+
db_path = f.name
|
|
125
|
+
|
|
126
|
+
queue = PersistentTaskQueue(db_path=db_path, task_name="entity_extraction", max_retries=3)
|
|
127
|
+
|
|
128
|
+
# Setup and enqueue data
|
|
129
|
+
queue.setup()
|
|
130
|
+
queue.enqueue_dataframe(df)
|
|
131
|
+
|
|
132
|
+
# Process tasks with concurrency control (supports Ctrl+C for graceful shutdown)
|
|
133
|
+
queue.process(worker_func=extract_entity, concurrency=10)
|
|
134
|
+
|
|
135
|
+
# Get results
|
|
136
|
+
results = queue.get_results(response_model=EntityModel)
|
|
137
|
+
print(results)
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Changelog
|
|
141
|
+
|
|
142
|
+
### v0.0.4 (2026-03-07)
|
|
143
|
+
- Added `task_utils` module with `with_resilience` decorator for API resilience
|
|
144
|
+
- Added `PersistentTaskQueue` class for persistent task processing with SQLite backend
|
|
145
|
+
- Added comprehensive documentation for new features
|
|
146
|
+
- Bumped version to 0.0.4
|
|
147
|
+
- Updated dependencies (httpx, tencentcloud-sdk-python, pytest, etc.)
|
|
148
|
+
- Removed `hello` script and related functionality
|
|
149
|
+
- Added `polars`, `pydantic`, and `tqdm` as dependencies
|
|
150
|
+
- Improved translator module to use `tempfile` for cache paths
|
toolkitx-0.0.4/README.md
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# toolkitx
|
|
2
|
+
|
|
3
|
+
A personal Python toolkit for common tasks. This package provides various utility functions to simplify common development workflows.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
* **Text Utilities** (`toolkitx.text_utils`):
|
|
8
|
+
* `truncate_text_smart`: Smartly truncates text by characters or words, with options for suffix and tolerance, attempting to preserve sentence or word boundaries.
|
|
9
|
+
* `split_text_by_word_count`: Splits long text into overlapping chunks based on word count.
|
|
10
|
+
|
|
11
|
+
* **Task Utilities** (`toolkitx.task_utils`):
|
|
12
|
+
* `with_resilience`: A decorator for API resilience with rate limiting (QPS), exponential backoff retry, and jitter to prevent thundering herd.
|
|
13
|
+
* `PersistentTaskQueue`: A persistent task queue with SQLite backend, supporting concurrent processing, automatic retry, crash recovery, and graceful shutdown.
|
|
14
|
+
|
|
15
|
+
* **Experimental Translator** (`toolkitx.lab.translator`):
|
|
16
|
+
* `Translator`: A class providing translation capabilities using Baidu or Tencent translation APIs, with disk-based caching for performance. (Requires API credentials)
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
1. Clone the repository:
|
|
21
|
+
```bash
|
|
22
|
+
git clone https://github.com/ider-zh/toolkitx.git
|
|
23
|
+
cd toolkitx
|
|
24
|
+
```
|
|
25
|
+
2. Install the package. For development, you can install it in editable mode with development dependencies:
|
|
26
|
+
```bash
|
|
27
|
+
pip install -e ".[dev]"
|
|
28
|
+
```
|
|
29
|
+
For regular installation:
|
|
30
|
+
```bash
|
|
31
|
+
pip install .
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Usage
|
|
35
|
+
|
|
36
|
+
### Text Utilities
|
|
37
|
+
|
|
38
|
+
```python
|
|
39
|
+
from toolkitx import truncate_text_smart, split_text_by_word_count
|
|
40
|
+
|
|
41
|
+
# Smart Truncation
|
|
42
|
+
text = "This is a very long sentence that needs to be truncated."
|
|
43
|
+
truncated_char = truncate_text_smart(text, limit=20, mode="char", suffix="...")
|
|
44
|
+
print(f"Char truncated: {truncated_char}")
|
|
45
|
+
|
|
46
|
+
truncated_word = truncate_text_smart(text, limit=5, mode="word", suffix="...")
|
|
47
|
+
print(f"Word truncated: {truncated_word}")
|
|
48
|
+
|
|
49
|
+
# Split Text
|
|
50
|
+
long_text = "This is a long piece of text that we want to split into several smaller chunks with some overlap between them for context."
|
|
51
|
+
chunks = split_text_by_word_count(long_text, max_words=10, overlap=2)
|
|
52
|
+
for i, chunk in enumerate(chunks):
|
|
53
|
+
print(f"Chunk {i+1}: {chunk}")
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Task Utilities
|
|
57
|
+
|
|
58
|
+
#### with_resilience Decorator
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
from toolkitx.task_utils import with_resilience
|
|
62
|
+
import requests
|
|
63
|
+
|
|
64
|
+
@with_resilience(qps=5.0, max_retries=3, base_delay=1.0, max_delay=60.0)
|
|
65
|
+
def call_api_with_retry(url: str) -> dict:
|
|
66
|
+
"""Call API with automatic retry and rate limiting"""
|
|
67
|
+
response = requests.get(url, timeout=10)
|
|
68
|
+
response.raise_for_status()
|
|
69
|
+
return response.json()
|
|
70
|
+
|
|
71
|
+
# The decorator will automatically:
|
|
72
|
+
# - Limit requests to 5 per second (QPS)
|
|
73
|
+
# - Retry up to 3 times on failure with exponential backoff
|
|
74
|
+
# - Add random jitter to prevent thundering herd
|
|
75
|
+
result = call_api_with_retry("https://api.example.com/data")
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
#### PersistentTaskQueue
|
|
79
|
+
|
|
80
|
+
```python
|
|
81
|
+
import polars as pl
|
|
82
|
+
from pydantic import BaseModel
|
|
83
|
+
from toolkitx.task_utils import PersistentTaskQueue
|
|
84
|
+
import tempfile
|
|
85
|
+
|
|
86
|
+
# Define your data model
|
|
87
|
+
class EntityModel(BaseModel):
|
|
88
|
+
name: str
|
|
89
|
+
is_company: bool
|
|
90
|
+
|
|
91
|
+
# Define your processing function
|
|
92
|
+
def extract_entity(text: str) -> EntityModel:
|
|
93
|
+
"""Extract entity information from text"""
|
|
94
|
+
# Your processing logic here
|
|
95
|
+
return EntityModel(name=text.split()[0], is_company=True)
|
|
96
|
+
|
|
97
|
+
# Prepare data
|
|
98
|
+
df = pl.DataFrame({
|
|
99
|
+
"batch_id": ["batch1", "batch1", "batch2"],
|
|
100
|
+
"input_text": ["Apple Inc.", "Google Corp.", "Microsoft"]
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
# Initialize queue with temporary database
|
|
104
|
+
with tempfile.NamedTemporaryFile(suffix=".db", delete=False) as f:
|
|
105
|
+
db_path = f.name
|
|
106
|
+
|
|
107
|
+
queue = PersistentTaskQueue(db_path=db_path, task_name="entity_extraction", max_retries=3)
|
|
108
|
+
|
|
109
|
+
# Setup and enqueue data
|
|
110
|
+
queue.setup()
|
|
111
|
+
queue.enqueue_dataframe(df)
|
|
112
|
+
|
|
113
|
+
# Process tasks with concurrency control (supports Ctrl+C for graceful shutdown)
|
|
114
|
+
queue.process(worker_func=extract_entity, concurrency=10)
|
|
115
|
+
|
|
116
|
+
# Get results
|
|
117
|
+
results = queue.get_results(response_model=EntityModel)
|
|
118
|
+
print(results)
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Changelog
|
|
122
|
+
|
|
123
|
+
### v0.0.4 (2026-03-07)
|
|
124
|
+
- Added `task_utils` module with `with_resilience` decorator for API resilience
|
|
125
|
+
- Added `PersistentTaskQueue` class for persistent task processing with SQLite backend
|
|
126
|
+
- Added comprehensive documentation for new features
|
|
127
|
+
- Bumped version to 0.0.4
|
|
128
|
+
- Updated dependencies (httpx, tencentcloud-sdk-python, pytest, etc.)
|
|
129
|
+
- Removed `hello` script and related functionality
|
|
130
|
+
- Added `polars`, `pydantic`, and `tqdm` as dependencies
|
|
131
|
+
- Improved translator module to use `tempfile` for cache paths
|
toolkitx-0.0.4/makefile
ADDED
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "toolkitx"
|
|
3
|
-
version = "0.0.
|
|
3
|
+
version = "0.0.4"
|
|
4
4
|
description = "A personal Python toolkit for common tasks"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.12"
|
|
7
7
|
dependencies = [
|
|
8
8
|
"diskcache>=5.6.3",
|
|
9
|
-
"httpx>=0.
|
|
10
|
-
"
|
|
9
|
+
"httpx>=0.28.1",
|
|
10
|
+
"polars>=1.38.1",
|
|
11
|
+
"pydantic>=2.12.5",
|
|
12
|
+
"tencentcloud-sdk-python>=3.1.50",
|
|
13
|
+
"tqdm>=4.67.3",
|
|
11
14
|
]
|
|
12
15
|
|
|
13
16
|
[project.optional-dependencies]
|
|
14
17
|
dev = [
|
|
15
|
-
"pytest",
|
|
16
|
-
"pytest-dotenv",
|
|
18
|
+
"pytest>=9.0.2",
|
|
19
|
+
"pytest-dotenv>=0.5.2",
|
|
17
20
|
]
|
|
18
21
|
|
|
19
|
-
[project.scripts]
|
|
20
|
-
hello = "toolkitx.hello:hello"
|
|
21
|
-
|
|
22
22
|
[build-system]
|
|
23
23
|
requires = ["hatchling"]
|
|
24
24
|
build-backend = "hatchling.build"
|
|
@@ -28,4 +28,4 @@ packages = ["toolkitx"]
|
|
|
28
28
|
|
|
29
29
|
[project.urls]
|
|
30
30
|
"Homepage" = "https://github.com/ider-zh/toolkitx"
|
|
31
|
-
"Bug Tracker" = "https://github.com/ider-zh/toolkitx/issues"
|
|
31
|
+
"Bug Tracker" = "https://github.com/ider-zh/toolkitx/issues"
|