# -*- coding: utf-8 -*-
from setuptools import setup

packages = \
['pandas_dataclasses', 'pandas_dataclasses.pandas']

package_data = \
{'': ['*']}

install_requires = \
['morecopy>=0.2,<0.3', 'typing-extensions>=4.1,<5.0']

extras_require = \
{':python_full_version >= "3.7.1" and python_version < "3.8"': ['numpy>=1.20,<1.22',
                                                                'pandas>=1.3,<1.4'],
 ':python_version >= "3.8" and python_version < "3.11"': ['numpy>=1.20,<2.0',
                                                          'pandas>=1.3,<2.0']}

setup_kwargs = {
    'name': 'pandas-dataclasses',
    'version': '0.3.0',
    'description': 'pandas extension for typed Series and DataFrame creation',
    'long_description': '# pandas-dataclasses\n\n[![Release](https://img.shields.io/pypi/v/pandas-dataclasses?label=Release&color=cornflowerblue&style=flat-square)](https://pypi.org/project/pandas-dataclasses/)\n[![Python](https://img.shields.io/pypi/pyversions/pandas-dataclasses?label=Python&color=cornflowerblue&style=flat-square)](https://pypi.org/project/pandas-dataclasses/)\n![Downloads](https://img.shields.io/pypi/dm/pandas-dataclasses?label=Downloads&color=cornflowerblue&style=flat-square)\n[![DOI](https://img.shields.io/badge/DOI-10.5281/zenodo.6127352-cornflowerblue?style=flat-square)](https://doi.org/10.5281/zenodo.6127352)\n[![Tests](https://img.shields.io/github/workflow/status/astropenguin/pandas-dataclasses/Tests?label=Tests&style=flat-square)](https://github.com/astropenguin/pandas-dataclasses/actions)\n\npandas extension for typed Series and DataFrame creation\n\n## Overview\n\npandas-dataclass makes it easy to create [pandas] Series and DataFrame objects that are "typed" (i.e. fixed data types, attributes, and names) using [dataclass]:\n\n<details>\n<summary>Click to see all imports</summary>\n\n```python\nfrom dataclasses import dataclass\nfrom pandas_dataclasses import AsDataFrame, Data, Index\n```\n</details>\n\n```python\n@dataclass\nclass Weather(AsDataFrame):\n    """Weather information."""\n\n    year: Index[int]\n    month: Index[int]\n    temp: Data[float]\n    humid: Data[float]\n\n\ndf = Weather.new(\n    [2020, 2020, 2021, 2021, 2022],\n    [1, 7, 1, 7, 1],\n    [7.1, 24.3, 5.4, 25.9, 4.9],\n    [65, 89, 57, 83, 52],\n)\n```\n\n```plaintext\n            temp  humid\nyear month\n2020 1       7.1   65.0\n     7      24.3   89.0\n2021 1       5.4   57.0\n     7      25.9   83.0\n2022 1       4.9   52.0\n```\n\n### Features\n\n- Type casting to [NumPy] and [pandas] data types\n- Easy hierarchial indexing (`MultiIndex`)\n- Metadata storing in attributes (`attrs`)\n- Support for dataclass features (`field`, `__post_init__`, ...)\n- Support for static type check ([Pylance], [Pyright], ...)\n\n### Installation\n\n```bash\npip install pandas-dataclasses\n```\n\n## How it works\n\npandas-dataclasses provides you the following features:\n\n- Type hints for dataclass fields (`Attr`, `Data`, `Index`, `Name`) for specifying field types and data types\n- Mix-in classes for dataclasses (`AsDataFrame`, `AsSeries`) for creating a Series or DataFrame object via a classmethod (`new`)\n\nWhen you call `new`, it will first create a dataclass object and then create a Series or DataFrame object from the dataclass object according the type hints and values in it.\nIn the example above, `df = Weather.new(...)` is thus equivalent to:\n\n```python\nobj = Weather([2020, ...], [1, ...], [7.1, ...], [65, ...])\ndf = asdataframe(obj)\n```\n\nwhere `asdataframe` is a conversion function.\npandas-dataclasses does not touch the dataclass object creation itself; this allows you to fully customize your dataclass before conversion using the dataclass features (`field`, `__post_init__`, ...).\n\n## Basic usage\n\n### DataFrame creation\n\nAs shown in the example above, a dataclass that has the `AsDataFrame` mix-in will create DataFrame objects:\n\n<details>\n<summary>Click to see all imports</summary>\n\n```python\nfrom dataclasses import dataclass\nfrom pandas_dataclasses import AsDataFrame, Data, Index\n```\n</details>\n\n```python\n@dataclass\nclass Weather(AsDataFrame):\n    """Weather information."""\n\n    year: Index[int]\n    month: Index[int]\n    temp: Data[float]\n    humid: Data[float]\n\n\ndf = Weather.new(...)\n```\n\nwhere fields typed by `Index` are "index fields", each value of which will become an index or a part of a hierarchial index of a DataFrame object.\nFields typed by `Data` are "data fields", each value of which will become a data column of a DataFrame object.\nFields typed by other types are just ignored in DataFrame creation.\n\nEach data or index will be cast to the data type specified in the type hint like `Index[int]`.\nUse `Any` or `None` if you do not want type casting.\nSee [data typing rules](#data-typing-rules) for more examples.\n\nBy default, field name (i.e. argument name) is used for the name of data or index.\nSee [custom data/index naming](#custom-naming) if you want customization.\n\n### Series creation\n\nA dataclass that has the `AsSeries` mix-in will create Series objects:\n\n<details>\n<summary>Click to see all imports</summary>\n\n```python\nfrom dataclasses import dataclass\nfrom pandas_dataclasses import AsSeries, Data, Index\n```\n</details>\n\n```python\n@dataclass\nclass Temperature(AsSeries):\n    """Temperature information."""\n\n    year: Index[int]\n    month: Index[int]\n    temp: Data[float]\n\n\nser = Temperature.new(...)\n```\n\nUnlike `AsDataFrame`, the second and subsequent data fields are ignored in Series creation.\nOther rules are the same as for the DataFrame creation.\n\n## Advanced usage\n\n### Metadata storing\n\nFields typed by `Attr` are "attribute fields", each value of which will become an item of attributes (`attrs`) of a DataFrame of Series object:\n\n<details>\n<summary>Click to see all imports</summary>\n\n```python\nfrom dataclasses import dataclass\nfrom pandas_dataclasses import AsDataFrame, Attr, Data, Index\n```\n</details>\n\n```python\n@dataclass\nclass Weather(AsDataFrame):\n    """Weather information."""\n\n    year: Index[int]\n    month: Index[int]\n    temp: Data[float]\n    humid: Data[float]\n    loc: Attr[str] = "Tokyo"\n    lon: Attr[float] = 139.69167\n    lat: Attr[float] = 35.68944\n```\n\nIn this example, `Weather.new(...).attrs` will become like:\n\n```python\n{"loc": "Tokyo", "lon": 139.69167, "lat": 35.68944}\n```\n\n### Custom naming\n\nThe name of data, index, or attribute can be explicitly specified by adding an annotation to the corresponding type:\n\n<details>\n<summary>Click to see all imports</summary>\n\n```python\nfrom dataclasses import dataclass\nfrom typing import Annotated as Ann\nfrom pandas_dataclasses import AsDataFrame, Attr, Data, Index\n```\n</details>\n\n```python\n@dataclass\nclass Weather(AsDataFrame):\n    """Weather information."""\n\n    year: Ann[Index[int], "Year"]\n    month: Ann[Index[int], "Month"]\n    temp: Ann[Data[float], "Temperature (deg C)"]\n    humid: Ann[Data[float], "Humidity (%)"]\n    loc: Ann[Attr[str], "Location"] = "Tokyo"\n    lon: Ann[Attr[float], "Longitude (deg)"] = 139.69167\n    lat: Ann[Attr[float], "Latitude (deg)"] = 35.68944\n```\n\nIn this example, `Weather.new(...)` and its attributes will become like:\n\n```plaintext\n            Temperature (deg C)  Humidity (%)\nYear Month\n2020 1                      7.1          65.0\n     7                     24.3          89.0\n2021 1                      5.4          57.0\n     7                     25.9          83.0\n2022 1                      4.9          52.0\n```\n\n```python\n{"Location": "Tokyo", "Longitude (deg)": 139.69167, "Latitude (deg)": 35.68944}\n```\n\nFor the Series creation, a field typed by `Name` is a "name field", whose value will become the name of a Series object.\nThis is useful for dynamic naming.\nSee also [naming rules](#naming-rules) for more details and examples.\n\n### Custom pandas factory\n\nA custom class can be used as a factory of Series or DataFrame creation by `As`, the generic version of the mix-in classes:\n\n<details>\n<summary>Click to see all imports</summary>\n\n```python\nimport pandas as pd\nfrom dataclasses import dataclass\nfrom pandas_dataclasses import As, Data, Index\n```\n</details>\n\n```python\nclass CustomSeries(pd.Series):\n    """Custom pandas Series."""\n\n    pass\n\n\n@dataclass\nclass Temperature(As[CustomSeries]):\n    """Temperature information."""\n\n    year: Index[int]\n    month: Index[int]\n    temp: Data[float]\n\n\nser = Temperature.new(...)\nisinstance(ser, CustomSeries)  # True\n```\n\n## Appendix\n\n### Data typing rules\n\nThe data type (dtype) of data/index is inferred from the first `Data`/`Index` type of the corresponding field.\nThe following table shows how the data type is inferred:\n\n<details>\n<summary>Click to see all imports</summary>\n\n```python\nfrom typing import Any\nfrom typing import Annotated as Ann\nfrom typing import Literal as L\nfrom pandas_dataclasses import Data\n```\n</details>\n\nType hint | Inferred data type\n--- | ---\n`Data[Any]` | None (no type casting)\n`Data[None]` | None (no type casting)\n`Data[int]` | `numpy.dtype("i8")`\n`Data[numpy.int32]` | `numpy.dtype("i4")`\n`Data[L["datetime64[ns]"]]` | `numpy.dtype("<M8[ns]")`\n`Data[L["category"]]` | `pandas.CategoricalDtype()`\n`Data[int] \\| str` | `numpy.dtype("i8")`\n`Data[int] \\| Data[float]` | `numpy.dtype("i8")`\n`Ann[Data[int], "spam"]` | `numpy.dtype("i8")`\n`Data[Ann[int, "spam"]]` | `numpy.dtype("i8")`\n\n### Naming rules\n\nThe name of data/index is determined by the following rules:\n\n1. If a name field exists, its value will be preferentially used (Series creation only)\n1. If a data/index field is annotated, the first hashable annotation in the first `Data`/`Index` type will be used\n1. Otherwise, the field name (i.e. argument name) will be used\n\nThe following table shows how the name is inferred in the case of 2 and 3:\n\n<details>\n<summary>Click to see all imports</summary>\n\n```python\nfrom typing import Any\nfrom typing import Annotated as Ann\nfrom pandas_dataclasses import Data\n```\n</details>\n\nType hint | Inferred name\n--- | ---\n`Data[Any]` | (field name)\n`Ann[Data[Any], {}]` | (field name)\n`Ann[Data[Any], "spam"]` | `"spam"`\n`Ann[Data[Any], "spam"]` | `"spam"`\n`Ann[Data[Any], "spam", "ham"]` | `"spam"`\n`Ann[Data[Any], {}, "spam"]` | `"spam"`\n`Ann[Data[Any], "spam"] \\| Ann[str, "ham"]` | `"spam"`\n`Ann[Data[Any], "spam"] \\| Ann[Data[float], "ham"]` | `"spam"`\n\n### Development roadmap\n\nRelease version | Features\n--- | ---\nv0.4.0 | Support for hierarchial column\nv1.0.0 | Initial major release (freezing public features until v2.0.0)\n\n<!-- References -->\n[dataclass]: https://docs.python.org/3/library/dataclasses.html\n[NumPy]: https://numpy.org\n[pandas]: https://pandas.pydata.org\n[Pylance]: https://github.com/microsoft/pylance-release\n[Pyright]: https://github.com/microsoft/pyright\n',
    'author': 'Akio Taniguchi',
    'author_email': 'taniguchi@a.phys.nagoya-u.ac.jp',
    'maintainer': None,
    'maintainer_email': None,
    'url': 'https://github.com/astropenguin/pandas-dataclasses/',
    'packages': packages,
    'package_data': package_data,
    'install_requires': install_requires,
    'extras_require': extras_require,
    'python_requires': '>=3.7.1,<3.11',
}


setup(**setup_kwargs)
