mbpc-improved 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mbpc_improved-1.0.0/LICENSE +21 -0
- mbpc_improved-1.0.0/MANIFEST.in +4 -0
- mbpc_improved-1.0.0/PKG-INFO +301 -0
- mbpc_improved-1.0.0/README.md +263 -0
- mbpc_improved-1.0.0/mbpc/__init__.py +11 -0
- mbpc_improved-1.0.0/mbpc/classdef.py +89 -0
- mbpc_improved-1.0.0/mbpc/interfacedef.py +40 -0
- mbpc_improved-1.0.0/mbpc/interfaces.py +13 -0
- mbpc_improved-1.0.0/mbpc/structdef.py +79 -0
- mbpc_improved-1.0.0/mbpc/utilities.py +12 -0
- mbpc_improved-1.0.0/mbpc_improved.egg-info/PKG-INFO +301 -0
- mbpc_improved-1.0.0/mbpc_improved.egg-info/SOURCES.txt +16 -0
- mbpc_improved-1.0.0/mbpc_improved.egg-info/dependency_links.txt +1 -0
- mbpc_improved-1.0.0/mbpc_improved.egg-info/requires.txt +10 -0
- mbpc_improved-1.0.0/mbpc_improved.egg-info/top_level.txt +1 -0
- mbpc_improved-1.0.0/pyproject.toml +88 -0
- mbpc_improved-1.0.0/setup.cfg +4 -0
- mbpc_improved-1.0.0/setup.py +10 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Pac-Dessert1436
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mbpc-improved
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Enhanced version of MBPC (Much Better Python Classes) for advanced OOP in Python
|
|
5
|
+
Author-email: Pac-Dessert1436 <pac-dessert1436@example.com>
|
|
6
|
+
Maintainer-email: Pac-Dessert1436 <pac-dessert1436@example.com>
|
|
7
|
+
License: MIT
|
|
8
|
+
Project-URL: Homepage, https://github.com/Pac-Dessert1436/mbpc-improved
|
|
9
|
+
Project-URL: Bug Reports, https://github.com/Pac-Dessert1436/mbpc-improved/issues
|
|
10
|
+
Project-URL: Source, https://github.com/Pac-Dessert1436/mbpc-improved
|
|
11
|
+
Project-URL: Documentation, https://github.com/Pac-Dessert1436/mbpc-improved#readme
|
|
12
|
+
Project-URL: Changelog, https://github.com/Pac-Dessert1436/mbpc-improved/blob/main/CHANGELOG.md
|
|
13
|
+
Project-URL: Repository, https://github.com/Pac-Dessert1436/mbpc-improved.git
|
|
14
|
+
Keywords: oop,object-oriented,classes,interfaces,structs,type-safe,decorators,inheritance,metaprogramming,code-generation
|
|
15
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
16
|
+
Classifier: Intended Audience :: Developers
|
|
17
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
18
|
+
Classifier: Operating System :: OS Independent
|
|
19
|
+
Classifier: Programming Language :: Python :: 3
|
|
20
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
21
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
22
|
+
Classifier: Topic :: Software Development :: Code Generators
|
|
23
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
24
|
+
Classifier: Topic :: Utilities
|
|
25
|
+
Requires-Python: >=3.7
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
License-File: LICENSE
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
30
|
+
Requires-Dist: pytest-cov>=4.0; extra == "dev"
|
|
31
|
+
Requires-Dist: flake8>=5.0; extra == "dev"
|
|
32
|
+
Requires-Dist: black>=22.0; extra == "dev"
|
|
33
|
+
Requires-Dist: isort>=5.0; extra == "dev"
|
|
34
|
+
Requires-Dist: twine>=4.0; extra == "dev"
|
|
35
|
+
Requires-Dist: build>=0.7; extra == "dev"
|
|
36
|
+
Requires-Dist: mypy>=1.0; extra == "dev"
|
|
37
|
+
Dynamic: license-file
|
|
38
|
+
|
|
39
|
+
# `mbpc-improved`: Enhanced "Much Better Python Classes"
|
|
40
|
+
|
|
41
|
+
## Description
|
|
42
|
+
|
|
43
|
+
`mbpc-improved` is an enhanced version of [MBPC](https://github.com/MintLF/MBPC/) ("Much Better Python Classes"), a powerful library that introduces advanced object-oriented programming capabilities to Python. It provides utilities for defining interfaces, classes, and structs in a more structured, type-safe manner, bringing some of the best features of statically-typed languages to Python's dynamic environment.
|
|
44
|
+
|
|
45
|
+
### Key Improvements Over Original MBPC
|
|
46
|
+
- **Snake_case Consistency**: All identifiers converted from camelCase to Python's standard snake_case.
|
|
47
|
+
- **Improved Readability**: Lambda expressions replaced with explicit `def-return` statements.
|
|
48
|
+
- **Struct Support**: Added `structdef` for creating data-focused structures with interface support.
|
|
49
|
+
- **Simplified Initialization**: Renamed `initialize` method to `init` for brevity and consistency.
|
|
50
|
+
- **Object Cloning**: Added `clone` method for deep copying objects.
|
|
51
|
+
- **Enhanced Iterability**: Eliminated need for manual list conversion when iterating over interfaces.
|
|
52
|
+
|
|
53
|
+
_Note: For built-in iterability, simply use Python's `reversed(...)` function._
|
|
54
|
+
|
|
55
|
+
## Installation
|
|
56
|
+
|
|
57
|
+
### Prerequisites
|
|
58
|
+
- Python 3.7 or higher
|
|
59
|
+
|
|
60
|
+
### Via `pip`
|
|
61
|
+
Install the package directly from PyPI:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
pip install mbpc-improved
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### From Source
|
|
68
|
+
1. Clone the repository:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
git clone https://github.com/Pac-Dessert1436/mbpc-improved.git
|
|
72
|
+
cd mbpc-improved
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
2. Install in development mode:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
pip install -e .
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
> **Note**: Avoid running scripts directly within the `mbpc` directory, as this may cause import errors. Always run from the project root or install the package first.
|
|
82
|
+
|
|
83
|
+
## Core Components
|
|
84
|
+
|
|
85
|
+
`mbpc-improved` provides three primary decorators for defining structured components:
|
|
86
|
+
|
|
87
|
+
| Component | Description |
|
|
88
|
+
|-----------|-------------|
|
|
89
|
+
| `interfacedef` | Define interfaces with required methods that must be implemented by classes or structs. |
|
|
90
|
+
| `classdef` | Create classes with inheritance and interface implementation capabilities. |
|
|
91
|
+
| `structdef` | Define data-focused structures (similar to C structs) with interface support. |
|
|
92
|
+
|
|
93
|
+
## Usage Examples
|
|
94
|
+
|
|
95
|
+
### 1. Defining Interfaces
|
|
96
|
+
|
|
97
|
+
Interfaces define contracts that classes or structs must implement. Use `interfacedef` to create interfaces with required methods:
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
from mbpc.interfacedef import interfacedef
|
|
101
|
+
|
|
102
|
+
@interfacedef()
|
|
103
|
+
def Hashable(self):
|
|
104
|
+
"""Interface for objects that can be hashed."""
|
|
105
|
+
@self.method
|
|
106
|
+
def hashcode() -> int: ... # Must return an integer hash value
|
|
107
|
+
|
|
108
|
+
@interfacedef()
|
|
109
|
+
def Equatable(self):
|
|
110
|
+
"""Interface for objects that can be compared for equality."""
|
|
111
|
+
@self.method
|
|
112
|
+
def equals(other) -> bool: ... # Must return a boolean
|
|
113
|
+
|
|
114
|
+
# NOTE: Common interfaces like Hashable and Equatable are already available in `mbpc.interfaces`
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### 2. Creating Structs
|
|
118
|
+
|
|
119
|
+
Structs are lightweight, data-focused structures that can implement interfaces. They're ideal for simple data containers:
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
from mbpc.structdef import structdef
|
|
123
|
+
from mbpc.interfaces import Hashable, Equatable
|
|
124
|
+
|
|
125
|
+
@structdef(Hashable, Equatable)
|
|
126
|
+
def Point(self, x: int, y: int):
|
|
127
|
+
"""A 2D point struct with x and y coordinates."""
|
|
128
|
+
# Initialize instance variables
|
|
129
|
+
self.x = x
|
|
130
|
+
self.y = y
|
|
131
|
+
|
|
132
|
+
# Implement Hashable interface
|
|
133
|
+
@self.method
|
|
134
|
+
def hashcode(self) -> int:
|
|
135
|
+
"""Generate a hash value for the point."""
|
|
136
|
+
return hash((self.x, self.y))
|
|
137
|
+
|
|
138
|
+
# Implement Equatable interface
|
|
139
|
+
@self.method
|
|
140
|
+
def equals(self, other) -> bool:
|
|
141
|
+
"""Compare two points for equality."""
|
|
142
|
+
if not hasattr(other, 'x') or not hasattr(other, 'y'):
|
|
143
|
+
return False
|
|
144
|
+
return self.x == other.x and self.y == other.y
|
|
145
|
+
|
|
146
|
+
# Example Usage:
|
|
147
|
+
p1 = Point(2, 3)
|
|
148
|
+
p2 = Point(2, 3)
|
|
149
|
+
p3 = Point(5, 7)
|
|
150
|
+
|
|
151
|
+
print(p1.x, p1.y) # Output: 2 3
|
|
152
|
+
print(p1.hashcode()) # Output: (hash value of (2, 3))
|
|
153
|
+
print(p1.equals(p2)) # Output: True
|
|
154
|
+
print(p1.equals(p3)) # Output: False
|
|
155
|
+
print(p1.to_string()) # Output: {'x': 2, 'y': 3} (built-in method)
|
|
156
|
+
print(p1.clone()) # Output: Point(x=2, y=3) (deep copy)
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### 3. Defining Classes
|
|
160
|
+
|
|
161
|
+
Classes support full object-oriented features including inheritance and interface implementation, but the parent constructor are always called first:
|
|
162
|
+
|
|
163
|
+
```python
|
|
164
|
+
from mbpc.classdef import classdef
|
|
165
|
+
from mbpc.interfaces import Equatable
|
|
166
|
+
|
|
167
|
+
@classdef()
|
|
168
|
+
def Person(self, name: str, age: int):
|
|
169
|
+
"""A person class with name and age attributes."""
|
|
170
|
+
# Call parent constructor (required for all classes)
|
|
171
|
+
self.super.init()
|
|
172
|
+
|
|
173
|
+
# Initialize instance variables
|
|
174
|
+
self.name = name
|
|
175
|
+
self.age = age
|
|
176
|
+
|
|
177
|
+
# Define instance methods
|
|
178
|
+
@self.method
|
|
179
|
+
def greet(self) -> str:
|
|
180
|
+
"""Return a greeting message."""
|
|
181
|
+
return f"Hello, my name is {self.name}"
|
|
182
|
+
|
|
183
|
+
# Implement Equatable interface
|
|
184
|
+
@self.method
|
|
185
|
+
def equals(self, other) -> bool:
|
|
186
|
+
"""Compare two Person objects for equality."""
|
|
187
|
+
if not isinstance(other, Person):
|
|
188
|
+
return False
|
|
189
|
+
return self.name == other.name and self.age == other.age
|
|
190
|
+
|
|
191
|
+
# Define to_string method (built-in method override)
|
|
192
|
+
@self.method
|
|
193
|
+
def to_string(self) -> str:
|
|
194
|
+
"""Return a string representation of the person."""
|
|
195
|
+
return f"Person(name='{self.name}', age={self.age})"
|
|
196
|
+
|
|
197
|
+
# Example Usage:
|
|
198
|
+
person1 = Person("Alice", 30)
|
|
199
|
+
person2 = Person("Alice", 30)
|
|
200
|
+
person3 = Person("Bob", 25)
|
|
201
|
+
|
|
202
|
+
print(person1.greet()) # Output: Hello, my name is Alice
|
|
203
|
+
print(person1.equals(person2)) # Output: True
|
|
204
|
+
print(person1.equals(person3)) # Output: False
|
|
205
|
+
print(person1.to_string()) # Output: Person(name='Alice', age=30)
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### 4. Class Inheritance
|
|
209
|
+
|
|
210
|
+
Classes can inherit from other classes, overriding methods as needed:
|
|
211
|
+
|
|
212
|
+
```python
|
|
213
|
+
from mbpc.classdef import classdef
|
|
214
|
+
|
|
215
|
+
# Inherit from the Person class defined in the previous example
|
|
216
|
+
@classdef(Person) # Specify the parent class
|
|
217
|
+
def Student(self, name: str, age: int, major: str, student_id: str):
|
|
218
|
+
"""A Student class inheriting from Person."""
|
|
219
|
+
# Call parent constructor with required parameters
|
|
220
|
+
self.super.init(name, age)
|
|
221
|
+
|
|
222
|
+
# Add new instance variables
|
|
223
|
+
self.major = major
|
|
224
|
+
self.student_id = student_id
|
|
225
|
+
|
|
226
|
+
# Override the greet method from Person
|
|
227
|
+
@self.method
|
|
228
|
+
def greet(self) -> str:
|
|
229
|
+
"""Return a student-specific greeting."""
|
|
230
|
+
return f"Hello, I'm {self.name}, studying {self.major} (ID: {self.student_id})"
|
|
231
|
+
|
|
232
|
+
# Override to_string to include student-specific information
|
|
233
|
+
@self.method
|
|
234
|
+
def to_string(self) -> str:
|
|
235
|
+
"""Return a string representation of the student."""
|
|
236
|
+
return f"Student(name='{self.name}', age={self.age}, major='{self.major}', id='{self.student_id}')"
|
|
237
|
+
|
|
238
|
+
# Example Usage:
|
|
239
|
+
student = Student("Bob", 20, "Computer Science", "CS12345")
|
|
240
|
+
print(student.greet()) # Output: Hello, I'm Bob, studying Computer Science (ID: CS12345)
|
|
241
|
+
print(student.to_string()) # Output: Student(name='Bob', age=20, major='Computer Science', id='CS12345')
|
|
242
|
+
|
|
243
|
+
# Access inherited attributes
|
|
244
|
+
print(student.name) # Output: Bob
|
|
245
|
+
print(student.age) # Output: 20
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
## Interface Enforcement
|
|
249
|
+
|
|
250
|
+
`mbpc-improved` enforces strict interface implementation at runtime, ensuring that classes and structs adhere to the contracts defined by interfaces:
|
|
251
|
+
|
|
252
|
+
### Validation Checks
|
|
253
|
+
- **Missing Methods**: Raises `InterfaceError` if any required interface method is not implemented.
|
|
254
|
+
- **Incorrect Signatures**: Validates method parameters and return type hints.
|
|
255
|
+
- **Method Types**: Supports both instance methods and static methods.
|
|
256
|
+
|
|
257
|
+
### Example of Enforcement
|
|
258
|
+
|
|
259
|
+
```python
|
|
260
|
+
from mbpc.interfacedef import interfacedef
|
|
261
|
+
from mbpc.classdef import classdef
|
|
262
|
+
from mbpc.interfaces import InterfaceError
|
|
263
|
+
|
|
264
|
+
@interfacedef()
|
|
265
|
+
def Countable(self):
|
|
266
|
+
@self.method
|
|
267
|
+
def count() -> int: ... # Must return an integer
|
|
268
|
+
|
|
269
|
+
# This will raise an error because count() is not implemented
|
|
270
|
+
@classdef(Countable)
|
|
271
|
+
def BrokenCounter(self):
|
|
272
|
+
self.value = 0
|
|
273
|
+
|
|
274
|
+
# Missing count() method implementation
|
|
275
|
+
|
|
276
|
+
# This will also raise an error because count() returns wrong type
|
|
277
|
+
@classdef(Countable)
|
|
278
|
+
def WrongReturnType(self):
|
|
279
|
+
self.value = 0
|
|
280
|
+
|
|
281
|
+
@self.method
|
|
282
|
+
def count(self) -> str: # Should return int, not str
|
|
283
|
+
return "5"
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
## Contributing
|
|
287
|
+
|
|
288
|
+
Contributions are welcome! Please feel free to submit issues, feature requests, or pull requests on the [GitHub repository](https://github.com/Pac-Dessert1436/mbpc-improved).
|
|
289
|
+
|
|
290
|
+
## License
|
|
291
|
+
|
|
292
|
+
This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
|
|
293
|
+
|
|
294
|
+
## Authors
|
|
295
|
+
|
|
296
|
+
- Original MBPC by [MintLF](https://github.com/MintLF)
|
|
297
|
+
- Enhanced version by [Pac-Dessert1436](https://github.com/Pac-Dessert1436)
|
|
298
|
+
|
|
299
|
+
## Support
|
|
300
|
+
|
|
301
|
+
If you encounter any issues or have questions, please [open an issue](https://github.com/Pac-Dessert1436/mbpc-improved/issues) on GitHub.
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
# `mbpc-improved`: Enhanced "Much Better Python Classes"
|
|
2
|
+
|
|
3
|
+
## Description
|
|
4
|
+
|
|
5
|
+
`mbpc-improved` is an enhanced version of [MBPC](https://github.com/MintLF/MBPC/) ("Much Better Python Classes"), a powerful library that introduces advanced object-oriented programming capabilities to Python. It provides utilities for defining interfaces, classes, and structs in a more structured, type-safe manner, bringing some of the best features of statically-typed languages to Python's dynamic environment.
|
|
6
|
+
|
|
7
|
+
### Key Improvements Over Original MBPC
|
|
8
|
+
- **Snake_case Consistency**: All identifiers converted from camelCase to Python's standard snake_case.
|
|
9
|
+
- **Improved Readability**: Lambda expressions replaced with explicit `def-return` statements.
|
|
10
|
+
- **Struct Support**: Added `structdef` for creating data-focused structures with interface support.
|
|
11
|
+
- **Simplified Initialization**: Renamed `initialize` method to `init` for brevity and consistency.
|
|
12
|
+
- **Object Cloning**: Added `clone` method for deep copying objects.
|
|
13
|
+
- **Enhanced Iterability**: Eliminated need for manual list conversion when iterating over interfaces.
|
|
14
|
+
|
|
15
|
+
_Note: For built-in iterability, simply use Python's `reversed(...)` function._
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
### Prerequisites
|
|
20
|
+
- Python 3.7 or higher
|
|
21
|
+
|
|
22
|
+
### Via `pip`
|
|
23
|
+
Install the package directly from PyPI:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
pip install mbpc-improved
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### From Source
|
|
30
|
+
1. Clone the repository:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
git clone https://github.com/Pac-Dessert1436/mbpc-improved.git
|
|
34
|
+
cd mbpc-improved
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
2. Install in development mode:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pip install -e .
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
> **Note**: Avoid running scripts directly within the `mbpc` directory, as this may cause import errors. Always run from the project root or install the package first.
|
|
44
|
+
|
|
45
|
+
## Core Components
|
|
46
|
+
|
|
47
|
+
`mbpc-improved` provides three primary decorators for defining structured components:
|
|
48
|
+
|
|
49
|
+
| Component | Description |
|
|
50
|
+
|-----------|-------------|
|
|
51
|
+
| `interfacedef` | Define interfaces with required methods that must be implemented by classes or structs. |
|
|
52
|
+
| `classdef` | Create classes with inheritance and interface implementation capabilities. |
|
|
53
|
+
| `structdef` | Define data-focused structures (similar to C structs) with interface support. |
|
|
54
|
+
|
|
55
|
+
## Usage Examples
|
|
56
|
+
|
|
57
|
+
### 1. Defining Interfaces
|
|
58
|
+
|
|
59
|
+
Interfaces define contracts that classes or structs must implement. Use `interfacedef` to create interfaces with required methods:
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
from mbpc.interfacedef import interfacedef
|
|
63
|
+
|
|
64
|
+
@interfacedef()
|
|
65
|
+
def Hashable(self):
|
|
66
|
+
"""Interface for objects that can be hashed."""
|
|
67
|
+
@self.method
|
|
68
|
+
def hashcode() -> int: ... # Must return an integer hash value
|
|
69
|
+
|
|
70
|
+
@interfacedef()
|
|
71
|
+
def Equatable(self):
|
|
72
|
+
"""Interface for objects that can be compared for equality."""
|
|
73
|
+
@self.method
|
|
74
|
+
def equals(other) -> bool: ... # Must return a boolean
|
|
75
|
+
|
|
76
|
+
# NOTE: Common interfaces like Hashable and Equatable are already available in `mbpc.interfaces`
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### 2. Creating Structs
|
|
80
|
+
|
|
81
|
+
Structs are lightweight, data-focused structures that can implement interfaces. They're ideal for simple data containers:
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
from mbpc.structdef import structdef
|
|
85
|
+
from mbpc.interfaces import Hashable, Equatable
|
|
86
|
+
|
|
87
|
+
@structdef(Hashable, Equatable)
|
|
88
|
+
def Point(self, x: int, y: int):
|
|
89
|
+
"""A 2D point struct with x and y coordinates."""
|
|
90
|
+
# Initialize instance variables
|
|
91
|
+
self.x = x
|
|
92
|
+
self.y = y
|
|
93
|
+
|
|
94
|
+
# Implement Hashable interface
|
|
95
|
+
@self.method
|
|
96
|
+
def hashcode(self) -> int:
|
|
97
|
+
"""Generate a hash value for the point."""
|
|
98
|
+
return hash((self.x, self.y))
|
|
99
|
+
|
|
100
|
+
# Implement Equatable interface
|
|
101
|
+
@self.method
|
|
102
|
+
def equals(self, other) -> bool:
|
|
103
|
+
"""Compare two points for equality."""
|
|
104
|
+
if not hasattr(other, 'x') or not hasattr(other, 'y'):
|
|
105
|
+
return False
|
|
106
|
+
return self.x == other.x and self.y == other.y
|
|
107
|
+
|
|
108
|
+
# Example Usage:
|
|
109
|
+
p1 = Point(2, 3)
|
|
110
|
+
p2 = Point(2, 3)
|
|
111
|
+
p3 = Point(5, 7)
|
|
112
|
+
|
|
113
|
+
print(p1.x, p1.y) # Output: 2 3
|
|
114
|
+
print(p1.hashcode()) # Output: (hash value of (2, 3))
|
|
115
|
+
print(p1.equals(p2)) # Output: True
|
|
116
|
+
print(p1.equals(p3)) # Output: False
|
|
117
|
+
print(p1.to_string()) # Output: {'x': 2, 'y': 3} (built-in method)
|
|
118
|
+
print(p1.clone()) # Output: Point(x=2, y=3) (deep copy)
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### 3. Defining Classes
|
|
122
|
+
|
|
123
|
+
Classes support full object-oriented features including inheritance and interface implementation, but the parent constructor are always called first:
|
|
124
|
+
|
|
125
|
+
```python
|
|
126
|
+
from mbpc.classdef import classdef
|
|
127
|
+
from mbpc.interfaces import Equatable
|
|
128
|
+
|
|
129
|
+
@classdef()
|
|
130
|
+
def Person(self, name: str, age: int):
|
|
131
|
+
"""A person class with name and age attributes."""
|
|
132
|
+
# Call parent constructor (required for all classes)
|
|
133
|
+
self.super.init()
|
|
134
|
+
|
|
135
|
+
# Initialize instance variables
|
|
136
|
+
self.name = name
|
|
137
|
+
self.age = age
|
|
138
|
+
|
|
139
|
+
# Define instance methods
|
|
140
|
+
@self.method
|
|
141
|
+
def greet(self) -> str:
|
|
142
|
+
"""Return a greeting message."""
|
|
143
|
+
return f"Hello, my name is {self.name}"
|
|
144
|
+
|
|
145
|
+
# Implement Equatable interface
|
|
146
|
+
@self.method
|
|
147
|
+
def equals(self, other) -> bool:
|
|
148
|
+
"""Compare two Person objects for equality."""
|
|
149
|
+
if not isinstance(other, Person):
|
|
150
|
+
return False
|
|
151
|
+
return self.name == other.name and self.age == other.age
|
|
152
|
+
|
|
153
|
+
# Define to_string method (built-in method override)
|
|
154
|
+
@self.method
|
|
155
|
+
def to_string(self) -> str:
|
|
156
|
+
"""Return a string representation of the person."""
|
|
157
|
+
return f"Person(name='{self.name}', age={self.age})"
|
|
158
|
+
|
|
159
|
+
# Example Usage:
|
|
160
|
+
person1 = Person("Alice", 30)
|
|
161
|
+
person2 = Person("Alice", 30)
|
|
162
|
+
person3 = Person("Bob", 25)
|
|
163
|
+
|
|
164
|
+
print(person1.greet()) # Output: Hello, my name is Alice
|
|
165
|
+
print(person1.equals(person2)) # Output: True
|
|
166
|
+
print(person1.equals(person3)) # Output: False
|
|
167
|
+
print(person1.to_string()) # Output: Person(name='Alice', age=30)
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### 4. Class Inheritance
|
|
171
|
+
|
|
172
|
+
Classes can inherit from other classes, overriding methods as needed:
|
|
173
|
+
|
|
174
|
+
```python
|
|
175
|
+
from mbpc.classdef import classdef
|
|
176
|
+
|
|
177
|
+
# Inherit from the Person class defined in the previous example
|
|
178
|
+
@classdef(Person) # Specify the parent class
|
|
179
|
+
def Student(self, name: str, age: int, major: str, student_id: str):
|
|
180
|
+
"""A Student class inheriting from Person."""
|
|
181
|
+
# Call parent constructor with required parameters
|
|
182
|
+
self.super.init(name, age)
|
|
183
|
+
|
|
184
|
+
# Add new instance variables
|
|
185
|
+
self.major = major
|
|
186
|
+
self.student_id = student_id
|
|
187
|
+
|
|
188
|
+
# Override the greet method from Person
|
|
189
|
+
@self.method
|
|
190
|
+
def greet(self) -> str:
|
|
191
|
+
"""Return a student-specific greeting."""
|
|
192
|
+
return f"Hello, I'm {self.name}, studying {self.major} (ID: {self.student_id})"
|
|
193
|
+
|
|
194
|
+
# Override to_string to include student-specific information
|
|
195
|
+
@self.method
|
|
196
|
+
def to_string(self) -> str:
|
|
197
|
+
"""Return a string representation of the student."""
|
|
198
|
+
return f"Student(name='{self.name}', age={self.age}, major='{self.major}', id='{self.student_id}')"
|
|
199
|
+
|
|
200
|
+
# Example Usage:
|
|
201
|
+
student = Student("Bob", 20, "Computer Science", "CS12345")
|
|
202
|
+
print(student.greet()) # Output: Hello, I'm Bob, studying Computer Science (ID: CS12345)
|
|
203
|
+
print(student.to_string()) # Output: Student(name='Bob', age=20, major='Computer Science', id='CS12345')
|
|
204
|
+
|
|
205
|
+
# Access inherited attributes
|
|
206
|
+
print(student.name) # Output: Bob
|
|
207
|
+
print(student.age) # Output: 20
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
## Interface Enforcement
|
|
211
|
+
|
|
212
|
+
`mbpc-improved` enforces strict interface implementation at runtime, ensuring that classes and structs adhere to the contracts defined by interfaces:
|
|
213
|
+
|
|
214
|
+
### Validation Checks
|
|
215
|
+
- **Missing Methods**: Raises `InterfaceError` if any required interface method is not implemented.
|
|
216
|
+
- **Incorrect Signatures**: Validates method parameters and return type hints.
|
|
217
|
+
- **Method Types**: Supports both instance methods and static methods.
|
|
218
|
+
|
|
219
|
+
### Example of Enforcement
|
|
220
|
+
|
|
221
|
+
```python
|
|
222
|
+
from mbpc.interfacedef import interfacedef
|
|
223
|
+
from mbpc.classdef import classdef
|
|
224
|
+
from mbpc.interfaces import InterfaceError
|
|
225
|
+
|
|
226
|
+
@interfacedef()
|
|
227
|
+
def Countable(self):
|
|
228
|
+
@self.method
|
|
229
|
+
def count() -> int: ... # Must return an integer
|
|
230
|
+
|
|
231
|
+
# This will raise an error because count() is not implemented
|
|
232
|
+
@classdef(Countable)
|
|
233
|
+
def BrokenCounter(self):
|
|
234
|
+
self.value = 0
|
|
235
|
+
|
|
236
|
+
# Missing count() method implementation
|
|
237
|
+
|
|
238
|
+
# This will also raise an error because count() returns wrong type
|
|
239
|
+
@classdef(Countable)
|
|
240
|
+
def WrongReturnType(self):
|
|
241
|
+
self.value = 0
|
|
242
|
+
|
|
243
|
+
@self.method
|
|
244
|
+
def count(self) -> str: # Should return int, not str
|
|
245
|
+
return "5"
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
## Contributing
|
|
249
|
+
|
|
250
|
+
Contributions are welcome! Please feel free to submit issues, feature requests, or pull requests on the [GitHub repository](https://github.com/Pac-Dessert1436/mbpc-improved).
|
|
251
|
+
|
|
252
|
+
## License
|
|
253
|
+
|
|
254
|
+
This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
|
|
255
|
+
|
|
256
|
+
## Authors
|
|
257
|
+
|
|
258
|
+
- Original MBPC by [MintLF](https://github.com/MintLF)
|
|
259
|
+
- Enhanced version by [Pac-Dessert1436](https://github.com/Pac-Dessert1436)
|
|
260
|
+
|
|
261
|
+
## Support
|
|
262
|
+
|
|
263
|
+
If you encounter any issues or have questions, please [open an issue](https://github.com/Pac-Dessert1436/mbpc-improved/issues) on GitHub.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
from .utilities import InterfaceError, MbpcSelf
|
|
2
|
+
from inspect import signature
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def _ClassBase(self):
|
|
6
|
+
@self.method
|
|
7
|
+
def to_string(debug: bool = False):
|
|
8
|
+
return self.__dict__ if debug else f"{self.__classname__} object"
|
|
9
|
+
|
|
10
|
+
return self
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
_ClassBase.__mbpctype__ = "class"
|
|
14
|
+
_ClassBase.__interfaces__ = []
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def classdef(super_cls=_ClassBase, *interfaces):
|
|
18
|
+
interfaces = list(interfaces)
|
|
19
|
+
if super_cls.__mbpctype__ == "interface":
|
|
20
|
+
interfaces.insert(0, super_cls)
|
|
21
|
+
super_cls = _ClassBase
|
|
22
|
+
elif super_cls.__mbpctype__ == "struct":
|
|
23
|
+
raise InterfaceError(
|
|
24
|
+
f"Cannot inherit from a struct (super_cls: {super_cls.__name__}). Structs do not support inheritance."
|
|
25
|
+
)
|
|
26
|
+
interfaces.extend(super_cls.__interfaces__)
|
|
27
|
+
|
|
28
|
+
def myclass(deco_class):
|
|
29
|
+
def mybase(*args, **kwargs):
|
|
30
|
+
self = MbpcSelf()
|
|
31
|
+
args = list(args)
|
|
32
|
+
if args and type(args[0]) == type(self):
|
|
33
|
+
self = args[0]
|
|
34
|
+
args.pop(0)
|
|
35
|
+
|
|
36
|
+
def initialize(*args, **kwargs):
|
|
37
|
+
self.__dict__ |= super_cls(self, *args, **kwargs).__dict__
|
|
38
|
+
|
|
39
|
+
def super(): pass
|
|
40
|
+
for name in self.__dict__:
|
|
41
|
+
super.__dict__[name] = self.__dict__[name]
|
|
42
|
+
super.init = initialize
|
|
43
|
+
self.super = super
|
|
44
|
+
|
|
45
|
+
self.__classname__ = deco_class.__name__
|
|
46
|
+
deco_class(self, *args, **kwargs)
|
|
47
|
+
|
|
48
|
+
for interface in reversed(interfaces):
|
|
49
|
+
for k in interface.__interface__.methods.keys():
|
|
50
|
+
if not k in self.__dict__:
|
|
51
|
+
raise InterfaceError(
|
|
52
|
+
f"Class \"{self.__classname__}\" does not implement the interface \"{interface.__interface__.__interfacename__}\" (missing the method \"{k}\")."
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
if not signature(self.__dict__[k]) == interface.__interface__.methods[k]:
|
|
56
|
+
raise InterfaceError(
|
|
57
|
+
f"Class \"{self.__classname__}\" does not implement the interface \"{interface.__interface__.__interfacename__}\" (incorrectly defining the method \"{k}\")."
|
|
58
|
+
)
|
|
59
|
+
return self
|
|
60
|
+
|
|
61
|
+
def method(f):
|
|
62
|
+
mybase.__dict__[f.__name__] = f
|
|
63
|
+
|
|
64
|
+
mybase.__dict__ = super_cls.__dict__ | mybase.__dict__
|
|
65
|
+
mybase.method = method
|
|
66
|
+
mybase.__mbpctype__ = "class" if super_cls.__mbpctype__ == _ClassBase else "struct"
|
|
67
|
+
mybase.__interfaces__ = interfaces
|
|
68
|
+
|
|
69
|
+
def initialize():
|
|
70
|
+
for interface in reversed(interfaces):
|
|
71
|
+
for k in interface.__methods__.keys():
|
|
72
|
+
if not k in mybase.__dict__:
|
|
73
|
+
raise InterfaceError(
|
|
74
|
+
f"Class \"{deco_class.__name__}\" does not implement the interface \"{interface.__interface__.__interfacename__}\" (missing the static method \"{k}\")."
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
if not signature(mybase.__dict__[k]) == interface.__methods__[k]:
|
|
78
|
+
raise InterfaceError(
|
|
79
|
+
f"Class \"{deco_class.__name__}\" does not implement the interface \"{interface.__interface__.__interfacename__}\" (incorrectly defining the static method \"{k}\")."
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
def clone():
|
|
83
|
+
from copy import deepcopy
|
|
84
|
+
return deepcopy(mybase.__dict__)
|
|
85
|
+
|
|
86
|
+
mybase.init = initialize
|
|
87
|
+
mybase.clone = clone
|
|
88
|
+
return mybase
|
|
89
|
+
return myclass
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
from .utilities import InterfaceError
|
|
2
|
+
from inspect import signature
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def _Interface():
|
|
6
|
+
def interface(): return ...
|
|
7
|
+
interface.methods = {}
|
|
8
|
+
|
|
9
|
+
def method(func):
|
|
10
|
+
interface.methods[func.__name__] = signature(func)
|
|
11
|
+
|
|
12
|
+
interface.method = method
|
|
13
|
+
return interface
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def interfacedef(*super_interfaces):
|
|
17
|
+
interface = _Interface()
|
|
18
|
+
|
|
19
|
+
for super_interface in reversed(super_interfaces):
|
|
20
|
+
interface.__dict__ |= super_interface.__interface__.__dict__
|
|
21
|
+
|
|
22
|
+
def wrapper(decorated_interface):
|
|
23
|
+
decorated_interface(interface)
|
|
24
|
+
interface.__interfacename__ = decorated_interface.__name__
|
|
25
|
+
|
|
26
|
+
def mybase(*args, **kwargs):
|
|
27
|
+
raise InterfaceError("Cannot initialize an interface object.")
|
|
28
|
+
|
|
29
|
+
mybase.__interface__ = interface
|
|
30
|
+
mybase.__mbpctype__ = "interface"
|
|
31
|
+
|
|
32
|
+
mybase.__methods__ = {}
|
|
33
|
+
|
|
34
|
+
def method(func):
|
|
35
|
+
mybase.__methods__[func.__name__] = signature(func)
|
|
36
|
+
|
|
37
|
+
mybase.method = method
|
|
38
|
+
|
|
39
|
+
return mybase
|
|
40
|
+
return wrapper
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
from .utilities import InterfaceError, MbpcSelf
|
|
2
|
+
from inspect import signature
|
|
3
|
+
|
|
4
|
+
def _StructBase(self):
|
|
5
|
+
existing = self.__dict__.copy()
|
|
6
|
+
|
|
7
|
+
@self.method
|
|
8
|
+
def to_string() -> str:
|
|
9
|
+
filtered = {}
|
|
10
|
+
method_names = [name for name, func in self.__dict__.items()
|
|
11
|
+
if hasattr(func, '__name__') and func.__name__ in self.__dict__]
|
|
12
|
+
for key, value in self.__dict__.items():
|
|
13
|
+
if key not in [*existing, *method_names, "__classname__"]:
|
|
14
|
+
filtered[key] = value
|
|
15
|
+
return str(filtered)
|
|
16
|
+
|
|
17
|
+
return self
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
_StructBase.__mbpctype__ = "struct"
|
|
21
|
+
_StructBase.__interfaces__ = []
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def structdef(*interfaces):
|
|
25
|
+
interfaces = list(interfaces)
|
|
26
|
+
struct = _StructBase
|
|
27
|
+
|
|
28
|
+
def mystruct(deco_struct):
|
|
29
|
+
def mybase(*args, **kwargs):
|
|
30
|
+
self = MbpcSelf()
|
|
31
|
+
args = list(args)
|
|
32
|
+
if args and type(args[0]) == type(self):
|
|
33
|
+
self = args[0]
|
|
34
|
+
args.pop(0)
|
|
35
|
+
self.__dict__ |= struct(self).__dict__
|
|
36
|
+
self.__classname__ = deco_struct.__name__
|
|
37
|
+
deco_struct(self, *args, **kwargs)
|
|
38
|
+
|
|
39
|
+
for interface in reversed(interfaces):
|
|
40
|
+
for k in interface.__interface__.methods.keys():
|
|
41
|
+
if not k in self.__dict__:
|
|
42
|
+
raise InterfaceError(
|
|
43
|
+
f"Struct \"{self.__classname__}\" does not implement the interface \"{interface.__interface__.__interfacename__}\" (missing the method \"{k}\")."
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
if not signature(self.__dict__[k]) == interface.__interface__.methods[k]:
|
|
47
|
+
raise InterfaceError(
|
|
48
|
+
f"Struct \"{self.__classname__}\" does not implement the interface \"{interface.__interface__.__interfacename__}\" (incorrectly defining the method \"{k}\")."
|
|
49
|
+
)
|
|
50
|
+
return self
|
|
51
|
+
|
|
52
|
+
def method(f):
|
|
53
|
+
mybase.__dict__[f.__name__] = f
|
|
54
|
+
|
|
55
|
+
mybase.method = method
|
|
56
|
+
mybase.__mbpctype__ = "struct"
|
|
57
|
+
mybase.__interfaces__ = interfaces
|
|
58
|
+
|
|
59
|
+
def initialize():
|
|
60
|
+
for interface in reversed(interfaces):
|
|
61
|
+
for k in interface.__methods__.keys():
|
|
62
|
+
if not k in mybase.__dict__:
|
|
63
|
+
raise InterfaceError(
|
|
64
|
+
f"Struct \"{deco_struct.__name__}\" does not implement the interface \"{interface.__interface__.__interfacename__}\" (missing the static method \"{k}\")."
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
if not signature(mybase.__dict__[k]) == interface.__methods__[k]:
|
|
68
|
+
raise InterfaceError(
|
|
69
|
+
f"Struct \"{deco_struct.__name__}\" does not implement the interface \"{interface.__interface__.__interfacename__}\" (incorrectly defining the static method \"{k}\")."
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
def clone():
|
|
73
|
+
from copy import deepcopy
|
|
74
|
+
return deepcopy(mybase.__dict__)
|
|
75
|
+
|
|
76
|
+
mybase.init = initialize
|
|
77
|
+
mybase.clone = clone
|
|
78
|
+
return mybase
|
|
79
|
+
return mystruct
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mbpc-improved
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Enhanced version of MBPC (Much Better Python Classes) for advanced OOP in Python
|
|
5
|
+
Author-email: Pac-Dessert1436 <pac-dessert1436@example.com>
|
|
6
|
+
Maintainer-email: Pac-Dessert1436 <pac-dessert1436@example.com>
|
|
7
|
+
License: MIT
|
|
8
|
+
Project-URL: Homepage, https://github.com/Pac-Dessert1436/mbpc-improved
|
|
9
|
+
Project-URL: Bug Reports, https://github.com/Pac-Dessert1436/mbpc-improved/issues
|
|
10
|
+
Project-URL: Source, https://github.com/Pac-Dessert1436/mbpc-improved
|
|
11
|
+
Project-URL: Documentation, https://github.com/Pac-Dessert1436/mbpc-improved#readme
|
|
12
|
+
Project-URL: Changelog, https://github.com/Pac-Dessert1436/mbpc-improved/blob/main/CHANGELOG.md
|
|
13
|
+
Project-URL: Repository, https://github.com/Pac-Dessert1436/mbpc-improved.git
|
|
14
|
+
Keywords: oop,object-oriented,classes,interfaces,structs,type-safe,decorators,inheritance,metaprogramming,code-generation
|
|
15
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
16
|
+
Classifier: Intended Audience :: Developers
|
|
17
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
18
|
+
Classifier: Operating System :: OS Independent
|
|
19
|
+
Classifier: Programming Language :: Python :: 3
|
|
20
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
21
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
22
|
+
Classifier: Topic :: Software Development :: Code Generators
|
|
23
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
24
|
+
Classifier: Topic :: Utilities
|
|
25
|
+
Requires-Python: >=3.7
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
License-File: LICENSE
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
30
|
+
Requires-Dist: pytest-cov>=4.0; extra == "dev"
|
|
31
|
+
Requires-Dist: flake8>=5.0; extra == "dev"
|
|
32
|
+
Requires-Dist: black>=22.0; extra == "dev"
|
|
33
|
+
Requires-Dist: isort>=5.0; extra == "dev"
|
|
34
|
+
Requires-Dist: twine>=4.0; extra == "dev"
|
|
35
|
+
Requires-Dist: build>=0.7; extra == "dev"
|
|
36
|
+
Requires-Dist: mypy>=1.0; extra == "dev"
|
|
37
|
+
Dynamic: license-file
|
|
38
|
+
|
|
39
|
+
# `mbpc-improved`: Enhanced "Much Better Python Classes"
|
|
40
|
+
|
|
41
|
+
## Description
|
|
42
|
+
|
|
43
|
+
`mbpc-improved` is an enhanced version of [MBPC](https://github.com/MintLF/MBPC/) ("Much Better Python Classes"), a powerful library that introduces advanced object-oriented programming capabilities to Python. It provides utilities for defining interfaces, classes, and structs in a more structured, type-safe manner, bringing some of the best features of statically-typed languages to Python's dynamic environment.
|
|
44
|
+
|
|
45
|
+
### Key Improvements Over Original MBPC
|
|
46
|
+
- **Snake_case Consistency**: All identifiers converted from camelCase to Python's standard snake_case.
|
|
47
|
+
- **Improved Readability**: Lambda expressions replaced with explicit `def-return` statements.
|
|
48
|
+
- **Struct Support**: Added `structdef` for creating data-focused structures with interface support.
|
|
49
|
+
- **Simplified Initialization**: Renamed `initialize` method to `init` for brevity and consistency.
|
|
50
|
+
- **Object Cloning**: Added `clone` method for deep copying objects.
|
|
51
|
+
- **Enhanced Iterability**: Eliminated need for manual list conversion when iterating over interfaces.
|
|
52
|
+
|
|
53
|
+
_Note: For built-in iterability, simply use Python's `reversed(...)` function._
|
|
54
|
+
|
|
55
|
+
## Installation
|
|
56
|
+
|
|
57
|
+
### Prerequisites
|
|
58
|
+
- Python 3.7 or higher
|
|
59
|
+
|
|
60
|
+
### Via `pip`
|
|
61
|
+
Install the package directly from PyPI:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
pip install mbpc-improved
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### From Source
|
|
68
|
+
1. Clone the repository:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
git clone https://github.com/Pac-Dessert1436/mbpc-improved.git
|
|
72
|
+
cd mbpc-improved
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
2. Install in development mode:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
pip install -e .
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
> **Note**: Avoid running scripts directly within the `mbpc` directory, as this may cause import errors. Always run from the project root or install the package first.
|
|
82
|
+
|
|
83
|
+
## Core Components
|
|
84
|
+
|
|
85
|
+
`mbpc-improved` provides three primary decorators for defining structured components:
|
|
86
|
+
|
|
87
|
+
| Component | Description |
|
|
88
|
+
|-----------|-------------|
|
|
89
|
+
| `interfacedef` | Define interfaces with required methods that must be implemented by classes or structs. |
|
|
90
|
+
| `classdef` | Create classes with inheritance and interface implementation capabilities. |
|
|
91
|
+
| `structdef` | Define data-focused structures (similar to C structs) with interface support. |
|
|
92
|
+
|
|
93
|
+
## Usage Examples
|
|
94
|
+
|
|
95
|
+
### 1. Defining Interfaces
|
|
96
|
+
|
|
97
|
+
Interfaces define contracts that classes or structs must implement. Use `interfacedef` to create interfaces with required methods:
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
from mbpc.interfacedef import interfacedef
|
|
101
|
+
|
|
102
|
+
@interfacedef()
|
|
103
|
+
def Hashable(self):
|
|
104
|
+
"""Interface for objects that can be hashed."""
|
|
105
|
+
@self.method
|
|
106
|
+
def hashcode() -> int: ... # Must return an integer hash value
|
|
107
|
+
|
|
108
|
+
@interfacedef()
|
|
109
|
+
def Equatable(self):
|
|
110
|
+
"""Interface for objects that can be compared for equality."""
|
|
111
|
+
@self.method
|
|
112
|
+
def equals(other) -> bool: ... # Must return a boolean
|
|
113
|
+
|
|
114
|
+
# NOTE: Common interfaces like Hashable and Equatable are already available in `mbpc.interfaces`
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### 2. Creating Structs
|
|
118
|
+
|
|
119
|
+
Structs are lightweight, data-focused structures that can implement interfaces. They're ideal for simple data containers:
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
from mbpc.structdef import structdef
|
|
123
|
+
from mbpc.interfaces import Hashable, Equatable
|
|
124
|
+
|
|
125
|
+
@structdef(Hashable, Equatable)
|
|
126
|
+
def Point(self, x: int, y: int):
|
|
127
|
+
"""A 2D point struct with x and y coordinates."""
|
|
128
|
+
# Initialize instance variables
|
|
129
|
+
self.x = x
|
|
130
|
+
self.y = y
|
|
131
|
+
|
|
132
|
+
# Implement Hashable interface
|
|
133
|
+
@self.method
|
|
134
|
+
def hashcode(self) -> int:
|
|
135
|
+
"""Generate a hash value for the point."""
|
|
136
|
+
return hash((self.x, self.y))
|
|
137
|
+
|
|
138
|
+
# Implement Equatable interface
|
|
139
|
+
@self.method
|
|
140
|
+
def equals(self, other) -> bool:
|
|
141
|
+
"""Compare two points for equality."""
|
|
142
|
+
if not hasattr(other, 'x') or not hasattr(other, 'y'):
|
|
143
|
+
return False
|
|
144
|
+
return self.x == other.x and self.y == other.y
|
|
145
|
+
|
|
146
|
+
# Example Usage:
|
|
147
|
+
p1 = Point(2, 3)
|
|
148
|
+
p2 = Point(2, 3)
|
|
149
|
+
p3 = Point(5, 7)
|
|
150
|
+
|
|
151
|
+
print(p1.x, p1.y) # Output: 2 3
|
|
152
|
+
print(p1.hashcode()) # Output: (hash value of (2, 3))
|
|
153
|
+
print(p1.equals(p2)) # Output: True
|
|
154
|
+
print(p1.equals(p3)) # Output: False
|
|
155
|
+
print(p1.to_string()) # Output: {'x': 2, 'y': 3} (built-in method)
|
|
156
|
+
print(p1.clone()) # Output: Point(x=2, y=3) (deep copy)
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### 3. Defining Classes
|
|
160
|
+
|
|
161
|
+
Classes support full object-oriented features including inheritance and interface implementation, but the parent constructor are always called first:
|
|
162
|
+
|
|
163
|
+
```python
|
|
164
|
+
from mbpc.classdef import classdef
|
|
165
|
+
from mbpc.interfaces import Equatable
|
|
166
|
+
|
|
167
|
+
@classdef()
|
|
168
|
+
def Person(self, name: str, age: int):
|
|
169
|
+
"""A person class with name and age attributes."""
|
|
170
|
+
# Call parent constructor (required for all classes)
|
|
171
|
+
self.super.init()
|
|
172
|
+
|
|
173
|
+
# Initialize instance variables
|
|
174
|
+
self.name = name
|
|
175
|
+
self.age = age
|
|
176
|
+
|
|
177
|
+
# Define instance methods
|
|
178
|
+
@self.method
|
|
179
|
+
def greet(self) -> str:
|
|
180
|
+
"""Return a greeting message."""
|
|
181
|
+
return f"Hello, my name is {self.name}"
|
|
182
|
+
|
|
183
|
+
# Implement Equatable interface
|
|
184
|
+
@self.method
|
|
185
|
+
def equals(self, other) -> bool:
|
|
186
|
+
"""Compare two Person objects for equality."""
|
|
187
|
+
if not isinstance(other, Person):
|
|
188
|
+
return False
|
|
189
|
+
return self.name == other.name and self.age == other.age
|
|
190
|
+
|
|
191
|
+
# Define to_string method (built-in method override)
|
|
192
|
+
@self.method
|
|
193
|
+
def to_string(self) -> str:
|
|
194
|
+
"""Return a string representation of the person."""
|
|
195
|
+
return f"Person(name='{self.name}', age={self.age})"
|
|
196
|
+
|
|
197
|
+
# Example Usage:
|
|
198
|
+
person1 = Person("Alice", 30)
|
|
199
|
+
person2 = Person("Alice", 30)
|
|
200
|
+
person3 = Person("Bob", 25)
|
|
201
|
+
|
|
202
|
+
print(person1.greet()) # Output: Hello, my name is Alice
|
|
203
|
+
print(person1.equals(person2)) # Output: True
|
|
204
|
+
print(person1.equals(person3)) # Output: False
|
|
205
|
+
print(person1.to_string()) # Output: Person(name='Alice', age=30)
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### 4. Class Inheritance
|
|
209
|
+
|
|
210
|
+
Classes can inherit from other classes, overriding methods as needed:
|
|
211
|
+
|
|
212
|
+
```python
|
|
213
|
+
from mbpc.classdef import classdef
|
|
214
|
+
|
|
215
|
+
# Inherit from the Person class defined in the previous example
|
|
216
|
+
@classdef(Person) # Specify the parent class
|
|
217
|
+
def Student(self, name: str, age: int, major: str, student_id: str):
|
|
218
|
+
"""A Student class inheriting from Person."""
|
|
219
|
+
# Call parent constructor with required parameters
|
|
220
|
+
self.super.init(name, age)
|
|
221
|
+
|
|
222
|
+
# Add new instance variables
|
|
223
|
+
self.major = major
|
|
224
|
+
self.student_id = student_id
|
|
225
|
+
|
|
226
|
+
# Override the greet method from Person
|
|
227
|
+
@self.method
|
|
228
|
+
def greet(self) -> str:
|
|
229
|
+
"""Return a student-specific greeting."""
|
|
230
|
+
return f"Hello, I'm {self.name}, studying {self.major} (ID: {self.student_id})"
|
|
231
|
+
|
|
232
|
+
# Override to_string to include student-specific information
|
|
233
|
+
@self.method
|
|
234
|
+
def to_string(self) -> str:
|
|
235
|
+
"""Return a string representation of the student."""
|
|
236
|
+
return f"Student(name='{self.name}', age={self.age}, major='{self.major}', id='{self.student_id}')"
|
|
237
|
+
|
|
238
|
+
# Example Usage:
|
|
239
|
+
student = Student("Bob", 20, "Computer Science", "CS12345")
|
|
240
|
+
print(student.greet()) # Output: Hello, I'm Bob, studying Computer Science (ID: CS12345)
|
|
241
|
+
print(student.to_string()) # Output: Student(name='Bob', age=20, major='Computer Science', id='CS12345')
|
|
242
|
+
|
|
243
|
+
# Access inherited attributes
|
|
244
|
+
print(student.name) # Output: Bob
|
|
245
|
+
print(student.age) # Output: 20
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
## Interface Enforcement
|
|
249
|
+
|
|
250
|
+
`mbpc-improved` enforces strict interface implementation at runtime, ensuring that classes and structs adhere to the contracts defined by interfaces:
|
|
251
|
+
|
|
252
|
+
### Validation Checks
|
|
253
|
+
- **Missing Methods**: Raises `InterfaceError` if any required interface method is not implemented.
|
|
254
|
+
- **Incorrect Signatures**: Validates method parameters and return type hints.
|
|
255
|
+
- **Method Types**: Supports both instance methods and static methods.
|
|
256
|
+
|
|
257
|
+
### Example of Enforcement
|
|
258
|
+
|
|
259
|
+
```python
|
|
260
|
+
from mbpc.interfacedef import interfacedef
|
|
261
|
+
from mbpc.classdef import classdef
|
|
262
|
+
from mbpc.interfaces import InterfaceError
|
|
263
|
+
|
|
264
|
+
@interfacedef()
|
|
265
|
+
def Countable(self):
|
|
266
|
+
@self.method
|
|
267
|
+
def count() -> int: ... # Must return an integer
|
|
268
|
+
|
|
269
|
+
# This will raise an error because count() is not implemented
|
|
270
|
+
@classdef(Countable)
|
|
271
|
+
def BrokenCounter(self):
|
|
272
|
+
self.value = 0
|
|
273
|
+
|
|
274
|
+
# Missing count() method implementation
|
|
275
|
+
|
|
276
|
+
# This will also raise an error because count() returns wrong type
|
|
277
|
+
@classdef(Countable)
|
|
278
|
+
def WrongReturnType(self):
|
|
279
|
+
self.value = 0
|
|
280
|
+
|
|
281
|
+
@self.method
|
|
282
|
+
def count(self) -> str: # Should return int, not str
|
|
283
|
+
return "5"
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
## Contributing
|
|
287
|
+
|
|
288
|
+
Contributions are welcome! Please feel free to submit issues, feature requests, or pull requests on the [GitHub repository](https://github.com/Pac-Dessert1436/mbpc-improved).
|
|
289
|
+
|
|
290
|
+
## License
|
|
291
|
+
|
|
292
|
+
This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
|
|
293
|
+
|
|
294
|
+
## Authors
|
|
295
|
+
|
|
296
|
+
- Original MBPC by [MintLF](https://github.com/MintLF)
|
|
297
|
+
- Enhanced version by [Pac-Dessert1436](https://github.com/Pac-Dessert1436)
|
|
298
|
+
|
|
299
|
+
## Support
|
|
300
|
+
|
|
301
|
+
If you encounter any issues or have questions, please [open an issue](https://github.com/Pac-Dessert1436/mbpc-improved/issues) on GitHub.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
MANIFEST.in
|
|
3
|
+
README.md
|
|
4
|
+
pyproject.toml
|
|
5
|
+
setup.py
|
|
6
|
+
mbpc/__init__.py
|
|
7
|
+
mbpc/classdef.py
|
|
8
|
+
mbpc/interfacedef.py
|
|
9
|
+
mbpc/interfaces.py
|
|
10
|
+
mbpc/structdef.py
|
|
11
|
+
mbpc/utilities.py
|
|
12
|
+
mbpc_improved.egg-info/PKG-INFO
|
|
13
|
+
mbpc_improved.egg-info/SOURCES.txt
|
|
14
|
+
mbpc_improved.egg-info/dependency_links.txt
|
|
15
|
+
mbpc_improved.egg-info/requires.txt
|
|
16
|
+
mbpc_improved.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
mbpc
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "mbpc-improved"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
description = "Enhanced version of MBPC (Much Better Python Classes) for advanced OOP in Python"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.7"
|
|
11
|
+
license = {text = "MIT"}
|
|
12
|
+
authors = [
|
|
13
|
+
{name = "Pac-Dessert1436", email = "pac-dessert1436@example.com"}
|
|
14
|
+
]
|
|
15
|
+
maintainers = [
|
|
16
|
+
{name = "Pac-Dessert1436", email = "pac-dessert1436@example.com"}
|
|
17
|
+
]
|
|
18
|
+
keywords = [
|
|
19
|
+
"oop",
|
|
20
|
+
"object-oriented",
|
|
21
|
+
"classes",
|
|
22
|
+
"interfaces",
|
|
23
|
+
"structs",
|
|
24
|
+
"type-safe",
|
|
25
|
+
"decorators",
|
|
26
|
+
"inheritance",
|
|
27
|
+
"metaprogramming",
|
|
28
|
+
"code-generation"
|
|
29
|
+
]
|
|
30
|
+
classifiers = [
|
|
31
|
+
"Development Status :: 5 - Production/Stable",
|
|
32
|
+
"Intended Audience :: Developers",
|
|
33
|
+
"License :: OSI Approved :: MIT License",
|
|
34
|
+
"Operating System :: OS Independent",
|
|
35
|
+
"Programming Language :: Python :: 3",
|
|
36
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
37
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
38
|
+
"Topic :: Software Development :: Code Generators",
|
|
39
|
+
"Topic :: Software Development :: Libraries",
|
|
40
|
+
"Topic :: Utilities"
|
|
41
|
+
]
|
|
42
|
+
dependencies = []
|
|
43
|
+
|
|
44
|
+
[project.optional-dependencies]
|
|
45
|
+
dev = [
|
|
46
|
+
"pytest>=7.0",
|
|
47
|
+
"pytest-cov>=4.0",
|
|
48
|
+
"flake8>=5.0",
|
|
49
|
+
"black>=22.0",
|
|
50
|
+
"isort>=5.0",
|
|
51
|
+
"twine>=4.0",
|
|
52
|
+
"build>=0.7",
|
|
53
|
+
"mypy>=1.0"
|
|
54
|
+
]
|
|
55
|
+
|
|
56
|
+
[project.urls]
|
|
57
|
+
"Homepage" = "https://github.com/Pac-Dessert1436/mbpc-improved"
|
|
58
|
+
"Bug Reports" = "https://github.com/Pac-Dessert1436/mbpc-improved/issues"
|
|
59
|
+
"Source" = "https://github.com/Pac-Dessert1436/mbpc-improved"
|
|
60
|
+
"Documentation" = "https://github.com/Pac-Dessert1436/mbpc-improved#readme"
|
|
61
|
+
"Changelog" = "https://github.com/Pac-Dessert1436/mbpc-improved/blob/main/CHANGELOG.md"
|
|
62
|
+
"Repository" = "https://github.com/Pac-Dessert1436/mbpc-improved.git"
|
|
63
|
+
|
|
64
|
+
[tool.setuptools]
|
|
65
|
+
packages = ["mbpc"]
|
|
66
|
+
|
|
67
|
+
[tool.setuptools.package-data]
|
|
68
|
+
mbpc = ["*.py"]
|
|
69
|
+
|
|
70
|
+
[tool.black]
|
|
71
|
+
line-length = 100
|
|
72
|
+
target-version = ['py37', 'py38', 'py39', 'py310', 'py311']
|
|
73
|
+
|
|
74
|
+
[tool.isort]
|
|
75
|
+
profile = "black"
|
|
76
|
+
line_length = 100
|
|
77
|
+
|
|
78
|
+
[tool.pytest.ini_options]
|
|
79
|
+
testpaths = ["tests"]
|
|
80
|
+
python_files = ["test_*.py"]
|
|
81
|
+
python_classes = ["Test*"]
|
|
82
|
+
python_functions = ["test_*"]
|
|
83
|
+
|
|
84
|
+
[tool.mypy]
|
|
85
|
+
python_version = "3.7"
|
|
86
|
+
warn_return_any = true
|
|
87
|
+
warn_unused_configs = true
|
|
88
|
+
disallow_untyped_defs = false
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Minimal setup.py for backward compatibility with older pip versions.
|
|
3
|
+
Main configuration is in pyproject.toml (PEP 621 compliant).
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from setuptools import setup
|
|
7
|
+
|
|
8
|
+
# All configuration is in pyproject.toml
|
|
9
|
+
# This file exists only for compatibility with very old pip versions
|
|
10
|
+
setup()
|