{"id":13770098,"url":"https://github.com/alfred82santa/dirty-models","last_synced_at":"2025-04-14T15:30:31.230Z","repository":{"id":13461829,"uuid":"16151568","full_name":"alfred82santa/dirty-models","owner":"alfred82santa","description":"Dirty model for python","archived":false,"fork":false,"pushed_at":"2021-12-09T10:20:36.000Z","size":304,"stargazers_count":10,"open_issues_count":5,"forks_count":2,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-03-28T04:23:35.954Z","etag":null,"topics":["model","python"],"latest_commit_sha":null,"homepage":"http://dirty-models.readthedocs.io","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alfred82santa.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-01-22T20:26:25.000Z","updated_at":"2023-03-24T02:59:58.000Z","dependencies_parsed_at":"2022-09-26T19:31:31.301Z","dependency_job_id":null,"html_url":"https://github.com/alfred82santa/dirty-models","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alfred82santa%2Fdirty-models","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alfred82santa%2Fdirty-models/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alfred82santa%2Fdirty-models/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alfred82santa%2Fdirty-models/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alfred82santa","download_url":"https://codeload.github.com/alfred82santa/dirty-models/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248906314,"owners_count":21181154,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["model","python"],"created_at":"2024-08-03T17:00:34.221Z","updated_at":"2025-04-14T15:30:31.187Z","avatar_url":"https://github.com/alfred82santa.png","language":"Python","funding_links":[],"categories":["Model, Schema"],"sub_categories":[],"readme":"|travis-master| |coverall-master| |doc-master| |pypi-lastrelease| |python-versions|\n|project-status| |project-license| |project-format| |project-implementation|\n\n.. |travis-master| image:: https://travis-ci.org/alfred82santa/dirty-models.svg?branch=master\n    :target: https://travis-ci.org/alfred82santa/dirty-models\n\n.. |coverall-master| image:: https://coveralls.io/repos/alfred82santa/dirty-models/badge.svg?branch=master\u0026service=github\n    :target: https://coveralls.io/r/alfred82santa/dirty-models?branch=master\n\n.. |doc-master| image:: https://readthedocs.org/projects/dirty-models/badge/?version=latest\n    :target: http://dirty-models.readthedocs.io/?badge=latest\n    :alt: Documentation Status\n\n.. |pypi-downloads| image:: https://img.shields.io/pypi/dm/dirty-models.svg\n    :target: https://pypi.python.org/pypi/dirty-models/\n    :alt: Downloads\n\n.. |pypi-lastrelease| image:: https://img.shields.io/pypi/v/dirty-models.svg\n    :target: https://pypi.python.org/pypi/dirty-models/\n    :alt: Latest Version\n\n.. |python-versions| image:: https://img.shields.io/pypi/pyversions/dirty-models.svg\n    :target: https://pypi.python.org/pypi/dirty-models/\n    :alt: Supported Python versions\n\n.. |project-status| image:: https://img.shields.io/pypi/status/dirty-models.svg\n    :target: https://pypi.python.org/pypi/dirty-models/\n    :alt: Development Status\n\n.. |project-license| image:: https://img.shields.io/pypi/l/dirty-models.svg\n    :target: https://pypi.python.org/pypi/dirty-models/\n    :alt: License\n\n.. |project-format| image:: https://img.shields.io/pypi/format/dirty-models.svg\n    :target: https://pypi.python.org/pypi/dirty-models/\n    :alt: Download format\n\n.. |project-implementation| image:: https://img.shields.io/pypi/implementation/dirty-models.svg\n    :target: https://pypi.python.org/pypi/dirty-models/\n    :alt: Supported Python implementations\n\n.. _Dirty Models Sphinx extension: http://dirty-models-sphinx-extension.readthedocs.io\n\n============\nDirty Models\n============\n\nDirty models for python 3\n\n-------------\nDocumentation\n-------------\n\nhttp://dirty-models.readthedocs.io/\n\n--------\nFeatures\n--------\n\n- Python 3 package.\n- Easy to create a model.\n- Non destructive modifications.\n- Non false positive modifications.\n- Able to restore original data for each field or whole model.\n- Access to original data.\n- Read only fields.\n- Alias for fields.\n- Custom getters and setters for each fields.\n- Automatic cast value.\n- Easy import from/export to dict.\n- Basic field type implemented.\n- Multi type fields.\n- Default values for each field or whole model.\n- HashMap model. It could be used instead of DynamicModel.\n- FastDynamicModel. It could be used instead of DynamicModel. Same behavior, better performance.\n- Pickable models.\n- Datetime fields can use any datetime format using parser and formatter functions.\n- No database dependent.\n- Auto documentation using `Dirty Models Sphinx extension`_.\n- Json encoder.\n- Field access like dictionary but with wildcards.\n- Opensource (BSD License)\n\n---------\nChangelog\n---------\n\nVersion 0.12.4\n--------------\n\n* Make it compatible with Python 3.10.\n\nVersion 0.12.3\n--------------\n\n* Fix HashMapsModel's hardcode field type.\n\nVersion 0.12.2\n--------------\n\n* Fix access to HashMapsModel's field type when it is hardcoded in a class.\n\nVersion 0.12.1\n--------------\n\n* Fix :class:`~dirty_models.fields.MultiFieldType` on creation mode.\n\n* Fix :class:`~dirty_models.utils.BaseModelFormatterIter` to be aware about override access modes.\n\n* Exposed all useful classes on package root.\n\n\nVersion 0.12.0\n--------------\n\n* Added `access_mode` property to fields.\n  It could be :class:`~dirty_models.base.AccessMode.READ_AND_WRITE` in order to allow to read and write.\n  :class:`~dirty_models.base.AccessMode.WRITABLE_ONLY_ON_CREATION` in order to set value only on creation.\n  :class:`~dirty_models.base.AccessMode.READ_ONLY` in order to prevent writing.\n  And :class:`~dirty_models.base.AccessMode.HIDDEN` in order to hide field.\n\n* Old field property `read_only` is deprecated in favor of `access_mode` but it can be used like until this version.\n\n* Helper :class:`~dirty_models.base.Creating` to mark model as in creation mode.\n\n* Added class method :meth:`~dirty_models.models.BaseModel.create_new_model` build a model and insert data\n  in creation mode.\n\n* Allowed to override field access model on inherited fields using\n  :attr:`~dirty_models.models.BaseModel.__override_field_access_modes__` hashmap.\n\n\nVersion 0.11.3\n--------------\n\n- Fix bug casting string negative float.\n- Fix exception casting non valid values to enumerations.\n- Added `title` property to fields.\n- Added `metadata` property to fields. It could be used to store anything.\n- Improved model formatter.\n\nVersion 0.11.2\n--------------\n\n- Fix bug #107.\n\n- Added :class:`~dirty_models.utils.ModelIterator` class in order to be able to iterate over model fields.\n\n  .. code-block:: python\n\n     from dirty_models.utils import ModelIterator\n\n     for fieldname, field_obj, value in ModelIterator(my_model):\n         print('Field name: {}'.format(fieldname))\n         print('Field alias: {}'.format(field_obj.alias))\n         print('Field value: {}'.format(value))\n\n- Some fixes about read only data.\n\n\nVersion 0.11.1\n--------------\n\n- Distribution fixes.\n\n\nVersion 0.11.0\n--------------\n\n- New field type :class:`~dirty_models.fields.BytesField`.\n\n- String to integer casting could use any format allowed by Python: HEX (`0x23`), OCT (`0o43`) or\n  no-meaning underscores (`1_232_232`, only since Python 3.6).\n\nVersion 0.10.1\n--------------\n\n- :class:`Factory\u003cdirty_models.utils\u003e` feature. It allows to define a factory as\n  default value in order to be executed each time model is instanced. (Issue #100)\n\n  .. code-block:: python\n\n     from dirty_models.utils import factory\n     from datetime import datetime\n\n     class Model(BaseModel):\n\n        field_1 = DateTimeField(default=factory(datetime.now))\n\n     model = Model()\n     print(model.field_1)\n\n     # 2017-11-02 21:52:46.339040\n\n- Makefile fixes.\n- Python 3.6 is supported officially. It works since first day, but now tests run on Travis for Python 3.6.\n\nVersion 0.10.0\n--------------\n\n- Pickable lists.\n- Improved pickle performance.\n- Setting ``None`` to a field remove content.\n- More tests.\n- Some code improvements.\n\nVersion 0.9.2\n-------------\n\n- Fix timezone when convert timestamp to datetime.\n\nVersion 0.9.1\n-------------\n\n- Fix installation.\n\nVersion 0.9.0\n-------------\n\n- New EnumField.\n- Fixes on setup.py.\n- Fixes on requirements.\n- Fixes on formatter iters.\n- Fixes on code.\n- Added ``__version__`` to main package file.\n- Synchronized version between main packege file, ``setup.py`` and docs.\n- Export only modifications.\n\n\nVersion 0.8.1\n-------------\n\n- Added __contains__ function to models and lists. It allows to use ``in`` operator.\n- Added ``default_timezone`` parameter to DateTimeFields and TimeFields. If value entered has no a timezone\n  defined, default one will be set.\n- Added ``force_timezone`` parameter to DateTimeFields in order to convert values to a specific timezone.\n- More cleanups.\n\nVersion 0.8.0\n-------------\n\n- Renamed internal fields. Now they use double score format ``__fieldname__``.\n- Raise a RunTimeError exception if two fields use same alias in a model.\n- Fixed default docstrings.\n- Cleanup default data. Only real name fields are allowed to use as key.\n- Added :meth:`~dirty_models.models.BaseModel.get_attrs_by_path` in order to get all values using path.\n- Added :meth:`~dirty_models.models.BaseModel.get_1st_attr_by_path` in order to get first value using path.\n- Added option to access fields like in a dictionary, but using wildcards. Only for getters.\n  See: :meth:`~dirty_models.models.BaseModel.get_1st_attr_by_path`.\n- Added some documentation.\n\nVersion 0.7.2\n-------------\n\n- Fixed inherited structure\n- Added ``get_default_data`` method to models in order to retrieve default data.\n\nVersion 0.7.1\n-------------\n\n- Solved problem formatting dynamic models\n- Added date, time and timedelta fields to dynamic models.\n\nVersion 0.7.0\n-------------\n\n- Timedelta field\n- Generic formatters\n- Json encoder\n\n.. code-block:: python\n\n    import json\n    from datetime import datetime\n    from dirty_models import BaseModel, DatetimeField\n    from dirty_models.utils import JSONEncoder\n\n\n    class ExampleModel(BaseModel):\n        field_datetime = DatetimeField(parse_format=\"%Y-%m-%dT%H:%M:%S\")\n\n    model = ExampleModel(field_datetime=datetime.now())\n\n    assert json.dumps(model, cls=JSONEncoder) == '{\"field_datetime\": \"2016-05-30T22:22:22\"}'\n\n- Auto camelCase fields metaclass\n\n\nVersion 0.6.3\n-------------\n\n- Documentation fixed.\n- Allow import main members from root package.\n\nVersion 0.6.2\n-------------\n\n- Improved datetime fields parser and formatter definitions. Now there are three ways to define them:\n\n* Format string to use both parse and formatter:\n\n.. code-block:: python\n\n    class ExampleModel(BaseModel):\n        datetime_field = DateTimeField(parse_format='%Y-%m-%dT%H:%M:%SZ')\n\n\n* Define a format string or function for parse and format datetime:\n\n.. code-block:: python\n\n    class ExampleModel(BaseModel):\n        datetime_field = DateTimeField(parse_format={'parser': callable_func,\n                                                     'formatter': '%Y-%m-%dT%H:%M:%SZ'})\n\n* Use predefined format:\n\n.. code-block:: python\n\n    DateTimeField.date_parsers = {\n        'iso8061': {\n            'formatter': '%Y-%m-%dT%H:%M:%SZ',\n            'parser': iso8601.parse_date\n        }\n    }\n    class ExampleModel(BaseModel):\n        datetime_field = DateTimeField(parse_format='iso8061')\n\n\nVersion 0.6.1\n-------------\n\n- Improved model field autoreference.\n\n.. code-block:: python\n\n    class ExampleModel(BaseModel):\n        model_field = ModelField()  # Field with a ExampleModel\n        array_of_model = ArrayField(field_type=ModelField())  # Array of ExampleModels\n\n\nVersion 0.6.0\n-------------\n\n- Added default value for fields.\n\n..  code-block:: python\n\n    class ExampleModel(BaseModel):\n        integer_field = IntegerField(default=1)\n\n    model = ExampleModel()\n    assert model.integer_field is 1\n\n- Added default values at model level. Inherit default values could be override on new model classes.\n\n..  code-block:: python\n\n    class InheritExampleModel(ExampleModel):\n        __default_data__ = {'integer_field': 2}\n\n    model = InheritExampleModel()\n    assert model.integer_field is 2\n\n- Added multi type fields.\n\n..  code-block:: python\n\n    class ExampleModel(BaseModel):\n        multi_field = MultiTypeField(field_types=[IntegerField(), StringField()])\n\n    model = ExampleModel()\n    model.multi_field = 2\n    assert model.multi_field is 2\n\n    model.multi_field = 'foo'\n    assert model.multi_field is 'foo'\n\nVersion 0.5.2\n-------------\n\n- Fixed model structure.\n- Makefile helpers.\n\n\nVersion 0.5.1\n-------------\n\n- Added a easy way to get model structure. It will be used by autodoc libraries as sphinx or json-schema.\n\nVersion 0.5.0\n-------------\n\n- Added autolist parameter to ArrayField. It allows to assign a single item to a list field,\n  so it will be converted to a list with this value.\n\n..  code-block:: python\n\n    class ExampleModel(BaseModel):\n        array_field = ArrayField(field_type=StringField(), autolist=True)\n\n    model = ExampleModel()\n    model.array_field = 'foo'\n    assert model.array_field[0] is 'foo'\n\n------------\nInstallation\n------------\n\n.. code-block:: bash\n\n    $ pip install dirty-models\n\n------\nIssues\n------\n\n- Getter and setter feature needs refactor to be able to use as decorators.\n- DynamicModel is too strange. I don't trust in it. Try to use HashMapModel or FastDynamicModel.\n\n-----------\nBasic usage\n-----------\n\n.. code-block:: python\n\n    from dirty_models.models import BaseModel\n    from dirty_models.fields import StringField, IntegerField\n\n    class FooBarModel(BaseModel):\n        foo = IntegerField()\n        bar = StringField(name=\"real_bar\")\n        alias_field = IntegerField(alias=['alias1', 'alias2'])\n\n\n\n    fb = FooBarModel()\n\n    fb.foo = 2\n    assert fb.foo is 2\n\n    fb.bar = 'wow'\n    assert fb.bar is 'wow'\n    assert fb.real_bar is 'wow'\n\n    fb.alias_field = 3\n    assert fb.alias_field is 3\n    assert fb.alias1 is fb.alias_field\n    assert fb.alias2 is fb.alias_field\n    assert fb['alias_field'] is 3\n\n.. note::\n\n    More examples and documentation on http://dirty-models.readthedocs.io/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falfred82santa%2Fdirty-models","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falfred82santa%2Fdirty-models","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falfred82santa%2Fdirty-models/lists"}