Metadata-Version: 2.4
Name: wanting
Version: 0.4.0
Summary: A library for creating, and working with models that may have incomplete information.
Author-email: Narvin Singh <Narvin.A.Singh@gmail.com>
License: Wanting is a library for working with incomplete models.
        Copyright (C) 2025  Narvin Singh
        
        This program is free software: you can redistribute it and/or modify
        it under the terms of the GNU General Public License as published by
        the Free Software Foundation, either version 3 of the License, or
        (at your option) any later version.
        
        This program is distributed in the hope that it will be useful,
        but WITHOUT ANY WARRANTY; without even the implied warranty of
        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        GNU General Public License for more details.
        
        You should have received a copy of the GNU General Public License
        along with this program.  If not, see <https://www.gnu.org/licenses/>.
        
Project-URL: Homepage, https://gitlab.com/narvin/wanting
Project-URL: Repository, https://gitlab.com/narvin/wanting
Project-URL: Bug Tracker, https://gitlab.com/narvin/wanting/-/issues
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
Classifier: Operating System :: OS Independent
Requires-Python: >=3.12
Description-Content-Type: text/x-rst
License-File: LICENSE
Requires-Dist: pydantic~=2.11
Provides-Extra: dev
Requires-Dist: mypy~=1.18; extra == "dev"
Requires-Dist: pre-commit~=4.3; extra == "dev"
Requires-Dist: pytest~=8.4; extra == "dev"
Requires-Dist: ruff~=0.13.0; extra == "dev"
Provides-Extra: doc
Requires-Dist: python-docs-theme~=2025.9; extra == "doc"
Requires-Dist: sphinx~=8.2; extra == "doc"
Provides-Extra: deploy
Requires-Dist: build~=1.3; extra == "deploy"
Requires-Dist: twine~=6.2; extra == "deploy"
Dynamic: license-file

Wanting
#######

Wanting is a library for creating, and working with models that may have
incomplete information.

Motivation
**********

Instances of domain models don't always spring into existence fully formed.
They may be partially constructed intially, then filled in over time. Making a
model field optional that is not intially available, but eventually required is
inaccurate because an optional field may *always* be optional, so it never has
to be filled in. It would be better to make the field a required union of the
type it wants, and a placholder type. The wanting types are such placeholders.
They can include metadata, such as the source of the update with missing data,
and even partial data from that source.

Usage
*****

A domain model may look like this:

.. code-block:: python

   from typing import Literal

   import wanting
   import pydantic
 
   class User(pydantic.BaseModel):
       name: str 
       employee_id: str | wanting.Unavailable
       department_code: Literal["TECH", "FO", "BO", "HR"] | wanting.Unmapped
       
Then there is an onboarding system that creates a ``User``. However, the
``employee_id`` is unavailable at this time because it will be generated later.
The onboarding system sources the department code from some other system, which
uses different values than those in the ``User`` model. The onboarding system
knows how to map some of the codes from the other system to the ``User``
department codes, but not all of them. However, because ``employee_id``, and
``department_code`` may also be wanting fields in the ``User`` model, the
onboarding system can still create a fully valid model, while also indicating
that some information is missing:

.. code-block:: python

   user = User(
       name="Charlotte",
       employee_id=wanting.Unavailable(source="onboarding"),
       department_code=wanting.Unmapped(source="onboarding", value="art"),
   )

The model validates, and all the wanting fields serialize to valid JSON:

.. code-block:: python

   assert user.model_dump() == {
       "name": "Charlotte",
       "employee_id": {
           "kind": "unavailable",
           "source": "onboarding",
           "value": b"null",
       },
       "department_code": {
           "kind": "unmapped",
           "source": "onboarding",
           "value": b'"art"',
       },
   }

This user can now be persisted, then queried, and updated later by other
systems.
