Added ProxyObject + CLAUDE.md

This commit is contained in:
2025-12-03 21:20:20 +01:00
parent 0ef9523e6b
commit d8b1ef2e2c
5 changed files with 628 additions and 6 deletions

158
README.md
View File

@@ -3,8 +3,7 @@
## Overview
The **MyUtils** project is a Python library providing utilities to enhance Python objects, enabling features like
dynamic property access and observability of attributes. The library is designed to modify and extend the behavior of
objects in an easy-to-use and modular way, making it more developer-friendly.
dynamic property access, observability of attributes, and flexible property mapping. The library is designed to modify and extend the behavior of objects in an easy-to-use and modular way, making it more developer-friendly.
---
@@ -335,6 +334,149 @@ print(exp.new_key) # Output: new_value
---
### 3. **ProxyObject**
The `ProxyObject` module provides a way to create proxy objects that map properties from a source object to new property names, with support for nested properties and wildcards.
#### Key Features:
- Map object properties to different names using a mapping dictionary
- Access nested properties using dot notation (e.g., `"address.city"`)
- Support for wildcard patterns to copy multiple properties at once
- Automatically resolve property paths during initialization
#### Key Classes/Functions:
- **`ProxyObject`**:
A class that wraps an object and exposes its properties through a customizable mapping.
#### Example Usage:
Here are examples using the `ProxyObject` module:
##### Basic Property Mapping
```python
from myutils.ProxyObject import ProxyObject
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
person = Person("John", 30)
# Map 'name' to 'display_name' and 'age' to 'years'
mappings = {
"display_name": "name",
"years": "age"
}
proxy = ProxyObject(person, mappings)
print(proxy.display_name) # Output: John
print(proxy.years) # Output: 30
```
##### Nested Property Mapping
```python
from myutils.ProxyObject import ProxyObject
class Address:
def __init__(self, city, country):
self.city = city
self.country = country
class Employee:
def __init__(self, name, address):
self.name = name
self.address = address
address = Address("Paris", "France")
employee = Employee("Alice", address)
# Map nested properties using dot notation
mappings = {
"employee_name": "name",
"city_name": "address.city"
}
proxy = ProxyObject(employee, mappings)
print(proxy.employee_name) # Output: Alice
print(proxy.city_name) # Output: Paris
```
##### Wildcard Patterns
```python
from myutils.ProxyObject import ProxyObject
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
person = Person("John", 30)
# Copy all properties from the source object
mappings = {"*": ""}
proxy = ProxyObject(person, mappings)
print(proxy.name) # Output: John
print(proxy.age) # Output: 30
```
```python
# Copy all properties from a nested object
class Employee:
def __init__(self, name, address):
self.name = name
self.address = address
class Address:
def __init__(self, city, country):
self.city = city
self.country = country
address = Address("Paris", "France")
employee = Employee("Alice", address)
# Copy all properties from 'address' to the proxy
mappings = {"*": "address"}
proxy = ProxyObject(employee, mappings)
print(proxy.city) # Output: Paris
print(proxy.country) # Output: France
```
```python
# Flatten nested object properties
class City:
def __init__(self, name, zip_code):
self.name = name
self.zip_code = zip_code
class Address:
def __init__(self, city, country):
self.city = city
self.country = country
address = Address(City("Paris", "75001"), "France")
employee = Employee("Alice", address)
# Flatten all properties from address.* (expands city's properties and country)
mappings = {"*": "address.*"}
proxy = ProxyObject(employee, mappings)
print(proxy.name) # Output: Paris (from address.city.name)
print(proxy.zip_code) # Output: 75001 (from address.city.zip_code)
print(proxy.country) # Output: France (from address.country)
```
---
## Project Structure
To understand the file organization, here's the structure of the project:
@@ -344,12 +486,17 @@ To understand the file organization, here's the structure of the project:
MyUtils
├── src
│ └── myutils
── __init__.py # Main package initialization
── __init__.py # Main package initialization
│ ├── Dummy.py #
│ ├── Expando.py #
│ ├── observable.py #
│ └── ProxyObject.py #
├── tests
│ ├── __init__.py # Test package initialization
│ ├── test_dummy.py # Tests for Dummy module
│ ├── test_expando.py # Tests for Expando module
── test_observable.py # Tests for Observable module
── test_observable.py # Tests for Observable module
│ └── test_proxyobject.py # Tests for ProxyObject module
├── .gitignore # Git ignore file
├── main.py # Application entry point
├── requirements.txt # Project dependencies
@@ -396,4 +543,5 @@ Special thanks to the Python and open-source community for their tools, inspirat
* 0.1.0 : Initial release
* 0.2.0 : Observable results can be collected using `collect_return_values`
* 0.3.0 : Added `unbind`, `unbind_all`, `has_listeners` `get_listener_count` to Observable
* 0.4.0 : Added `add_event_listener` and `remove_event_listener`
* 0.4.0 : Added `add_event_listener` and `remove_event_listener`
* 0.5.0 : Added `ProxyObject`