baseclasses


Namebaseclasses JSON
Version 0.1.1 PyPI version JSON
download
home_pagehttps://github.com/yanovs/baseclasses
SummaryDataclasses alternative
upload_time2023-05-14 23:59:38
maintainer
docs_urlNone
author
requires_python>=3.7
licenseApache License 2.0
keywords dataclasses
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # baseclasses

Simple dataclasses alternative (beta)

[![PyPI version](https://badge.fury.io/py/baseclasses.svg)](https://badge.fury.io/py/baseclasses)
[![PyPI Supported Python Versions](https://img.shields.io/pypi/pyversions/baseclasses.svg)](https://pypi.python.org/pypi/baseclasses/)
[![GitHub Actions (Tests)](https://github.com/yanovs/baseclasses/workflows/Test/badge.svg)](https://github.com/yanovs/baseclasses)

## Installation

`baseclasses` is available on [PyPI](https://pypi.org/project/baseclasses/):

```bash
pip install baseclasses
```

## Quick Start

`baseclasses` is an alternative to [`dataclasses`](https://docs.python.org/3/library/dataclasses.html).

There are many such alternatives, and there are a lot of reasons 
to use them (including the built-in
`dataclasses`), but if you want a library with:

- No monkey-patched methods generated from strings
- No special decorators, just regular inheritance
- Ability to order fields in subclasses as desired
- Auto-inheritance of parent properties, with ability to change per subclass
- Emphasis on keyword args over positional args
- Optional `__pre_init__` ability to mutate kwargs
- Optional ability to reference other kwargs in `default_factory` func
- A shorthand helper to specify `InternalStateField`
- Ability to differentiate between `str` and `repr`

you can give `baseclasses` a try. E.g.:

```python
from typing import Dict, Optional

import baseclasses


# No decorator
class Foo(baseclasses.FrozenBaseClass):
    a: int
    b: int
    c: Optional[str] = baseclasses.Field(default="hello", hash=False)
    _d: Dict = baseclasses.InternalStateField(default_factory=dict)


# Auto-inherits FrozenBaseClass properties
class ChildFoo(Foo):
    # No problems with child class field ordering
    x: float

    # Dynamic defaults
    y: int = baseclasses.Field(
        default_factory=lambda **kwargs: kwargs["a"] * 2.0
    )


# Override frozen state per child class
class MutableChildFoo(ChildFoo, frozen=False):
    pass
```

## Comparisons to Alternatives

See [`tests/test_compare.py`](https://github.com/yanovs/baseclasses/blob/main/baseclasses/tests/test_compare.py).

Like [dataclasses](https://docs.python.org/3/library/dataclasses.html), but:
- No issues with adding new optional fields because you're forced to 
use `kwargs` in all but the simplest cases
- Uses `metaclass` and simple inheritance over monkey-patched generated code
- Child classes automatically inherit state from parent, 
so no need to re-declare
- But you can also change `frozen` status per child class
- You can use `default_factory(lambda **kwargs: ...)` to access init fields
- Or you can mutate kwargs with an optional `__pre_init__`
- More consistent with traditional OOP style 
(e.g., `obj.get_fields()` instead of `dataclasses.get_fields(obj)`)

Like [dataclassy](https://github.com/biqqles/dataclassy) but:
- Uses `metaclass` and simple inheritance over monkey-patched generated code

There are others:
- [attrs](https://github.com/python-attrs/attrs)
- [pydantic](https://github.com/samuelcolvin/pydantic)
- [traitlets](https://github.com/ipython/traitlets)
- [param](https://param.holoviz.org/)

Note: there are [perfectly valid reasons](https://peps.python.org/pep-0557/#rationale) 
for why the Python community
decided to use generated code over simple inheritance.
`baseclasses` is just an alternative that implements things differently.

## TODO

- [ ] Add `init` property to field (to mirror `dataclasses`)
- [ ] Expose `obj.replace(**kwargs)` (to mirror `dataclasses`)
- [ ] Consider `serialize` property to field
- [ ] Take advantage of [PEP 681 included in Python 3.11](https://docs.python.org/3/whatsnew/3.11.html#whatsnew311-pep681)

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/yanovs/baseclasses",
    "name": "baseclasses",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.7",
    "maintainer_email": "",
    "keywords": "dataclasses",
    "author": "",
    "author_email": "",
    "download_url": "https://files.pythonhosted.org/packages/db/c8/11ed8eab6cf265bffbabaea9bb4af2c1bbb3f3f0141bdefde10bd9ba4512/baseclasses-0.1.1.tar.gz",
    "platform": "any",
    "description": "# baseclasses\n\nSimple dataclasses alternative (beta)\n\n[![PyPI version](https://badge.fury.io/py/baseclasses.svg)](https://badge.fury.io/py/baseclasses)\n[![PyPI Supported Python Versions](https://img.shields.io/pypi/pyversions/baseclasses.svg)](https://pypi.python.org/pypi/baseclasses/)\n[![GitHub Actions (Tests)](https://github.com/yanovs/baseclasses/workflows/Test/badge.svg)](https://github.com/yanovs/baseclasses)\n\n## Installation\n\n`baseclasses` is available on [PyPI](https://pypi.org/project/baseclasses/):\n\n```bash\npip install baseclasses\n```\n\n## Quick Start\n\n`baseclasses` is an alternative to [`dataclasses`](https://docs.python.org/3/library/dataclasses.html).\n\nThere are many such alternatives, and there are a lot of reasons \nto use them (including the built-in\n`dataclasses`), but if you want a library with:\n\n- No monkey-patched methods generated from strings\n- No special decorators, just regular inheritance\n- Ability to order fields in subclasses as desired\n- Auto-inheritance of parent properties, with ability to change per subclass\n- Emphasis on keyword args over positional args\n- Optional `__pre_init__` ability to mutate kwargs\n- Optional ability to reference other kwargs in `default_factory` func\n- A shorthand helper to specify `InternalStateField`\n- Ability to differentiate between `str` and `repr`\n\nyou can give `baseclasses` a try. E.g.:\n\n```python\nfrom typing import Dict, Optional\n\nimport baseclasses\n\n\n# No decorator\nclass Foo(baseclasses.FrozenBaseClass):\n    a: int\n    b: int\n    c: Optional[str] = baseclasses.Field(default=\"hello\", hash=False)\n    _d: Dict = baseclasses.InternalStateField(default_factory=dict)\n\n\n# Auto-inherits FrozenBaseClass properties\nclass ChildFoo(Foo):\n    # No problems with child class field ordering\n    x: float\n\n    # Dynamic defaults\n    y: int = baseclasses.Field(\n        default_factory=lambda **kwargs: kwargs[\"a\"] * 2.0\n    )\n\n\n# Override frozen state per child class\nclass MutableChildFoo(ChildFoo, frozen=False):\n    pass\n```\n\n## Comparisons to Alternatives\n\nSee [`tests/test_compare.py`](https://github.com/yanovs/baseclasses/blob/main/baseclasses/tests/test_compare.py).\n\nLike [dataclasses](https://docs.python.org/3/library/dataclasses.html), but:\n- No issues with adding new optional fields because you're forced to \nuse `kwargs` in all but the simplest cases\n- Uses `metaclass` and simple inheritance over monkey-patched generated code\n- Child classes automatically inherit state from parent, \nso no need to re-declare\n- But you can also change `frozen` status per child class\n- You can use `default_factory(lambda **kwargs: ...)` to access init fields\n- Or you can mutate kwargs with an optional `__pre_init__`\n- More consistent with traditional OOP style \n(e.g., `obj.get_fields()` instead of `dataclasses.get_fields(obj)`)\n\nLike [dataclassy](https://github.com/biqqles/dataclassy) but:\n- Uses `metaclass` and simple inheritance over monkey-patched generated code\n\nThere are others:\n- [attrs](https://github.com/python-attrs/attrs)\n- [pydantic](https://github.com/samuelcolvin/pydantic)\n- [traitlets](https://github.com/ipython/traitlets)\n- [param](https://param.holoviz.org/)\n\nNote: there are [perfectly valid reasons](https://peps.python.org/pep-0557/#rationale) \nfor why the Python community\ndecided to use generated code over simple inheritance.\n`baseclasses` is just an alternative that implements things differently.\n\n## TODO\n\n- [ ] Add `init` property to field (to mirror `dataclasses`)\n- [ ] Expose `obj.replace(**kwargs)` (to mirror `dataclasses`)\n- [ ] Consider `serialize` property to field\n- [ ] Take advantage of [PEP 681 included in Python 3.11](https://docs.python.org/3/whatsnew/3.11.html#whatsnew311-pep681)\n",
    "bugtrack_url": null,
    "license": "Apache License 2.0",
    "summary": "Dataclasses alternative",
    "version": "0.1.1",
    "project_urls": {
        "Homepage": "https://github.com/yanovs/baseclasses",
        "Packaging": "https://pypi.org/project/baseclasses/",
        "Source": "https://github.com/yanovs/baseclasses",
        "Tracker": "https://github.com/yanovs/baseclasses/issues"
    },
    "split_keywords": [
        "dataclasses"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "3abed5ff9b8715d36b4b63e4a8fdbc04c8a48f4068fbd091d7bacf86eea478ad",
                "md5": "33cb13c3ed1056560261dc259e6dba50",
                "sha256": "567008c26e9616984888fccba2e371295fb65d46ddecf3428d7a26bc326fe951"
            },
            "downloads": -1,
            "filename": "baseclasses-0.1.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "33cb13c3ed1056560261dc259e6dba50",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.7",
            "size": 15195,
            "upload_time": "2023-05-14T23:59:36",
            "upload_time_iso_8601": "2023-05-14T23:59:36.983666Z",
            "url": "https://files.pythonhosted.org/packages/3a/be/d5ff9b8715d36b4b63e4a8fdbc04c8a48f4068fbd091d7bacf86eea478ad/baseclasses-0.1.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "dbc811ed8eab6cf265bffbabaea9bb4af2c1bbb3f3f0141bdefde10bd9ba4512",
                "md5": "8dff184a1fca5f6982161f0e59bd7deb",
                "sha256": "851c7d32bff8733217a1c6ac4eff7696a270ad9822e6817264cce30c7ade27a1"
            },
            "downloads": -1,
            "filename": "baseclasses-0.1.1.tar.gz",
            "has_sig": false,
            "md5_digest": "8dff184a1fca5f6982161f0e59bd7deb",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.7",
            "size": 18073,
            "upload_time": "2023-05-14T23:59:38",
            "upload_time_iso_8601": "2023-05-14T23:59:38.775170Z",
            "url": "https://files.pythonhosted.org/packages/db/c8/11ed8eab6cf265bffbabaea9bb4af2c1bbb3f3f0141bdefde10bd9ba4512/baseclasses-0.1.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-05-14 23:59:38",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "yanovs",
    "github_project": "baseclasses",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "baseclasses"
}
        
Elapsed time: 0.08466s