File element.py#
File List > libpisoundmicro > pypisoundmicro > pypisoundmicro > element.py
Go to the documentation of this file
from .swig import pypisoundmicro as psm
from ._utils import copy_doc
from typing import Optional, Self, Type, Union
from .name import ElementName
from .types import Pin, ElementType, PinDirection, PinPull, ActivityType
from .valuefd import ValueFd
import os
@copy_doc(psm.Element)
class Element:
def __init__(self, native_obj: Optional[psm.Element] = None) -> None:
"""Initialize an Element.
Args:
native_obj: The native SWIG-wrapped Element object
"""
# Increments the reference counter of the native context.
# This is necessary to ensure smooth cleanup on exit.
psm.upisnd_init()
self._native_obj = native_obj if native_obj is not None else psm.Element()
@property
@copy_doc(psm.Element.isValid)
def is_valid(self) -> bool:
if self._native_obj:
return self._native_obj.isValid()
return False
@copy_doc(psm.Element.release)
def release(self) -> None:
if self._native_obj:
self._native_obj.release()
self._native_obj = None
# Decrement the reference counter of the native context.
psm.upisnd_uninit()
@property
@copy_doc(psm.Element.getName)
def name(self) -> Optional[str]:
if self._native_obj:
return self._native_obj.getName()
return None
@property
@copy_doc(psm.Element.getType)
def type(self) -> ElementType:
if self._native_obj:
return ElementType(self._native_obj.getType())
return ElementType.INVALID
@property
@copy_doc(psm.Element.getPin)
def pin(self) -> Pin:
if self._native_obj:
return Pin(self._native_obj.getPin())
return Pin.INVALID
@copy_doc(psm.Element.openValueFd)
def open_value_fd(self, flags: int = os.O_RDWR | os.O_CLOEXEC) -> Optional[ValueFd]:
if self._native_obj:
# Use the native openValueFd method of the Element object
native_fd = self._native_obj.openValueFd(flags)
if native_fd and native_fd.isValid():
# Convert from native ValueFd to our Python ValueFd
return ValueFd(native_fd)
return None
def as_encoder(self) -> Optional['Encoder']:
"""Cast the element to an Encoder if possible."""
from .encoder import Encoder
if self._native_obj and self.type == ElementType.ENCODER:
# Use the SWIG-provided as_encoder method that properly handles reference counting
swig_encoder = self._native_obj.as_encoder()
if swig_encoder and swig_encoder.isValid():
return Encoder(swig_encoder)
return None
def as_analog_input(self) -> Optional['AnalogInput']:
"""Cast the element to an AnalogInput if possible."""
from .analoginput import AnalogInput
if self._native_obj and self.type == ElementType.ANALOG_INPUT:
# Use the SWIG-provided as_analog_input method that properly handles reference counting
swig_analog = self._native_obj.as_analog_input()
if swig_analog and swig_analog.isValid():
return AnalogInput(swig_analog)
return None
def as_gpio(self) -> Optional['Gpio']:
"""Cast the element to a GPIO if possible."""
from .gpio import Gpio
if self._native_obj and self.type == ElementType.GPIO:
# Use the SWIG-provided as_gpio method that properly handles reference counting
swig_gpio = self._native_obj.as_gpio()
if swig_gpio and swig_gpio.isValid():
return Gpio(swig_gpio)
return None
def as_activity(self) -> Optional['Activity']:
"""Cast the element to an Activity if possible."""
from .activity import Activity
if self._native_obj and self.type == ElementType.ACTIVITY:
# Use the SWIG-provided as_activity method that properly handles reference counting
swig_activity = self._native_obj.as_activity()
if swig_activity and swig_activity.isValid():
return Activity(swig_activity)
return None
@classmethod
@copy_doc(psm.Element.get)
def get(cls, name: Union[str, ElementName]) -> Optional[Self]:
if isinstance(name, str):
name = psm.ElementName.regular(name)
native_obj = psm.Element.get(name)
if native_obj.isValid():
return cls(native_obj)
return None
@classmethod
@copy_doc(psm.Element.setup)
def setup(cls, name: Union[str, ElementName], setup: Union[int, 'Setup']) -> Optional[Self]:
if isinstance(name, str):
name = psm.ElementName.regular(name)
# Handle both raw integers and Setup objects
if hasattr(setup, 'to_int'):
setup_value = setup.to_int()
else:
setup_value = setup
native_obj = psm.Element.setup(name, setup_value)
if native_obj.isValid():
return cls(native_obj)
return None
def __enter__(self) -> Self:
"""Context manager support."""
return self
def __exit__(self, exc_type, exc_val, exc_tb) -> None:
"""Context manager support for auto-releasing resources."""
self.release()
def __del__(self) -> None:
"""Destructor to ensure resources are released.
Note: This may not always be called immediately when the object goes out of scope,
especially if the object is part of a reference cycle. For deterministic cleanup,
use the release() method explicitly or use the object as a context manager.
"""
try:
# Check if _native_obj is still accessible
if hasattr(self, '_native_obj') and self._native_obj:
self.release()
except Exception:
# Silently ignore exceptions during garbage collection
# This prevents errors that would be swallowed by Python anyway
pass