Skip to content

Commit b8ad0fa

Browse files
committed
Initial release: cpulimiter v1.0.0 with auto-publishing setup
1 parent 2e26963 commit b8ad0fa

File tree

15 files changed

+381
-3
lines changed

15 files changed

+381
-3
lines changed

.github/workflows/auto-publish.yml

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
name: Auto Version Bump and Publish
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
paths:
7+
- 'cpulimiter/**'
8+
- 'setup.py'
9+
- 'pyproject.toml'
10+
workflow_dispatch: # Allow manual trigger
11+
12+
jobs:
13+
bump-version:
14+
if: "!contains(github.event.head_commit.message, '[skip-version]')"
15+
runs-on: ubuntu-latest
16+
17+
steps:
18+
- uses: actions/checkout@v4
19+
with:
20+
token: ${{ secrets.GITHUB_TOKEN }}
21+
fetch-depth: 0
22+
23+
- name: Set up Python
24+
uses: actions/setup-python@v4
25+
with:
26+
python-version: '3.x'
27+
28+
- name: Install dependencies
29+
run: |
30+
python -m pip install --upgrade pip
31+
pip install build twine bump2version
32+
33+
- name: Configure Git
34+
run: |
35+
git config --local user.email "action@github.com"
36+
git config --local user.name "GitHub Action"
37+
38+
- name: Bump patch version
39+
run: |
40+
# Get current version from setup.py
41+
current_version=$(python setup.py --version)
42+
echo "Current version: $current_version"
43+
44+
# Bump patch version (e.g., 1.0.0 -> 1.0.1)
45+
python -c "
46+
import re
47+
with open('setup.py', 'r') as f:
48+
content = f.read()
49+
version_match = re.search(r'version=\"([^\"]+)\"', content)
50+
if version_match:
51+
old_version = version_match.group(1)
52+
version_parts = old_version.split('.')
53+
version_parts[-1] = str(int(version_parts[-1]) + 1)
54+
new_version = '.'.join(version_parts)
55+
new_content = content.replace(f'version=\"{old_version}\"', f'version=\"{new_version}\"')
56+
with open('setup.py', 'w') as f:
57+
f.write(new_content)
58+
print(f'Updated version from {old_version} to {new_version}')
59+
"
60+
61+
# Update pyproject.toml as well
62+
python -c "
63+
import re
64+
with open('pyproject.toml', 'r') as f:
65+
content = f.read()
66+
version_match = re.search(r'version = \"([^\"]+)\"', content)
67+
if version_match:
68+
old_version = version_match.group(1)
69+
version_parts = old_version.split('.')
70+
version_parts[-1] = str(int(version_parts[-1]) + 1)
71+
new_version = '.'.join(version_parts)
72+
new_content = content.replace(f'version = \"{old_version}\"', f'version = \"{new_version}\"')
73+
with open('pyproject.toml', 'w') as f:
74+
f.write(new_content)
75+
print(f'Updated pyproject.toml version from {old_version} to {new_version}')
76+
"
77+
78+
- name: Get new version
79+
id: version
80+
run: |
81+
new_version=$(python setup.py --version)
82+
echo "new_version=$new_version" >> $GITHUB_OUTPUT
83+
echo "New version: $new_version"
84+
85+
- name: Build package
86+
run: python -m build
87+
88+
- name: Publish to PyPI
89+
env:
90+
TWINE_USERNAME: __token__
91+
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
92+
run: twine upload dist/*
93+
94+
- name: Commit version bump
95+
run: |
96+
git add setup.py pyproject.toml
97+
git commit -m "🚀 Bump version to ${{ steps.version.outputs.new_version }} [skip-version]"
98+
git tag "v${{ steps.version.outputs.new_version }}"
99+
git push origin main
100+
git push origin "v${{ steps.version.outputs.new_version }}"

.github/workflows/publish.yml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
name: Publish to PyPI
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*' # Triggers on version tags like v1.0.1, v2.0.0, etc.
7+
release:
8+
types: [published]
9+
10+
jobs:
11+
publish:
12+
runs-on: ubuntu-latest
13+
14+
steps:
15+
- uses: actions/checkout@v4
16+
17+
- name: Set up Python
18+
uses: actions/setup-python@v4
19+
with:
20+
python-version: '3.x'
21+
22+
- name: Install dependencies
23+
run: |
24+
python -m pip install --upgrade pip
25+
pip install build twine
26+
27+
- name: Build package
28+
run: python -m build
29+
30+
- name: Publish to PyPI
31+
env:
32+
TWINE_USERNAME: __token__
33+
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
34+
run: twine upload dist/*

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2025 Ahmed Ashraf
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.

MANIFEST.in

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
include README.md
2+
include LICENSE
3+
include pyproject.toml
4+
recursive-include cpulimiter *.py

README.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@ A Python library for Windows to limit the CPU usage of running processes.
1515
pip install cpulimiter
1616
```
1717

18-
_(Note: This package is not yet published to PyPI.)_
19-
2018
## Quick Start 📖
2119

2220
The following example demonstrates how to limit `chrome.exe` to 5% of CPU usage (a 95% limit).

cpulimiter.egg-info/PKG-INFO

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
Metadata-Version: 2.4
2+
Name: cpulimiter
3+
Version: 1.0.0
4+
Summary: A Python library for Windows to programmatically limit the CPU usage of running processes
5+
Home-page: https://github.com/ahmed0x77/cpulimiter
6+
Author: ahmed0x77
7+
Author-email: ahmed0x77 <ahmed0x77@github.com>
8+
License: MIT
9+
Project-URL: Homepage, https://github.com/ahmed0x77/cpulimiter
10+
Project-URL: Repository, https://github.com/ahmed0x77/cpulimiter
11+
Project-URL: Issues, https://github.com/ahmed0x77/cpulimiter/issues
12+
Keywords: cpu,limit,throttle,process,windows,performance
13+
Classifier: Development Status :: 4 - Beta
14+
Classifier: Intended Audience :: Developers
15+
Classifier: License :: OSI Approved :: MIT License
16+
Classifier: Operating System :: Microsoft :: Windows
17+
Classifier: Programming Language :: Python :: 3
18+
Classifier: Programming Language :: Python :: 3.7
19+
Classifier: Programming Language :: Python :: 3.8
20+
Classifier: Programming Language :: Python :: 3.9
21+
Classifier: Programming Language :: Python :: 3.10
22+
Classifier: Programming Language :: Python :: 3.11
23+
Classifier: Programming Language :: Python :: 3.12
24+
Classifier: Topic :: System :: Monitoring
25+
Classifier: Topic :: System :: Systems Administration
26+
Requires-Python: >=3.7
27+
Description-Content-Type: text/markdown
28+
License-File: LICENSE
29+
Requires-Dist: psutil>=5.8.0
30+
Requires-Dist: pygetwindow>=0.0.9
31+
Requires-Dist: pywin32>=227
32+
Dynamic: author
33+
Dynamic: home-page
34+
Dynamic: license-file
35+
Dynamic: requires-python
36+
37+
# cpulimiter 🚀
38+
39+
A Python library for Windows to limit the CPU usage of running processes.
40+
41+
## Features ✨
42+
43+
- 🎯 Limit process CPU usage by a specified percentage.
44+
- 🔍 Target processes by Process ID (PID), executable name, or window title.
45+
- 🤝 Manage and control multiple limited processes simultaneously.
46+
- 🛠️ Utility functions to discover running and active processes.
47+
48+
## Installation 📦
49+
50+
```bash
51+
pip install cpulimiter
52+
```
53+
54+
_(Note: This package is not yet published to PyPI.)_
55+
56+
## Quick Start 📖
57+
58+
The following example demonstrates how to limit `chrome.exe` to 5% of CPU usage (a 95% limit).
59+
60+
```python
61+
from cpulimiter import CpuLimiter
62+
import time
63+
64+
# 1. Initialize the limiter
65+
limiter = CpuLimiter()
66+
67+
# 2. Add the process directly by its name.
68+
# The library will find the PID for "chrome.exe" for you.
69+
limiter.add(process_name="chrome.exe", limit_percentage=95)
70+
71+
# 3. Start the limit
72+
# You can also start it by name.
73+
print("Limiting Chrome for 15 seconds...")
74+
limiter.start(process_name="chrome.exe")
75+
76+
time.sleep(15)
77+
78+
# 4. Stop the limit
79+
print("Stopping limit.")
80+
limiter.stop(process_name="chrome.exe")
81+
print("Process limit removed.")
82+
```
83+
84+
## API Reference
85+
86+
### `CpuLimiter` Class
87+
88+
The primary class for managing process limits.
89+
90+
#### `limiter.add(pid, process_name, window_title_contains, limit_percentage)`
91+
92+
Adds a process to the limiter's management list.
93+
94+
- `pid` (int): The Process ID.
95+
- `process_name` (str): The executable name (e.g., `"chrome.exe"`).
96+
- `window_title_contains` (str): A substring to match in a window title.
97+
- `limit_percentage` (int): The percentage by which to limit the CPU (e.g., `95` means the process can use up to 5% of a core).
98+
99+
#### `limiter.start(pid, process_name, window_title_contains)`
100+
101+
Starts the CPU limit on a specific, previously added process.
102+
103+
#### `limiter.stop(pid, process_name, window_title_contains)`
104+
105+
Stops the CPU limit on a specific process.
106+
107+
#### `limiter.start_all()`
108+
109+
Starts the CPU limit on all managed processes.
110+
111+
#### `limiter.stop_all()`
112+
113+
Stops the CPU limit on all managed processes.
114+
115+
### Utility Functions
116+
117+
#### `get_active_window_info()`
118+
119+
Returns a dictionary containing the `pid`, `name`, and `title` of the foreground window.
120+
121+
#### `get_active_app_pids()`
122+
123+
Returns a dictionary of all processes with visible windows.

cpulimiter.egg-info/SOURCES.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
LICENSE
2+
MANIFEST.in
3+
README.md
4+
pyproject.toml
5+
setup.py
6+
cpulimiter/__init__.py
7+
cpulimiter/limiter.py
8+
cpulimiter/utils.py
9+
cpulimiter.egg-info/PKG-INFO
10+
cpulimiter.egg-info/SOURCES.txt
11+
cpulimiter.egg-info/dependency_links.txt
12+
cpulimiter.egg-info/requires.txt
13+
cpulimiter.egg-info/top_level.txt
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+

cpulimiter.egg-info/requires.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
psutil>=5.8.0
2+
pygetwindow>=0.0.9
3+
pywin32>=227

cpulimiter.egg-info/top_level.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
cpulimiter

0 commit comments

Comments
 (0)