# baseclasses
Simple dataclasses alternative (beta)
[](https://badge.fury.io/py/baseclasses)
[](https://pypi.python.org/pypi/baseclasses/)
[](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[](https://badge.fury.io/py/baseclasses)\n[](https://pypi.python.org/pypi/baseclasses/)\n[](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"
}