Metadata-Version: 2.4
Name: groupcast
Version: 1.1.1
Summary: Dynamic method broadcasting to groups of objects
Author-email: Tzur Soffer <tzur.soffer@gmail.com>
License-Expression: MIT
Project-URL: Homepage, https://github.com/TzurSoffer/Groupcast
Project-URL: Repository, https://github.com/TzurSoffer/Groupcast
Keywords: delegation,broadcasting,group,OOP,metaprogramming
Classifier: Programming Language :: Python :: 3
Classifier: Operating System :: OS Independent
Description-Content-Type: text/markdown
License-File: LICENCE
Dynamic: license-file



Groupcast
============

**Groupcast** is a lightweight Python utility for broadcasting method calls and aggregating attribute access across a group of objects — as if they were a single entity.

It supports both serial and parallel execution modes, along with list-like behavior (iteration, indexing, appending, popping).


---

## Features

- ✅ Broadcast method calls across objects (`group.method(args)`)
- ✅ Access non-callable attributes as aggregated lists (`group.attr`)
- ✅ Switch between **serial** and **parallel** execution modes
- ✅ Direct control via `apply()` for methods and `get()` for attributes
- ✅ List-like behavior: `len()`, `[]`, iteration, `append()`, `pop()`

---

## Installation

This library is instable via pip using the command `pip install groupcast`, if you would rather not use pip, you could also just drop this file into your project and import it that way.

Simple Usage
-----

```python
class Example:
    def __init__(self, x):
        self.x = x
    def double(self):
        return self.x * 2
inputs = [1, 2, 3]
group = groupcast.Group(inputs=inputs, class_=Example) 
print(group.x)
# should result in [1, 2, 3]

print(group.double())
# should result in [2, 4, 6]

print(group[0].x)    #< to only print the value for the first object
# should result in 1
```

Constructor
-----------

`Group(inputs=None, class_=None, objects=None, parallel=False, maxWorkers=None)`

You can initialize a `Group` in two ways:

1.  **Using `inputs` and `class_`**:
    
    *   Creates a list of objects by passing each element of `inputs` to the `class_` constructor.
        
2.  **Using `objects` directly**:
    
    *   Pass in a list of pre-created objects.
        

If neither `objects` nor both `inputs` and `class_` are provided, a `TypeError` is raised.

Execution Modes
---------------

Use `.changeExecutionMode(parallel=True, maxWorkers=...)` to toggle between:

*   **Serial mode (default):** runs method calls one after another.
    
*   **Parallel mode:** runs method calls concurrently using threads.

To change modes, use the following:<br>
`group.changeExecutionMode(parallel=True) # now runs in parallel` <br>
You can also set it to false to return back to serial mode

Attribute & Method Access
-------------------------

*   `group.attr` returns a list of attribute values (e.g., `group.x will return [x1,x2,x3,x4] for every object`)
    
*   `group.method(*args)` broadcasts the call across all objects and will return the results
    
*   For explicit control:
    
    *   `group.get("attrName")`
        
    *   `group.apply("methodName", *args)`
        

* * *

Appending & Removing
--------------------

To append, you can use the append and pass the same varibles as you pass to __init__ <br>
EX:
`group.append(input=4, class_=Example)` will add a new Example object initialized with the value `4`

You can append using either an `input` and `class_`, or a ready `object`.

Example Use Cases
-----------------

*   Managing multiple similar sensor or device objects.
    
*   Group operations on widgets, models, or entities in simulations/games.
    
*   Synchronous control of multiple instances for testing or broadcasting commands.
    

License
-------

MIT License (see LICENSE file for more information)
