meerschaum 2.3.0rc5__py3-none-any.whl → 2.3.2__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.
meerschaum/__init__.py CHANGED
@@ -24,7 +24,7 @@ from meerschaum.utils.packages import attempt_import
24
24
  from meerschaum.core.Pipe import Pipe
25
25
  from meerschaum.plugins import Plugin
26
26
  from meerschaum.utils.venv import Venv
27
- from meerschaum.jobs import Job, Executor, make_executor
27
+ from meerschaum.jobs import Job, make_executor
28
28
  from meerschaum.connectors import get_connector, Connector, make_connector
29
29
  from meerschaum.utils import get_pipes
30
30
  from meerschaum.utils.formatting import pprint
@@ -45,13 +45,12 @@ __all__ = (
45
45
  "Venv",
46
46
  "Plugin",
47
47
  "Job",
48
- "Executor",
49
- "make_executor",
50
48
  "pprint",
51
49
  "attempt_import",
52
50
  "actions",
53
51
  "config",
54
52
  "connectors",
53
+ "jobs",
55
54
  "plugins",
56
55
  "utils",
57
56
  "SuccessTuple",
@@ -106,8 +106,8 @@ def parse_arguments(sysargs: List[str]) -> Dict[str, Any]:
106
106
  for i, word in enumerate(sysargs):
107
107
  is_sub_arg = False
108
108
  if not found_begin_decorator:
109
- found_begin_decorator = word.startswith(begin_decorator)
110
- found_end_decorator = word.endswith(end_decorator)
109
+ found_begin_decorator = str(word).startswith(begin_decorator)
110
+ found_end_decorator = str(word).endswith(end_decorator)
111
111
 
112
112
  if found_begin_decorator:
113
113
  ### check if sub arg is ever closed
@@ -117,15 +117,15 @@ def parse_arguments(sysargs: List[str]) -> Dict[str, Any]:
117
117
  found_begin_decorator = False
118
118
  elif found_end_decorator:
119
119
  for a in sysargs[:i]:
120
- if a.startswith(begin_decorator):
120
+ if str(a).startswith(begin_decorator):
121
121
  is_sub_arg = True
122
122
  found_begin_decorator = False
123
123
  if is_sub_arg:
124
124
  ### remove decorators
125
125
  sa = word
126
- if sa.startswith(begin_decorator):
126
+ if str(sa).startswith(begin_decorator):
127
127
  sa = sa[len(begin_decorator):]
128
- if sa.endswith(end_decorator):
128
+ if str(sa).endswith(end_decorator):
129
129
  sa = sa[:-1 * len(end_decorator)]
130
130
  sub_arguments.append(sa)
131
131
  ### remove sub-argument from action list
@@ -144,7 +144,7 @@ def parse_arguments(sysargs: List[str]) -> Dict[str, Any]:
144
144
  except Exception as e:
145
145
  _action = []
146
146
  for a in filtered_sysargs:
147
- if a.startswith('-'):
147
+ if str(a).startswith('-'):
148
148
  break
149
149
  _action.append(a)
150
150
  args_dict = {'action': _action, 'sysargs': sysargs}
@@ -267,7 +267,7 @@ def parse_dict_to_sysargs(
267
267
  action = args_dict.get('action', None)
268
268
  sysargs: List[str] = []
269
269
  sysargs.extend(action or [])
270
- allow_none_args = {'location_keys'}
270
+ allow_none_args = {'location_keys', 'begin', 'end', 'executor_keys'}
271
271
 
272
272
  triggers = get_arguments_triggers()
273
273
 
@@ -278,12 +278,18 @@ def parse_dict_to_sysargs(
278
278
  ### Add boolean flags
279
279
  if isinstance(args_dict[a], bool):
280
280
  if args_dict[a] is True:
281
- sysargs += [t[0]]
281
+ sysargs.extend([t[0]])
282
282
  else:
283
283
  ### Add list flags
284
284
  if isinstance(args_dict[a], (list, tuple)):
285
285
  if len(args_dict[a]) > 0:
286
- sysargs += [t[0]] + list(args_dict[a])
286
+ sysargs.extend(
287
+ [t[0]]
288
+ + [
289
+ str(item)
290
+ for item in args_dict[a]
291
+ ]
292
+ )
287
293
 
288
294
  ### Add dict flags
289
295
  elif isinstance(args_dict[a], dict):
@@ -292,7 +298,7 @@ def parse_dict_to_sysargs(
292
298
 
293
299
  ### Account for None and other values
294
300
  elif (args_dict[a] is not None) or (args_dict[a] is None and a in allow_none_args):
295
- sysargs += [t[0], args_dict[a]]
301
+ sysargs += [t[0], str(args_dict[a])]
296
302
 
297
303
  return sysargs
298
304
 
@@ -125,7 +125,7 @@ def parse_version(sysargs: List[str]):
125
125
  return print(doc)
126
126
 
127
127
 
128
- def parse_name(name_str: str) -> str:
128
+ def parse_name(name_str: str) -> Union[str, None]:
129
129
  """
130
130
  Ensure that `--name` is not an empty string.
131
131
  """
@@ -36,8 +36,9 @@ For your convenience, the following classes and functions may be imported from t
36
36
  <li><code>meerschaum.Connector</code></li>
37
37
  <li><code>meerschaum.Pipe</code></li>
38
38
  <li><code>meerschaum.Plugin</code></li>
39
- <li><code>meerschaum.SuccessTuple</code></li>
39
+ <li><code>meerschaum.Job</code></li>
40
40
  <li><code>meerschaum.Venv</code></li>
41
+ <li><code>meerschaum.SuccessTuple</code></li>
41
42
  </ul>
42
43
 
43
44
  </div>
@@ -54,6 +55,7 @@ For your convenience, the following classes and functions may be imported from t
54
55
  <li><code>meerschaum.make_connector()</code></li>
55
56
  <li><code>meerschaum.pprint()</code></li>
56
57
  <li><code>meerschaum.attempt_import()</code></li>
58
+ <li><code>meerschaum.entry()</code></li>
57
59
  </ul>
58
60
 
59
61
  </div>
@@ -61,7 +63,10 @@ For your convenience, the following classes and functions may be imported from t
61
63
 
62
64
  ### Examples
63
65
 
64
- #### Build a Connector
66
+ <details>
67
+ <summary><b>Build a Connector</b></summary>
68
+
69
+ Get existing connectors or build a new one in-memory with the `meerschaum.get_connector()` factory function:
65
70
 
66
71
  ```python
67
72
  import meerschaum as mrsm
@@ -80,9 +85,14 @@ sql_conn.to_sql(df, 'foo')
80
85
  print(sql_conn.read('foo'))
81
86
  # foo
82
87
  # 0 1
88
+
83
89
  ```
90
+ </details>
91
+
92
+ <details>
93
+ <summary><b>Create a Custom Connector Class</b></summary>
84
94
 
85
- #### Create a Custom Connector Class
95
+ Decorate your connector classes with `meerschaum.make_connector()` to designate it as a custom connector:
86
96
 
87
97
  ```python
88
98
  from datetime import datetime, timezone
@@ -113,8 +123,12 @@ foo_conn = mrsm.get_connector(
113
123
  )
114
124
  docs = foo_conn.fetch()
115
125
  ```
126
+ </details>
116
127
 
117
- #### Build a Pipe
128
+ <details>
129
+ <summary><b>Build a Pipe</b></summary>
130
+
131
+ Build a `meerschaum.Pipe` in-memory:
118
132
 
119
133
  ```python
120
134
  from datetime import datetime
@@ -135,7 +149,23 @@ print(df)
135
149
  # 2 2024-01-01 3 96
136
150
  ```
137
151
 
138
- #### Get Registered Pipes
152
+ Add `temporary=True` to skip registering the pipe in the pipes table.
153
+
154
+ </details>
155
+
156
+ <details>
157
+ <summary><b>Get Registered Pipes</b></summary>
158
+
159
+ The `meerschaum.get_pipes()` function returns a dictionary hierarchy of pipes by connector, metric, and location:
160
+
161
+ ```python
162
+ import meerschaum as mrsm
163
+
164
+ pipes = mrsm.get_pipes(instance='sql:temp')
165
+ pipe = pipes['foo:bar']['demo'][None]
166
+ ```
167
+
168
+ Add `as_list=True` to flatten the hierarchy:
139
169
 
140
170
  ```python
141
171
  import meerschaum as mrsm
@@ -148,8 +178,12 @@ pipes = mrsm.get_pipes(
148
178
  print(pipes)
149
179
  # [Pipe('foo:bar', 'demo', instance='sql:temp')]
150
180
  ```
181
+ </details>
151
182
 
152
- #### Access a Plugin's Module
183
+ <details>
184
+ <summary><b>Import Plugins</b></summary>
185
+
186
+ You can import a plugin's module through `meerschaum.Plugin.module`:
153
187
 
154
188
  ```python
155
189
  import meerschaum as mrsm
@@ -157,10 +191,211 @@ import meerschaum as mrsm
157
191
  plugin = mrsm.Plugin('noaa')
158
192
  with mrsm.Venv(plugin):
159
193
  noaa = plugin.module
160
- print(noaa.get_station_info('KGMU'))
161
- # {'name': 'Greenville Downtown Airport', 'geometry': {'type': 'Point', 'coordinates': [-82.35004, 34.84873]}}
162
194
  ```
163
195
 
196
+ If your plugin has submodules, use `meerschaum.plugins.from_plugin_import`:
197
+
198
+ ```python
199
+ from meerschaum.plugins import from_plugin_import
200
+ get_defined_pipes = from_plugin_import('compose.utils.pipes', 'get_defined_pipes')
201
+ ```
202
+
203
+ Import multiple plugins with `meerschaum.plugins.import_plugins`:
204
+
205
+ ```python
206
+ from meerschaum.plugins import import_plugins
207
+ noaa, compose = import_plugins('noaa', 'compose')
208
+ ```
209
+
210
+ </details>
211
+
212
+ <details>
213
+ <summary><b>Create a Job</b></summary>
214
+
215
+ Create a `meerschaum.Job` with `name` and `sysargs`:
216
+
217
+ ```python
218
+ import meerschaum as mrsm
219
+
220
+ job = mrsm.Job('syncing-engine', 'sync pipes --loop')
221
+ success, msg = job.start()
222
+ ```
223
+
224
+ Pass `executor_keys` as the connectors keys of an API instance to create a remote job:
225
+
226
+ ```python
227
+ import meerschaum as mrsm
228
+
229
+ job = mrsm.Job(
230
+ 'foo',
231
+ 'sync pipes -s daily',
232
+ executor_keys='api:main',
233
+ )
234
+ ```
235
+
236
+ </details>
237
+
238
+ <details>
239
+ <summary><b>Import from a Virtual Environment</b></summary>
240
+ Use the `meerschaum.Venv` context manager to activate a virtual environment:
241
+ ```python
242
+ import meerschaum as mrsm
243
+
244
+ with mrsm.Venv('noaa'):
245
+ import requests
246
+
247
+ print(requests.__file__)
248
+ # /home/bmeares/.config/meerschaum/venvs/noaa/lib/python3.12/site-packages/requests/__init__.py
249
+ ```
250
+
251
+ To import packages which may not be installed, use `meerschaum.attempt_import()`:
252
+
253
+ ```python
254
+ import meerschaum as mrsm
255
+
256
+ requests = mrsm.attempt_import('requests', venv='noaa')
257
+ print(requests.__file__)
258
+ # /home/bmeares/.config/meerschaum/venvs/noaa/lib/python3.12/site-packages/requests/__init__.py
259
+ ```
260
+
261
+ </details>
262
+
263
+ <details>
264
+ <summary><b>Run Actions</b></summary>
265
+
266
+ Run `sysargs` with `meerschaum.entry()`:
267
+
268
+ ```python
269
+ import meerschaum as mrsm
270
+
271
+ success, msg = mrsm.entry('show pipes + show version : x2')
272
+ ```
273
+
274
+ Use `meerschaum.actions.get_action()` to access an action function directly:
275
+
276
+ ```python
277
+ from meerschaum.actions import get_action
278
+
279
+ show_pipes = get_action(['show', 'pipes'])
280
+ success, msg = show_pipes(connector_keys=['plugin:noaa'])
281
+ ```
282
+
283
+ Get a dictionary of available subactions with `meerschaum.actions.get_subactions()`:
284
+
285
+ ```python
286
+ from meerschaum.actions import get_subactions
287
+
288
+ subactions = get_subactions('show')
289
+ success, msg = subactions['pipes']()
290
+ ```
291
+
292
+ </details>
293
+
294
+ <details>
295
+ <summary><b>Create a Plugin</b></summary>
296
+
297
+ Run `bootstrap plugin` to create a new plugin:
298
+
299
+ ```
300
+ mrsm bootstrap plugin example
301
+ ```
302
+
303
+ This will create `example.py` in your plugins directory (default `~/.config/meerschaum/plugins/`, Windows: `%APPDATA%\Meerschaum\plugins`). You may paste the example code from the "Create a Custom Action" example below.
304
+
305
+ Open your plugin with `edit plugin`:
306
+
307
+ ```
308
+ mrsm edit plugin example
309
+ ```
310
+
311
+ *Run `edit plugin` and paste the example code below to try out the features.*
312
+
313
+ See the [writing plugins guide](https://meerschaum.io/reference/plugins/writing-plugins/) for more in-depth documentation.
314
+
315
+ </details>
316
+
317
+ <details>
318
+ <summary><b>Create a Custom Action</b></summary>
319
+
320
+ Decorate a function with `meerschaum.actions.make_action` to designate it as an action. Subactions will be automatically detected if not decorated:
321
+
322
+ ```python
323
+ from meerschaum.actions import make_action
324
+
325
+ @make_action
326
+ def sing():
327
+ print('What would you like me to sing?')
328
+ return True, "Success"
329
+
330
+ def sing_tune():
331
+ return False, "I don't know that song!"
332
+
333
+ def sing_song():
334
+ print('Hello, World!')
335
+ return True, "Success"
336
+
337
+ ```
338
+
339
+ Use `meerschaum.plugins.add_plugin_argument()` to create new parameters for your action:
340
+
341
+ ```python
342
+ from meerschaum.plugins import make_action, add_plugin_argument
343
+
344
+ add_plugin_argument(
345
+ '--song', type=str, help='What song to sing.',
346
+ )
347
+
348
+ @make_action
349
+ def sing_melody(action=None, song=None):
350
+ to_sing = action[0] if action else song
351
+ if not to_sing:
352
+ return False, "Please tell me what to sing!"
353
+
354
+ return True, f'~I am singing {to_sing}~'
355
+ ```
356
+
357
+ ```
358
+ mrsm sing melody lalala
359
+
360
+ mrsm sing melody --song do-re-mi
361
+ ```
362
+
363
+ </details>
364
+
365
+ <details>
366
+ <summary><b>Add a Page to the Web Dashboard</b></summary>
367
+ Use the decorators `meerschaum.plugins.dash_plugin()` and `meerschaum.plugins.web_page()` to add new pages to the web dashboard:
368
+
369
+ ```python
370
+ from meerschaum.plugins import dash_plugin, web_page
371
+
372
+ @dash_plugin
373
+ def init_dash(dash_app):
374
+
375
+ import dash.html as html
376
+ import dash_bootstrap_components as dbc
377
+ from dash import Input, Output, no_update
378
+
379
+ ### Routes to '/dash/my-page'
380
+ @web_page('/my-page', login_required=False)
381
+ def my_page():
382
+ return dbc.Container([
383
+ html.H1("Hello, World!"),
384
+ dbc.Button("Click me", id='my-button'),
385
+ html.Div(id="my-output-div"),
386
+ ])
387
+
388
+ @dash_app.callback(
389
+ Output('my-output-div', 'children'),
390
+ Input('my-button', 'n_clicks'),
391
+ )
392
+ def my_button_click(n_clicks):
393
+ if not n_clicks:
394
+ return no_update
395
+ return html.P(f'You clicked {n_clicks} times!')
396
+ ```
397
+ </details>
398
+
164
399
  ## Submodules
165
400
 
166
401
  <details>
@@ -206,6 +441,28 @@ with mrsm.Venv(plugin):
206
441
 
207
442
  </details>
208
443
 
444
+ <details>
445
+ <summary>
446
+ `meerschaum.jobs`<br>
447
+ Start background jobs.
448
+ </summary>
449
+
450
+ - `meerschaum.jobs.Job`
451
+ - `meerschaum.jobs.Executor`
452
+ - `meerschaum.jobs.systemd.SystemdExecutor`
453
+ - `meerschaum.jobs.get_jobs()`
454
+ - `meerschaum.jobs.get_filtered_jobs()`
455
+ - `meerschaum.jobs.get_running_jobs()`
456
+ - `meerschaum.jobs.get_stopped_jobs()`
457
+ - `meerschaum.jobs.get_paused_jobs()`
458
+ - `meerschaum.jobs.get_restart_jobs()`
459
+ - `meerschaum.jobs.make_executor()`
460
+ - `meerschaum.jobs.check_restart_jobs()`
461
+ - `meerschaum.jobs.start_check_jobs_thread()`
462
+ - `meerschaum.jobs.stop_check_jobs_thread()`
463
+
464
+ </details>
465
+
209
466
  <details>
210
467
  <summary>
211
468
  `meerschaum.plugins`<br>
@@ -11,6 +11,16 @@ from meerschaum.utils.typing import Callable, Any, Optional, Union, List, Dict,
11
11
  from meerschaum.utils.packages import get_modules_from_package
12
12
  _custom_actions = []
13
13
 
14
+ __all__ = (
15
+ 'get_action',
16
+ 'get_subactions',
17
+ 'make_action',
18
+ 'pre_sync_hook',
19
+ 'post_sync_hook',
20
+ 'get_main_action_name',
21
+ 'get_completer',
22
+ )
23
+
14
24
  def get_subactions(
15
25
  action: Union[str, List[str]],
16
26
  _actions: Optional[Dict[str, Callable[[Any], Any]]] = None,
@@ -101,9 +111,9 @@ def get_action(
101
111
 
102
112
 
103
113
  def get_main_action_name(
104
- action: Union[List[str], str],
105
- _actions: Optional[Dict[str, Callable[[Any], SuccessTuple]]] = None,
106
- ) -> Union[str, None]:
114
+ action: Union[List[str], str],
115
+ _actions: Optional[Dict[str, Callable[[Any], SuccessTuple]]] = None,
116
+ ) -> Union[str, None]:
107
117
  """
108
118
  Given an action list, return the name of the main function.
109
119
  For subactions, this will return the root function.
@@ -140,9 +150,9 @@ def get_main_action_name(
140
150
 
141
151
 
142
152
  def get_completer(
143
- action: Union[List[str], str],
144
- _actions: Optional[Dict[str, Callable[[Any], SuccessTuple]]] = None,
145
- ) -> Union[
153
+ action: Union[List[str], str],
154
+ _actions: Optional[Dict[str, Callable[[Any], SuccessTuple]]] = None,
155
+ ) -> Union[
146
156
  Callable[['meerschaum._internal.shell.Shell', str, str, int, int], List[str]], None
147
157
  ]:
148
158
  """Search for a custom completer function for an action."""
@@ -179,10 +189,10 @@ def get_completer(
179
189
 
180
190
 
181
191
  def choose_subaction(
182
- action: Optional[List[str]] = None,
183
- options: Optional[Dict[str, Any]] = None,
184
- **kw
185
- ) -> SuccessTuple:
192
+ action: Optional[List[str]] = None,
193
+ options: Optional[Dict[str, Any]] = None,
194
+ **kw
195
+ ) -> SuccessTuple:
186
196
  """
187
197
  Given a dictionary of options and the standard Meerschaum actions list,
188
198
  check if choice is valid and execute chosen function, else show available
@@ -247,7 +257,7 @@ def _get_subaction_names(action: str, globs: dict = None) -> List[str]:
247
257
  return subactions
248
258
 
249
259
 
250
- def choices_docstring(action: str, globs : Optional[Dict[str, Any]] = None) -> str:
260
+ def choices_docstring(action: str, globs: Optional[Dict[str, Any]] = None) -> str:
251
261
  """
252
262
  Append the an action's available options to the module docstring.
253
263
  This function is to be placed at the bottom of each action module.
@@ -79,7 +79,13 @@ def _restart_jobs(
79
79
  action = action or []
80
80
 
81
81
  while True:
82
- jobs = get_filtered_jobs(executor_keys, action, include_hidden=True, debug=debug)
82
+ jobs = get_filtered_jobs(
83
+ executor_keys or 'local',
84
+ action,
85
+ include_hidden=True,
86
+ combine_local_and_systemd=False,
87
+ debug=debug,
88
+ )
83
89
  restart_jobs = get_restart_jobs(executor_keys, jobs, debug=debug) if not action else jobs
84
90
  if not restart_jobs and not loop:
85
91
  return True, "No jobs need to be restarted."
@@ -99,7 +99,7 @@ def _start_jobs(
99
99
  To start a stopped job, pass the job name after `start job`.
100
100
 
101
101
  You may also run a background job with the `-d` or `--daemon` flags.
102
-
102
+
103
103
  Examples:
104
104
 
105
105
  Create new jobs:
@@ -108,9 +108,9 @@ def _start_jobs(
108
108
  Run the action `sync pipes --loop` as a background job.
109
109
  Generates a random name; e.g. 'happy_seal'.
110
110
 
111
- - `start api --daemon --name api_server`
111
+ - `start api --daemon --name api-server`
112
112
  Run the action `start api` as a background job, and assign the job
113
- the name 'api_server'.
113
+ the name 'api-server'.
114
114
 
115
115
  Start stopped jobs:
116
116
 
@@ -119,7 +119,6 @@ def _start_jobs(
119
119
 
120
120
  - `start job --name happy_seal`
121
121
  Start the job 'happy_seal' but via the `--name` flag.
122
- This only applies when no text follows the words 'start job'.
123
122
  """
124
123
  from meerschaum.utils.warnings import warn, info
125
124
  from meerschaum.utils.daemon._names import get_new_daemon_name
@@ -128,7 +128,7 @@ def clean_sysargs(sysargs: List[str]) -> List[str]:
128
128
  @app.post(endpoints['jobs'] + '/{name}', tags=['Jobs'])
129
129
  def create_job(
130
130
  name: str,
131
- sysargs: List[str],
131
+ metadata: Union[List[str], Dict[str, Any]],
132
132
  curr_user=(
133
133
  fastapi.Depends(manager) if not no_auth else None
134
134
  ),
@@ -136,7 +136,14 @@ def create_job(
136
136
  """
137
137
  Create and start a new job.
138
138
  """
139
- job = Job(name, clean_sysargs(sysargs), executor_keys=EXECUTOR_KEYS)
139
+ sysargs = metadata if isinstance(metadata, list) else metadata['sysargs']
140
+ properties = metadata['properties'] if isinstance(metadata, dict) else None
141
+ job = Job(
142
+ name,
143
+ clean_sysargs(sysargs),
144
+ executor_keys=EXECUTOR_KEYS,
145
+ _properties=properties,
146
+ )
140
147
  if job.exists():
141
148
  raise fastapi.HTTPException(
142
149
  status_code=409,
@@ -112,6 +112,7 @@ default_system_config = {
112
112
  'join_fetch': False,
113
113
  'inplace_sync': True,
114
114
  'uv_pip': True,
115
+ 'systemd_healthcheck': False,
115
116
  },
116
117
  }
117
118
  default_pipes_config = {
@@ -2,4 +2,4 @@
2
2
  Specify the Meerschaum release version.
3
3
  """
4
4
 
5
- __version__ = "2.3.0rc5"
5
+ __version__ = "2.3.2"
@@ -377,5 +377,4 @@ def _load_builtin_custom_connectors():
377
377
  """
378
378
  Import custom connectors decorated with `@make_connector` or `@make_executor`.
379
379
  """
380
- import meerschaum.jobs._SystemdExecutor
381
- # import meerschaum.jobs._LocalExecutor
380
+ import meerschaum.jobs.systemd
@@ -12,7 +12,7 @@ import json
12
12
  from datetime import datetime
13
13
 
14
14
  import meerschaum as mrsm
15
- from meerschaum.utils.typing import Dict, Any, SuccessTuple, List, Union, Callable
15
+ from meerschaum.utils.typing import Dict, Any, SuccessTuple, List, Union, Callable, Optional
16
16
  from meerschaum.jobs import Job
17
17
  from meerschaum.config.static import STATIC_CONFIG
18
18
  from meerschaum.utils.warnings import warn, dprint
@@ -184,11 +184,24 @@ def start_job(self, name: str, debug: bool = False) -> SuccessTuple:
184
184
  return tuple(response.json())
185
185
 
186
186
 
187
- def create_job(self, name: str, sysargs: List[str], debug: bool = False) -> SuccessTuple:
187
+ def create_job(
188
+ self,
189
+ name: str,
190
+ sysargs: List[str],
191
+ properties: Optional[Dict[str, str]] = None,
192
+ debug: bool = False,
193
+ ) -> SuccessTuple:
188
194
  """
189
195
  Create a job.
190
196
  """
191
- response = self.post(JOBS_ENDPOINT + f"/{name}", json=sysargs, debug=debug)
197
+ response = self.post(
198
+ JOBS_ENDPOINT + f"/{name}",
199
+ json={
200
+ 'sysargs': sysargs,
201
+ 'properties': properties,
202
+ },
203
+ debug=debug,
204
+ )
192
205
  if not response:
193
206
  if 'detail' in response.text:
194
207
  return False, response.json()['detail']
@@ -10,7 +10,7 @@ from __future__ import annotations
10
10
  from abc import abstractmethod
11
11
 
12
12
  from meerschaum.connectors import Connector
13
- from meerschaum.utils.typing import List, Dict, SuccessTuple, TYPE_CHECKING
13
+ from meerschaum.utils.typing import List, Dict, SuccessTuple, TYPE_CHECKING, Optional, Any
14
14
 
15
15
  if TYPE_CHECKING:
16
16
  from meerschaum.jobs import Job
@@ -33,7 +33,13 @@ class Executor(Connector):
33
33
  """
34
34
 
35
35
  @abstractmethod
36
- def create_job(self, name: str, sysargs: List[str], debug: bool = False) -> SuccessTuple:
36
+ def create_job(
37
+ self,
38
+ name: str,
39
+ sysargs: List[str],
40
+ properties: Optional[Dict[str, Any]] = None,
41
+ debug: bool = False,
42
+ ) -> SuccessTuple:
37
43
  """
38
44
  Create a new job.
39
45
  """