Skip to content

Commit 51d3be5

Browse files
Merge pull request #5 from caffeine-addictt/dev
v0.1.0 release
2 parents 14c5d02 + 530da06 commit 51d3be5

File tree

9 files changed

+566
-5
lines changed

9 files changed

+566
-5
lines changed

.coverage

0 Bytes
Binary file not shown.

README.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ Fully compatible with the threading library, this project hopes to provide a mor
4444
<br />
4545

4646
**!! Important !!**<br />
47-
THis project is in it's very early stages of development and bugs are to be expected.
47+
This project is in it's very early stages of development and bugs are to be expected.
4848

4949
<br />
5050

@@ -105,7 +105,10 @@ _Below is an example of how you can instruct your audience on installing and set
105105
## Roadmap
106106

107107
- [x] 0.0.1 Release
108-
- [ ] Bug fixes
108+
- [x] Bug fixes
109+
- [x] 0.1.0 Release
110+
- [ ] New Features
111+
- [ ] 0.1.1 Release
109112

110113
See the [open issues](https://github.com/caffeine-addictt/thread/issues) for a full list of proposed features (and known issues).
111114

docs/exceptions.md

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
# Exceptions
2+
3+
> [!NOTE]
4+
> Exceptions from Python's `threading` module are not included
5+
6+
<br />
7+
<details>
8+
<summary>Jump to</summary>
9+
<ul>
10+
<li><a href='#ignoring-exceptions'> Ignoring Exceptions</a></li>
11+
<li><a href='#exceptions-1'> Exceptions </a></li>
12+
</ul>
13+
</details>
14+
15+
16+
Don't have the thread library? [See here](./getting-started.md) for installing thread
17+
18+
---
19+
20+
## Ignoring exceptions
21+
22+
When initializing a thread, you can parse a [**suppress_errors**](./threading.md#parameters) bool.<br />
23+
By default it is false, but if set to true, exceptions will not be propagated but just stored within `Thread._errors`
24+
25+
When initializing a thread, you can parse a [**ignore_errors**](./threading.md#parameters) sequence.<br />
26+
By default it is an empty tuple.<br />
27+
Ignored errors will not be propagated and not stored within `Thread._errors`
28+
29+
<br />
30+
31+
### Example
32+
```py
33+
from thread import Thread
34+
35+
def bad_function():
36+
raise RuntimeError('>:cc')
37+
38+
39+
# Normal behaviour
40+
thread0 = Thread(
41+
target = bad_function
42+
)
43+
thread0.start()
44+
thread0.join()
45+
# exit(1) RuntimeError(':<<')
46+
47+
48+
# Suppress exceptions
49+
thread1 = Thread(
50+
target = bad_function,
51+
suppress_errors = True
52+
)
53+
thread1.start()
54+
thread1.join()
55+
print(thread1._errors) # list[RuntimeError('>:cc')]
56+
57+
58+
# Ignore error
59+
thread2 = Thread(
60+
target = bad_function,
61+
ignore_errors = [RuntimeError]
62+
)
63+
thread2.start()
64+
thread2.join()
65+
print(thread2._errors) # list[]
66+
67+
68+
# Non-ignored error
69+
thread3 = Thread(
70+
target = bad_function,
71+
ignore_errors = [ValueError]
72+
)
73+
thread3.start()
74+
thread3.join()
75+
# exit(1) RuntimeError(':<<')
76+
77+
78+
# Non-ignored error with suppressing
79+
thread4 = Thread(
80+
target = bad_function,
81+
ignore_errors = [ValueError],
82+
suppress_errors = True
83+
)
84+
thread4.start()
85+
thread4.join()
86+
print(thread4._errors) # list[RuntimeError(':<<')]
87+
88+
89+
# Ignored error with suppressing
90+
thread5 = Thread(
91+
target = bad_function,
92+
ignore_errors = [RuntimeError],
93+
suppress_errors = True
94+
)
95+
thread5.start()
96+
thread5.join()
97+
print(thread5._errors) # list[]
98+
```
99+
100+
<br />
101+
102+
103+
## Exceptions
104+
105+
The list of exceptions that can be thrown
106+
107+
<br />
108+
109+
110+
### ThreadErrorBase
111+
112+
This is the base exception class that all exceptions inherit from
113+
114+
<br />
115+
116+
117+
### ThreadStillRunningError
118+
119+
This is raised when you attempt to invoke a method which requries the thread to not be running, but is running.
120+
> You can wait for the thread to terminate with [**Thread.join()**](./threading.md#methods) before invoking the method
121+
122+
> You can check if the thread is running with [**Thread.is_alive()**](threading.md#methods) before invoking the method
123+
124+
<br />
125+
126+
127+
### ThreadNotRunningError
128+
129+
This is raised when you attempt to invoke a method which requires the thread to be running, but isn't
130+
> You can run the thread with [**Thread.start()**](threading.md#methods) before invoking the method
131+
132+
<br />
133+
134+
135+
### ThreadNotInitializedError
136+
137+
This is raised when you attempt to invoke a method which requires the thread to be initialized, but isn't
138+
> You can initialize and start the thread with [**Thread.start()**](threading.md#methods) before invoking the method
139+
140+
<br />
141+
142+
143+
### HookRuntimeError
144+
145+
This is raised when hooks raise an exception<br />
146+
Conforms to when thread is ran with errors suppressed or ignored
147+
148+
Example traceback
149+
```text
150+
HookRuntimeError: Encountered runtime errors in hooks
151+
152+
1. my_function
153+
>>>>>>>>>>
154+
/usr/home/proj/main.py:50
155+
ZeroDivisionError:
156+
<<<<<<<<<<
157+
158+
2. my_otherfunction
159+
>>>>>>>>>>
160+
ImportError:
161+
<<<<<<<<<<
162+
```
163+
164+
<br />
165+
166+
[See here](./threading.md) for how to using the `thread.Thread` class!

docs/getting-started.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# Getting started with thread
2+
3+
Thanks for using thread! I hope you find it useful for your projects.
4+
5+
Here's to you get started.
6+
7+
---
8+
9+
## Prerequisites
10+
11+
* Python 3.11+
12+
13+
The project is quite heavily type-annotated, and we use `Concatenate[Any, ...]` in some function declarations.
14+
However `Python <=3.10` does not support `...` being the last argument as laid out in [this stack overflow question](https://stackoverflow.com/questions/74893354/is-literal-ellipsis-really-valid-as-paramspec-last-argument).
15+
16+
If possible, I may release a sister version of thread that is compatible with `Python 3.9+` in the future, but for the time being,
17+
support will extend only from Python 3.11+
18+
19+
<br />
20+
21+
22+
## Installing
23+
24+
### From pip (Recommended)
25+
```sh
26+
pip install thread
27+
```
28+
29+
### Building from source (Not Recommended)
30+
```sh
31+
# Clone this repository
32+
git clone https://github.com/caffeine-addictt/thread
33+
34+
# Install dependencies
35+
pip install poetry
36+
37+
# Build the distribution
38+
python3 -m poetry build
39+
40+
# Install the distribution
41+
pip install -e .
42+
```
43+
44+
<br />
45+
46+
47+
## Importing thread
48+
49+
Import thread into your .py file
50+
```py
51+
import thread
52+
```
53+
54+
Now you have successfully installed thread!
55+
56+
[See here](./threading.md) for how to using the `thread.Thread` class!

docs/parallel-processing.md

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
# Parallel Processing Documentation
2+
3+
I will lay out how to use the `thread.ParallelProcessing` class!
4+
5+
<br />
6+
<details>
7+
<summary>Jump to</summary>
8+
<ul>
9+
<li><a href='#how-does-it-work'> How it works </a></li>
10+
<li><a href='#initializing-a-parallel-process'> Initialize a Parallel Process </a></li>
11+
<li><a href='#parameters'> Parameters </a></li>
12+
<li><a href='#attributes'> Attributes </a></li>
13+
<li><a href='#methods'> Class Methods </a></li>
14+
</ul>
15+
</details>
16+
17+
18+
Don't have the thread library? [See here](./getting-started.md) for installing thread
19+
20+
---
21+
22+
## Importing the class
23+
24+
```py
25+
from thread import ParallelProcessing
26+
```
27+
28+
<br />
29+
30+
31+
## How does it work?
32+
33+
Parallel Processing works best by optimizing data processing with large datasets.
34+
35+
What it does:
36+
```py
37+
dataset = [1, 2, 3, ..., 2e10]
38+
39+
# Splits into chunks as evenly as possible
40+
# thread_count = min(max_threads, len(dataset))
41+
# n == len(chunks) == len(thread_count)
42+
chunks = [[1, 2, 3, ...], [50, 51, 52, ...], ...]
43+
44+
# Initialize and run n threads
45+
# each thread handles 1 chunk of data and parses it into the function
46+
47+
# processed data is arranged back in order
48+
49+
# processed data is returned as a list[Data_Out]
50+
```
51+
52+
<br />
53+
54+
55+
## Initializing a parallel process
56+
57+
A simple example
58+
```py
59+
def my_data_processor(Data_In) -> Data_Out: ...
60+
61+
# Reccommended way
62+
my_processor = ParallelProcessing(
63+
function = my_data_processor,
64+
dataset = [i in range(0, n)]
65+
)
66+
67+
# OR
68+
# Not the reccommended way
69+
my_processor = ParallelProcessing(my_data_processor, [i in range(0, n)])
70+
```
71+
72+
It can be ran by invoking the `start()` method
73+
```py
74+
my_processor.start()
75+
```
76+
77+
> [!NOTE]
78+
> The **threading.ParallelProcessing()** class from python will only be initialized when **start()** is invoked
79+
80+
<br />
81+
82+
83+
### Parameters
84+
85+
* function : (DataProcessor, dataset, *args, **kwargs) -> Any | Data_Out
86+
> This should be a function that takes in a dataset and/or anything and returns Data_Out and/or anything
87+
88+
* dataset : Sequence[Data_In] = ()
89+
> This should be an interable sequence of arguments parsed to the `DataProcessor` function<br />
90+
> (e.g. tuple('foo', 'bar'))
91+
92+
* *overflow_args : Overflow_In
93+
> These are arguments parsed to [**thread.Thread**](./threading.md#parameters)
94+
95+
* **overflow_kwargs : Overflow_In
96+
> These are arguments parsed to [**thread.Thread**](./threading.md#parameters)<br />
97+
> [!NOTE]
98+
> If `args` is present, then it will automatically be removed from kwargs and joined with `overflow_args`
99+
100+
* **Raises** AssertionError: max_threads is invalid
101+
102+
<br />
103+
104+
105+
### Attributes
106+
107+
These are attributes of [`ParallelProcessing`](#importing-the-class) class
108+
109+
* results : List[Data_Out]
110+
> The result value
111+
> **Raises** [`ThreadNotInitializedError`](./exceptions.md#threadNotInitializedError)
112+
> **Raises** [`ThreadNotRunningError`](./exceptions.md#threadnotrunningerror)
113+
> **Raises** [`ThreadStillRunningError`](./exceptions.md#threadStillRunningError)
114+
115+
<br />
116+
117+
118+
### Methods
119+
120+
These are methods of [`ParallelProcessing`](#importing-the-class) class
121+
122+
* start : () -> None
123+
> Initializes the threads and starts it<br />
124+
> **Raises** [`ThreadStillRunningError`](./exceptions.md#threadStillRunningError)
125+
126+
* is_alive : () -> bool
127+
> Indicates whether the thread is still alive<br />
128+
> **Raises** [`ThreadNotInitializedError`](./exceptions.md#threadNotInitializedError)
129+
130+
* get_return_values : () -> Data_Out
131+
> Halts the current thread execution until the thread completes
132+
133+
* join : () -> JoinTerminatedStatus
134+
> Halts the current thread execution until a thread completes or exceeds the timeout
135+
> **Raises** [`ThreadNotInitializedError`](./exceptions.md#threadNotInitializedError)
136+
> **Raises** [`ThreadNotRunningError`](./exceptions.md#threadnotrunningerror)
137+
138+
<br />
139+
140+
141+
Now you know how to use the [`ParallelProcessing`](#importing-the-class) class!
142+
143+
[See here](./parallel-processing.md) for how to using the `thread.ParallelProcessing` class!

0 commit comments

Comments
 (0)