permitstack 1.0.0__py3-none-any.whl

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.
Files changed (68) hide show
  1. permitstack/__init__.py +17 -0
  2. permitstack/_hooks/__init__.py +4 -0
  3. permitstack/_hooks/sdkhooks.py +74 -0
  4. permitstack/_hooks/types.py +112 -0
  5. permitstack/_version.py +15 -0
  6. permitstack/basesdk.py +396 -0
  7. permitstack/bulk_export.py +241 -0
  8. permitstack/contractors.py +625 -0
  9. permitstack/errors/__init__.py +39 -0
  10. permitstack/errors/httpvalidationerror.py +28 -0
  11. permitstack/errors/no_response_error.py +17 -0
  12. permitstack/errors/permitstackdefaulterror.py +40 -0
  13. permitstack/errors/permitstackerror.py +30 -0
  14. permitstack/errors/responsevalidationerror.py +27 -0
  15. permitstack/health.py +171 -0
  16. permitstack/httpclient.py +125 -0
  17. permitstack/models/__init__.py +158 -0
  18. permitstack/models/contractorprofile.py +108 -0
  19. permitstack/models/contractorsearchresponse.py +24 -0
  20. permitstack/models/contractorsummary.py +57 -0
  21. permitstack/models/delete_webhookop.py +16 -0
  22. permitstack/models/export_permits_csvop.py +98 -0
  23. permitstack/models/get_contractor_permitsop.py +46 -0
  24. permitstack/models/get_contractorop.py +16 -0
  25. permitstack/models/get_permitop.py +16 -0
  26. permitstack/models/get_permits_by_addressop.py +46 -0
  27. permitstack/models/get_property_historyop.py +18 -0
  28. permitstack/models/permitcategory.py +27 -0
  29. permitstack/models/permitdetail.py +164 -0
  30. permitstack/models/permitsearchresponse.py +24 -0
  31. permitstack/models/permitstatus.py +16 -0
  32. permitstack/models/permitsummary.py +121 -0
  33. permitstack/models/propertytype.py +14 -0
  34. permitstack/models/search_contractorsop.py +98 -0
  35. permitstack/models/search_permitsop.py +247 -0
  36. permitstack/models/security.py +42 -0
  37. permitstack/models/validationerror.py +57 -0
  38. permitstack/models/webhookcreate.py +60 -0
  39. permitstack/permits.py +866 -0
  40. permitstack/property_history.py +207 -0
  41. permitstack/py.typed +1 -0
  42. permitstack/sdk.py +218 -0
  43. permitstack/sdkconfiguration.py +49 -0
  44. permitstack/types/__init__.py +21 -0
  45. permitstack/types/basemodel.py +77 -0
  46. permitstack/utils/__init__.py +178 -0
  47. permitstack/utils/annotations.py +79 -0
  48. permitstack/utils/datetimes.py +23 -0
  49. permitstack/utils/dynamic_imports.py +54 -0
  50. permitstack/utils/enums.py +134 -0
  51. permitstack/utils/eventstreaming.py +309 -0
  52. permitstack/utils/forms.py +234 -0
  53. permitstack/utils/headers.py +136 -0
  54. permitstack/utils/logger.py +27 -0
  55. permitstack/utils/metadata.py +119 -0
  56. permitstack/utils/queryparams.py +217 -0
  57. permitstack/utils/requestbodies.py +66 -0
  58. permitstack/utils/retries.py +271 -0
  59. permitstack/utils/security.py +215 -0
  60. permitstack/utils/serializers.py +225 -0
  61. permitstack/utils/unmarshal_json_response.py +38 -0
  62. permitstack/utils/url.py +155 -0
  63. permitstack/utils/values.py +137 -0
  64. permitstack/webhooks.py +593 -0
  65. permitstack-1.0.0.dist-info/METADATA +541 -0
  66. permitstack-1.0.0.dist-info/RECORD +68 -0
  67. permitstack-1.0.0.dist-info/WHEEL +5 -0
  68. permitstack-1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,14 @@
1
+ """Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
2
+
3
+ from __future__ import annotations
4
+ from typing import Literal
5
+
6
+
7
+ PropertyType = Literal[
8
+ "residential",
9
+ "commercial",
10
+ "industrial",
11
+ "mixed_use",
12
+ "institutional",
13
+ "unknown",
14
+ ]
@@ -0,0 +1,98 @@
1
+ """Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
2
+
3
+ from __future__ import annotations
4
+ from permitstack.types import (
5
+ BaseModel,
6
+ Nullable,
7
+ OptionalNullable,
8
+ UNSET,
9
+ UNSET_SENTINEL,
10
+ )
11
+ from permitstack.utils import FieldMetadata, QueryParamMetadata
12
+ from pydantic import model_serializer
13
+ from typing import Optional
14
+ from typing_extensions import Annotated, NotRequired, TypedDict
15
+
16
+
17
+ class SearchContractorsRequestTypedDict(TypedDict):
18
+ name: NotRequired[Nullable[str]]
19
+ r"""Contractor name (partial match)"""
20
+ state: NotRequired[Nullable[str]]
21
+ r"""2-letter state code"""
22
+ city: NotRequired[Nullable[str]]
23
+ r"""City name"""
24
+ specialty: NotRequired[Nullable[str]]
25
+ r"""Specialty tag (e.g. solar, roofing, hvac)"""
26
+ min_permits: NotRequired[Nullable[int]]
27
+ r"""Minimum total permits"""
28
+ page: NotRequired[int]
29
+ per_page: NotRequired[int]
30
+
31
+
32
+ class SearchContractorsRequest(BaseModel):
33
+ name: Annotated[
34
+ OptionalNullable[str],
35
+ FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
36
+ ] = UNSET
37
+ r"""Contractor name (partial match)"""
38
+
39
+ state: Annotated[
40
+ OptionalNullable[str],
41
+ FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
42
+ ] = UNSET
43
+ r"""2-letter state code"""
44
+
45
+ city: Annotated[
46
+ OptionalNullable[str],
47
+ FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
48
+ ] = UNSET
49
+ r"""City name"""
50
+
51
+ specialty: Annotated[
52
+ OptionalNullable[str],
53
+ FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
54
+ ] = UNSET
55
+ r"""Specialty tag (e.g. solar, roofing, hvac)"""
56
+
57
+ min_permits: Annotated[
58
+ OptionalNullable[int],
59
+ FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
60
+ ] = UNSET
61
+ r"""Minimum total permits"""
62
+
63
+ page: Annotated[
64
+ Optional[int],
65
+ FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
66
+ ] = 1
67
+
68
+ per_page: Annotated[
69
+ Optional[int],
70
+ FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
71
+ ] = 25
72
+
73
+ @model_serializer(mode="wrap")
74
+ def serialize_model(self, handler):
75
+ optional_fields = set(
76
+ ["name", "state", "city", "specialty", "min_permits", "page", "per_page"]
77
+ )
78
+ nullable_fields = set(["name", "state", "city", "specialty", "min_permits"])
79
+ serialized = handler(self)
80
+ m = {}
81
+
82
+ for n, f in type(self).model_fields.items():
83
+ k = f.alias or n
84
+ val = serialized.get(k, serialized.get(n))
85
+ is_nullable_and_explicitly_set = (
86
+ k in nullable_fields
87
+ and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member
88
+ )
89
+
90
+ if val != UNSET_SENTINEL:
91
+ if (
92
+ val is not None
93
+ or k not in optional_fields
94
+ or is_nullable_and_explicitly_set
95
+ ):
96
+ m[k] = val
97
+
98
+ return m
@@ -0,0 +1,247 @@
1
+ """Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
2
+
3
+ from __future__ import annotations
4
+ from .permitcategory import PermitCategory
5
+ from .permitstatus import PermitStatus
6
+ from .propertytype import PropertyType
7
+ from datetime import date
8
+ from permitstack.types import (
9
+ BaseModel,
10
+ Nullable,
11
+ OptionalNullable,
12
+ UNSET,
13
+ UNSET_SENTINEL,
14
+ )
15
+ from permitstack.utils import FieldMetadata, QueryParamMetadata
16
+ from pydantic import model_serializer
17
+ from typing import Optional
18
+ from typing_extensions import Annotated, NotRequired, TypedDict
19
+
20
+
21
+ class SearchPermitsRequestTypedDict(TypedDict):
22
+ zip_code: NotRequired[Nullable[str]]
23
+ r"""5-digit ZIP code"""
24
+ city: NotRequired[Nullable[str]]
25
+ r"""City name"""
26
+ state: NotRequired[Nullable[str]]
27
+ r"""2-letter state code"""
28
+ lat: NotRequired[Nullable[float]]
29
+ r"""Latitude for radius search"""
30
+ lng: NotRequired[Nullable[float]]
31
+ r"""Longitude for radius search"""
32
+ radius_miles: NotRequired[float]
33
+ r"""Radius in miles (used with lat/lng)"""
34
+ category: NotRequired[Nullable[PermitCategory]]
35
+ r"""Permit category (e.g. solar, roofing, hvac)"""
36
+ status: NotRequired[Nullable[PermitStatus]]
37
+ r"""Permit status (e.g. issued, filed, final)"""
38
+ property_type: NotRequired[Nullable[PropertyType]]
39
+ r"""Property type (e.g. residential, commercial)"""
40
+ tag: NotRequired[Nullable[str]]
41
+ r"""Filter by tag"""
42
+ filed_after: NotRequired[Nullable[date]]
43
+ r"""Filed on or after this date"""
44
+ filed_before: NotRequired[Nullable[date]]
45
+ r"""Filed on or before this date"""
46
+ issued_after: NotRequired[Nullable[date]]
47
+ r"""Issued on or after this date"""
48
+ issued_before: NotRequired[Nullable[date]]
49
+ r"""Issued on or before this date"""
50
+ min_value: NotRequired[Nullable[float]]
51
+ r"""Minimum estimated value"""
52
+ max_value: NotRequired[Nullable[float]]
53
+ r"""Maximum estimated value"""
54
+ q: NotRequired[Nullable[str]]
55
+ r"""Full-text search query"""
56
+ contractor_name: NotRequired[Nullable[str]]
57
+ r"""Contractor name (partial match)"""
58
+ page: NotRequired[int]
59
+ per_page: NotRequired[int]
60
+
61
+
62
+ class SearchPermitsRequest(BaseModel):
63
+ zip_code: Annotated[
64
+ OptionalNullable[str],
65
+ FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
66
+ ] = UNSET
67
+ r"""5-digit ZIP code"""
68
+
69
+ city: Annotated[
70
+ OptionalNullable[str],
71
+ FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
72
+ ] = UNSET
73
+ r"""City name"""
74
+
75
+ state: Annotated[
76
+ OptionalNullable[str],
77
+ FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
78
+ ] = UNSET
79
+ r"""2-letter state code"""
80
+
81
+ lat: Annotated[
82
+ OptionalNullable[float],
83
+ FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
84
+ ] = UNSET
85
+ r"""Latitude for radius search"""
86
+
87
+ lng: Annotated[
88
+ OptionalNullable[float],
89
+ FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
90
+ ] = UNSET
91
+ r"""Longitude for radius search"""
92
+
93
+ radius_miles: Annotated[
94
+ Optional[float],
95
+ FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
96
+ ] = 5
97
+ r"""Radius in miles (used with lat/lng)"""
98
+
99
+ category: Annotated[
100
+ OptionalNullable[PermitCategory],
101
+ FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
102
+ ] = UNSET
103
+ r"""Permit category (e.g. solar, roofing, hvac)"""
104
+
105
+ status: Annotated[
106
+ OptionalNullable[PermitStatus],
107
+ FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
108
+ ] = UNSET
109
+ r"""Permit status (e.g. issued, filed, final)"""
110
+
111
+ property_type: Annotated[
112
+ OptionalNullable[PropertyType],
113
+ FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
114
+ ] = UNSET
115
+ r"""Property type (e.g. residential, commercial)"""
116
+
117
+ tag: Annotated[
118
+ OptionalNullable[str],
119
+ FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
120
+ ] = UNSET
121
+ r"""Filter by tag"""
122
+
123
+ filed_after: Annotated[
124
+ OptionalNullable[date],
125
+ FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
126
+ ] = UNSET
127
+ r"""Filed on or after this date"""
128
+
129
+ filed_before: Annotated[
130
+ OptionalNullable[date],
131
+ FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
132
+ ] = UNSET
133
+ r"""Filed on or before this date"""
134
+
135
+ issued_after: Annotated[
136
+ OptionalNullable[date],
137
+ FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
138
+ ] = UNSET
139
+ r"""Issued on or after this date"""
140
+
141
+ issued_before: Annotated[
142
+ OptionalNullable[date],
143
+ FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
144
+ ] = UNSET
145
+ r"""Issued on or before this date"""
146
+
147
+ min_value: Annotated[
148
+ OptionalNullable[float],
149
+ FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
150
+ ] = UNSET
151
+ r"""Minimum estimated value"""
152
+
153
+ max_value: Annotated[
154
+ OptionalNullable[float],
155
+ FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
156
+ ] = UNSET
157
+ r"""Maximum estimated value"""
158
+
159
+ q: Annotated[
160
+ OptionalNullable[str],
161
+ FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
162
+ ] = UNSET
163
+ r"""Full-text search query"""
164
+
165
+ contractor_name: Annotated[
166
+ OptionalNullable[str],
167
+ FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
168
+ ] = UNSET
169
+ r"""Contractor name (partial match)"""
170
+
171
+ page: Annotated[
172
+ Optional[int],
173
+ FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
174
+ ] = 1
175
+
176
+ per_page: Annotated[
177
+ Optional[int],
178
+ FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
179
+ ] = 25
180
+
181
+ @model_serializer(mode="wrap")
182
+ def serialize_model(self, handler):
183
+ optional_fields = set(
184
+ [
185
+ "zip_code",
186
+ "city",
187
+ "state",
188
+ "lat",
189
+ "lng",
190
+ "radius_miles",
191
+ "category",
192
+ "status",
193
+ "property_type",
194
+ "tag",
195
+ "filed_after",
196
+ "filed_before",
197
+ "issued_after",
198
+ "issued_before",
199
+ "min_value",
200
+ "max_value",
201
+ "q",
202
+ "contractor_name",
203
+ "page",
204
+ "per_page",
205
+ ]
206
+ )
207
+ nullable_fields = set(
208
+ [
209
+ "zip_code",
210
+ "city",
211
+ "state",
212
+ "lat",
213
+ "lng",
214
+ "category",
215
+ "status",
216
+ "property_type",
217
+ "tag",
218
+ "filed_after",
219
+ "filed_before",
220
+ "issued_after",
221
+ "issued_before",
222
+ "min_value",
223
+ "max_value",
224
+ "q",
225
+ "contractor_name",
226
+ ]
227
+ )
228
+ serialized = handler(self)
229
+ m = {}
230
+
231
+ for n, f in type(self).model_fields.items():
232
+ k = f.alias or n
233
+ val = serialized.get(k, serialized.get(n))
234
+ is_nullable_and_explicitly_set = (
235
+ k in nullable_fields
236
+ and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member
237
+ )
238
+
239
+ if val != UNSET_SENTINEL:
240
+ if (
241
+ val is not None
242
+ or k not in optional_fields
243
+ or is_nullable_and_explicitly_set
244
+ ):
245
+ m[k] = val
246
+
247
+ return m
@@ -0,0 +1,42 @@
1
+ """Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
2
+
3
+ from __future__ import annotations
4
+ from permitstack.types import BaseModel, UNSET_SENTINEL
5
+ from permitstack.utils import FieldMetadata, SecurityMetadata
6
+ from pydantic import model_serializer
7
+ from typing import Optional
8
+ from typing_extensions import Annotated, NotRequired, TypedDict
9
+
10
+
11
+ class SecurityTypedDict(TypedDict):
12
+ api_key: NotRequired[str]
13
+
14
+
15
+ class Security(BaseModel):
16
+ api_key: Annotated[
17
+ Optional[str],
18
+ FieldMetadata(
19
+ security=SecurityMetadata(
20
+ scheme=True,
21
+ scheme_type="apiKey",
22
+ sub_type="header",
23
+ field_name="X-API-Key",
24
+ )
25
+ ),
26
+ ] = None
27
+
28
+ @model_serializer(mode="wrap")
29
+ def serialize_model(self, handler):
30
+ optional_fields = set(["ApiKey"])
31
+ serialized = handler(self)
32
+ m = {}
33
+
34
+ for n, f in type(self).model_fields.items():
35
+ k = f.alias or n
36
+ val = serialized.get(k, serialized.get(n))
37
+
38
+ if val != UNSET_SENTINEL:
39
+ if val is not None or k not in optional_fields:
40
+ m[k] = val
41
+
42
+ return m
@@ -0,0 +1,57 @@
1
+ """Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
2
+
3
+ from __future__ import annotations
4
+ from permitstack.types import BaseModel, UNSET_SENTINEL
5
+ from pydantic import model_serializer
6
+ from typing import Any, List, Optional, Union
7
+ from typing_extensions import NotRequired, TypeAliasType, TypedDict
8
+
9
+
10
+ LocTypedDict = TypeAliasType("LocTypedDict", Union[str, int])
11
+
12
+
13
+ Loc = TypeAliasType("Loc", Union[str, int])
14
+
15
+
16
+ class ContextTypedDict(TypedDict):
17
+ pass
18
+
19
+
20
+ class Context(BaseModel):
21
+ pass
22
+
23
+
24
+ class ValidationErrorTypedDict(TypedDict):
25
+ loc: List[LocTypedDict]
26
+ msg: str
27
+ type: str
28
+ input: NotRequired[Any]
29
+ ctx: NotRequired[ContextTypedDict]
30
+
31
+
32
+ class ValidationError(BaseModel):
33
+ loc: List[Loc]
34
+
35
+ msg: str
36
+
37
+ type: str
38
+
39
+ input: Optional[Any] = None
40
+
41
+ ctx: Optional[Context] = None
42
+
43
+ @model_serializer(mode="wrap")
44
+ def serialize_model(self, handler):
45
+ optional_fields = set(["input", "ctx"])
46
+ serialized = handler(self)
47
+ m = {}
48
+
49
+ for n, f in type(self).model_fields.items():
50
+ k = f.alias or n
51
+ val = serialized.get(k, serialized.get(n))
52
+
53
+ if val != UNSET_SENTINEL:
54
+ if val is not None or k not in optional_fields:
55
+ m[k] = val
56
+
57
+ return m
@@ -0,0 +1,60 @@
1
+ """Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
2
+
3
+ from __future__ import annotations
4
+ from permitstack.types import (
5
+ BaseModel,
6
+ Nullable,
7
+ OptionalNullable,
8
+ UNSET,
9
+ UNSET_SENTINEL,
10
+ )
11
+ from pydantic import model_serializer
12
+ from typing_extensions import NotRequired, TypedDict
13
+
14
+
15
+ class WebhookCreateTypedDict(TypedDict):
16
+ url: str
17
+ city: NotRequired[Nullable[str]]
18
+ state: NotRequired[Nullable[str]]
19
+ category: NotRequired[Nullable[str]]
20
+ zip_code: NotRequired[Nullable[str]]
21
+ description: NotRequired[Nullable[str]]
22
+
23
+
24
+ class WebhookCreate(BaseModel):
25
+ url: str
26
+
27
+ city: OptionalNullable[str] = UNSET
28
+
29
+ state: OptionalNullable[str] = UNSET
30
+
31
+ category: OptionalNullable[str] = UNSET
32
+
33
+ zip_code: OptionalNullable[str] = UNSET
34
+
35
+ description: OptionalNullable[str] = UNSET
36
+
37
+ @model_serializer(mode="wrap")
38
+ def serialize_model(self, handler):
39
+ optional_fields = set(["city", "state", "category", "zip_code", "description"])
40
+ nullable_fields = set(["city", "state", "category", "zip_code", "description"])
41
+ serialized = handler(self)
42
+ m = {}
43
+
44
+ for n, f in type(self).model_fields.items():
45
+ k = f.alias or n
46
+ val = serialized.get(k, serialized.get(n))
47
+ is_nullable_and_explicitly_set = (
48
+ k in nullable_fields
49
+ and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member
50
+ )
51
+
52
+ if val != UNSET_SENTINEL:
53
+ if (
54
+ val is not None
55
+ or k not in optional_fields
56
+ or is_nullable_and_explicitly_set
57
+ ):
58
+ m[k] = val
59
+
60
+ return m