You've already forked MicroPythonOS
mirror of
https://github.com/m5stack/MicroPythonOS.git
synced 2026-05-20 11:51:27 -07:00
continue porting python-nostr
This commit is contained in:
@@ -1,43 +1,85 @@
|
||||
# dataclasses.py: Minimal MicroPython compatibility layer for Python's dataclasses
|
||||
# Implements @dataclass with __init__ and __repr__ generation
|
||||
# dataclasses.py: MicroPython compatibility layer for Python's dataclasses
|
||||
# Implements @dataclass, field, and Field with support for default_factory
|
||||
|
||||
MISSING = object() # Sentinel for missing values
|
||||
|
||||
class Field:
|
||||
"""Represents a dataclass field, supporting default_factory."""
|
||||
def __init__(self, default=MISSING, default_factory=MISSING, init=True, repr=True):
|
||||
self.name = None # Set by dataclass decorator
|
||||
self.type = None # Set by dataclass decorator
|
||||
self.default = default
|
||||
self.default_factory = default_factory
|
||||
self.init = init
|
||||
self.repr = repr
|
||||
|
||||
def field(*, default=MISSING, default_factory=MISSING, init=True, repr=True):
|
||||
"""Specify a dataclass field with optional default_factory."""
|
||||
if default is not MISSING and default_factory is not MISSING:
|
||||
raise ValueError("Cannot specify both default and default_factory")
|
||||
return Field(default=default, default_factory=default_factory, init=init, repr=repr)
|
||||
|
||||
def dataclass(cls):
|
||||
"""Decorator to emulate Python's @dataclass, generating __init__ and __repr__."""
|
||||
"""Decorator to emulate @dataclass, generating __init__ and __repr__."""
|
||||
# Get class annotations and defaults
|
||||
annotations = getattr(cls, '__annotations__', {})
|
||||
defaults = {}
|
||||
fields = {}
|
||||
|
||||
# Process class attributes for defaults and field() calls
|
||||
for name in dir(cls):
|
||||
if not name.startswith('__'):
|
||||
attr = getattr(cls, name, None)
|
||||
if not callable(attr) and name in annotations:
|
||||
defaults[name] = attr
|
||||
if not callable(attr):
|
||||
if isinstance(attr, Field):
|
||||
fields[name] = attr
|
||||
fields[name].name = name
|
||||
fields[name].type = annotations.get(name)
|
||||
if attr.default is not MISSING:
|
||||
defaults[name] = attr.default
|
||||
elif name in annotations:
|
||||
defaults[name] = attr
|
||||
|
||||
# Ensure all annotated fields have a Field object
|
||||
for name in annotations:
|
||||
if name not in fields:
|
||||
fields[name] = Field(default=defaults.get(name, MISSING), init=True, repr=True)
|
||||
fields[name].name = name
|
||||
fields[name].type = annotations.get(name)
|
||||
|
||||
# Generate __init__ method
|
||||
def __init__(self, *args, **kwargs):
|
||||
# Positional arguments
|
||||
fields = list(annotations.keys())
|
||||
init_fields = [name for name, f in fields.items() if f.init]
|
||||
for i, value in enumerate(args):
|
||||
if i >= len(fields):
|
||||
if i >= len(init_fields):
|
||||
raise TypeError(f"Too many positional arguments")
|
||||
setattr(self, fields[i], value)
|
||||
setattr(self, init_fields[i], value)
|
||||
|
||||
# Keyword arguments and defaults
|
||||
for name in fields:
|
||||
if name in kwargs:
|
||||
# Keyword arguments, defaults, and default_factory
|
||||
for name, field in fields.items():
|
||||
if field.init and name in kwargs:
|
||||
setattr(self, name, kwargs[name])
|
||||
elif not hasattr(self, name):
|
||||
if name in defaults:
|
||||
setattr(self, name, defaults[name])
|
||||
else:
|
||||
if field.default_factory is not MISSING:
|
||||
setattr(self, name, field.default_factory())
|
||||
elif field.default is not MISSING:
|
||||
setattr(self, name, field.default)
|
||||
elif field.init:
|
||||
raise TypeError(f"Missing required argument: {name}")
|
||||
|
||||
# Call __post_init__ if defined
|
||||
if hasattr(self, '__post_init__'):
|
||||
self.__post_init__()
|
||||
|
||||
# Generate __repr__ method
|
||||
def __repr__(self):
|
||||
fields = [
|
||||
fields_repr = [
|
||||
f"{name}={getattr(self, name)!r}"
|
||||
for name in annotations
|
||||
for name, field in fields.items()
|
||||
if field.repr
|
||||
]
|
||||
return f"{cls.__name__}({', '.join(fields)})"
|
||||
return f"{cls.__name__}({', '.join(fields_repr)})"
|
||||
|
||||
# Attach generated methods to class
|
||||
setattr(cls, '__init__', __init__)
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
# for python-nostr
|
||||
|
||||
# enum.py: MicroPython compatibility layer for Python's enum module
|
||||
# Implements Enum and IntEnum for integer-based enumerations, avoiding metaclass keyword
|
||||
|
||||
class Enum:
|
||||
"""Base class for enumerations."""
|
||||
def __init__(self, value, name):
|
||||
self.value = value
|
||||
self.name = name
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def __repr__(self):
|
||||
return f"<{self.__class__.__name__}.{self.name}: {self.value}>"
|
||||
|
||||
def __eq__(self, other):
|
||||
if isinstance(other, Enum):
|
||||
return self.value == other.value
|
||||
return self.value == other
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.value)
|
||||
|
||||
def create_enum_class(base_class, name, attrs):
|
||||
"""Factory function to create an enum class with metaclass-like behavior."""
|
||||
members = {}
|
||||
values = {}
|
||||
for key, value in attrs.items():
|
||||
if not key.startswith('__') and not callable(value):
|
||||
enum_item = base_class(value, key)
|
||||
members[key] = enum_item
|
||||
values[value] = enum_item
|
||||
attrs[key] = enum_item
|
||||
attrs['_members'] = members
|
||||
attrs['_values'] = values
|
||||
|
||||
# Define iteration and lookup
|
||||
def __iter__(cls):
|
||||
return iter(cls._members.values())
|
||||
|
||||
def __getitem__(cls, value):
|
||||
return cls._values.get(value)
|
||||
|
||||
attrs['__iter__'] = __iter__
|
||||
attrs['__getitem__'] = __getitem__
|
||||
|
||||
# Create class using type
|
||||
return type(name, (base_class,), attrs)
|
||||
|
||||
# Define IntEnum using factory function
|
||||
IntEnum = create_enum_class(Enum, 'IntEnum', {
|
||||
'__int__': lambda self: self.value
|
||||
})
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,5 @@
|
||||
# typing.py: MicroPython compatibility layer for Python's typing module
|
||||
# Provides List for type annotations
|
||||
|
||||
class List:
|
||||
pass
|
||||
Reference in New Issue
Block a user