-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
1,419 additions
and
765 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,61 +1,175 @@ | ||
# TQuota | ||
|
||
[![GitHub Release](https://img.shields.io/github/v/release/aljbri/tquota)](https://github.com/aljbri/tquota/releases/latest) | ||
[![GitHub License](https://img.shields.io/github/license/aljbri/tquota)](https://github.com/aljbri/tquota/blob/master/LICENSE) | ||
[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/tquota)](https://pypi.org/project/tquota) | ||
[![PyPI - Format](https://img.shields.io/pypi/format/tquota)](https://pypi.org/project/tquota) | ||
[![PyPI - Version](https://img.shields.io/pypi/v/tquota)](https://pypi.org/project/tquota) | ||
<!-- | ||
[![wheel](https://img.shields.io/pypi/wheel/tquota)](https://pypi.org/project/tquota) | ||
[![PyPI - Downloads](https://img.shields.io/pypi/dm/tquota)]() | ||
--> | ||
|
||
# TQuota | ||
Processing timer module: help if the code is running on the cloud server which has a quota limitation, such as [kaggle](https://www.kaggle.com/) and [colab](https://colab.research.google.com/) which have a limit for 9 hours of processing on each session | ||
`tquota.Quota` is a lightweight processing timer module designed to monitor time effectively when running code on cloud platforms with quota limitations, such as [Kaggle](https://www.kaggle.com/) and [Google Colab](https://colab.research.google.com/). These platforms impose a limit of `x` hours of processing per session, the `Quota` class allows users to set a processing quota time and a buffer time before the quota limit ends, ensuring efficient resource management. | ||
|
||
## Features | ||
|
||
- **Quota Management**: Easily track and manage session time to avoid overuse of limited resources on platforms with quota restrictions. | ||
- **Dynamic Gap Timing**: Automatically adjusts the buffer time (`gap_time`) based on the remaining session time when set to `'auto'`. | ||
- **Auto Gap Calculation**: When `gap_time` is set to `'auto'`, the system dynamically calculates the optimal gap before the session ends, ensuring efficient timing without the need for manual setup. | ||
- **Simple Interface**: The class provides Easy-to-use and intuitive methods to check whether time is still available or if the session has reached its limit. | ||
- **Optional Logging**: Enable logging to track quota usage and gap timing for debugging or monitoring purposes. | ||
- **Compatibility**: It can work with Python versions 2.7 and 3.0+. | ||
|
||
--- | ||
## Quota Class | ||
|
||
# quota class | ||
The package has only one class (quota) that has two parameters | ||
* **quota_time**: type (str) default value (6h) : represent the quota time for the session | ||
* **gap_time**: type (str) default value (30m): represent the time gap between the quota limit and the actual closing time for the session | ||
The package `tquota` includes a single class, `Quota`, which has two main parameters and an optional one: | ||
|
||
The time has a strict format to be passed with; it has to part *dw* while | ||
*d*: represent the time as digits | ||
*w*: the time and one character(w) to represent the time period | ||
- **s** : Seconds | ||
- **m** : Minutes | ||
- **h** : Hours | ||
- **d** : Days | ||
* **quota_time**: (str) Default value: `6h`. Represents the maximum processing time for the session. | ||
* **gap_time**: (str) Default value: `'auto'`. Represents the buffer time before the session closes, adjusted dynamically based on elapsed time. | ||
* **enable_logging**: (bool, optional) Default value: `False`. Whether to enable logging or not. | ||
|
||
## functions | ||
### Time Format | ||
|
||
quota class has two functions: | ||
* time_up : return True if the process reaches it is limit | ||
* hastime : return True if the process still has time to process | ||
|
||
# install | ||
you can install the package from [pypi](https://pypi.org/project/tquota). | ||
The time should be specified in a strict format, consisting of two parts: *`dw`*, where: | ||
- **d**: Represents the time as digits | ||
- **w**: Represents the time unit with one character: | ||
|
||
[ s: Seconds, m: Minutes, h: Hours, d: Days] | ||
|
||
## Functions | ||
|
||
The `Quota` class provides the following key methods: | ||
|
||
**`time_up`**: | ||
- **Description**: This method checks whether the processing time has reached or exceeded its quota limit. | ||
- **Returns**: | ||
- `True`: If the process has reached or exceeded the defined quota time. | ||
- `False`: If there is still time remaining within the quota limit. | ||
- **Usage**: | ||
```python | ||
if qt.time_up(): | ||
print('Time limit reached.') | ||
``` | ||
|
||
pip install tquota | ||
**`hastime`**: | ||
- **Description**: This method checks whether there is still time left before the process reaches the quota limit. | ||
- **Returns**: | ||
- `True`: If there is still time remaining before reaching the quota. | ||
- `False`: If the process has exceeded the quota time or is within the gap buffer. | ||
- **Usage**: | ||
```python | ||
if qt.hastime(): | ||
print('There’s still time to process.') | ||
``` | ||
|
||
**`remaining_time`**: | ||
- **Description**: This method returns the remaining time before the quota limit is reached in a human-readable format. | ||
- **Returns**: A string representing the remaining time formatted as `"xh:xm:xs"` (e.g., `"0h:10m:15s"` for 10 minutes and 15 seconds remaining). | ||
- **Usage**: | ||
```python | ||
remaining = qt.remaining_time() | ||
print(f'Remaining time: {remaining}') | ||
``` | ||
--- | ||
## Installation | ||
|
||
# usage | ||
Import the quota class as following | ||
You can install the package from [PyPI](https://pypi.org/project/tquota) using the following command: | ||
|
||
```bash | ||
pip install tquota | ||
``` | ||
|
||
Alternatively, you can clone the repository and install the package directly: | ||
|
||
```bash | ||
git clone https://github.com/aljbri/tquota.git | ||
cd tquota | ||
pip install . | ||
``` | ||
--- | ||
## Usage | ||
|
||
Import the `Quota` class as follows: | ||
|
||
```python | ||
from tquota import Quota | ||
``` | ||
|
||
from tquota import quota | ||
### Example Usage | ||
|
||
Example on using the package: | ||
- Using the **time_up** function: | ||
|
||
- Using **time_up** function: | ||
```python | ||
from tquota import quota | ||
from tquota import Quota | ||
import time | ||
# quota _time was set for 1 minute and the gap _time as 30 second | ||
qt = quota('1m','30s') | ||
|
||
# Quota time is set for 1 minute and gap time is auto-adjusted | ||
qt = Quota('1m') | ||
# Set quota_time for 1 minute and gap_time for 30 seconds | ||
# qt = Quota('1m', '30s') | ||
|
||
for i in range(1000): | ||
time.sleep(1) | ||
if qt.time_up(): | ||
print('The process has reached the limited time') | ||
print('The process has reached the limited time.') | ||
break | ||
``` | ||
- Using **hastime** function: | ||
- Using the **hastime** function: | ||
|
||
```python | ||
from tquota import quota | ||
from tquota import Quota | ||
import time | ||
# quota _time was set for 1 minute and the gap _time as 30 second | ||
qt = quota('1m','30s') | ||
|
||
# Quota time is set for 1 minute and gap time is auto-adjusted | ||
# qt = Quota('1m') | ||
|
||
# Set quota_time for 1 minute and gap_time for 30 seconds | ||
qt = Quota('1m', '30s') | ||
|
||
for i in range(1000): | ||
time.sleep(1) | ||
if not qt.hastime(): | ||
print('The process has reached the limited time') | ||
print('The process has reached the limited time.') | ||
break | ||
``` | ||
``` | ||
|
||
--- | ||
## Error Handling | ||
|
||
The `Quota` class may raise the following exceptions: | ||
|
||
- `ValueError`: Raised for invalid time formats or non-positive time values. | ||
- `TypeError`: Raised if non-string values are provided for time parameters. | ||
- `AttributeError`: Raised if internal properties are accessed incorrectly. | ||
--- | ||
## License | ||
|
||
This project is licensed under the MIT License. See the [LICENSE](https://github.com/aljbri/tquota/blob/master/LICENSE) file for details. | ||
|
||
--- | ||
## Updates | ||
|
||
### v0.0.1 | ||
- Initial implementation of the `quota` class. | ||
|
||
### v0.0.2 | ||
- Major error fix `quota` class. | ||
|
||
### v0.0.3 | ||
- **Auto Gap Time**: Added support for automatic calculation of `gap_time` when it is set to `'auto'`, dynamically adjusting the buffer time based on the session duration. | ||
- **Error Handling Enhancements**: Improved validation for time formats, with clearer exceptions raised (`ValueError`, `TypeError`, `AttributeError`) for invalid inputs or improper usage. | ||
- **Optimized Logging**: Added an optional logging feature that provides detailed output for quota time, gap time, and overall usage when enabled. | ||
- **Performance Improvements**: Optimized the time-tracking logic for smoother integration into various cloud platforms. | ||
- **Python Compatibility**: Compatible with Python versions 2.7 and 3.0+. | ||
|
||
--- | ||
## Contributing | ||
|
||
Contributions are welcome! If you have suggestions or improvements, please feel free to submit a pull request or open an issue. | ||
|
||
--- | ||
## Contact | ||
|
||
For inquiries or feedback, please contact the author at [mr.aljbri@gmail.com](mailto:mr.aljbri@gmail.com). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
tquota.appenvs.com |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
[build-system] | ||
requires = ["setuptools>=42", "wheel"] | ||
build-backend = "setuptools.build_meta" | ||
|
||
[project] | ||
name = "tquota" | ||
version = "0.0.3" | ||
description = "A lightweight processing timer module for quota-based cloud environments." | ||
authors = [ | ||
{ name = "Abdussalam Aljbri", email = "mr.aljbri@gmail.com" } | ||
] | ||
maintainers = [ | ||
{ name = "Abdussalam Aljbri", email = "mr.aljbri@gmail.com" } | ||
] | ||
license = {text = "MIT License"} | ||
readme = {file = "README.md", content-type = "text/markdown"} | ||
keywords = ["quota", "cloud", "timer", "kaggle", "colab", "session", "management", 'monitor'] | ||
requires-python = ">=2.7, <4" # Minimum required Python version | ||
|
||
classifiers = [ | ||
'Programming Language :: Python :: 2.7', | ||
'Programming Language :: Python :: 3.0', | ||
'Programming Language :: Python :: 3', | ||
'License :: OSI Approved :: MIT License', | ||
'Operating System :: OS Independent' | ||
] | ||
|
||
[project.urls] | ||
Homepage = "https://github.com/aljbri/tquota/" | ||
Documentation = "https://aljbri.github.io/tquota/" | ||
Repository = "https://github.com/aljbri/tquota/" | ||
Issues = "https://github.com/aljbri/tquota/issues" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
from setuptools import setup, find_packages | ||
|
||
# Read the contents of your README file | ||
with open("README.md", "r", encoding="utf-8") as fh: | ||
long_description = fh.read() | ||
|
||
setup( | ||
name="tquota", # Name of the package | ||
version="0.0.3", # Version number | ||
author="Abdussalam Aljbri", # Author name | ||
author_email="mr.aljbri@gmail.com", # Author email | ||
description="A processing timer module for cloud servers with session quota limitations.", | ||
long_description=long_description, # Use the README.md as the long description | ||
long_description_content_type="text/markdown", # Make sure to specify that it's markdown | ||
url="https://github.com/aljbri/tquota", # Project GitHub URL | ||
packages=find_packages(), # Automatically discover all the packages in your project | ||
classifiers=[ | ||
"Programming Language :: Python :: 2.7", | ||
"Programming Language :: Python :: 3.0", | ||
"Programming Language :: Python :: 3", # Allows for all 3.x versions | ||
"License :: OSI Approved :: MIT License", # License type | ||
"Operating System :: OS Independent", # OS compatibility | ||
], | ||
python_requires='>=2.7, <4', # Minimum version of Python required | ||
install_requires=[], # Add any dependencies your package needs here | ||
keywords="quota timer cloud session limit processing kaggle colab", # Useful keywords | ||
project_urls={ | ||
"Bug Tracker": "https://github.com/aljbri/tquota/issues", # URL to submit issues | ||
"Documentation": "https://github.com/aljbri/tquota/blob/main/README.md", # Documentation URL | ||
"Source Code": "https://github.com/aljbri/tquota", # Source code URL | ||
}, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import unittest | ||
import time | ||
from tquota import Quota | ||
|
||
class TestQuota(unittest.TestCase): | ||
|
||
def test_initialization_valid(self): | ||
"""Test that valid initialization works properly.""" | ||
quota = Quota('1h', '5m') | ||
self.assertEqual(quota.quota_time, 3600) | ||
self.assertEqual(quota.gap_time, 300) | ||
|
||
def test_initialization_invalid_time_format(self): | ||
"""Test that invalid time formats raise a ValueError.""" | ||
with self.assertRaises(ValueError): | ||
Quota('invalid', '5m') | ||
|
||
def test_to_seconds(self): | ||
"""Test conversion from time format to seconds.""" | ||
quota = Quota('1h') | ||
self.assertEqual(quota._to_seconds('30s'), 30) | ||
self.assertEqual(quota._to_seconds('5m'), 300) | ||
self.assertEqual(quota._to_seconds('2h'), 7200) | ||
self.assertEqual(quota._to_seconds('1d'), 86400) | ||
|
||
def test_hastime_before_gap(self): | ||
"""Test hastime returns True before gap time is reached.""" | ||
quota = Quota('1m', '10s') | ||
time.sleep(2) # Sleep for a few seconds to simulate execution | ||
self.assertTrue(quota.hastime()) | ||
|
||
def test_time_up_after_quota(self): | ||
"""Test time_up returns True after quota time is reached.""" | ||
quota = Quota('3s', '1s') | ||
time.sleep(4) # Sleep to exceed quota time | ||
self.assertTrue(quota.time_up()) | ||
|
||
def test_dynamic_gap_time_auto(self): | ||
"""Test automatic gap time adjustment based on execution times.""" | ||
quota = Quota('10s', 'auto') # Set gap time to auto | ||
for _ in range(5): # Simulate loop execution | ||
time.sleep(0.5) # Each iteration takes ~0.5s | ||
quota.hastime() # This will update the gap time | ||
self.assertGreater(quota.gap_time, 0.4) # Check if gap time was adjusted | ||
|
||
def test_format_time(self): | ||
"""Test that the time formatting function works as expected.""" | ||
quota = Quota('1h') | ||
formatted_time = quota._format_time(3661) | ||
self.assertEqual(formatted_time, '1h:1m:1s') | ||
|
||
def test_remaining_time(self): | ||
"""Test remaining time calculation.""" | ||
quota = Quota('10s') | ||
time.sleep(3) | ||
remaining = quota._remaining_time() | ||
self.assertLessEqual(remaining, 7) | ||
|
||
def test_gap_time_greater_than_quota(self): | ||
"""Test that setting gap time greater than quota raises an error.""" | ||
with self.assertRaises(ValueError): | ||
Quota('5m', '10m') | ||
|
||
def test_logging_enabled(self): | ||
"""Test that logging can be enabled without errors.""" | ||
quota = Quota('10s', enable_logging=True) | ||
self.assertTrue(quota.enable_logging) | ||
|
||
if __name__ == '__main__': | ||
unittest.main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.