@seamapi/nextlove-sdk-generator 1.5.3 → 1.5.4

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. package/lib/endpoints-returning-deprecated-action-attempt.d.ts +2 -0
  2. package/lib/endpoints-returning-deprecated-action-attempt.js +10 -0
  3. package/lib/endpoints-returning-deprecated-action-attempt.js.map +1 -0
  4. package/lib/generate-php-sdk/generate-php-sdk.js +4 -18
  5. package/lib/generate-php-sdk/generate-php-sdk.js.map +1 -1
  6. package/lib/generate-php-sdk/utils/php-client.d.ts +3 -3
  7. package/lib/generate-php-sdk/utils/php-client.js.map +1 -1
  8. package/lib/generate-python-sdk/class-file.d.ts +15 -2
  9. package/lib/generate-python-sdk/class-file.js +140 -21
  10. package/lib/generate-python-sdk/class-file.js.map +1 -1
  11. package/lib/generate-python-sdk/generate-python-sdk.js +65 -17
  12. package/lib/generate-python-sdk/generate-python-sdk.js.map +1 -1
  13. package/lib/generate-python-sdk/map-python-type.d.ts +1 -1
  14. package/lib/generate-python-sdk/map-python-type.js +6 -2
  15. package/lib/generate-python-sdk/map-python-type.js.map +1 -1
  16. package/lib/generate-python-sdk/templates/.gitignore.template.d.ts +2 -0
  17. package/lib/generate-python-sdk/templates/.gitignore.template.js +12 -0
  18. package/lib/generate-python-sdk/templates/.gitignore.template.js.map +1 -0
  19. package/lib/generate-python-sdk/templates/__init__.py.template.d.ts +2 -0
  20. package/lib/generate-python-sdk/templates/__init__.py.template.js +7 -0
  21. package/lib/generate-python-sdk/templates/__init__.py.template.js.map +1 -0
  22. package/lib/generate-python-sdk/templates/conftest.py.template.js +75 -6
  23. package/lib/generate-python-sdk/templates/conftest.py.template.js.map +1 -1
  24. package/lib/generate-python-sdk/templates/prebuild.py.template.d.ts +2 -0
  25. package/lib/generate-python-sdk/templates/prebuild.py.template.js +13 -0
  26. package/lib/generate-python-sdk/templates/prebuild.py.template.js.map +1 -0
  27. package/lib/generate-python-sdk/templates/pyproject.toml.template.js +6 -2
  28. package/lib/generate-python-sdk/templates/pyproject.toml.template.js.map +1 -1
  29. package/lib/generate-python-sdk/templates/seam.py.template.js +90 -14
  30. package/lib/generate-python-sdk/templates/seam.py.template.js.map +1 -1
  31. package/lib/generate-python-sdk/templates/snippets/abstract-seam.template.js +12 -5
  32. package/lib/generate-python-sdk/templates/snippets/abstract-seam.template.js.map +1 -1
  33. package/lib/generate-python-sdk/templates/snippets/resource-dataclass.template.js +6 -1
  34. package/lib/generate-python-sdk/templates/snippets/resource-dataclass.template.js.map +1 -1
  35. package/lib/generate-python-sdk/templates/snippets/seam-api-exception-class.template.d.ts +2 -0
  36. package/lib/generate-python-sdk/templates/snippets/seam-api-exception-class.template.js +17 -0
  37. package/lib/generate-python-sdk/templates/snippets/seam-api-exception-class.template.js.map +1 -0
  38. package/lib/generate-python-sdk/templates/utils/get_sentry_dsn.py.template.d.ts +2 -0
  39. package/lib/generate-python-sdk/templates/utils/get_sentry_dsn.py.template.js +6 -0
  40. package/lib/generate-python-sdk/templates/utils/get_sentry_dsn.py.template.js.map +1 -0
  41. package/lib/generate-python-sdk/templates/utils/report_error.py.template.d.ts +2 -0
  42. package/lib/generate-python-sdk/templates/utils/report_error.py.template.js +17 -0
  43. package/lib/generate-python-sdk/templates/utils/report_error.py.template.js.map +1 -0
  44. package/lib/openapi/get-parameter-and-response-schema.js +9 -9
  45. package/lib/openapi/get-parameter-and-response-schema.js.map +1 -1
  46. package/lib/openapi/map-parent-to-children-resource.d.ts +3 -0
  47. package/lib/openapi/map-parent-to-children-resource.js +17 -0
  48. package/lib/openapi/map-parent-to-children-resource.js.map +1 -0
  49. package/package.json +1 -1
  50. package/src/lib/endpoints-returning-deprecated-action-attempt.ts +10 -0
  51. package/src/lib/generate-php-sdk/generate-php-sdk.ts +6 -30
  52. package/src/lib/generate-php-sdk/utils/php-client.ts +2 -2
  53. package/src/lib/generate-python-sdk/class-file.ts +232 -49
  54. package/src/lib/generate-python-sdk/generate-python-sdk.ts +96 -23
  55. package/src/lib/generate-python-sdk/map-python-type.ts +9 -3
  56. package/src/lib/generate-python-sdk/templates/.gitignore.template.ts +11 -0
  57. package/src/lib/generate-python-sdk/templates/__init__.py.template.ts +6 -0
  58. package/src/lib/generate-python-sdk/templates/conftest.py.template.ts +75 -6
  59. package/src/lib/generate-python-sdk/templates/prebuild.py.template.ts +12 -0
  60. package/src/lib/generate-python-sdk/templates/pyproject.toml.template.ts +6 -2
  61. package/src/lib/generate-python-sdk/templates/seam.py.template.ts +90 -14
  62. package/src/lib/generate-python-sdk/templates/snippets/abstract-seam.template.ts +12 -5
  63. package/src/lib/generate-python-sdk/templates/snippets/resource-dataclass.template.ts +9 -1
  64. package/src/lib/generate-python-sdk/templates/snippets/seam-api-exception-class.template.ts +16 -0
  65. package/src/lib/generate-python-sdk/templates/utils/get_sentry_dsn.py.template.ts +5 -0
  66. package/src/lib/generate-python-sdk/templates/utils/report_error.py.template.ts +16 -0
  67. package/src/lib/openapi/get-parameter-and-response-schema.ts +8 -11
  68. package/src/lib/openapi/map-parent-to-children-resource.ts +28 -0
@@ -1,6 +1,6 @@
1
1
  export default () => `[tool.poetry]
2
2
  name = "seamapi"
3
- version = "2.14.0"
3
+ version = "2.18.0"
4
4
  description = "A Python Library for Seam's API https://getseam.com"
5
5
  authors = ["Severin Ibarluzea <seveibar@gmail.com>"]
6
6
  license = "MIT"
@@ -8,13 +8,17 @@ license = "MIT"
8
8
  [tool.poetry.dependencies]
9
9
  python = "^3.7"
10
10
  requests = "^2.26.0"
11
+ dataclasses-json = "^0.5.6"
12
+ sentry-sdk = "^1.9.10"
11
13
 
12
14
  [tool.poetry.dev-dependencies]
13
15
  pytest = "^6.2.5"
14
16
  python-dotenv = "^0.19.2"
15
17
  black = "^21.12b0"
18
+ testcontainers = {extras = ["postgresql"], version = "^3.4.2"}
16
19
  responses = "^0.22.0"
17
20
 
18
21
  [build-system]
19
22
  requires = ["poetry-core>=1.0.0"]
20
- build-backend = "poetry.core.masonry.api"`
23
+ build-backend = "poetry.core.masonry.api"
24
+ `
@@ -1,19 +1,51 @@
1
1
  export default () => `import os
2
2
 
3
+ from seamapi.utils.get_sentry_dsn import get_sentry_dsn
3
4
  from .routes import Routes
4
5
  import requests
5
- from importlib.metadata import version
6
+ import sentry_sdk
7
+ import pkg_resources
6
8
  from typing import Optional, cast
7
- from .types import AbstractSeam, SeamAPIException
9
+ from .types import AbstractSeam, SeamApiException
8
10
 
9
11
 
10
12
  class Seam(AbstractSeam):
13
+ """
14
+ Initial Seam class used to interact with Seam API
15
+
16
+ ...
17
+
18
+ Attributes
19
+ ----------
20
+ api_key : str
21
+ API key (default None)
22
+ api_url : str
23
+ API url (default None)
24
+ workspaces : Workspaces
25
+ Workspaces class
26
+ connected_accounts : ConnectedAccounts
27
+ Connected accounts class
28
+ connect_webviews : ConnectWebviews
29
+ Connect webviews class
30
+ devices : Devices
31
+ Devices class
32
+ events : Events
33
+ Events class
34
+ locks : Locks
35
+ Locks class
36
+ access_codes : AccessCodes
37
+ Access codes class
38
+ action_attempts : ActionAttempts
39
+ Action attempts class
40
+ """
41
+
11
42
  api_key: str
12
43
  api_url: str = "https://connect.getseam.com"
13
44
 
14
45
  def __init__(
15
46
  self,
16
47
  api_key: Optional[str] = None,
48
+ workspace_id: Optional[str] = None,
17
49
  api_url: Optional[str] = None,
18
50
  should_report_exceptions: Optional[bool] = False,
19
51
  ):
@@ -22,8 +54,12 @@ class Seam(AbstractSeam):
22
54
  ----------
23
55
  api_key : str, optional
24
56
  API key
57
+ workspace_id : str, optional
58
+ Workspace id
25
59
  api_url : str, optional
26
60
  API url
61
+ should_report_exceptions : bool, optional
62
+ Defaults to False. If true, thrown exceptions will be reported to Seam.
27
63
  """
28
64
  Routes.__init__(self)
29
65
 
@@ -33,10 +69,34 @@ class Seam(AbstractSeam):
33
69
  raise Exception(
34
70
  "SEAM_API_KEY not found in environment, and api_key not provided"
35
71
  )
36
- if api_url is None:
37
- api_url = os.environ.get("SEAM_API_URL", self.api_url)
72
+ if workspace_id is None:
73
+ workspace_id = os.environ.get("SEAM_WORKSPACE_ID", None)
38
74
  self.api_key = api_key
39
- self.api_url = cast(str, api_url)
75
+ self.workspace_id = workspace_id
76
+
77
+ if os.environ.get("SEAM_API_URL", None) is not None:
78
+ print(
79
+ '\\n'
80
+ '\\033[93m'
81
+ 'Using the SEAM_API_URL environment variable is deprecated. '
82
+ 'Support will be removed in a later major version. Use SEAM_ENDPOINT instead.'
83
+ '\\033[0m'
84
+ )
85
+ api_url = os.environ.get("SEAM_API_URL", None) or os.environ.get("SEAM_ENDPOINT", None) or api_url
86
+ if api_url is not None:
87
+ self.api_url = cast(str, api_url)
88
+
89
+ self.should_report_exceptions = should_report_exceptions
90
+
91
+ if self.should_report_exceptions:
92
+ self.sentry_client = sentry_sdk.Hub(sentry_sdk.Client(
93
+ dsn=get_sentry_dsn(),
94
+ ))
95
+ self.sentry_client.scope.set_context("sdk_info", {
96
+ "repository": "https://github.com/seamapi/python",
97
+ "version": pkg_resources.get_distribution("seamapi").version,
98
+ "endpoint": self.api_url,
99
+ })
40
100
 
41
101
  def make_request(self, method: str, path: str, **kwargs):
42
102
  """
@@ -53,21 +113,37 @@ class Seam(AbstractSeam):
53
113
  """
54
114
 
55
115
  url = self.api_url + path
116
+ sdk_version = pkg_resources.get_distribution("seamapi").version
56
117
  headers = {
57
118
  "Authorization": "Bearer " + self.api_key,
58
119
  "Content-Type": "application/json",
59
- "User-Agent": "Python SDK v" + version("seamapi") + " (https://github.com/seamapi/python)",
120
+ "User-Agent": "Python SDK v" + sdk_version + " (https://github.com/seamapi/python)",
121
+ "seam-sdk-name": "seamapi/python",
122
+ "seam-sdk-version": sdk_version,
60
123
  }
124
+ if self.workspace_id is not None:
125
+ headers["seam-workspace"] = self.workspace_id
61
126
  response = requests.request(method, url, headers=headers, **kwargs)
62
127
 
63
- parsed_response = response.json()
128
+ if self.should_report_exceptions and response.status_code:
129
+ # Add breadcrumb
130
+ self.sentry_client.add_breadcrumb(
131
+ category="http",
132
+ level="info",
133
+ data={
134
+ "method": method,
135
+ "url": url,
136
+ "status_code": response.status_code,
137
+ "request_id": response.headers.get("seam-request-id", "unknown"),
138
+ },
139
+ )
140
+
64
141
 
65
142
  if response.status_code != 200:
66
- raise SeamAPIException(
67
- response.status_code,
68
- response.headers.get("seam-request-id", None),
69
- parsed_response["error"],
70
- )
71
- ## TODO automatically paginate if kwargs["auto_paginate"] is True
143
+ raise SeamApiException(response)
144
+
145
+ if "application/json" in response.headers["content-type"]:
146
+ return response.json()
72
147
 
73
- return parsed_response`
148
+ return response.text
149
+ `
@@ -1,8 +1,15 @@
1
1
  export default () => `@dataclass
2
2
  class AbstractSeam(AbstractRoutes):
3
- api_key: str
4
- api_url: str
3
+ api_key: str
4
+ workspace_id: str
5
+ api_url: str
5
6
 
6
- @abc.abstractmethod
7
- def __init__(self, api_key: Optional[str] = None):
8
- raise NotImplementedError`
7
+ @abc.abstractmethod
8
+ def __init__(
9
+ self,
10
+ api_key: Optional[str] = None,
11
+ workspace_id: Optional[str] = None,
12
+ api_url: Optional[str] = None,
13
+ should_report_exceptions: Optional[bool] = False,
14
+ ):
15
+ raise NotImplementedError`
@@ -11,5 +11,13 @@ ${parameters.map((p) => ` ${p.name}: ${p.type}`).join("\n")}
11
11
  @staticmethod
12
12
  def from_dict(d: Dict[str, Any]):
13
13
  return ${name}(
14
- ${parameters.map((p) => ` ${p.name}=d.get("${p.name}", None),`).join("\n")}
14
+ ${parameters
15
+ .map((p) => {
16
+ const is_dict_param = p.type.startsWith("Dict") || p.name === "properties"
17
+
18
+ return ` ${p.name}=${is_dict_param ? "DeepAttrDict(" : ""}d.get("${
19
+ p.name
20
+ }", None)${is_dict_param ? ")" : ""},`
21
+ })
22
+ .join("\n")}
15
23
  )`
@@ -0,0 +1,16 @@
1
+ export default () => `class SeamApiException(Exception):
2
+ def __init__(
3
+ self,
4
+ response,
5
+ ):
6
+ self.status_code = response.status_code
7
+ self.request_id = response.headers.get("seam-request-id", None)
8
+
9
+ self.metadata = None
10
+ if "application/json" in response.headers["content-type"]:
11
+ parsed_response = response.json()
12
+ self.metadata = parsed_response.get("error", None)
13
+
14
+ super().__init__(
15
+ f"SeamApiException: status={self.status_code}, request_id={self.request_id}, metadata={self.metadata}"
16
+ )`
@@ -0,0 +1,5 @@
1
+ export default () => `import os
2
+
3
+ def get_sentry_dsn():
4
+ # This is replaced with a hard-coded value during the build process (see scripts/prebuild.py)
5
+ return os.environ.get("SENTRY_DSN", None)`
@@ -0,0 +1,16 @@
1
+ export default () => `from seamapi.types import SeamApiException
2
+
3
+ """
4
+ A decorator for model methods that will report errors to Sentry (if enabled).
5
+ Expects that the model has a \`seam\` attribute that is a \`Seam\` instance.
6
+ """
7
+ def report_error(f):
8
+ def wrapper(self, *args, **kwargs):
9
+ try:
10
+ return f(self, *args, **kwargs)
11
+ except Exception as error:
12
+ if self.seam.should_report_exceptions and type(error) is not SeamApiException:
13
+ self.seam.sentry_client.capture_exception(error)
14
+
15
+ raise error
16
+ return wrapper`
@@ -44,16 +44,13 @@ export const getParameterAndResponseSchema = (route: Route) => {
44
44
  parameter_schema,
45
45
  nullable,
46
46
  }
47
- }
48
-
49
- const response_obj_type = response_obj_ref?.split("/")?.pop()!
50
- const response_arr_type = response_arr_ref?.split("/")?.pop()!
51
-
52
- return {
53
- response_obj_type,
54
- response_arr_type,
55
- parameter_schema,
56
- res_return_schema: res_return_schema as ObjSchema | undefined,
57
- nullable,
47
+ } else {
48
+ return {
49
+ response_obj_type: response_obj_ref?.split("/")?.pop(),
50
+ response_arr_type: response_arr_ref?.split("/")?.pop(),
51
+ parameter_schema,
52
+ res_return_schema: res_return_schema as ObjSchema | undefined,
53
+ nullable,
54
+ }
58
55
  }
59
56
  }
@@ -0,0 +1,28 @@
1
+ import type { Route } from "lib/types.js"
2
+
3
+ const mapParentToChildrenResources = (
4
+ routes: Route[]
5
+ ): Record<string, string[]> =>
6
+ routes.reduce((acc: Record<string, string[]>, route) => {
7
+ if (!route.post?.["x-fern-sdk-group-name"]) return acc
8
+
9
+ const [parent_resource_name, child_resource_name] =
10
+ route.post["x-fern-sdk-group-name"]
11
+
12
+ if (!parent_resource_name) return acc
13
+
14
+ if (!acc[parent_resource_name]) {
15
+ acc[parent_resource_name] = []
16
+ }
17
+
18
+ if (
19
+ child_resource_name &&
20
+ !acc[parent_resource_name]!.includes(child_resource_name)
21
+ ) {
22
+ acc[parent_resource_name]!.push(child_resource_name)
23
+ }
24
+
25
+ return acc
26
+ }, {})
27
+
28
+ export default mapParentToChildrenResources