meerschaum 2.3.5.dev0__py3-none-any.whl → 2.4.0.dev0__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 (62) hide show
  1. meerschaum/_internal/arguments/__init__.py +2 -1
  2. meerschaum/_internal/arguments/_parse_arguments.py +86 -7
  3. meerschaum/_internal/entry.py +29 -13
  4. meerschaum/actions/api.py +16 -16
  5. meerschaum/actions/bootstrap.py +36 -10
  6. meerschaum/actions/start.py +16 -15
  7. meerschaum/api/_events.py +11 -7
  8. meerschaum/api/dash/__init__.py +7 -6
  9. meerschaum/api/dash/callbacks/__init__.py +1 -0
  10. meerschaum/api/dash/callbacks/dashboard.py +7 -5
  11. meerschaum/api/dash/callbacks/pipes.py +42 -0
  12. meerschaum/api/dash/pages/__init__.py +1 -0
  13. meerschaum/api/dash/pages/pipes.py +16 -0
  14. meerschaum/api/dash/pipes.py +79 -47
  15. meerschaum/api/dash/users.py +19 -6
  16. meerschaum/api/routes/_actions.py +0 -98
  17. meerschaum/api/routes/_jobs.py +38 -18
  18. meerschaum/api/routes/_login.py +4 -4
  19. meerschaum/api/routes/_pipes.py +3 -3
  20. meerschaum/config/_default.py +9 -2
  21. meerschaum/config/_version.py +1 -1
  22. meerschaum/config/stack/__init__.py +59 -18
  23. meerschaum/config/static/__init__.py +2 -0
  24. meerschaum/connectors/Connector.py +19 -13
  25. meerschaum/connectors/__init__.py +9 -5
  26. meerschaum/connectors/api/_actions.py +22 -36
  27. meerschaum/connectors/api/_jobs.py +1 -0
  28. meerschaum/connectors/poll.py +30 -24
  29. meerschaum/connectors/sql/_pipes.py +126 -154
  30. meerschaum/connectors/sql/_plugins.py +45 -43
  31. meerschaum/connectors/sql/_users.py +46 -38
  32. meerschaum/connectors/valkey/ValkeyConnector.py +535 -0
  33. meerschaum/connectors/valkey/__init__.py +8 -0
  34. meerschaum/connectors/valkey/_fetch.py +75 -0
  35. meerschaum/connectors/valkey/_pipes.py +839 -0
  36. meerschaum/connectors/valkey/_plugins.py +265 -0
  37. meerschaum/connectors/valkey/_users.py +305 -0
  38. meerschaum/core/Pipe/__init__.py +2 -0
  39. meerschaum/core/Pipe/_attributes.py +1 -2
  40. meerschaum/core/Pipe/_drop.py +4 -4
  41. meerschaum/core/Pipe/_dtypes.py +14 -14
  42. meerschaum/core/Pipe/_edit.py +15 -14
  43. meerschaum/core/Pipe/_sync.py +134 -51
  44. meerschaum/core/User/_User.py +14 -12
  45. meerschaum/jobs/_Job.py +26 -8
  46. meerschaum/jobs/systemd.py +20 -8
  47. meerschaum/plugins/_Plugin.py +17 -13
  48. meerschaum/utils/_get_pipes.py +14 -20
  49. meerschaum/utils/dataframe.py +288 -101
  50. meerschaum/utils/dtypes/__init__.py +31 -6
  51. meerschaum/utils/dtypes/sql.py +4 -4
  52. meerschaum/utils/misc.py +3 -3
  53. meerschaum/utils/packages/_packages.py +1 -0
  54. meerschaum/utils/prompt.py +1 -1
  55. {meerschaum-2.3.5.dev0.dist-info → meerschaum-2.4.0.dev0.dist-info}/METADATA +3 -1
  56. {meerschaum-2.3.5.dev0.dist-info → meerschaum-2.4.0.dev0.dist-info}/RECORD +62 -54
  57. {meerschaum-2.3.5.dev0.dist-info → meerschaum-2.4.0.dev0.dist-info}/WHEEL +1 -1
  58. {meerschaum-2.3.5.dev0.dist-info → meerschaum-2.4.0.dev0.dist-info}/LICENSE +0 -0
  59. {meerschaum-2.3.5.dev0.dist-info → meerschaum-2.4.0.dev0.dist-info}/NOTICE +0 -0
  60. {meerschaum-2.3.5.dev0.dist-info → meerschaum-2.4.0.dev0.dist-info}/entry_points.txt +0 -0
  61. {meerschaum-2.3.5.dev0.dist-info → meerschaum-2.4.0.dev0.dist-info}/top_level.txt +0 -0
  62. {meerschaum-2.3.5.dev0.dist-info → meerschaum-2.4.0.dev0.dist-info}/zip-safe +0 -0
@@ -0,0 +1,265 @@
1
+ #! /usr/bin/env python3
2
+ # vim:fenc=utf-8
3
+
4
+ """
5
+ Define methods for registering plugins.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import json
11
+
12
+ import meerschaum as mrsm
13
+ from meerschaum.utils.typing import Optional, Any, List, SuccessTuple, Dict, Union
14
+
15
+ PLUGINS_TABLE: str = "mrsm_plugins"
16
+ PLUGIN_PREFIX: str = "mrsm_plugin"
17
+
18
+
19
+ def get_plugins_pipe(self) -> mrsm.Pipe:
20
+ """
21
+ Return the pipe to store the plugins.
22
+ """
23
+ return mrsm.Pipe(
24
+ 'mrsm', 'plugins',
25
+ columns=['plugin_name'],
26
+ temporary=True,
27
+ target=PLUGINS_TABLE,
28
+ instance=self,
29
+ )
30
+
31
+
32
+ @classmethod
33
+ def get_plugin_key(cls, plugin_name: str, sub_key: str) -> str:
34
+ """
35
+ Return the key for a plugin's attribute.
36
+ """
37
+ return cls.get_entity_key(PLUGIN_PREFIX, plugin_name, sub_key)
38
+
39
+
40
+ @classmethod
41
+ def get_plugin_keys_vals(
42
+ cls,
43
+ plugin: 'mrsm.core.Plugin',
44
+ mutable_only: bool = False,
45
+ ) -> Dict[str, str]:
46
+ """
47
+ Return a dictionary containing keys and values to set for the plugin.
48
+
49
+ Parameters
50
+ ----------
51
+ plugin: mrsm.core.Plugin
52
+ The plugin for which to generate the keys.
53
+
54
+ mutable_only: bool, default False
55
+ If `True`, only return keys which may be edited.
56
+
57
+ Returns
58
+ -------
59
+ A dictionary mapping a plugins's keys to values.
60
+ """
61
+ plugin_attributes_str = json.dumps(plugin.attributes, separators=(',', ':'))
62
+ mutable_keys_vals = {
63
+ cls.get_plugin_key(plugin.name, 'attributes'): plugin_attributes_str,
64
+ cls.get_plugin_key(plugin.name, 'version'): plugin.version,
65
+ }
66
+ if mutable_only:
67
+ return mutable_keys_vals
68
+
69
+ immutable_keys_vals = {
70
+ cls.get_plugin_key(plugin.name, 'user_id'): plugin.user_id,
71
+ }
72
+
73
+ return {**immutable_keys_vals, **mutable_keys_vals}
74
+
75
+
76
+ def register_plugin(
77
+ self,
78
+ plugin: 'mrsm.core.Plugin',
79
+ force: bool = False,
80
+ debug: bool = False,
81
+ **kw: Any
82
+ ) -> SuccessTuple:
83
+ """Register a new plugin to the `mrsm_plugins` "table"."""
84
+ from meerschaum.utils.misc import generate_password
85
+
86
+ plugins_pipe = self.get_plugins_pipe()
87
+ keys_vals = self.get_plugin_keys_vals(plugin)
88
+
89
+ try:
90
+ sync_success, sync_msg = plugins_pipe.sync(
91
+ [
92
+ {
93
+ 'plugin_name': plugin.name,
94
+ 'user_id': plugin.user_id,
95
+ },
96
+ ],
97
+ check_existing=False,
98
+ debug=debug,
99
+ )
100
+ if not sync_success:
101
+ return sync_success, sync_msg
102
+
103
+ for key, val in keys_vals.items():
104
+ if val is not None:
105
+ self.set(key, val)
106
+
107
+ success, msg = True, "Success"
108
+ except Exception as e:
109
+ success = False
110
+ msg = f"Failed to register plugin '{plugin.name}':\n{e}"
111
+
112
+ if not success:
113
+ for key in keys_vals:
114
+ try:
115
+ self.client.delete(key)
116
+ except Exception:
117
+ pass
118
+
119
+ return success, msg
120
+
121
+
122
+ def get_plugin_id(
123
+ self,
124
+ plugin: 'mrsm.core.Plugin',
125
+ debug: bool = False
126
+ ) -> Union[str, None]:
127
+ """
128
+ Return a plugin's ID.
129
+ """
130
+ return plugin.name
131
+
132
+
133
+ def get_plugin_version(
134
+ self,
135
+ plugin: 'mrsm.core.Plugin',
136
+ debug: bool = False,
137
+ ) -> Union[str, None]:
138
+ """
139
+ Return a plugin's version.
140
+ """
141
+ version_key = self.get_plugin_key(plugin.name, 'version')
142
+
143
+ try:
144
+ return self.get(version_key)
145
+ except Exception:
146
+ return None
147
+
148
+
149
+ def get_plugin_user_id(
150
+ self,
151
+ plugin: 'mrsm.core.Plugin',
152
+ debug: bool = False
153
+ ) -> Union[str, None]:
154
+ """
155
+ Return a plugin's user ID.
156
+ """
157
+ user_id_key = self.get_plugin_key(plugin.name, 'user_id')
158
+
159
+ try:
160
+ return self.get(user_id_key)
161
+ except Exception:
162
+ return None
163
+
164
+
165
+ def get_plugin_username(
166
+ self,
167
+ plugin: 'mrsm.core.Plugin',
168
+ debug: bool = False
169
+ ) -> Union[str]:
170
+ """
171
+ Return the username of a plugin's owner.
172
+ """
173
+ user_id = self.get_plugin_user_id(plugin, debug=debug)
174
+ if user_id is None:
175
+ return None
176
+
177
+ username_key = self.get_user_key(user_id, 'username')
178
+ try:
179
+ return self.get(username_key)
180
+ except Exception:
181
+ return None
182
+
183
+
184
+ def get_plugin_attributes(
185
+ self,
186
+ plugin: 'mrsm.core.Plugin',
187
+ debug: bool = False
188
+ ) -> Dict[str, Any]:
189
+ """
190
+ Return the attributes of a plugin.
191
+ """
192
+ attributes_key = self.get_plugin_key(plugin.name, 'attributes')
193
+ try:
194
+ attributes_str = self.get(attributes_key)
195
+ if not attributes_str:
196
+ return {}
197
+ return json.loads(attributes_str)
198
+ except Exception:
199
+ return {}
200
+
201
+
202
+ def get_plugins(
203
+ self,
204
+ user_id: Optional[int] = None,
205
+ search_term: Optional[str] = None,
206
+ debug: bool = False,
207
+ **kw: Any
208
+ ) -> List[str]:
209
+ """
210
+ Return a list of plugin names.
211
+ """
212
+ plugins_pipe = self.get_plugins_pipe()
213
+ params = {}
214
+ if user_id:
215
+ params['user_id'] = user_id
216
+
217
+ df = plugins_pipe.get_data(['plugin_name'], params=params, debug=debug)
218
+ docs = df.to_dict(orient='records')
219
+
220
+ return [
221
+ doc['plugin_name']
222
+ for doc in docs
223
+ if (plugin_name := doc['plugin_name']).startswith(search_term or '')
224
+ ]
225
+
226
+
227
+ def delete_plugin(
228
+ self,
229
+ plugin: 'mrsm.core.Plugin',
230
+ debug: bool = False,
231
+ **kw: Any
232
+ ) -> SuccessTuple:
233
+ """
234
+ Delete a plugin from the plugins table.
235
+ """
236
+ plugins_pipe = self.get_plugins_pipe()
237
+ clear_success, clear_msg = plugins_pipe.clear(params={'plugin_name': plugin.name}, debug=debug)
238
+ if not clear_success:
239
+ return clear_success, clear_msg
240
+
241
+ keys_vals = self.get_plugin_keys_vals(plugin)
242
+ try:
243
+ old_keys_vals = {
244
+ key: self.get(key)
245
+ for key in keys_vals
246
+ }
247
+ except Exception as e:
248
+ return False, f"Failed to delete plugin '{plugin.name}':\n{e}"
249
+
250
+ try:
251
+ for key in keys_vals:
252
+ self.client.delete(key)
253
+ success, msg = True, "Success"
254
+ except Exception as e:
255
+ success = False
256
+ msg = f"Failed to delete plugin '{plugin.name}':\n{e}"
257
+
258
+ if not success:
259
+ try:
260
+ for key, old_val in old_keys_vals.items():
261
+ self.set(key, old_val)
262
+ except Exception:
263
+ pass
264
+
265
+ return success, msg
@@ -0,0 +1,305 @@
1
+ #! /usr/bin/env python3
2
+ # vim:fenc=utf-8
3
+
4
+ """
5
+ Define methods for managing users.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import json
11
+
12
+ import meerschaum as mrsm
13
+ from meerschaum.utils.typing import Any, Union, SuccessTuple, Dict, List
14
+
15
+ USERS_TABLE: str = 'mrsm_users'
16
+ USER_PREFIX: str = 'mrsm_user'
17
+
18
+
19
+ def get_users_pipe(self):
20
+ """
21
+ Return the pipe which stores the registered users.
22
+ """
23
+ return mrsm.Pipe(
24
+ 'mrsm', 'users',
25
+ columns=['user_id'],
26
+ temporary=True,
27
+ target=USERS_TABLE,
28
+ instance=self,
29
+ )
30
+
31
+
32
+ @classmethod
33
+ def get_user_key(cls, user_id_or_username: str, sub_key: str, by_username: bool = False) -> str:
34
+ """
35
+ Return the key to store metadata about a user.
36
+
37
+ Parameters
38
+ ----------
39
+ user_id_or_username: str
40
+ The user ID or username of the given user.
41
+ If `by_username` is `True`, then provide the username.
42
+
43
+ sub_key: str
44
+ The key suffix, e.g. `'attributes'`.
45
+
46
+ by_username: bool, default False
47
+ If `True`, then treat `user_id_or_username` as a username.
48
+
49
+ Returns
50
+ -------
51
+ A key to store information about a user.
52
+
53
+ Examples
54
+ --------
55
+ >>> get_user_key('deadbeef', 'attributes')
56
+ 'mrsm_user:user_id:deadbeef:attributes'
57
+ >>> get_user_key('foo', 'user_id', by_username=True)
58
+ 'mrsm_user:username:foo:user_id'
59
+ """
60
+ key_type = 'user_id' if not by_username else 'username'
61
+ return cls.get_entity_key(USER_PREFIX, key_type, user_id_or_username, sub_key)
62
+
63
+
64
+ @classmethod
65
+ def get_user_keys_vals(
66
+ cls,
67
+ user: 'mrsm.core.User',
68
+ mutable_only: bool = False,
69
+ ) -> Dict[str, str]:
70
+ """
71
+ Return a dictionary containing keys and values to set for the user.
72
+
73
+ Parameters
74
+ ----------
75
+ user: mrsm.core.User
76
+ The user for which to generate the keys.
77
+
78
+ mutable_only: bool, default False
79
+ If `True`, only return keys which may be edited.
80
+
81
+ Returns
82
+ -------
83
+ A dictionary mapping a user's keys to values.
84
+ """
85
+ user_attributes_str = json.dumps(user.attributes, separators=(',', ':'))
86
+ mutable_keys_vals = {
87
+ cls.get_user_key(user.user_id, 'attributes'): user_attributes_str,
88
+ cls.get_user_key(user.user_id, 'email'): user.email,
89
+ cls.get_user_key(user.user_id, 'type'): user.type,
90
+ cls.get_user_key(user.user_id, 'password_hash'): user.password_hash,
91
+ }
92
+ if mutable_only:
93
+ return mutable_keys_vals
94
+
95
+ immutable_keys_vals = {
96
+ cls.get_user_key(user.user_id, 'username'): user.username,
97
+ cls.get_user_key(user.username, 'user_id', by_username=True): user.user_id,
98
+ }
99
+
100
+ return {**immutable_keys_vals, **mutable_keys_vals}
101
+
102
+
103
+ def register_user(
104
+ self,
105
+ user: 'mrsm.core.User',
106
+ debug: bool = False,
107
+ **kwargs: Any
108
+ ) -> SuccessTuple:
109
+ """
110
+ Register a new user.
111
+ """
112
+ from meerschaum.utils.misc import generate_password
113
+
114
+ user.user_id = generate_password(12)
115
+ users_pipe = self.get_users_pipe()
116
+ keys_vals = self.get_user_keys_vals(user)
117
+
118
+ try:
119
+ sync_success, sync_msg = users_pipe.sync(
120
+ [
121
+ {
122
+ 'user_id': user.user_id,
123
+ 'username': user.username,
124
+ },
125
+ ],
126
+ check_existing=False,
127
+ debug=debug,
128
+ )
129
+ if not sync_success:
130
+ return sync_success, sync_msg
131
+
132
+ for key, val in keys_vals.items():
133
+ if val is not None:
134
+ self.set(key, val)
135
+
136
+ success, msg = True, "Success"
137
+ except Exception as e:
138
+ success = False
139
+ import traceback
140
+ traceback.print_exc()
141
+ msg = f"Failed to register '{user.username}':\n{e}"
142
+
143
+ if not success:
144
+ for key in keys_vals:
145
+ try:
146
+ self.client.delete(key)
147
+ except Exception:
148
+ pass
149
+
150
+ return success, msg
151
+
152
+
153
+ def get_user_id(self, user: 'mrsm.core.User', debug: bool = False) -> Union[str, None]:
154
+ """
155
+ Return the ID for a user, or `None`.
156
+ """
157
+ username_user_id_key = self.get_user_key(user.username, 'user_id', by_username=True)
158
+ try:
159
+ user_id = self.get(username_user_id_key)
160
+ except Exception:
161
+ user_id = None
162
+ return user_id
163
+
164
+
165
+ def edit_user(
166
+ self,
167
+ user: 'mrsm.core.User',
168
+ debug: bool = False,
169
+ **kw: Any
170
+ ) -> SuccessTuple:
171
+ """
172
+ Edit the attributes for an existing user.
173
+ """
174
+ keys_vals = self.get_user_keys_vals(user, mutable_only=True)
175
+ try:
176
+ old_keys_vals = {
177
+ key: self.get(key)
178
+ for key in keys_vals
179
+ }
180
+ except Exception as e:
181
+ return False, f"Failed to edit user:\n{e}"
182
+
183
+ try:
184
+ for key, val in keys_vals.items():
185
+ self.set(key, val)
186
+ success, msg = True, "Success"
187
+ except Exception as e:
188
+ success = False
189
+ msg = f"Failed to edit user:\n{e}"
190
+
191
+ if not success:
192
+ try:
193
+ for key, old_val in old_keys_vals.items():
194
+ self.set(key, old_val)
195
+ except Exception:
196
+ pass
197
+
198
+ return success, msg
199
+
200
+
201
+ def get_user_attributes(
202
+ self,
203
+ user: 'mrsm.core.User',
204
+ debug: bool = False
205
+ ) -> Union[Dict[str, Any], None]:
206
+ """
207
+ Return the user's attributes.
208
+ """
209
+ user_id = user.user_id if user.user_id is not None else self.get_user_id(user, debug=debug)
210
+ user_id_attributes_key = self.get_user_key(user_id, 'attributes')
211
+ try:
212
+ return json.loads(self.get(user_id_attributes_key))
213
+ except Exception:
214
+ return None
215
+
216
+
217
+ def delete_user(
218
+ self,
219
+ user: 'mrsm.core.User',
220
+ debug: bool = False
221
+ ) -> SuccessTuple:
222
+ """
223
+ Delete a user's keys.
224
+ """
225
+ user_id = user.user_id if user.user_id is not None else self.get_user_id(user, debug=debug)
226
+ users_pipe = self.get_users_pipe()
227
+ keys_vals = self.get_user_keys_vals(user)
228
+ try:
229
+ old_keys_vals = {
230
+ key: self.get(key)
231
+ for key in keys_vals
232
+ }
233
+ except Exception as e:
234
+ return False, f"Failed to delete user:\n{e}"
235
+
236
+ clear_success, clear_msg = users_pipe.clear(params={'user_id': user_id})
237
+ if not clear_success:
238
+ return clear_success, clear_msg
239
+
240
+ try:
241
+ for key in keys_vals:
242
+ self.client.delete(key)
243
+ success, msg = True, "Success"
244
+ except Exception as e:
245
+ success = False
246
+ msg = f"Failed to delete user:\n{e}"
247
+
248
+ if not success:
249
+ try:
250
+ for key, old_val in old_keys_vals.items():
251
+ self.set(key, old_val)
252
+ except Exception:
253
+ pass
254
+
255
+ return success, msg
256
+
257
+
258
+ def get_users(
259
+ self,
260
+ debug: bool = False,
261
+ **kw: Any
262
+ ) -> List[str]:
263
+ """
264
+ Get the registered usernames.
265
+ """
266
+ users_pipe = self.get_users_pipe()
267
+ df = users_pipe.get_data()
268
+ if df is None:
269
+ return []
270
+
271
+ return list(df['username'])
272
+
273
+
274
+ def get_user_password_hash(
275
+ self,
276
+ user: 'mrsm.core.User',
277
+ debug: bool = False,
278
+ **kw: Any
279
+ ) -> Union[str, None]:
280
+ """
281
+ Return the password has for a user.
282
+ """
283
+ user_id = user.user_id if user.user_id is not None else self.get_user_id(user, debug=debug)
284
+ user_id_password_hash_key = self.get_user_key(user_id, 'password_hash')
285
+ try:
286
+ return self.get(user_id_password_hash_key)
287
+ except Exception:
288
+ return None
289
+
290
+
291
+ def get_user_type(
292
+ self,
293
+ user: 'mrsm.core.User',
294
+ debug: bool = False,
295
+ **kw: Any
296
+ ) -> Union[str, None]:
297
+ """
298
+ Return the user's type.
299
+ """
300
+ user_id = user.user_id if user.user_id is not None else self.get_user_id(user, debug=debug)
301
+ user_id_type_key = self.get_user_key(user_id, 'type')
302
+ try:
303
+ return self.get(user_id_type_key)
304
+ except Exception:
305
+ return None
@@ -121,6 +121,8 @@ class Pipe:
121
121
  filter_existing,
122
122
  _get_chunk_label,
123
123
  get_num_workers,
124
+ _persist_new_json_columns,
125
+ _persist_new_numeric_columns,
124
126
  )
125
127
  from ._verify import (
126
128
  verify,
@@ -122,8 +122,7 @@ def dtypes(self) -> Union[Dict[str, Any], None]:
122
122
  configured_dtypes = self.parameters.get('dtypes', {})
123
123
  remote_dtypes = self.infer_dtypes(persist=False)
124
124
  patched_dtypes = apply_patch_to_config(remote_dtypes, configured_dtypes)
125
- self.parameters['dtypes'] = patched_dtypes
126
- return self.parameters['dtypes']
125
+ return patched_dtypes
127
126
 
128
127
 
129
128
  @dtypes.setter
@@ -10,10 +10,10 @@ from __future__ import annotations
10
10
  from meerschaum.utils.typing import SuccessTuple, Any
11
11
 
12
12
  def drop(
13
- self,
14
- debug: bool = False,
15
- **kw: Any
16
- ) -> SuccessTuple:
13
+ self,
14
+ debug: bool = False,
15
+ **kw: Any
16
+ ) -> SuccessTuple:
17
17
  """
18
18
  Call the Pipe's instance connector's `drop_pipe()` method.
19
19
 
@@ -16,12 +16,12 @@ if TYPE_CHECKING:
16
16
  pd = mrsm.attempt_import('pandas')
17
17
 
18
18
  def enforce_dtypes(
19
- self,
20
- df: 'pd.DataFrame',
21
- chunksize: Optional[int] = -1,
22
- safe_copy: bool = True,
23
- debug: bool = False,
24
- ) -> 'pd.DataFrame':
19
+ self,
20
+ df: 'pd.DataFrame',
21
+ chunksize: Optional[int] = -1,
22
+ safe_copy: bool = True,
23
+ debug: bool = False,
24
+ ) -> 'pd.DataFrame':
25
25
  """
26
26
  Cast the input dataframe to the pipe's registered data types.
27
27
  If the pipe does not exist and dtypes are not set, return the dataframe.
@@ -35,7 +35,7 @@ def enforce_dtypes(
35
35
  if df is None:
36
36
  if debug:
37
37
  dprint(
38
- f"Received None instead of a DataFrame.\n"
38
+ "Received None instead of a DataFrame.\n"
39
39
  + " Skipping dtype enforcement..."
40
40
  )
41
41
  return df
@@ -46,24 +46,24 @@ def enforce_dtypes(
46
46
  if isinstance(df, str):
47
47
  df = parse_df_datetimes(
48
48
  pd.read_json(StringIO(df)),
49
- ignore_cols = [
49
+ ignore_cols=[
50
50
  col
51
51
  for col, dtype in pipe_dtypes.items()
52
52
  if 'datetime' not in str(dtype)
53
53
  ],
54
- chunksize = chunksize,
55
- debug = debug,
54
+ chunksize=chunksize,
55
+ debug=debug,
56
56
  )
57
57
  else:
58
58
  df = parse_df_datetimes(
59
59
  df,
60
- ignore_cols = [
60
+ ignore_cols=[
61
61
  col
62
62
  for col, dtype in pipe_dtypes.items()
63
63
  if 'datetime' not in str(dtype)
64
64
  ],
65
- chunksize = chunksize,
66
- debug = debug,
65
+ chunksize=chunksize,
66
+ debug=debug,
67
67
  )
68
68
  except Exception as e:
69
69
  warn(f"Unable to cast incoming data as a DataFrame...:\n{e}\n\n{traceback.format_exc()}")
@@ -80,7 +80,7 @@ def enforce_dtypes(
80
80
  return _enforce_dtypes(df, pipe_dtypes, safe_copy=safe_copy, debug=debug)
81
81
 
82
82
 
83
- def infer_dtypes(self, persist: bool=False, debug: bool=False) -> Dict[str, Any]:
83
+ def infer_dtypes(self, persist: bool = False, debug: bool = False) -> Dict[str, Any]:
84
84
  """
85
85
  If `dtypes` is not set in `meerschaum.Pipe.parameters`,
86
86
  infer the data types from the underlying table if it exists.