CentralizedAppraiser


NameCentralizedAppraiser JSON
Version 0.0.9 PyPI version JSON
download
home_pageNone
SummaryA centralized method of accessing appraiser data, using each counties local property appraiser's data.
upload_time2024-09-05 05:09:09
maintainerNone
docs_urlNone
authorNone
requires_python>=3.8
licenseMIT License Copyright (c) 2024 Reed Graff 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 real estate appraiser property data centralized api
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # CentralizedAppraiser
A new form of accessing real estate data because nobody wants to pay >$80,000 for Regrid and still not have access to up to date information.

TRY IT WITH ANY ADDRESS IN MIAMIDADE/BROWARD COUNTY.



## Installation
```bash
pip install CentralizedAppraiser
```






## This may be used in unison with regrid, however, it is distinguished in a few ways:
* It dynamically accesses property appraiser data (meaning it is always up to date)
* It enables you to access all the additional county specific data
* It enables you to interact with the county website (for example, to screenshot the property appraiser website)
* It is free
* It is open source (please contribute)








## Below are the steps explaining how this library works:
1. Create a client of a map provider (for example, google maps, regrid, apple maps, etc.)
2. Geocode the address and get the address components (no matter what client you use CentralizedAppraiser will ensure the address components are standardized)
3. Determine the county which the address is in
4. Determine the folio if not provided
5. Request the data from the county (this is similarly standardized so that all municipalities/cities can be accessed in the same way)







## Usage Examples
Using the Google Maps client, get the appraiser info for an address given the Google Place ID. Also refer to the examples directory for more examples in the github repository.

#### Regrid Client
This is a simple implementation which when given an address, it will return the appraiser information.
```python
import CentralizedAppraiser
from CentralizedAppraiser.clients import RegridClient

client = RegridClient("YOUR_REGRID_API_KEY")
addressInfo, errorHandler = client.getByAddress("6760 SW 48TH ST")
appraiserInfo, errorHandler = CentralizedAppraiser.appraiserInfoByAddressInfo(addressInfo, client)

print(appraiserInfo.get())
```

This is a more complex implementation which accomplishes the same thing as the above code, however it is more verbose and shows each step of the process.
```python
import CentralizedAppraiser
from CentralizedAppraiser.clients import RegridClient

client = RegridClient("YOUR_REGRID_API_KEY") # API KEY
addressInfo, errorHandler = client.getByAddress("6760 SW 48TH ST")
classPointer, errorHandler = CentralizedAppraiser.classByAddressInfo(addressInfo)
data, errorHandler = addressInfo.get()
# folio, errorHandler = classPointer.folioByAddressInfo(addressInfo) # commented out because Regrid already provides the folio
appraiserInfo, errorHandler = classPointer.appraiserInfoByFolio(data["folio"], client)

print(appraiserInfo.get())
```

#### Google Client
This is a simple implementation which when given an address, it will return the appraiser information.
```python
import CentralizedAppraiser
from CentralizedAppraiser.clients import GoogleClient

client = GoogleClient("YOUR_GOOGLE_API_KEY")
addressInfo, errorHandler = client.getByAddress("6760 SW 48TH ST")
appraiserInfo, errorHandler = CentralizedAppraiser.appraiserInfoByAddressInfo(addressInfo, client)

print(appraiserInfo.get())
```

This is a more complex implementation which accomplishes the same thing as the above code, however it is more verbose and shows each step of the process.
```python
import CentralizedAppraiser
from CentralizedAppraiser.clients import GoogleClient

client = GoogleClient("YOUR_GOOGLE_API_KEY") # API KEY
addressInfo, errorHandler = client.getByAddress("6760 SW 48TH ST")
classPointer, errorHandler = CentralizedAppraiser.classByAddressInfo(addressInfo)
folio, errorHandler = classPointer.folioByAddressInfo(addressInfo)
appraiserInfo, errorHandler = classPointer.appraiserInfoByFolio(folio, client)

print(appraiserInfo.get())
```






## Functions

#### CentralizedAppraiser
* `appraiserInfoByAddressInfo(addressInfo:AddressInfo, client:Client) -> set[AppraiserInfo, dict]`
    * Returns the appraiser info by the address info
* `classByAddressInfo(addressInfo:AddressInfo) -> set[Country, dict]`
    * Returns the class pointer by the address info
* `classByPath(path:list) -> set[Country, dict]`
    * Returns the class pointer by the path to the county website
* `pathByAddressInfo(addressInfo:AddressInfo) -> set[list, dict]`
    * Returns the path to the county website as a list of strings

#### AddressSchematic (extended by AddressInfo, and AppraiserInfo)
* `__init__(self, data:dict, client, translateStrategy) -> None`
    * Initializes the AddressSchematic object
* `get(self) -> set[dict, dict]`
    * Returns the standardized address components and the error handler

#### Client (extended by GoogleClient, and RegridClient)
* `__init__(self, key:str="") -> None`
    * Initializes the client object with an api key
* `getByAddress(self, location:str) -> set[AddressInfo, dict]`
    * Returns the address info by the location as a string
* `getByID(self, placeID:str) -> set[AddressInfo, dict]`
    * Returns the address info by the place id as a string
* `__translate(cls, data: dict) -> dict`
    * Translates the data to the standardized format from the client's format

#### Country (*extended by all other locations)
* `def getDefiningGeometryKey(cls) -> str:`
    * Returns the key for the geometry json parameters
* `def folioByAddressInfo(cls, search:AddressInfo) -> set[str, dict]:`
    * Returns the folio by the address info
* `def appraiserInfoByFolio(cls, folio:str, client:Client) -> set[AppraiserInfo, dict]:`
    * Returns the appraiser info by the folio
* `def appraiserInfoByAddressInfo(cls, search:AddressInfo, client:Client) -> set[AppraiserInfo, dict]:`
    * Returns the appraiser info by the address info. This just implements the folioByAddressInfo and appraiserInfoByFolio functions
* `def getScreenshotByFolio(cls, folio:str) -> set[bool, dict]:`
    * Returns the screenshot of the property appraiser website by the folio with selenium



## Schemas
The following are various schemas used by different parts of the program. These schemas are used to ensure that the data is standardized and that the data is correct. The schemas are written with the [schema](https://pypi.org/project/schema/) library.

#### AddressInfo Schema
```python
Schema({
    "formattedAddress": And(str, len),
    "folio": Or(None, And(str, Use(len))),
    "addressComponents": {
        "streetNumber": str,
        "street": str,
        "streetDirection": str,
        "city": str,
        "county": str,
        "state": And(str, len),
        "country": And(str, len),
        "zip": And(str, len)
    },
    "geo": {
        "lat": And(Use(float), lambda n: -90 <= n <= 90),
        "lng": And(Use(float), lambda n: -180 <= n <= 180)
    }
})
```

#### AppraiserInfo Schema
```python
Schema({
    "assessments": [
        {
            "assessedValue": And(int, lambda n: n >= 0),
            
            "buildingValue": And(int, lambda n: n >= 0),
            "landValue": And(int, lambda n: n >= 0),
            "totalValue": And(int, lambda n: n >= 0),
            "year": int
        },
    ],
    "propertyInfo": {
        "folio": And(str, len),
        "parentFolio": str,
        "legal": str,
        "use": int,
        "subdivision": str,
        "blk": int,
        "lot": int,
        "plat": {
            "book": int,
            "page": int
        },
        "lotSize": Or(None, int, float),
        "otherRecords": [
            {
                "type": str,
                "book": int,
                "page": int
            }
        ]
    },
    "owners": [
        {
            "name": And(str, len),
            # "type": str, Should be used for sole proprietorship, partnership, LLC, etc
            "mailingAddresses": [
                {
                    "formattedAddress": And(str, len),
                    'folio': Or(None, And(str, Use(len))),
                    "addressComponents": {
                        "streetNumber": str,
                        "street": str,
                        "streetDirection": str,
                        "city": str,
                        "county": str,
                        "state": And(str, len),
                        "country": And(str, len),
                        "zip": And(str, len)
                    },
                    "geo": {
                        "lat": And(Use(float), lambda n: -90 <= n <= 90),
                        "lng": And(Use(float), lambda n: -180 <= n <= 180)
                    }
                }
            ]
        }
    ],
    Optional("unStructured"): dict
})
```

#### Error Schema
```python
Schema({
    "status": Or("error", "success"), # "error" or "success"
    "message": str,
})
```





<!--
Notes for the author because he doesn't know what he's doing:

## Beginning:
```bash
python -m pip install --upgrade pip
python -m pip --version

python -m venv <myenvname>
venv\Scripts\Activate.ps1
pip install -r requirements.txt
```

## process to update pip:
```bash
pip freeze > requirements.txt 
# add this to the toml
# clear dist folder

python -m build
python -m twine upload --repository testpypi dist/*
```
View the package on testpypi: https://test.pypi.org/project/CentralizedAppraiser/

-->

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "CentralizedAppraiser",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": null,
    "keywords": "real estate, appraiser, property, data, centralized, api",
    "author": null,
    "author_email": "\"Reed Graff (Compliancy)\" <reed@withcompliancy.com>",
    "download_url": "https://files.pythonhosted.org/packages/25/d8/5ee5c597dc3f0fda5e1e56f8eabd38134c41b2817b62996995f670545948/centralizedappraiser-0.0.9.tar.gz",
    "platform": null,
    "description": "# CentralizedAppraiser\nA new form of accessing real estate data because nobody wants to pay >$80,000 for Regrid and still not have access to up to date information.\n\nTRY IT WITH ANY ADDRESS IN MIAMIDADE/BROWARD COUNTY.\n\n\n\n## Installation\n```bash\npip install CentralizedAppraiser\n```\n\n\n\n\n\n\n## This may be used in unison with regrid, however, it is distinguished in a few ways:\n* It dynamically accesses property appraiser data (meaning it is always up to date)\n* It enables you to access all the additional county specific data\n* It enables you to interact with the county website (for example, to screenshot the property appraiser website)\n* It is free\n* It is open source (please contribute)\n\n\n\n\n\n\n\n\n## Below are the steps explaining how this library works:\n1. Create a client of a map provider (for example, google maps, regrid, apple maps, etc.)\n2. Geocode the address and get the address components (no matter what client you use CentralizedAppraiser will ensure the address components are standardized)\n3. Determine the county which the address is in\n4. Determine the folio if not provided\n5. Request the data from the county (this is similarly standardized so that all municipalities/cities can be accessed in the same way)\n\n\n\n\n\n\n\n## Usage Examples\nUsing the Google Maps client, get the appraiser info for an address given the Google Place ID. Also refer to the examples directory for more examples in the github repository.\n\n#### Regrid Client\nThis is a simple implementation which when given an address, it will return the appraiser information.\n```python\nimport CentralizedAppraiser\nfrom CentralizedAppraiser.clients import RegridClient\n\nclient = RegridClient(\"YOUR_REGRID_API_KEY\")\naddressInfo, errorHandler = client.getByAddress(\"6760 SW 48TH ST\")\nappraiserInfo, errorHandler = CentralizedAppraiser.appraiserInfoByAddressInfo(addressInfo, client)\n\nprint(appraiserInfo.get())\n```\n\nThis is a more complex implementation which accomplishes the same thing as the above code, however it is more verbose and shows each step of the process.\n```python\nimport CentralizedAppraiser\nfrom CentralizedAppraiser.clients import RegridClient\n\nclient = RegridClient(\"YOUR_REGRID_API_KEY\") # API KEY\naddressInfo, errorHandler = client.getByAddress(\"6760 SW 48TH ST\")\nclassPointer, errorHandler = CentralizedAppraiser.classByAddressInfo(addressInfo)\ndata, errorHandler = addressInfo.get()\n# folio, errorHandler = classPointer.folioByAddressInfo(addressInfo) # commented out because Regrid already provides the folio\nappraiserInfo, errorHandler = classPointer.appraiserInfoByFolio(data[\"folio\"], client)\n\nprint(appraiserInfo.get())\n```\n\n#### Google Client\nThis is a simple implementation which when given an address, it will return the appraiser information.\n```python\nimport CentralizedAppraiser\nfrom CentralizedAppraiser.clients import GoogleClient\n\nclient = GoogleClient(\"YOUR_GOOGLE_API_KEY\")\naddressInfo, errorHandler = client.getByAddress(\"6760 SW 48TH ST\")\nappraiserInfo, errorHandler = CentralizedAppraiser.appraiserInfoByAddressInfo(addressInfo, client)\n\nprint(appraiserInfo.get())\n```\n\nThis is a more complex implementation which accomplishes the same thing as the above code, however it is more verbose and shows each step of the process.\n```python\nimport CentralizedAppraiser\nfrom CentralizedAppraiser.clients import GoogleClient\n\nclient = GoogleClient(\"YOUR_GOOGLE_API_KEY\") # API KEY\naddressInfo, errorHandler = client.getByAddress(\"6760 SW 48TH ST\")\nclassPointer, errorHandler = CentralizedAppraiser.classByAddressInfo(addressInfo)\nfolio, errorHandler = classPointer.folioByAddressInfo(addressInfo)\nappraiserInfo, errorHandler = classPointer.appraiserInfoByFolio(folio, client)\n\nprint(appraiserInfo.get())\n```\n\n\n\n\n\n\n## Functions\n\n#### CentralizedAppraiser\n* `appraiserInfoByAddressInfo(addressInfo:AddressInfo, client:Client) -> set[AppraiserInfo, dict]`\n    * Returns the appraiser info by the address info\n* `classByAddressInfo(addressInfo:AddressInfo) -> set[Country, dict]`\n    * Returns the class pointer by the address info\n* `classByPath(path:list) -> set[Country, dict]`\n    * Returns the class pointer by the path to the county website\n* `pathByAddressInfo(addressInfo:AddressInfo) -> set[list, dict]`\n    * Returns the path to the county website as a list of strings\n\n#### AddressSchematic (extended by AddressInfo, and AppraiserInfo)\n* `__init__(self, data:dict, client, translateStrategy) -> None`\n    * Initializes the AddressSchematic object\n* `get(self) -> set[dict, dict]`\n    * Returns the standardized address components and the error handler\n\n#### Client (extended by GoogleClient, and RegridClient)\n* `__init__(self, key:str=\"\") -> None`\n    * Initializes the client object with an api key\n* `getByAddress(self, location:str) -> set[AddressInfo, dict]`\n    * Returns the address info by the location as a string\n* `getByID(self, placeID:str) -> set[AddressInfo, dict]`\n    * Returns the address info by the place id as a string\n* `__translate(cls, data: dict) -> dict`\n    * Translates the data to the standardized format from the client's format\n\n#### Country (*extended by all other locations)\n* `def getDefiningGeometryKey(cls) -> str:`\n    * Returns the key for the geometry json parameters\n* `def folioByAddressInfo(cls, search:AddressInfo) -> set[str, dict]:`\n    * Returns the folio by the address info\n* `def appraiserInfoByFolio(cls, folio:str, client:Client) -> set[AppraiserInfo, dict]:`\n    * Returns the appraiser info by the folio\n* `def appraiserInfoByAddressInfo(cls, search:AddressInfo, client:Client) -> set[AppraiserInfo, dict]:`\n    * Returns the appraiser info by the address info. This just implements the folioByAddressInfo and appraiserInfoByFolio functions\n* `def getScreenshotByFolio(cls, folio:str) -> set[bool, dict]:`\n    * Returns the screenshot of the property appraiser website by the folio with selenium\n\n\n\n## Schemas\nThe following are various schemas used by different parts of the program. These schemas are used to ensure that the data is standardized and that the data is correct. The schemas are written with the [schema](https://pypi.org/project/schema/) library.\n\n#### AddressInfo Schema\n```python\nSchema({\n    \"formattedAddress\": And(str, len),\n    \"folio\": Or(None, And(str, Use(len))),\n    \"addressComponents\": {\n        \"streetNumber\": str,\n        \"street\": str,\n        \"streetDirection\": str,\n        \"city\": str,\n        \"county\": str,\n        \"state\": And(str, len),\n        \"country\": And(str, len),\n        \"zip\": And(str, len)\n    },\n    \"geo\": {\n        \"lat\": And(Use(float), lambda n: -90 <= n <= 90),\n        \"lng\": And(Use(float), lambda n: -180 <= n <= 180)\n    }\n})\n```\n\n#### AppraiserInfo Schema\n```python\nSchema({\n    \"assessments\": [\n        {\n            \"assessedValue\": And(int, lambda n: n >= 0),\n            \n            \"buildingValue\": And(int, lambda n: n >= 0),\n            \"landValue\": And(int, lambda n: n >= 0),\n            \"totalValue\": And(int, lambda n: n >= 0),\n            \"year\": int\n        },\n    ],\n    \"propertyInfo\": {\n        \"folio\": And(str, len),\n        \"parentFolio\": str,\n        \"legal\": str,\n        \"use\": int,\n        \"subdivision\": str,\n        \"blk\": int,\n        \"lot\": int,\n        \"plat\": {\n            \"book\": int,\n            \"page\": int\n        },\n        \"lotSize\": Or(None, int, float),\n        \"otherRecords\": [\n            {\n                \"type\": str,\n                \"book\": int,\n                \"page\": int\n            }\n        ]\n    },\n    \"owners\": [\n        {\n            \"name\": And(str, len),\n            # \"type\": str, Should be used for sole proprietorship, partnership, LLC, etc\n            \"mailingAddresses\": [\n                {\n                    \"formattedAddress\": And(str, len),\n                    'folio': Or(None, And(str, Use(len))),\n                    \"addressComponents\": {\n                        \"streetNumber\": str,\n                        \"street\": str,\n                        \"streetDirection\": str,\n                        \"city\": str,\n                        \"county\": str,\n                        \"state\": And(str, len),\n                        \"country\": And(str, len),\n                        \"zip\": And(str, len)\n                    },\n                    \"geo\": {\n                        \"lat\": And(Use(float), lambda n: -90 <= n <= 90),\n                        \"lng\": And(Use(float), lambda n: -180 <= n <= 180)\n                    }\n                }\n            ]\n        }\n    ],\n    Optional(\"unStructured\"): dict\n})\n```\n\n#### Error Schema\n```python\nSchema({\n    \"status\": Or(\"error\", \"success\"), # \"error\" or \"success\"\n    \"message\": str,\n})\n```\n\n\n\n\n\n<!--\nNotes for the author because he doesn't know what he's doing:\n\n## Beginning:\n```bash\npython -m pip install --upgrade pip\npython -m pip --version\n\npython -m venv <myenvname>\nvenv\\Scripts\\Activate.ps1\npip install -r requirements.txt\n```\n\n## process to update pip:\n```bash\npip freeze > requirements.txt \n# add this to the toml\n# clear dist folder\n\npython -m build\npython -m twine upload --repository testpypi dist/*\n```\nView the package on testpypi: https://test.pypi.org/project/CentralizedAppraiser/\n\n-->\n",
    "bugtrack_url": null,
    "license": "MIT License  Copyright (c) 2024 Reed Graff  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. ",
    "summary": "A centralized method of accessing appraiser data, using each counties local property appraiser's data.",
    "version": "0.0.9",
    "project_urls": {
        "Homepage": "https://github.com/ReedGraff/CentralizedAppraiser",
        "Issues": "https://github.com/ReedGraff/CentralizedAppraiser/issues"
    },
    "split_keywords": [
        "real estate",
        " appraiser",
        " property",
        " data",
        " centralized",
        " api"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "72684883360f3fbcd02ca3d23253bbd65955e6f011dd6f826cc73e7eb3dd4568",
                "md5": "dc4c071be5182c493f9a5eebf336080f",
                "sha256": "7e297c5c458310e6f431d3ae16589fdc48e168c8b03624ae7443216cb5543fb3"
            },
            "downloads": -1,
            "filename": "CentralizedAppraiser-0.0.9-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "dc4c071be5182c493f9a5eebf336080f",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 21780391,
            "upload_time": "2024-09-05T05:09:07",
            "upload_time_iso_8601": "2024-09-05T05:09:07.252582Z",
            "url": "https://files.pythonhosted.org/packages/72/68/4883360f3fbcd02ca3d23253bbd65955e6f011dd6f826cc73e7eb3dd4568/CentralizedAppraiser-0.0.9-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "25d85ee5c597dc3f0fda5e1e56f8eabd38134c41b2817b62996995f670545948",
                "md5": "b41145baa5f352c4462cf0ee968b9c0c",
                "sha256": "f10a74c1da0a888557e0eca9bbcc3af9815282eee9c693e979030521008b6036"
            },
            "downloads": -1,
            "filename": "centralizedappraiser-0.0.9.tar.gz",
            "has_sig": false,
            "md5_digest": "b41145baa5f352c4462cf0ee968b9c0c",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 21658411,
            "upload_time": "2024-09-05T05:09:09",
            "upload_time_iso_8601": "2024-09-05T05:09:09.602891Z",
            "url": "https://files.pythonhosted.org/packages/25/d8/5ee5c597dc3f0fda5e1e56f8eabd38134c41b2817b62996995f670545948/centralizedappraiser-0.0.9.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-09-05 05:09:09",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "ReedGraff",
    "github_project": "CentralizedAppraiser",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "centralizedappraiser"
}
        
Elapsed time: 0.29107s