singlestoredb 1.16.1__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 (183) hide show
  1. singlestoredb/__init__.py +75 -0
  2. singlestoredb/ai/__init__.py +2 -0
  3. singlestoredb/ai/chat.py +139 -0
  4. singlestoredb/ai/embeddings.py +128 -0
  5. singlestoredb/alchemy/__init__.py +90 -0
  6. singlestoredb/apps/__init__.py +3 -0
  7. singlestoredb/apps/_cloud_functions.py +90 -0
  8. singlestoredb/apps/_config.py +72 -0
  9. singlestoredb/apps/_connection_info.py +18 -0
  10. singlestoredb/apps/_dashboards.py +47 -0
  11. singlestoredb/apps/_process.py +32 -0
  12. singlestoredb/apps/_python_udfs.py +100 -0
  13. singlestoredb/apps/_stdout_supress.py +30 -0
  14. singlestoredb/apps/_uvicorn_util.py +36 -0
  15. singlestoredb/auth.py +245 -0
  16. singlestoredb/config.py +484 -0
  17. singlestoredb/connection.py +1487 -0
  18. singlestoredb/converters.py +950 -0
  19. singlestoredb/docstring/__init__.py +33 -0
  20. singlestoredb/docstring/attrdoc.py +126 -0
  21. singlestoredb/docstring/common.py +230 -0
  22. singlestoredb/docstring/epydoc.py +267 -0
  23. singlestoredb/docstring/google.py +412 -0
  24. singlestoredb/docstring/numpydoc.py +562 -0
  25. singlestoredb/docstring/parser.py +100 -0
  26. singlestoredb/docstring/py.typed +1 -0
  27. singlestoredb/docstring/rest.py +256 -0
  28. singlestoredb/docstring/tests/__init__.py +1 -0
  29. singlestoredb/docstring/tests/_pydoctor.py +21 -0
  30. singlestoredb/docstring/tests/test_epydoc.py +729 -0
  31. singlestoredb/docstring/tests/test_google.py +1007 -0
  32. singlestoredb/docstring/tests/test_numpydoc.py +1100 -0
  33. singlestoredb/docstring/tests/test_parse_from_object.py +109 -0
  34. singlestoredb/docstring/tests/test_parser.py +248 -0
  35. singlestoredb/docstring/tests/test_rest.py +547 -0
  36. singlestoredb/docstring/tests/test_util.py +70 -0
  37. singlestoredb/docstring/util.py +141 -0
  38. singlestoredb/exceptions.py +120 -0
  39. singlestoredb/functions/__init__.py +16 -0
  40. singlestoredb/functions/decorator.py +201 -0
  41. singlestoredb/functions/dtypes.py +1793 -0
  42. singlestoredb/functions/ext/__init__.py +1 -0
  43. singlestoredb/functions/ext/arrow.py +375 -0
  44. singlestoredb/functions/ext/asgi.py +2133 -0
  45. singlestoredb/functions/ext/json.py +420 -0
  46. singlestoredb/functions/ext/mmap.py +413 -0
  47. singlestoredb/functions/ext/rowdat_1.py +724 -0
  48. singlestoredb/functions/ext/timer.py +89 -0
  49. singlestoredb/functions/ext/utils.py +218 -0
  50. singlestoredb/functions/signature.py +1578 -0
  51. singlestoredb/functions/typing/__init__.py +41 -0
  52. singlestoredb/functions/typing/numpy.py +20 -0
  53. singlestoredb/functions/typing/pandas.py +2 -0
  54. singlestoredb/functions/typing/polars.py +2 -0
  55. singlestoredb/functions/typing/pyarrow.py +2 -0
  56. singlestoredb/functions/utils.py +421 -0
  57. singlestoredb/fusion/__init__.py +11 -0
  58. singlestoredb/fusion/graphql.py +213 -0
  59. singlestoredb/fusion/handler.py +916 -0
  60. singlestoredb/fusion/handlers/__init__.py +0 -0
  61. singlestoredb/fusion/handlers/export.py +525 -0
  62. singlestoredb/fusion/handlers/files.py +690 -0
  63. singlestoredb/fusion/handlers/job.py +660 -0
  64. singlestoredb/fusion/handlers/models.py +250 -0
  65. singlestoredb/fusion/handlers/stage.py +502 -0
  66. singlestoredb/fusion/handlers/utils.py +324 -0
  67. singlestoredb/fusion/handlers/workspace.py +956 -0
  68. singlestoredb/fusion/registry.py +249 -0
  69. singlestoredb/fusion/result.py +399 -0
  70. singlestoredb/http/__init__.py +27 -0
  71. singlestoredb/http/connection.py +1267 -0
  72. singlestoredb/magics/__init__.py +34 -0
  73. singlestoredb/magics/run_personal.py +137 -0
  74. singlestoredb/magics/run_shared.py +134 -0
  75. singlestoredb/management/__init__.py +9 -0
  76. singlestoredb/management/billing_usage.py +148 -0
  77. singlestoredb/management/cluster.py +462 -0
  78. singlestoredb/management/export.py +295 -0
  79. singlestoredb/management/files.py +1102 -0
  80. singlestoredb/management/inference_api.py +105 -0
  81. singlestoredb/management/job.py +887 -0
  82. singlestoredb/management/manager.py +373 -0
  83. singlestoredb/management/organization.py +226 -0
  84. singlestoredb/management/region.py +169 -0
  85. singlestoredb/management/utils.py +423 -0
  86. singlestoredb/management/workspace.py +1927 -0
  87. singlestoredb/mysql/__init__.py +177 -0
  88. singlestoredb/mysql/_auth.py +298 -0
  89. singlestoredb/mysql/charset.py +214 -0
  90. singlestoredb/mysql/connection.py +2032 -0
  91. singlestoredb/mysql/constants/CLIENT.py +38 -0
  92. singlestoredb/mysql/constants/COMMAND.py +32 -0
  93. singlestoredb/mysql/constants/CR.py +78 -0
  94. singlestoredb/mysql/constants/ER.py +474 -0
  95. singlestoredb/mysql/constants/EXTENDED_TYPE.py +3 -0
  96. singlestoredb/mysql/constants/FIELD_TYPE.py +48 -0
  97. singlestoredb/mysql/constants/FLAG.py +15 -0
  98. singlestoredb/mysql/constants/SERVER_STATUS.py +10 -0
  99. singlestoredb/mysql/constants/VECTOR_TYPE.py +6 -0
  100. singlestoredb/mysql/constants/__init__.py +0 -0
  101. singlestoredb/mysql/converters.py +271 -0
  102. singlestoredb/mysql/cursors.py +896 -0
  103. singlestoredb/mysql/err.py +92 -0
  104. singlestoredb/mysql/optionfile.py +20 -0
  105. singlestoredb/mysql/protocol.py +450 -0
  106. singlestoredb/mysql/tests/__init__.py +19 -0
  107. singlestoredb/mysql/tests/base.py +126 -0
  108. singlestoredb/mysql/tests/conftest.py +37 -0
  109. singlestoredb/mysql/tests/test_DictCursor.py +132 -0
  110. singlestoredb/mysql/tests/test_SSCursor.py +141 -0
  111. singlestoredb/mysql/tests/test_basic.py +452 -0
  112. singlestoredb/mysql/tests/test_connection.py +851 -0
  113. singlestoredb/mysql/tests/test_converters.py +58 -0
  114. singlestoredb/mysql/tests/test_cursor.py +141 -0
  115. singlestoredb/mysql/tests/test_err.py +16 -0
  116. singlestoredb/mysql/tests/test_issues.py +514 -0
  117. singlestoredb/mysql/tests/test_load_local.py +75 -0
  118. singlestoredb/mysql/tests/test_nextset.py +88 -0
  119. singlestoredb/mysql/tests/test_optionfile.py +27 -0
  120. singlestoredb/mysql/tests/thirdparty/__init__.py +6 -0
  121. singlestoredb/mysql/tests/thirdparty/test_MySQLdb/__init__.py +9 -0
  122. singlestoredb/mysql/tests/thirdparty/test_MySQLdb/capabilities.py +323 -0
  123. singlestoredb/mysql/tests/thirdparty/test_MySQLdb/dbapi20.py +865 -0
  124. singlestoredb/mysql/tests/thirdparty/test_MySQLdb/test_MySQLdb_capabilities.py +110 -0
  125. singlestoredb/mysql/tests/thirdparty/test_MySQLdb/test_MySQLdb_dbapi20.py +224 -0
  126. singlestoredb/mysql/tests/thirdparty/test_MySQLdb/test_MySQLdb_nonstandard.py +101 -0
  127. singlestoredb/mysql/times.py +23 -0
  128. singlestoredb/notebook/__init__.py +16 -0
  129. singlestoredb/notebook/_objects.py +213 -0
  130. singlestoredb/notebook/_portal.py +352 -0
  131. singlestoredb/py.typed +0 -0
  132. singlestoredb/pytest.py +352 -0
  133. singlestoredb/server/__init__.py +0 -0
  134. singlestoredb/server/docker.py +452 -0
  135. singlestoredb/server/free_tier.py +267 -0
  136. singlestoredb/tests/__init__.py +0 -0
  137. singlestoredb/tests/alltypes.sql +307 -0
  138. singlestoredb/tests/alltypes_no_nulls.sql +208 -0
  139. singlestoredb/tests/empty.sql +0 -0
  140. singlestoredb/tests/ext_funcs/__init__.py +702 -0
  141. singlestoredb/tests/local_infile.csv +3 -0
  142. singlestoredb/tests/test.ipynb +18 -0
  143. singlestoredb/tests/test.sql +680 -0
  144. singlestoredb/tests/test2.ipynb +18 -0
  145. singlestoredb/tests/test2.sql +1 -0
  146. singlestoredb/tests/test_basics.py +1332 -0
  147. singlestoredb/tests/test_config.py +318 -0
  148. singlestoredb/tests/test_connection.py +3103 -0
  149. singlestoredb/tests/test_dbapi.py +27 -0
  150. singlestoredb/tests/test_exceptions.py +45 -0
  151. singlestoredb/tests/test_ext_func.py +1472 -0
  152. singlestoredb/tests/test_ext_func_data.py +1101 -0
  153. singlestoredb/tests/test_fusion.py +1527 -0
  154. singlestoredb/tests/test_http.py +288 -0
  155. singlestoredb/tests/test_management.py +1599 -0
  156. singlestoredb/tests/test_plugin.py +33 -0
  157. singlestoredb/tests/test_results.py +171 -0
  158. singlestoredb/tests/test_types.py +132 -0
  159. singlestoredb/tests/test_udf.py +737 -0
  160. singlestoredb/tests/test_udf_returns.py +459 -0
  161. singlestoredb/tests/test_vectorstore.py +51 -0
  162. singlestoredb/tests/test_xdict.py +333 -0
  163. singlestoredb/tests/utils.py +141 -0
  164. singlestoredb/types.py +373 -0
  165. singlestoredb/utils/__init__.py +0 -0
  166. singlestoredb/utils/config.py +950 -0
  167. singlestoredb/utils/convert_rows.py +69 -0
  168. singlestoredb/utils/debug.py +13 -0
  169. singlestoredb/utils/dtypes.py +205 -0
  170. singlestoredb/utils/events.py +65 -0
  171. singlestoredb/utils/mogrify.py +151 -0
  172. singlestoredb/utils/results.py +585 -0
  173. singlestoredb/utils/xdict.py +425 -0
  174. singlestoredb/vectorstore.py +192 -0
  175. singlestoredb/warnings.py +5 -0
  176. singlestoredb-1.16.1.dist-info/METADATA +165 -0
  177. singlestoredb-1.16.1.dist-info/RECORD +183 -0
  178. singlestoredb-1.16.1.dist-info/WHEEL +5 -0
  179. singlestoredb-1.16.1.dist-info/entry_points.txt +2 -0
  180. singlestoredb-1.16.1.dist-info/licenses/LICENSE +201 -0
  181. singlestoredb-1.16.1.dist-info/top_level.txt +3 -0
  182. sqlx/__init__.py +4 -0
  183. sqlx/magic.py +113 -0
@@ -0,0 +1,34 @@
1
+ from IPython.core.interactiveshell import InteractiveShell
2
+
3
+ from .run_personal import RunPersonalMagic
4
+ from .run_shared import RunSharedMagic
5
+
6
+ # In order to actually use these magics, we must register them with a
7
+ # running IPython.
8
+
9
+
10
+ def load_ipython_extension(ip: InteractiveShell) -> None:
11
+ """
12
+ Any module file that define a function named `load_ipython_extension`
13
+ can be loaded via `%load_ext module.path` or be configured to be
14
+ autoloaded by IPython at startup time.
15
+ """
16
+
17
+ # Load jupysql extension
18
+ # This is necessary for jupysql to initialize internal state
19
+ # required to render messages
20
+ assert ip.extension_manager is not None
21
+ result = ip.extension_manager.load_extension('sql')
22
+ if result == 'no load function':
23
+ raise RuntimeError('Could not load sql extension. Is jupysql installed?')
24
+
25
+ # Check if %run magic command is defined
26
+ if ip.find_line_magic('run') is None:
27
+ raise RuntimeError(
28
+ '%run magic command is not defined. '
29
+ 'Is it available in your IPython environment?',
30
+ )
31
+
32
+ # Register run_personal and run_shared
33
+ ip.register_magics(RunPersonalMagic(ip))
34
+ ip.register_magics(RunSharedMagic(ip))
@@ -0,0 +1,137 @@
1
+ import os
2
+ import tempfile
3
+ from pathlib import Path
4
+ from typing import Any
5
+ from warnings import warn
6
+
7
+ from IPython.core.interactiveshell import InteractiveShell
8
+ from IPython.core.magic import line_magic
9
+ from IPython.core.magic import Magics
10
+ from IPython.core.magic import magics_class
11
+ from IPython.core.magic import needs_local_scope
12
+ from IPython.core.magic import no_var_expand
13
+ from IPython.utils.contexts import preserve_keys
14
+ from IPython.utils.syspathcontext import prepended_to_syspath
15
+ from jinja2 import Template
16
+
17
+
18
+ @magics_class
19
+ class RunPersonalMagic(Magics):
20
+ def __init__(self, shell: InteractiveShell):
21
+ Magics.__init__(self, shell=shell)
22
+
23
+ @no_var_expand
24
+ @needs_local_scope
25
+ @line_magic('run_personal')
26
+ def run_personal(self, line: str, local_ns: Any = None) -> Any:
27
+ """
28
+ Downloads a personal file using the %sql magic and then runs it using %run.
29
+
30
+ Examples::
31
+
32
+ # Line usage
33
+
34
+ %run_personal personal_file.ipynb
35
+
36
+ %run_personal {{ sample_notebook_name }}
37
+
38
+ """
39
+
40
+ template = Template(line.strip())
41
+ personal_file = template.render(local_ns)
42
+ if not personal_file:
43
+ raise ValueError('No personal file specified.')
44
+ if (personal_file.startswith("'") and personal_file.endswith("'")) or \
45
+ (personal_file.startswith('"') and personal_file.endswith('"')):
46
+ personal_file = personal_file[1:-1]
47
+ if not personal_file:
48
+ raise ValueError('No personal file specified.')
49
+
50
+ with tempfile.TemporaryDirectory() as temp_dir:
51
+ temp_file_path = os.path.join(temp_dir, personal_file)
52
+ sql_command = (
53
+ f"DOWNLOAD PERSONAL FILE '{personal_file}' "
54
+ f"TO '{temp_file_path}'"
55
+ )
56
+
57
+ # Execute the SQL command
58
+ self.shell.run_line_magic('sql', sql_command)
59
+ # Run the downloaded file
60
+ with preserve_keys(self.shell.user_ns, '__file__'):
61
+ self.shell.user_ns['__file__'] = temp_file_path
62
+ self.safe_execfile_ipy(temp_file_path, raise_exceptions=True)
63
+
64
+ def safe_execfile_ipy(
65
+ self,
66
+ fname: str,
67
+ shell_futures: bool = False,
68
+ raise_exceptions: bool = False,
69
+ ) -> None:
70
+ """Like safe_execfile, but for .ipy or .ipynb files with IPython syntax.
71
+
72
+ Parameters
73
+ ----------
74
+ fname : str
75
+ The name of the file to execute. The filename must have a
76
+ .ipy or .ipynb extension.
77
+ shell_futures : bool (False)
78
+ If True, the code will share future statements with the interactive
79
+ shell. It will both be affected by previous __future__ imports, and
80
+ any __future__ imports in the code will affect the shell. If False,
81
+ __future__ imports are not shared in either direction.
82
+ raise_exceptions : bool (False)
83
+ If True raise exceptions everywhere. Meant for testing.
84
+ """
85
+ fpath = Path(fname).expanduser().resolve()
86
+
87
+ # Make sure we can open the file
88
+ try:
89
+ with fpath.open('rb'):
90
+ pass
91
+ except Exception:
92
+ warn('Could not open file <%s> for safe execution.' % fpath)
93
+ return
94
+
95
+ # Find things also in current directory. This is needed to mimic the
96
+ # behavior of running a script from the system command line, where
97
+ # Python inserts the script's directory into sys.path
98
+ dname = str(fpath.parent)
99
+
100
+ def get_cells() -> Any:
101
+ """generator for sequence of code blocks to run"""
102
+ if fpath.suffix == '.ipynb':
103
+ from nbformat import read
104
+ nb = read(fpath, as_version=4)
105
+ if not nb.cells:
106
+ return
107
+ for cell in nb.cells:
108
+ if cell.cell_type == 'code':
109
+ if not cell.source.strip():
110
+ continue
111
+ if getattr(cell, 'metadata', {}).get('language', '') == 'sql':
112
+ output_redirect = getattr(
113
+ cell, 'metadata', {},
114
+ ).get('output_variable', '') or ''
115
+ if output_redirect:
116
+ output_redirect = f' {output_redirect} <<'
117
+ yield f'%%sql{output_redirect}\n{cell.source}'
118
+ else:
119
+ yield cell.source
120
+ else:
121
+ yield fpath.read_text(encoding='utf-8')
122
+
123
+ with prepended_to_syspath(dname):
124
+ try:
125
+ for cell in get_cells():
126
+ result = self.shell.run_cell(
127
+ cell, silent=True, shell_futures=shell_futures,
128
+ )
129
+ if raise_exceptions:
130
+ result.raise_error()
131
+ elif not result.success:
132
+ break
133
+ except Exception:
134
+ if raise_exceptions:
135
+ raise
136
+ self.shell.showtraceback()
137
+ warn('Unknown failure executing file: <%s>' % fpath)
@@ -0,0 +1,134 @@
1
+ import os
2
+ import tempfile
3
+ from pathlib import Path
4
+ from typing import Any
5
+ from warnings import warn
6
+
7
+ from IPython.core.interactiveshell import InteractiveShell
8
+ from IPython.core.magic import line_magic
9
+ from IPython.core.magic import Magics
10
+ from IPython.core.magic import magics_class
11
+ from IPython.core.magic import needs_local_scope
12
+ from IPython.core.magic import no_var_expand
13
+ from IPython.utils.contexts import preserve_keys
14
+ from IPython.utils.syspathcontext import prepended_to_syspath
15
+ from jinja2 import Template
16
+
17
+
18
+ @magics_class
19
+ class RunSharedMagic(Magics):
20
+ def __init__(self, shell: InteractiveShell):
21
+ Magics.__init__(self, shell=shell)
22
+
23
+ @no_var_expand
24
+ @needs_local_scope
25
+ @line_magic('run_shared')
26
+ def run_shared(self, line: str, local_ns: Any = None) -> Any:
27
+ """
28
+ Downloads a shared file using the %sql magic and then runs it using %run.
29
+
30
+ Examples::
31
+
32
+ # Line usage
33
+
34
+ %run_shared shared_file.ipynb
35
+
36
+ %run_shared {{ sample_notebook_name }}
37
+
38
+ """
39
+
40
+ template = Template(line.strip())
41
+ shared_file = template.render(local_ns)
42
+ if not shared_file:
43
+ raise ValueError('No shared file specified.')
44
+ if (shared_file.startswith("'") and shared_file.endswith("'")) or \
45
+ (shared_file.startswith('"') and shared_file.endswith('"')):
46
+ shared_file = shared_file[1:-1]
47
+ if not shared_file:
48
+ raise ValueError('No personal file specified.')
49
+
50
+ with tempfile.TemporaryDirectory() as temp_dir:
51
+ temp_file_path = os.path.join(temp_dir, shared_file)
52
+ sql_command = f"DOWNLOAD SHARED FILE '{shared_file}' TO '{temp_file_path}'"
53
+
54
+ # Execute the SQL command
55
+ self.shell.run_line_magic('sql', sql_command)
56
+ # Run the downloaded file
57
+ with preserve_keys(self.shell.user_ns, '__file__'):
58
+ self.shell.user_ns['__file__'] = temp_file_path
59
+ self.safe_execfile_ipy(temp_file_path, raise_exceptions=True)
60
+
61
+ def safe_execfile_ipy(
62
+ self,
63
+ fname: str,
64
+ shell_futures: bool = False,
65
+ raise_exceptions: bool = False,
66
+ ) -> None:
67
+ """Like safe_execfile, but for .ipy or .ipynb files with IPython syntax.
68
+
69
+ Parameters
70
+ ----------
71
+ fname : str
72
+ The name of the file to execute. The filename must have a
73
+ .ipy or .ipynb extension.
74
+ shell_futures : bool (False)
75
+ If True, the code will share future statements with the interactive
76
+ shell. It will both be affected by previous __future__ imports, and
77
+ any __future__ imports in the code will affect the shell. If False,
78
+ __future__ imports are not shared in either direction.
79
+ raise_exceptions : bool (False)
80
+ If True raise exceptions everywhere. Meant for testing.
81
+ """
82
+ fpath = Path(fname).expanduser().resolve()
83
+
84
+ # Make sure we can open the file
85
+ try:
86
+ with fpath.open('rb'):
87
+ pass
88
+ except Exception:
89
+ warn('Could not open file <%s> for safe execution.' % fpath)
90
+ return
91
+
92
+ # Find things also in current directory. This is needed to mimic the
93
+ # behavior of running a script from the system command line, where
94
+ # Python inserts the script's directory into sys.path
95
+ dname = str(fpath.parent)
96
+
97
+ def get_cells() -> Any:
98
+ """generator for sequence of code blocks to run"""
99
+ if fpath.suffix == '.ipynb':
100
+ from nbformat import read
101
+ nb = read(fpath, as_version=4)
102
+ if not nb.cells:
103
+ return
104
+ for cell in nb.cells:
105
+ if cell.cell_type == 'code':
106
+ if not cell.source.strip():
107
+ continue
108
+ if getattr(cell, 'metadata', {}).get('language', '') == 'sql':
109
+ output_redirect = getattr(
110
+ cell, 'metadata', {},
111
+ ).get('output_variable', '') or ''
112
+ if output_redirect:
113
+ output_redirect = f' {output_redirect} <<'
114
+ yield f'%%sql{output_redirect}\n{cell.source}'
115
+ else:
116
+ yield cell.source
117
+ else:
118
+ yield fpath.read_text(encoding='utf-8')
119
+
120
+ with prepended_to_syspath(dname):
121
+ try:
122
+ for cell in get_cells():
123
+ result = self.shell.run_cell(
124
+ cell, silent=True, shell_futures=shell_futures,
125
+ )
126
+ if raise_exceptions:
127
+ result.raise_error()
128
+ elif not result.success:
129
+ break
130
+ except Exception:
131
+ if raise_exceptions:
132
+ raise
133
+ self.shell.showtraceback()
134
+ warn('Unknown failure executing file: <%s>' % fpath)
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env python
2
+ from .cluster import manage_cluster
3
+ from .files import manage_files
4
+ from .manager import get_token
5
+ from .region import manage_regions
6
+ from .workspace import get_organization
7
+ from .workspace import get_secret
8
+ from .workspace import get_stage
9
+ from .workspace import manage_workspaces
@@ -0,0 +1,148 @@
1
+ #!/usr/bin/env python
2
+ """SingleStoreDB Cloud Billing Usage."""
3
+ import datetime
4
+ from typing import Any
5
+ from typing import Dict
6
+ from typing import List
7
+ from typing import Optional
8
+
9
+ from .manager import Manager
10
+ from .utils import camel_to_snake
11
+ from .utils import vars_to_str
12
+
13
+
14
+ class UsageItem(object):
15
+ """Usage statistics."""
16
+
17
+ def __init__(
18
+ self,
19
+ start_time: datetime.datetime,
20
+ end_time: datetime.datetime,
21
+ owner_id: str,
22
+ resource_id: str,
23
+ resource_name: str,
24
+ resource_type: str,
25
+ value: str,
26
+ ):
27
+ #: Starting time for the usage duration
28
+ self.start_time = start_time
29
+
30
+ #: Ending time for the usage duration
31
+ self.end_time = end_time
32
+
33
+ #: Owner ID
34
+ self.owner_id = owner_id
35
+
36
+ #: Resource ID
37
+ self.resource_id = resource_id
38
+
39
+ #: Resource name
40
+ self.resource_name = resource_name
41
+
42
+ #: Resource type
43
+ self.resource_type = resource_type
44
+
45
+ #: Usage statistic value
46
+ self.value = value
47
+
48
+ self._manager: Optional[Manager] = None
49
+
50
+ def __str__(self) -> str:
51
+ """Return string representation."""
52
+ return vars_to_str(self)
53
+
54
+ def __repr__(self) -> str:
55
+ """Return string representation."""
56
+ return str(self)
57
+
58
+ @classmethod
59
+ def from_dict(
60
+ cls,
61
+ obj: Dict[str, Any],
62
+ manager: Manager,
63
+ ) -> 'UsageItem':
64
+ """
65
+ Convert dictionary to a ``UsageItem`` object.
66
+
67
+ Parameters
68
+ ----------
69
+ obj : dict
70
+ Key-value pairs to retrieve billling usage information from
71
+ manager : WorkspaceManager, optional
72
+ The WorkspaceManager the UsageItem belongs to
73
+
74
+ Returns
75
+ -------
76
+ :class:`UsageItem`
77
+
78
+ """
79
+ out = cls(
80
+ end_time=datetime.datetime.fromisoformat(obj['endTime']),
81
+ start_time=datetime.datetime.fromisoformat(obj['startTime']),
82
+ owner_id=obj['ownerId'],
83
+ resource_id=obj['resourceId'],
84
+ resource_name=obj['resourceName'],
85
+ resource_type=obj['resource_type'],
86
+ value=obj['value'],
87
+ )
88
+ out._manager = manager
89
+ return out
90
+
91
+
92
+ class BillingUsageItem(object):
93
+ """Billing usage item."""
94
+
95
+ def __init__(
96
+ self,
97
+ description: str,
98
+ metric: str,
99
+ usage: List[UsageItem],
100
+ ):
101
+ """Use :attr:`WorkspaceManager.billing.usage` instead."""
102
+ #: Description of the usage metric
103
+ self.description = description
104
+
105
+ #: Name of the usage metric
106
+ self.metric = metric
107
+
108
+ #: Usage statistics
109
+ self.usage = list(usage)
110
+
111
+ self._manager: Optional[Manager] = None
112
+
113
+ def __str__(self) -> str:
114
+ """Return string representation."""
115
+ return vars_to_str(self)
116
+
117
+ def __repr__(self) -> str:
118
+ """Return string representation."""
119
+ return str(self)
120
+
121
+ @ classmethod
122
+ def from_dict(
123
+ cls,
124
+ obj: Dict[str, Any],
125
+ manager: Manager,
126
+ ) -> 'BillingUsageItem':
127
+ """
128
+ Convert dictionary to a ``BillingUsageItem`` object.
129
+
130
+ Parameters
131
+ ----------
132
+ obj : dict
133
+ Key-value pairs to retrieve billling usage information from
134
+ manager : WorkspaceManager, optional
135
+ The WorkspaceManager the BillingUsageItem belongs to
136
+
137
+ Returns
138
+ -------
139
+ :class:`BillingUsageItem`
140
+
141
+ """
142
+ out = cls(
143
+ description=obj['description'],
144
+ metric=str(camel_to_snake(obj['metric'])),
145
+ usage=[UsageItem.from_dict(x, manager) for x in obj['Usage']],
146
+ )
147
+ out._manager = manager
148
+ return out