Skip to main content

Wrap Instance

Project description

ExtendAnything

CI

ExtendAnything is a small Python helper for wrapping an already-created object with a new interface. A wrapper class can add methods, override selected method names, and still expose the original object's attributes without copying or reinitializing the original instance.

The package is currently pre-alpha (0.0.1) and requires Python 3.8 or newer.

Why it exists

Normal subclassing only helps before an object is created. ExtendAnything is for cases where the instance already exists, such as a trained model, configured client, or object returned by another library, and you want to attach project-specific behavior around it.

Conceptually, it behaves like a lightweight dynamic cast: the wrapper handles the behavior it defines, and missing attribute lookups fall through to the wrapped object.

How it works

Subclass ExtendAnything, accept the object to wrap, and call super().__init__(inner). The base class stores the original object on self._inner and implements __getattr__ so attributes and methods not found on the wrapper are read from self._inner.

from extendanything import ExtendAnything


class Predictor:
    def __init__(self, name):
        self.name = name

    def predict(self):
        return "base prediction"


class EnhancedPredictor(ExtendAnything):
    def __init__(self, inner, prefix):
        super().__init__(inner)
        self.prefix = prefix

    def predict(self):
        return f"{self.prefix}: {self._inner.predict()}"

    def explain(self):
        return f"{self.name} -> {self.predict()}"


base = Predictor("demo")
wrapped = EnhancedPredictor(base, "custom")

assert wrapped.name == "demo"  # forwarded to base
assert wrapped.predict() == "custom: base prediction"  # wrapper override
assert wrapped.explain() == "demo -> custom: base prediction"  # wrapper-only method

The wrapper also defines __getstate__ and __setstate__, so wrapped objects can round-trip through pickle and joblib when the wrapped object itself supports that.

Installation

The runtime package has no required third-party dependencies.

pip install extendanything

For local development from this repository:

pip install -r requirements_dev.txt
pip install -e .

Important behavior

  • Reads of missing attributes are forwarded to self._inner.
  • Methods and attributes defined on the wrapper take precedence over the wrapped object.
  • Assigning wrapped.attr = value writes to the wrapper, not to the inner object. To mutate the wrapped object, assign through wrapped._inner.attr.
  • If the inner object changes, forwarded reads reflect those changes unless the wrapper has already set an attribute with the same name.
  • Methods running inside the inner object still use the inner object's own method resolution. If an inner method calls self.predict(), it will not call a predict() override defined on the wrapper.
  • The wrapper is not registered as a subclass of the wrapped object's class, so isinstance(wrapped, InnerClass) is false.
  • Special methods such as indexing are not generally forwarded; use wrapped._inner[...] when direct access to the original object is needed.

Development

make test
make lint
make docs

Tests cover attribute forwarding, wrapper overrides, attribute detachment, repr, and pickle/joblib serialization.

ExtendAnything is released under the MIT license.

Changelog

0.0.1

  • First release on PyPI.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

extendanything-0.0.2.tar.gz (12.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

extendanything-0.0.2-py2.py3-none-any.whl (5.8 kB view details)

Uploaded Python 2Python 3

File details

Details for the file extendanything-0.0.2.tar.gz.

File metadata

  • Download URL: extendanything-0.0.2.tar.gz
  • Upload date:
  • Size: 12.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.25

File hashes

Hashes for extendanything-0.0.2.tar.gz
Algorithm Hash digest
SHA256 e03e91ad63e54bcc1f765b95dfcb3ae5516b3801153284a49a51268fe63e6f77
MD5 ea02389c856bf9b516ab1bc630a34f93
BLAKE2b-256 8b6fc532b41dc989ab8107a562873463ad84bcd4c1aa966948a5ea5450af262a

See more details on using hashes here.

File details

Details for the file extendanything-0.0.2-py2.py3-none-any.whl.

File metadata

File hashes

Hashes for extendanything-0.0.2-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 7d178f3c03e2e3237e2adab11a3a46e8876f600530b714232d472b0d103e7a35
MD5 a49af96a36086e63d2db0af778dce2c4
BLAKE2b-256 85df09cd78742012fdec6523314ecc46d54581c1cc0949f53314ef30be341936

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page