This is a Python library based on calling of frame's stack at runtime and mainly implements some C# features.
Project description
pymagic9
This is a Python library based on calling the stack of frames at runtime and analyzing the code object of frames. Basically, it implements some C# features. For example, it contains the nameof
function and auto-implemented properties
. See the documentation for more information.
Installation
You can install pymagic9
using pip:
pip install pymagic9
Features
getframe: The sys._getframe function is used here if it exists in the version of python being used. Otherwise, the _getframe polyfill is used.
isemptyfunction: Checks if a function is empty or not.
isfunctionincallchain: Determines whether the given function object or code object is present in the call chain.
nameof: This function correctly determines the "name" of an object, without being tied to the object itself. It can be used to retrieve the name of variables, functions, classes, modules, and more.
PropertyMeta: This metaclass allows you to create auto-implemented properties
(like in C#, where you can declare properties without explicitly defining a getter and setter), for which you can use an ellipsis or empty functions to indicate that the Python itself would create the auto-implemented accessor.
Usage of auto-implemented properties
- Import the PropertyMeta metaclass and assign it as a metaclass for the desired class:
from pymagic9 import PropertyMeta
class Person(metaclass=PropertyMeta):
pass
- Create properties in this class with empty accessors (using empty function or ellipsis) to indicate that this property will be auto-implemented:
from pymagic9 import PropertyMeta
class Person(metaclass=PropertyMeta):
"""class Person"""
def __init__(self, name):
self.name = name
name = property(fget=...,) # readonly property
age = property(fget=..., fset=...,) # ordinary property
- Now for an
ordinary
property we can get and put values into it at any time. But for areadonly
property, you can put a value into it only once, at the time of creating an instance of the class:
from pymagic9 import PropertyMeta
class Person(metaclass=PropertyMeta):
"""class Person"""
def __init__(self, name):
self.name = name
# self.name = "Sam" # raise AttributeError: 'property' is readonly (reassigning value)
name = property(fget=...,) # readonly property
age = property(fget=..., fset=...,) # ordinary property
if __name__ == "__main__":
person = Person("Tom")
person.age = 24
print(person.name + ',', person.age) # Tom, 24
# person.name = "Sam" # raise AttributeError: 'property' is readonly
- To delete a property value, use the
del
operator:
from pymagic9 import PropertyMeta
class Person(metaclass=PropertyMeta):
"""class Person"""
def __init__(self, name):
self.name = name
name = property(fget=...,) # readonly property
age = property(fget=..., fset=...,) # ordinary property
if __name__ == "__main__":
person = Person("Tom")
person.age = 24
print(person.name + ',', person.age) # Tom, 24
del person.name
# print(person.name) # raise AttributeError: auto-implemented field does not exist or has already been erased
- If the
getter
is specified by an empty accessor (using empty function or ellipsis), and thesetter
is not an empty function, thensetter
will also be called. This can be used as a callback when assigning a value to a property:
from pymagic9 import nameof, PropertyMeta
def NotifyPropertyChanged(propertyname, value):
"""Notify property changed"""
# Do something
print(propertyname + ',', value)
class Person(metaclass=PropertyMeta):
"""class Person"""
def __init__(self, name):
self.name = name
name = property(fget=...,) # readonly property
age = property(fget=..., fset=...,) # ordinary property
@property
def height(self):
"""Person height in cm"""
return
@height.setter
def height(self, value):
NotifyPropertyChanged(nameof(self.height), value)
if __name__ == "__main__":
person = Person("Tom")
person.age = 24
print(person.name + ',', person.age) # Tom, 24
person.height = 180 # height, 180
- Similar code for
Python 2.7
looks like this:
from pymagic9 import nameof, PropertyMeta
__metaclass__ = PropertyMeta
def NotifyPropertyChanged(propertyname, value):
"""Notify property changed"""
# Do something
print(propertyname + ', ' + str(value))
class Person:
"""class Person"""
def __init__(self, name):
self.name = name
name = property(fget=Ellipsis,) # readonly property
age = property(fget=Ellipsis, fset=Ellipsis,) # ordinary property
@property
def height(self):
"""Person height in cm"""
return
@height.setter
def height(self, value):
NotifyPropertyChanged(nameof(self.height), value)
if __name__ == "__main__":
person = Person("Tom")
person.age = 24
print(person.name + ', ' + str(person.age)) # Tom, 24
person.height = 180 # height, 180
The detailed operating principle is described in the documentation.
Compatibility
pymagic9
is compatible with the following versions of Python:
- CPython 2.7
- CPython 3.6
- CPython 3.7
- CPython 3.8
- CPython 3.9
- CPython 3.10
It is supported on Windows, Ubuntu, and MacOS platforms.
Documentation
For more information and detailed usage examples, please refer to the documentation.
License
This project is licensed under the Apache License 2.0. See the LICENSE file for more details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for pymagic9-0.9.0-py2.py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 2aba7f4d686a6f114cc3e7efec5719482aefc069faf1efdd9c8084f360644d32 |
|
MD5 | 4669e5177d5aa517c51c06850d4ad49a |
|
BLAKE2b-256 | 3ce07933525d8f9054165ab250c49465017153c53cfaacf0910507f6344f07bb |