Added ProxyObject + CLAUDE.md
This commit is contained in:
158
README.md
158
README.md
@@ -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`
|
||||
Reference in New Issue
Block a user