datafiniti-sdk 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,153 @@
1
+ Metadata-Version: 2.4
2
+ Name: datafiniti-sdk
3
+ Version: 0.1.0
4
+ Summary: Python SDK for Datafiniti Data APIs (Business, People, Property, Product)
5
+ Author-email: Leonard Trahan <leonard@datafiniti.co>
6
+ License: MIT
7
+ Keywords: datafiniti,api,sdk,business,property,people,product
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Operating System :: OS Independent
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
13
+ Requires-Python: >=3.9
14
+ Description-Content-Type: text/markdown
15
+ Requires-Dist: requests>=2.31.0
16
+ Provides-Extra: dev
17
+ Requires-Dist: pytest>=8.0.0; extra == "dev"
18
+
19
+ # Datafiniti SDK
20
+
21
+ Python SDK for the [Datafiniti](https://datafiniti.co) Data APIs — Business, People, Property, and Product data.
22
+
23
+ ## Installation
24
+
25
+ ```bash
26
+ pip install datafiniti-sdk
27
+ ```
28
+
29
+ ## Authentication
30
+
31
+ All SDK classes require a Datafiniti API key. You can pass it directly or set it as an environment variable:
32
+
33
+ ```bash
34
+ export DATAFINITI_API_KEY="your_api_key_here"
35
+ ```
36
+
37
+ ## Quick Start
38
+
39
+ ```python
40
+ from datafiniti import DatafinitiBusinessSDK, DatafinitiPeopleSDK, PropertyDataSDK, DatafinitiProductSDK
41
+
42
+ # Initialize from environment variable
43
+ sdk = PropertyDataSDK.from_env()
44
+
45
+ # Or pass the key directly
46
+ sdk = PropertyDataSDK(api_key="your_api_key_here")
47
+ ```
48
+
49
+ ## Business Data
50
+
51
+ ```python
52
+ from datafiniti import DatafinitiBusinessSDK
53
+
54
+ sdk = DatafinitiBusinessSDK.from_env()
55
+
56
+ # Search by name
57
+ results = sdk.search_by_name("Starbucks", city="Seattle", num_records=5)
58
+
59
+ # Count matching records
60
+ count = sdk.count('name:"Starbucks" AND country:US')
61
+
62
+ # Build a custom query
63
+ query = sdk.query().country("US").build()
64
+ results = sdk.search(query, num_records=10)
65
+
66
+ # Paginate through large result sets
67
+ for record in sdk.paginate('name:"Starbucks"', page_size=100, max_records=500):
68
+ print(record)
69
+ ```
70
+
71
+ ## People Data
72
+
73
+ ```python
74
+ from datafiniti import DatafinitiPeopleSDK
75
+
76
+ sdk = DatafinitiPeopleSDK.from_env()
77
+
78
+ # Search by name
79
+ results = sdk.search_by_name("John Smith", city="Austin", num_records=10)
80
+
81
+ # Count matching records
82
+ count = sdk.count('name:"John Smith" AND country:US')
83
+ ```
84
+
85
+ ## Property Data
86
+
87
+ ```python
88
+ from datafiniti import PropertyDataSDK
89
+
90
+ sdk = PropertyDataSDK.from_env()
91
+
92
+ # Search by address
93
+ results = sdk.search_by_address("123 Main St", postal_code="78701", num_records=1)
94
+
95
+ # Find properties for sale
96
+ results = sdk.for_sale(
97
+ postal_codes=["78701", "78702"],
98
+ property_types=["Single Family Residential"],
99
+ num_records=20
100
+ )
101
+
102
+ # Count matching records
103
+ count = sdk.count('country:US AND mostRecentStatus:"For Sale"')
104
+
105
+ # Paginate through results
106
+ for record in sdk.paginate('country:US AND mostRecentStatus:"For Sale"', page_size=100):
107
+ print(record["address"])
108
+ ```
109
+
110
+ ## Product Data
111
+
112
+ ```python
113
+ from datafiniti import DatafinitiProductSDK
114
+
115
+ sdk = DatafinitiProductSDK.from_env()
116
+
117
+ # Search by product name
118
+ results = sdk.search_by_name("iPhone 15", brand="Apple", num_records=10)
119
+
120
+ # Count matching records
121
+ count = sdk.count('brand:"Apple"')
122
+ ```
123
+
124
+ ## Common Methods
125
+
126
+ All four SDK classes inherit these methods:
127
+
128
+ | Method | Description |
129
+ | --- | --- |
130
+ | `search(query, num_records)` | Search and return up to `num_records` results |
131
+ | `count(query)` | Return the total number of matching records |
132
+ | `paginate(query, page_size, max_records)` | Generator that yields records page by page |
133
+ | `query()` | Returns a query builder for the data type |
134
+
135
+ ## Error Handling
136
+
137
+ ```python
138
+ from datafiniti import DatafinitiAPIError
139
+
140
+ try:
141
+ results = sdk.search("country:US", num_records=10)
142
+ except DatafinitiAPIError as e:
143
+ print(f"API error {e.status_code}: {e.message}")
144
+ ```
145
+
146
+ ## Requirements
147
+
148
+ - Python 3.9+
149
+ - `requests >= 2.31.0`
150
+
151
+ ## License
152
+
153
+ MIT
@@ -0,0 +1,135 @@
1
+ # Datafiniti SDK
2
+
3
+ Python SDK for the [Datafiniti](https://datafiniti.co) Data APIs — Business, People, Property, and Product data.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pip install datafiniti-sdk
9
+ ```
10
+
11
+ ## Authentication
12
+
13
+ All SDK classes require a Datafiniti API key. You can pass it directly or set it as an environment variable:
14
+
15
+ ```bash
16
+ export DATAFINITI_API_KEY="your_api_key_here"
17
+ ```
18
+
19
+ ## Quick Start
20
+
21
+ ```python
22
+ from datafiniti import DatafinitiBusinessSDK, DatafinitiPeopleSDK, PropertyDataSDK, DatafinitiProductSDK
23
+
24
+ # Initialize from environment variable
25
+ sdk = PropertyDataSDK.from_env()
26
+
27
+ # Or pass the key directly
28
+ sdk = PropertyDataSDK(api_key="your_api_key_here")
29
+ ```
30
+
31
+ ## Business Data
32
+
33
+ ```python
34
+ from datafiniti import DatafinitiBusinessSDK
35
+
36
+ sdk = DatafinitiBusinessSDK.from_env()
37
+
38
+ # Search by name
39
+ results = sdk.search_by_name("Starbucks", city="Seattle", num_records=5)
40
+
41
+ # Count matching records
42
+ count = sdk.count('name:"Starbucks" AND country:US')
43
+
44
+ # Build a custom query
45
+ query = sdk.query().country("US").build()
46
+ results = sdk.search(query, num_records=10)
47
+
48
+ # Paginate through large result sets
49
+ for record in sdk.paginate('name:"Starbucks"', page_size=100, max_records=500):
50
+ print(record)
51
+ ```
52
+
53
+ ## People Data
54
+
55
+ ```python
56
+ from datafiniti import DatafinitiPeopleSDK
57
+
58
+ sdk = DatafinitiPeopleSDK.from_env()
59
+
60
+ # Search by name
61
+ results = sdk.search_by_name("John Smith", city="Austin", num_records=10)
62
+
63
+ # Count matching records
64
+ count = sdk.count('name:"John Smith" AND country:US')
65
+ ```
66
+
67
+ ## Property Data
68
+
69
+ ```python
70
+ from datafiniti import PropertyDataSDK
71
+
72
+ sdk = PropertyDataSDK.from_env()
73
+
74
+ # Search by address
75
+ results = sdk.search_by_address("123 Main St", postal_code="78701", num_records=1)
76
+
77
+ # Find properties for sale
78
+ results = sdk.for_sale(
79
+ postal_codes=["78701", "78702"],
80
+ property_types=["Single Family Residential"],
81
+ num_records=20
82
+ )
83
+
84
+ # Count matching records
85
+ count = sdk.count('country:US AND mostRecentStatus:"For Sale"')
86
+
87
+ # Paginate through results
88
+ for record in sdk.paginate('country:US AND mostRecentStatus:"For Sale"', page_size=100):
89
+ print(record["address"])
90
+ ```
91
+
92
+ ## Product Data
93
+
94
+ ```python
95
+ from datafiniti import DatafinitiProductSDK
96
+
97
+ sdk = DatafinitiProductSDK.from_env()
98
+
99
+ # Search by product name
100
+ results = sdk.search_by_name("iPhone 15", brand="Apple", num_records=10)
101
+
102
+ # Count matching records
103
+ count = sdk.count('brand:"Apple"')
104
+ ```
105
+
106
+ ## Common Methods
107
+
108
+ All four SDK classes inherit these methods:
109
+
110
+ | Method | Description |
111
+ | --- | --- |
112
+ | `search(query, num_records)` | Search and return up to `num_records` results |
113
+ | `count(query)` | Return the total number of matching records |
114
+ | `paginate(query, page_size, max_records)` | Generator that yields records page by page |
115
+ | `query()` | Returns a query builder for the data type |
116
+
117
+ ## Error Handling
118
+
119
+ ```python
120
+ from datafiniti import DatafinitiAPIError
121
+
122
+ try:
123
+ results = sdk.search("country:US", num_records=10)
124
+ except DatafinitiAPIError as e:
125
+ print(f"API error {e.status_code}: {e.message}")
126
+ ```
127
+
128
+ ## Requirements
129
+
130
+ - Python 3.9+
131
+ - `requests >= 2.31.0`
132
+
133
+ ## License
134
+
135
+ MIT
@@ -0,0 +1,13 @@
1
+ from .business.sdk import DatafinitiBusinessSDK
2
+ from .people.sdk import DatafinitiPeopleSDK
3
+ from .property.sdk import PropertyDataSDK
4
+ from .product.sdk import DatafinitiProductSDK
5
+ from .errors import DatafinitiAPIError
6
+
7
+ __all__ = [
8
+ "DatafinitiBusinessSDK",
9
+ "DatafinitiPeopleSDK",
10
+ "PropertyDataSDK",
11
+ "DatafinitiProductSDK",
12
+ "DatafinitiAPIError",
13
+ ]
@@ -0,0 +1,109 @@
1
+ import os
2
+ import time
3
+ import requests
4
+
5
+ from .errors import DatafinitiAPIError
6
+
7
+
8
+ class BaseDatafinitiSDK:
9
+ BASE_URL = ""
10
+
11
+ def __init__(self, api_key=None, timeout=60, max_retries=3):
12
+ self.api_key = api_key or os.getenv("DATAFINITI_API_KEY")
13
+ self.timeout = timeout
14
+ self.max_retries = max_retries
15
+
16
+ if not self.api_key:
17
+ raise ValueError(
18
+ "Missing Datafiniti API key. Pass api_key or set DATAFINITI_API_KEY."
19
+ )
20
+
21
+ @classmethod
22
+ def from_env(cls):
23
+ return cls(api_key=os.getenv("DATAFINITI_API_KEY"))
24
+
25
+ def _headers(self):
26
+ return {
27
+ "Authorization": f"Bearer {self.api_key}",
28
+ "Content-Type": "application/json",
29
+ }
30
+
31
+ def _post(self, endpoint, payload, params=None):
32
+ url = f"{self.BASE_URL}/{endpoint.lstrip('/')}"
33
+ last_error = None
34
+
35
+ for attempt in range(1, self.max_retries + 1):
36
+ try:
37
+ response = requests.post(
38
+ url,
39
+ json=payload,
40
+ params=params,
41
+ headers=self._headers(),
42
+ timeout=self.timeout,
43
+ )
44
+
45
+ if response.status_code in (408, 429, 500, 502, 503, 504):
46
+ last_error = response
47
+ time.sleep(2 ** (attempt - 1))
48
+ continue
49
+
50
+ if not response.ok:
51
+ raise DatafinitiAPIError(
52
+ message=f"Datafiniti API error: {response.status_code}",
53
+ status_code=response.status_code,
54
+ response_body=response.text,
55
+ )
56
+
57
+ return response.json()
58
+
59
+ except requests.RequestException as exc:
60
+ last_error = exc
61
+ time.sleep(2 ** (attempt - 1))
62
+
63
+ raise DatafinitiAPIError(
64
+ message="Datafiniti API request failed after retries.",
65
+ response_body=str(last_error),
66
+ )
67
+
68
+ def search(self, query, num_records=10, format="JSON", view=None, download=False):
69
+ payload = {
70
+ "query": query,
71
+ "num_records": num_records,
72
+ "format": format,
73
+ }
74
+ if view:
75
+ payload["view"] = view
76
+ if download:
77
+ payload["download"] = True
78
+ return self._post("search", payload)
79
+
80
+ def count(self, query):
81
+ response = self.search(query=query, num_records=0)
82
+ return response.get("num_found", 0)
83
+
84
+ def paginate(self, query, page_size=100, max_records=None, format="JSON", view=None):
85
+ page = 1
86
+ total_yielded = 0
87
+
88
+ while True:
89
+ payload = {"query": query, "format": format}
90
+ if view:
91
+ payload["view"] = view
92
+
93
+ response = self._post(
94
+ endpoint="paginate",
95
+ payload=payload,
96
+ params={"page": page, "limit": page_size},
97
+ )
98
+
99
+ records = response.get("records", [])
100
+ if not records:
101
+ break
102
+
103
+ for record in records:
104
+ yield record
105
+ total_yielded += 1
106
+ if max_records and total_yielded >= max_records:
107
+ return
108
+
109
+ page += 1
@@ -0,0 +1,4 @@
1
+ from .sdk import DatafinitiBusinessSDK
2
+ from .queries import BusinessQuery
3
+
4
+ __all__ = ["DatafinitiBusinessSDK", "BusinessQuery"]
@@ -0,0 +1,50 @@
1
+ class BusinessQuery:
2
+ def __init__(self):
3
+ self.parts = []
4
+
5
+ def raw(self, query):
6
+ self.parts.append(f"({query})")
7
+ return self
8
+
9
+ def country(self, country):
10
+ self.parts.append(f"country:{country}")
11
+ return self
12
+
13
+ def province(self, province):
14
+ self.parts.append(f'province:"{province}"')
15
+ return self
16
+
17
+ def city(self, city):
18
+ self.parts.append(f'city:"{city}"')
19
+ return self
20
+
21
+ def postal_code(self, postal_code):
22
+ self.parts.append(f'postalCode:"{postal_code}"')
23
+ return self
24
+
25
+ def postal_codes(self, postal_codes):
26
+ values = " OR ".join([f'"{code}"' for code in postal_codes])
27
+ self.parts.append(f"postalCode:({values})")
28
+ return self
29
+
30
+ def name(self, name):
31
+ self.parts.append(f'name:"{name}"')
32
+ return self
33
+
34
+ def categories(self, categories):
35
+ if isinstance(categories, str):
36
+ categories = [categories]
37
+ values = " OR ".join([f'"{cat}"' for cat in categories])
38
+ self.parts.append(f"categories:({values})")
39
+ return self
40
+
41
+ def updated_after(self, date_string):
42
+ self.parts.append(f"dateUpdated:[{date_string} TO *]")
43
+ return self
44
+
45
+ def has_field(self, field):
46
+ self.parts.append(f"{field}:*")
47
+ return self
48
+
49
+ def build(self):
50
+ return " AND ".join(self.parts)
@@ -0,0 +1,17 @@
1
+ from .._base import BaseDatafinitiSDK
2
+ from .queries import BusinessQuery
3
+
4
+
5
+ class DatafinitiBusinessSDK(BaseDatafinitiSDK):
6
+ BASE_URL = "https://api.datafiniti.co/v4/businesses"
7
+
8
+ def query(self):
9
+ return BusinessQuery()
10
+
11
+ def search_by_name(self, name, city=None, country="US", num_records=10):
12
+ parts = [f'name:"{name}"']
13
+ if city:
14
+ parts.append(f'city:"{city}"')
15
+ if country:
16
+ parts.append(f"country:{country}")
17
+ return self.search(" AND ".join(parts), num_records=num_records)
@@ -0,0 +1,7 @@
1
+ class DatafinitiAPIError(Exception):
2
+ """Raised when the Datafiniti API returns an error response."""
3
+
4
+ def __init__(self, message, status_code=None, response_body=None):
5
+ super().__init__(message)
6
+ self.status_code = status_code
7
+ self.response_body = response_body
@@ -0,0 +1,4 @@
1
+ from .sdk import DatafinitiPeopleSDK
2
+ from .queries import PeopleQuery
3
+
4
+ __all__ = ["DatafinitiPeopleSDK", "PeopleQuery"]
@@ -0,0 +1,38 @@
1
+ class PeopleQuery:
2
+ def __init__(self):
3
+ self.parts = []
4
+
5
+ def raw(self, query):
6
+ self.parts.append(f"({query})")
7
+ return self
8
+
9
+ def country(self, country):
10
+ self.parts.append(f"country:{country}")
11
+ return self
12
+
13
+ def province(self, province):
14
+ self.parts.append(f'province:"{province}"')
15
+ return self
16
+
17
+ def city(self, city):
18
+ self.parts.append(f'city:"{city}"')
19
+ return self
20
+
21
+ def postal_code(self, postal_code):
22
+ self.parts.append(f'postalCode:"{postal_code}"')
23
+ return self
24
+
25
+ def name(self, name):
26
+ self.parts.append(f'name:"{name}"')
27
+ return self
28
+
29
+ def updated_after(self, date_string):
30
+ self.parts.append(f"dateUpdated:[{date_string} TO *]")
31
+ return self
32
+
33
+ def has_field(self, field):
34
+ self.parts.append(f"{field}:*")
35
+ return self
36
+
37
+ def build(self):
38
+ return " AND ".join(self.parts)
@@ -0,0 +1,17 @@
1
+ from .._base import BaseDatafinitiSDK
2
+ from .queries import PeopleQuery
3
+
4
+
5
+ class DatafinitiPeopleSDK(BaseDatafinitiSDK):
6
+ BASE_URL = "https://api.datafiniti.co/v4/people"
7
+
8
+ def query(self):
9
+ return PeopleQuery()
10
+
11
+ def search_by_name(self, name, city=None, country="US", num_records=10):
12
+ parts = [f'name:"{name}"']
13
+ if city:
14
+ parts.append(f'city:"{city}"')
15
+ if country:
16
+ parts.append(f"country:{country}")
17
+ return self.search(" AND ".join(parts), num_records=num_records)
@@ -0,0 +1,4 @@
1
+ from .sdk import DatafinitiProductSDK
2
+ from .queries import ProductQuery
3
+
4
+ __all__ = ["DatafinitiProductSDK", "ProductQuery"]
@@ -0,0 +1,39 @@
1
+ class ProductQuery:
2
+ def __init__(self):
3
+ self.parts = []
4
+
5
+ def raw(self, query):
6
+ self.parts.append(f"({query})")
7
+ return self
8
+
9
+ def name(self, name):
10
+ self.parts.append(f'name:"{name}"')
11
+ return self
12
+
13
+ def brand(self, brand):
14
+ self.parts.append(f'brand:"{brand}"')
15
+ return self
16
+
17
+ def categories(self, categories):
18
+ if isinstance(categories, str):
19
+ categories = [categories]
20
+ values = " OR ".join([f'"{cat}"' for cat in categories])
21
+ self.parts.append(f"categories:({values})")
22
+ return self
23
+
24
+ def price_range(self, min_price=None, max_price=None):
25
+ min_val = min_price if min_price is not None else "*"
26
+ max_val = max_price if max_price is not None else "*"
27
+ self.parts.append(f"prices.amountMin:[{min_val} TO {max_val}]")
28
+ return self
29
+
30
+ def updated_after(self, date_string):
31
+ self.parts.append(f"dateUpdated:[{date_string} TO *]")
32
+ return self
33
+
34
+ def has_field(self, field):
35
+ self.parts.append(f"{field}:*")
36
+ return self
37
+
38
+ def build(self):
39
+ return " AND ".join(self.parts)
@@ -0,0 +1,15 @@
1
+ from .._base import BaseDatafinitiSDK
2
+ from .queries import ProductQuery
3
+
4
+
5
+ class DatafinitiProductSDK(BaseDatafinitiSDK):
6
+ BASE_URL = "https://api.datafiniti.co/v4/products"
7
+
8
+ def query(self):
9
+ return ProductQuery()
10
+
11
+ def search_by_name(self, name, brand=None, num_records=10):
12
+ parts = [f'name:"{name}"']
13
+ if brand:
14
+ parts.append(f'brand:"{brand}"')
15
+ return self.search(" AND ".join(parts), num_records=num_records)
@@ -0,0 +1,4 @@
1
+ from .sdk import PropertyDataSDK
2
+ from .queries import PropertyQuery
3
+
4
+ __all__ = ["PropertyDataSDK", "PropertyQuery"]
@@ -0,0 +1,64 @@
1
+ class PropertyQuery:
2
+ def __init__(self):
3
+ self.parts = []
4
+
5
+ def raw(self, query):
6
+ self.parts.append(f"({query})")
7
+ return self
8
+
9
+ def country(self, country):
10
+ self.parts.append(f"country:{country}")
11
+ return self
12
+
13
+ def province(self, province):
14
+ self.parts.append(f'province:"{province}"')
15
+ return self
16
+
17
+ def city(self, city):
18
+ self.parts.append(f'city:"{city}"')
19
+ return self
20
+
21
+ def postal_code(self, postal_code):
22
+ self.parts.append(f'postalCode:"{postal_code}"')
23
+ return self
24
+
25
+ def postal_codes(self, postal_codes):
26
+ values = " OR ".join([f'"{code}"' for code in postal_codes])
27
+ self.parts.append(f"postalCode:({values})")
28
+ return self
29
+
30
+ def address(self, address):
31
+ self.parts.append(f'address:"{address}"')
32
+ return self
33
+
34
+ def most_recent_status(self, statuses):
35
+ if isinstance(statuses, str):
36
+ statuses = [statuses]
37
+ values = " OR ".join([f'"{status}"' for status in statuses])
38
+ self.parts.append(f"mostRecentStatus:({values})")
39
+ return self
40
+
41
+ def most_recent_rental_status(self, statuses):
42
+ if isinstance(statuses, str):
43
+ statuses = [statuses]
44
+ values = " OR ".join([f'"{status}"' for status in statuses])
45
+ self.parts.append(f"mostRecentRentalStatus:({values})")
46
+ return self
47
+
48
+ def property_types(self, property_types):
49
+ if isinstance(property_types, str):
50
+ property_types = [property_types]
51
+ values = " OR ".join([f'"{ptype}"' for ptype in property_types])
52
+ self.parts.append(f"propertyType:({values})")
53
+ return self
54
+
55
+ def updated_after(self, date_string):
56
+ self.parts.append(f"dateUpdated:[{date_string} TO *]")
57
+ return self
58
+
59
+ def has_field(self, field):
60
+ self.parts.append(f"{field}:*")
61
+ return self
62
+
63
+ def build(self):
64
+ return " AND ".join(self.parts)
@@ -0,0 +1,29 @@
1
+ from .._base import BaseDatafinitiSDK
2
+ from .queries import PropertyQuery
3
+
4
+
5
+ class PropertyDataSDK(BaseDatafinitiSDK):
6
+ BASE_URL = "https://api.datafiniti.co/v4/properties"
7
+
8
+ def query(self):
9
+ return PropertyQuery()
10
+
11
+ def search_by_address(self, address, postal_code=None, country="US", num_records=1):
12
+ parts = [f'address:"{address}"']
13
+ if postal_code:
14
+ parts.append(f'postalCode:"{postal_code}"')
15
+ if country:
16
+ parts.append(f"country:{country}")
17
+ return self.search(" AND ".join(parts), num_records=num_records)
18
+
19
+ def for_sale(self, postal_codes=None, property_types=None, num_records=10):
20
+ builder = (
21
+ self.query()
22
+ .country("US")
23
+ .most_recent_status(["For Sale", "Coming Soon", "Pending"])
24
+ )
25
+ if postal_codes:
26
+ builder.postal_codes(postal_codes)
27
+ if property_types:
28
+ builder.property_types(property_types)
29
+ return self.search(builder.build(), num_records=num_records)
@@ -0,0 +1,153 @@
1
+ Metadata-Version: 2.4
2
+ Name: datafiniti-sdk
3
+ Version: 0.1.0
4
+ Summary: Python SDK for Datafiniti Data APIs (Business, People, Property, Product)
5
+ Author-email: Leonard Trahan <leonard@datafiniti.co>
6
+ License: MIT
7
+ Keywords: datafiniti,api,sdk,business,property,people,product
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Operating System :: OS Independent
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
13
+ Requires-Python: >=3.9
14
+ Description-Content-Type: text/markdown
15
+ Requires-Dist: requests>=2.31.0
16
+ Provides-Extra: dev
17
+ Requires-Dist: pytest>=8.0.0; extra == "dev"
18
+
19
+ # Datafiniti SDK
20
+
21
+ Python SDK for the [Datafiniti](https://datafiniti.co) Data APIs — Business, People, Property, and Product data.
22
+
23
+ ## Installation
24
+
25
+ ```bash
26
+ pip install datafiniti-sdk
27
+ ```
28
+
29
+ ## Authentication
30
+
31
+ All SDK classes require a Datafiniti API key. You can pass it directly or set it as an environment variable:
32
+
33
+ ```bash
34
+ export DATAFINITI_API_KEY="your_api_key_here"
35
+ ```
36
+
37
+ ## Quick Start
38
+
39
+ ```python
40
+ from datafiniti import DatafinitiBusinessSDK, DatafinitiPeopleSDK, PropertyDataSDK, DatafinitiProductSDK
41
+
42
+ # Initialize from environment variable
43
+ sdk = PropertyDataSDK.from_env()
44
+
45
+ # Or pass the key directly
46
+ sdk = PropertyDataSDK(api_key="your_api_key_here")
47
+ ```
48
+
49
+ ## Business Data
50
+
51
+ ```python
52
+ from datafiniti import DatafinitiBusinessSDK
53
+
54
+ sdk = DatafinitiBusinessSDK.from_env()
55
+
56
+ # Search by name
57
+ results = sdk.search_by_name("Starbucks", city="Seattle", num_records=5)
58
+
59
+ # Count matching records
60
+ count = sdk.count('name:"Starbucks" AND country:US')
61
+
62
+ # Build a custom query
63
+ query = sdk.query().country("US").build()
64
+ results = sdk.search(query, num_records=10)
65
+
66
+ # Paginate through large result sets
67
+ for record in sdk.paginate('name:"Starbucks"', page_size=100, max_records=500):
68
+ print(record)
69
+ ```
70
+
71
+ ## People Data
72
+
73
+ ```python
74
+ from datafiniti import DatafinitiPeopleSDK
75
+
76
+ sdk = DatafinitiPeopleSDK.from_env()
77
+
78
+ # Search by name
79
+ results = sdk.search_by_name("John Smith", city="Austin", num_records=10)
80
+
81
+ # Count matching records
82
+ count = sdk.count('name:"John Smith" AND country:US')
83
+ ```
84
+
85
+ ## Property Data
86
+
87
+ ```python
88
+ from datafiniti import PropertyDataSDK
89
+
90
+ sdk = PropertyDataSDK.from_env()
91
+
92
+ # Search by address
93
+ results = sdk.search_by_address("123 Main St", postal_code="78701", num_records=1)
94
+
95
+ # Find properties for sale
96
+ results = sdk.for_sale(
97
+ postal_codes=["78701", "78702"],
98
+ property_types=["Single Family Residential"],
99
+ num_records=20
100
+ )
101
+
102
+ # Count matching records
103
+ count = sdk.count('country:US AND mostRecentStatus:"For Sale"')
104
+
105
+ # Paginate through results
106
+ for record in sdk.paginate('country:US AND mostRecentStatus:"For Sale"', page_size=100):
107
+ print(record["address"])
108
+ ```
109
+
110
+ ## Product Data
111
+
112
+ ```python
113
+ from datafiniti import DatafinitiProductSDK
114
+
115
+ sdk = DatafinitiProductSDK.from_env()
116
+
117
+ # Search by product name
118
+ results = sdk.search_by_name("iPhone 15", brand="Apple", num_records=10)
119
+
120
+ # Count matching records
121
+ count = sdk.count('brand:"Apple"')
122
+ ```
123
+
124
+ ## Common Methods
125
+
126
+ All four SDK classes inherit these methods:
127
+
128
+ | Method | Description |
129
+ | --- | --- |
130
+ | `search(query, num_records)` | Search and return up to `num_records` results |
131
+ | `count(query)` | Return the total number of matching records |
132
+ | `paginate(query, page_size, max_records)` | Generator that yields records page by page |
133
+ | `query()` | Returns a query builder for the data type |
134
+
135
+ ## Error Handling
136
+
137
+ ```python
138
+ from datafiniti import DatafinitiAPIError
139
+
140
+ try:
141
+ results = sdk.search("country:US", num_records=10)
142
+ except DatafinitiAPIError as e:
143
+ print(f"API error {e.status_code}: {e.message}")
144
+ ```
145
+
146
+ ## Requirements
147
+
148
+ - Python 3.9+
149
+ - `requests >= 2.31.0`
150
+
151
+ ## License
152
+
153
+ MIT
@@ -0,0 +1,22 @@
1
+ README.md
2
+ pyproject.toml
3
+ datafiniti/__init__.py
4
+ datafiniti/_base.py
5
+ datafiniti/errors.py
6
+ datafiniti/business/__init__.py
7
+ datafiniti/business/queries.py
8
+ datafiniti/business/sdk.py
9
+ datafiniti/people/__init__.py
10
+ datafiniti/people/queries.py
11
+ datafiniti/people/sdk.py
12
+ datafiniti/product/__init__.py
13
+ datafiniti/product/queries.py
14
+ datafiniti/product/sdk.py
15
+ datafiniti/property/__init__.py
16
+ datafiniti/property/queries.py
17
+ datafiniti/property/sdk.py
18
+ datafiniti_sdk.egg-info/PKG-INFO
19
+ datafiniti_sdk.egg-info/SOURCES.txt
20
+ datafiniti_sdk.egg-info/dependency_links.txt
21
+ datafiniti_sdk.egg-info/requires.txt
22
+ datafiniti_sdk.egg-info/top_level.txt
@@ -0,0 +1,4 @@
1
+ requests>=2.31.0
2
+
3
+ [dev]
4
+ pytest>=8.0.0
@@ -0,0 +1 @@
1
+ datafiniti
@@ -0,0 +1,32 @@
1
+ [project]
2
+ name = "datafiniti-sdk"
3
+ version = "0.1.0"
4
+ description = "Python SDK for Datafiniti Data APIs (Business, People, Property, Product)"
5
+ readme = "README.md"
6
+ license = { text = "MIT" }
7
+ authors = [{ name = "Leonard Trahan", email = "leonard@datafiniti.co" }]
8
+ keywords = ["datafiniti", "api", "sdk", "business", "property", "people", "product"]
9
+ classifiers = [
10
+ "Programming Language :: Python :: 3",
11
+ "License :: OSI Approved :: MIT License",
12
+ "Operating System :: OS Independent",
13
+ "Intended Audience :: Developers",
14
+ "Topic :: Software Development :: Libraries :: Python Modules",
15
+ ]
16
+ requires-python = ">=3.9"
17
+ dependencies = [
18
+ "requests>=2.31.0"
19
+ ]
20
+
21
+ [project.optional-dependencies]
22
+ dev = [
23
+ "pytest>=8.0.0"
24
+ ]
25
+
26
+ [build-system]
27
+ requires = ["setuptools>=61"]
28
+ build-backend = "setuptools.build_meta"
29
+
30
+ [tool.setuptools.packages.find]
31
+ where = ["."]
32
+ include = ["datafiniti*"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+