[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/ZeroIntensity/pointers.py/master/src/pointers/var_pointer.py [Back]  [Original]

import inspect
import warnings
from types import FrameType as Frame
from typing import Any, Dict, Optional, TypeVar, Union
from varname import nameof

from _pointers import force_update_locals

from .base_pointers import BasePointer
from .exceptions import NullPointerError, VariableLifetimeError
from .util import NULL, Nullable, handle

__all__ = "VarPointer", "to_var_ptr"

T = TypeVar("T")

class VarPointer(BasePointer[T]):
    def __init__(self, name: str, frame: Frame) -> None:
        self.name: Optional[str] = name
        self._frame = frame
        self._address = id(~self)

    def _get_scope(self) -> Dict[str, Any]:
        if not self.name:
            raise NullPointerError("pointer is NULL")

        frame = self._frame

        if self.name in frame.f_globals:
            return frame.f_globals

        if self.name in frame.f_locals:
            return frame.f_locals

        raise VariableLifetimeError(f'variable "{self.name}" no longer exists')

    @handle
    def move(
        self,
        target: Union[T, "BasePointer[T]"],
        *,
        unsafe: bool = False,
    ) -> None:
        if unsafe:
            warnings.warn("unsafe has no effect on variable pointers")

        if not self.name:
            raise NullPointerError("pointer is NULL")

        scope = self._get_scope()

        if (scope is self._frame.f_locals) and (
            self._frame.f_locals is not self._frame.f_globals
        ):
            force_update_locals(
                self._frame,
                self.name,
                (
                    ~target
                    if isinstance(
                        target,
                        BasePointer,
                    )
                    else target
                ),
            )
        else:
            scope[self.name] = (
                ~target
                if isinstance(
                    target,
                    BasePointer,
                )
                else target
            )

    @property
    def address(self) -> Optional[int]:
        return self._address

    def _cleanup(self) -> None:
        pass

    def __repr__(self) -> str:
        return f"VarPointer(name={self.name!r})"

    def dereference(self) -> T:
        if not self.name:
            raise NullPointerError("pointer is NULL")

        return self._get_scope()[self.name]

    def assign(self, value: Nullable[Union["VarPointer[T]", T]], *, frame: int = 2) -> None:
        if value is NULL:
            self._address = 0
            self.name = None
            return

        fframe = inspect.currentframe()
        assert fframe
        assert fframe.f_back

        self.name = nameof(value, frame=frame)
        self._address = id(value)

    def __irshift__(
        self,
        value: Nullable[Union["VarPointer[T]", T]],
    ):
        self.assign(value, frame=3)
        return self


def to_var_ptr(value: T) -> VarPointer[T]:
    frame = inspect.currentframe()
    assert frame
    assert frame.f_back
    name = nameof(value, frame=2)
    return VarPointer(name, frame.f_back)

Web Proxy Viewer  |  New URL  |  Original Page