smartsheet-pydantic


Namesmartsheet-pydantic JSON
Version 1.4.5 PyPI version JSON
download
home_page
SummarySmartsheet Python SDK and Pydantic Wrapper
upload_time2023-05-04 20:19:45
maintainer
docs_urlNone
authorTakahiro Watanabe
requires_python>=3.10
licenseThe MIT License (MIT) Copyright © 2023 <copyright holders> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
keywords smartsheet pydantic
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # smartsheet-pydantic
## What is it?
Smartsheet Python SDK wrapper, incorporating Pydantic models for type validation to guarantee successful data read/updates into Smartsheet.

Smartsheet API requires the incoming data to comply with Smartsheet column types. When the types do not align then the write call can fail. In order streamline the data validation this package piggybacks off the Pydantic BaseModel structure and their data validation capabilities as a "SmartModel".

This package also provides frameworks to create a "DataSource" class which you can declaratively define your data source and attach it to the SmartModel, so you can have a standard method of querying your datasource and create/update into Smartsheet.

---

# Getting Started

## Install & Import The Module
__requires python greater than 3.10__
Standard installation using pip install, and package import.
```
pip install smartsheet-pydantic
```
```python
# The package name uses underscore "_" instead of hyphen
import smartsheet_pydantic
```

---


## Everything revolves around the __Controller__

__smartsheet_pydantic__ package's function revolves around the __Controller__. Once a Controller is setup, it can facilitate data extraction from the user designated data source (RESTful API or PostgreSQL) and refresh the designated Smartsheet using an additive approach (data is updated or added, but never deleted). The __Controller__ can also facilitate writing into the Smartsheet.

During both the write, read, or update of the Smartsheet the __smartsheet_pydantic__ as the name suggest uses __Pydantic__'s BaseModel to validate the data. This ensures the data has the write data type and will not fail to write to the given Smartsheet.



## Defining the Controller

In order to generate the Controller we will use the __SheetDetail__ class to collect the necessary details.

1. __sheet_id__: Every Smartsheet grid has a unique id, this is used to target the Smartsheet.
2. __description__: User defined description of the target Smartsheet to give some context. Can be anything.
3. __smart_model__: A __smartsheet-pydantic__ model we will create to aid in data validation (Extension of Pydantic BaseModel).
4. __source__: default None. This field is used to override a Smartmodels default DataSource for unit testing purposes. Omit for normal use.

```python
from smartsheet_pydantic.controller import SheetDetail
from smartsheet_pydantic.smartmodels import SmartModel
from smartsheet_pydantic.sources import DataSource


sheet_detail = SheetDetail(
    sheet_id: int = 0123456789
    description: str = "Description of the target Smartsheet"
    smart_model: SmartModel = WeatherModel # we will create this in the subsequent steps
)
```

---
## Defining a DataSource
There are options when creating a data source. One is a RESTful API endpoint, where the you can extend the __DataSourceAPI__ class, and provide a __url__ attribute. The other is a PostgreSQL database source using __DataSourcePostgres__, where you can provide the access details as well as the query to use, and the column name designations. We will use the latter in this example.

```python
from smartsheet_pydantic.sources import DataSourceAPI, DataSourcePostgres


# DataSource class to call a RESTful API endpoint.
class WeatherRestAPI(DataSourceAPI):
    url = 'http://127.0.0.1:8000/weather_data'


# DataSource class for PostgreSQL database
class ExamplePostgres(DataSourcePostgres):
    user: str          = "username"
    password: str      = "password"
    host: str          = "host name"
    database: str      = "database name"
    query: str         = 'SELECT * FROM weather_table WHERE location = "USA"'
    columns: list[str] = [ "index", "date", "temperature", "humidity", "rain" ]
```

---


## Defining a SmartModel
A __SmartModel__ class is an extension of Pydantic BaseModel. Therefore the definition of a __SmartModel__ is very similar. Define the data fields and their type as a class attribute.

You will also need to define 2 additional Configuration parameters.
1. __source__: this is the DataSource class you defined in the previous step which is associated with this SmartModel.
1. __unique_key__: is a list of column names which the model will use to define uniqueness. When data in Smartsheet is updated these columns will be used to find and update the data if the data already exists.
2. __key_mapping__: if you have defined the data field names that differs from the source data, then this dictionary can be used to map and rename those columns. If the data field names are the same, the value must be set to None.

```python
from smartsheet_pydantic.smartmodels import SmartModel
from datetime import date


class WeatherModel(SmartModel):

    index: int
    date: date
    temperature: float
    humidity: float
    rain: bool

    class Configuration
        source = WeatherRestAPI
        unique_columns: list[int] = ['index']
        key_mapping: dict = None
```

---

## Generating the controller
Now that all of the components are ready we will now take the __SheetDetail__ instance, and provide it to the __SmartsheetControllerFactory__ class to generate a __ControllerFactory__. By calling on the __.get_controller()__ method we can generate the __SmarsheetController__ object.

```python
from smartsheet_pydantic.controller import SmartsheetController, SmartsheetControllerFactory

controller_factory = SmartsheetControllerFactory()
controller: SmartsheetController = controller_factory.get_controller(sheet_detail)
```

---

## Using the controller

### Use the provided data source to refresh the target Smartsheet
```python
controller.refresh_smartsheet_from_source()
```

### Extracting data from Smartsheet into a list of SmartModel instances.
```python
data: list[WeatherData] = controller.extract_as_smartmodel()
```

### Manually write new data, or update existing data to Smartsheet
```python
data: list[WeatherData]
controller.update_rows(data)
```


### Delete all row data from Smartsheet
```python
controller.delete_all_rows()
```

---

# SmartModel
Not all data can be handled within the SmartModel. You may want to manipulate the data using Pandas or Numpy. Therefore SmartModel has methods to aid in the transforming of data into a SmartModel, as well as extracting data out into a dictionary.
## Extracting Data From SmartModel
```python
weather_data: list[WeatherData]
extracted_data: list[dict] = [smart_model.dict() for smart_model in weather_data]

print(extracted_data)
```
#### Results
```python
[
    {
        'index': 1
        'date': date(2023, 1, 1)
        'temperature': 65.2
        'humidity': 14.5
        'rain': False
    },
    {
        'index': 2
        'date': date(2023, 1, 2)
        'temperature': 67.2
        'humidity': 14.2
        'rain': False
    },
    {
        'index': 1
        'date': date(2023, 1, 3)
        'temperature': 62.3
        'humidity': 12.2
        'rain': False
    },
]

```

## Converting Data Into SmartModel
```python
extracted_data: list[dict]

weather_data: list[WeatherData] = \
    [WeatherData.from_source(data) for data in extracted_data]
```

            

Raw data

            {
    "_id": null,
    "home_page": "",
    "name": "smartsheet-pydantic",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.10",
    "maintainer_email": "",
    "keywords": "smartsheet,pydantic",
    "author": "Takahiro Watanabe",
    "author_email": "",
    "download_url": "https://files.pythonhosted.org/packages/ea/d5/44a23a4346cfce2bbc77b957a6f062e11e32f287fe416b6c0b29bb923959/smartsheet-pydantic-1.4.5.tar.gz",
    "platform": null,
    "description": "# smartsheet-pydantic\n## What is it?\nSmartsheet Python SDK wrapper, incorporating Pydantic models for type validation to guarantee successful data read/updates into Smartsheet.\n\nSmartsheet API requires the incoming data to comply with Smartsheet column types. When the types do not align then the write call can fail. In order streamline the data validation this package piggybacks off the Pydantic BaseModel structure and their data validation capabilities as a \"SmartModel\".\n\nThis package also provides frameworks to create a \"DataSource\" class which you can declaratively define your data source and attach it to the SmartModel, so you can have a standard method of querying your datasource and create/update into Smartsheet.\n\n---\n\n# Getting Started\n\n## Install & Import The Module\n__requires python greater than 3.10__\nStandard installation using pip install, and package import.\n```\npip install smartsheet-pydantic\n```\n```python\n# The package name uses underscore \"_\" instead of hyphen\nimport smartsheet_pydantic\n```\n\n---\n\n\n## Everything revolves around the __Controller__\n\n__smartsheet_pydantic__ package's function revolves around the __Controller__. Once a Controller is setup, it can facilitate data extraction from the user designated data source (RESTful API or PostgreSQL) and refresh the designated Smartsheet using an additive approach (data is updated or added, but never deleted). The __Controller__ can also facilitate writing into the Smartsheet.\n\nDuring both the write, read, or update of the Smartsheet the __smartsheet_pydantic__ as the name suggest uses __Pydantic__'s BaseModel to validate the data. This ensures the data has the write data type and will not fail to write to the given Smartsheet.\n\n\n\n## Defining the Controller\n\nIn order to generate the Controller we will use the __SheetDetail__ class to collect the necessary details.\n\n1. __sheet_id__: Every Smartsheet grid has a unique id, this is used to target the Smartsheet.\n2. __description__: User defined description of the target Smartsheet to give some context. Can be anything.\n3. __smart_model__: A __smartsheet-pydantic__ model we will create to aid in data validation (Extension of Pydantic BaseModel).\n4. __source__: default None. This field is used to override a Smartmodels default DataSource for unit testing purposes. Omit for normal use.\n\n```python\nfrom smartsheet_pydantic.controller import SheetDetail\nfrom smartsheet_pydantic.smartmodels import SmartModel\nfrom smartsheet_pydantic.sources import DataSource\n\n\nsheet_detail = SheetDetail(\n    sheet_id: int = 0123456789\n    description: str = \"Description of the target Smartsheet\"\n    smart_model: SmartModel = WeatherModel # we will create this in the subsequent steps\n)\n```\n\n---\n## Defining a DataSource\nThere are options when creating a data source. One is a RESTful API endpoint, where the you can extend the __DataSourceAPI__ class, and provide a __url__ attribute. The other is a PostgreSQL database source using __DataSourcePostgres__, where you can provide the access details as well as the query to use, and the column name designations. We will use the latter in this example.\n\n```python\nfrom smartsheet_pydantic.sources import DataSourceAPI, DataSourcePostgres\n\n\n# DataSource class to call a RESTful API endpoint.\nclass WeatherRestAPI(DataSourceAPI):\n    url = 'http://127.0.0.1:8000/weather_data'\n\n\n# DataSource class for PostgreSQL database\nclass ExamplePostgres(DataSourcePostgres):\n    user: str          = \"username\"\n    password: str      = \"password\"\n    host: str          = \"host name\"\n    database: str      = \"database name\"\n    query: str         = 'SELECT * FROM weather_table WHERE location = \"USA\"'\n    columns: list[str] = [ \"index\", \"date\", \"temperature\", \"humidity\", \"rain\" ]\n```\n\n---\n\n\n## Defining a SmartModel\nA __SmartModel__ class is an extension of Pydantic BaseModel. Therefore the definition of a __SmartModel__ is very similar. Define the data fields and their type as a class attribute.\n\nYou will also need to define 2 additional Configuration parameters.\n1. __source__: this is the DataSource class you defined in the previous step which is associated with this SmartModel.\n1. __unique_key__: is a list of column names which the model will use to define uniqueness. When data in Smartsheet is updated these columns will be used to find and update the data if the data already exists.\n2. __key_mapping__: if you have defined the data field names that differs from the source data, then this dictionary can be used to map and rename those columns. If the data field names are the same, the value must be set to None.\n\n```python\nfrom smartsheet_pydantic.smartmodels import SmartModel\nfrom datetime import date\n\n\nclass WeatherModel(SmartModel):\n\n    index: int\n    date: date\n    temperature: float\n    humidity: float\n    rain: bool\n\n    class Configuration\n        source = WeatherRestAPI\n        unique_columns: list[int] = ['index']\n        key_mapping: dict = None\n```\n\n---\n\n## Generating the controller\nNow that all of the components are ready we will now take the __SheetDetail__ instance, and provide it to the __SmartsheetControllerFactory__ class to generate a __ControllerFactory__. By calling on the __.get_controller()__ method we can generate the __SmarsheetController__ object.\n\n```python\nfrom smartsheet_pydantic.controller import SmartsheetController, SmartsheetControllerFactory\n\ncontroller_factory = SmartsheetControllerFactory()\ncontroller: SmartsheetController = controller_factory.get_controller(sheet_detail)\n```\n\n---\n\n## Using the controller\n\n### Use the provided data source to refresh the target Smartsheet\n```python\ncontroller.refresh_smartsheet_from_source()\n```\n\n### Extracting data from Smartsheet into a list of SmartModel instances.\n```python\ndata: list[WeatherData] = controller.extract_as_smartmodel()\n```\n\n### Manually write new data, or update existing data to Smartsheet\n```python\ndata: list[WeatherData]\ncontroller.update_rows(data)\n```\n\n\n### Delete all row data from Smartsheet\n```python\ncontroller.delete_all_rows()\n```\n\n---\n\n# SmartModel\nNot all data can be handled within the SmartModel. You may want to manipulate the data using Pandas or Numpy. Therefore SmartModel has methods to aid in the transforming of data into a SmartModel, as well as extracting data out into a dictionary.\n## Extracting Data From SmartModel\n```python\nweather_data: list[WeatherData]\nextracted_data: list[dict] = [smart_model.dict() for smart_model in weather_data]\n\nprint(extracted_data)\n```\n#### Results\n```python\n[\n    {\n        'index': 1\n        'date': date(2023, 1, 1)\n        'temperature': 65.2\n        'humidity': 14.5\n        'rain': False\n    },\n    {\n        'index': 2\n        'date': date(2023, 1, 2)\n        'temperature': 67.2\n        'humidity': 14.2\n        'rain': False\n    },\n    {\n        'index': 1\n        'date': date(2023, 1, 3)\n        'temperature': 62.3\n        'humidity': 12.2\n        'rain': False\n    },\n]\n\n```\n\n## Converting Data Into SmartModel\n```python\nextracted_data: list[dict]\n\nweather_data: list[WeatherData] = \\\n    [WeatherData.from_source(data) for data in extracted_data]\n```\n",
    "bugtrack_url": null,
    "license": "The MIT License (MIT) Copyright \u00a9 2023 <copyright holders>  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \u201cSoftware\u201d), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.  THE SOFTWARE IS PROVIDED \u201cAS IS\u201d, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.",
    "summary": "Smartsheet Python SDK and Pydantic Wrapper",
    "version": "1.4.5",
    "project_urls": {
        "Homepage": "https://github.com/oneTakeda/smartsheet-pydantic"
    },
    "split_keywords": [
        "smartsheet",
        "pydantic"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "d8997d86af4dc59dbeb5abc5cce319c0dcc2a2f6313690309bb97dc40a746a79",
                "md5": "a67832aa74b991f5c4e095921990e9e1",
                "sha256": "9dac54423cc3be5d18ebe684f040fb08246b8b3af8e4bc145e80d47c975a0f17"
            },
            "downloads": -1,
            "filename": "smartsheet_pydantic-1.4.5-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "a67832aa74b991f5c4e095921990e9e1",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.10",
            "size": 13617,
            "upload_time": "2023-05-04T20:19:37",
            "upload_time_iso_8601": "2023-05-04T20:19:37.555540Z",
            "url": "https://files.pythonhosted.org/packages/d8/99/7d86af4dc59dbeb5abc5cce319c0dcc2a2f6313690309bb97dc40a746a79/smartsheet_pydantic-1.4.5-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "ead544a23a4346cfce2bbc77b957a6f062e11e32f287fe416b6c0b29bb923959",
                "md5": "300c59dc9a21c287ce4c94b6a77877fc",
                "sha256": "d54e589fe165d40e347288dde405323df7b39e37be86cde79ca41fe64029711b"
            },
            "downloads": -1,
            "filename": "smartsheet-pydantic-1.4.5.tar.gz",
            "has_sig": false,
            "md5_digest": "300c59dc9a21c287ce4c94b6a77877fc",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.10",
            "size": 18247,
            "upload_time": "2023-05-04T20:19:45",
            "upload_time_iso_8601": "2023-05-04T20:19:45.354382Z",
            "url": "https://files.pythonhosted.org/packages/ea/d5/44a23a4346cfce2bbc77b957a6f062e11e32f287fe416b6c0b29bb923959/smartsheet-pydantic-1.4.5.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-05-04 20:19:45",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "oneTakeda",
    "github_project": "smartsheet-pydantic",
    "github_not_found": true,
    "lcname": "smartsheet-pydantic"
}
        
Elapsed time: 0.20224s