dataops-sdk 0.3.0__tar.gz → 0.3.1__tar.gz

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 (87) hide show
  1. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/PKG-INFO +1 -1
  2. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/__init__.py +9 -1
  3. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/runner/utils/common.py +2 -1
  4. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/runner/utils/dbConn_sync.py +7 -8
  5. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/runner/utils/file_transfer_base.py +0 -1
  6. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/runner/utils/nacos.py +4 -1
  7. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/runner/utils/queue_base.py +0 -1
  8. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/schemas/datasource.py +2 -1
  9. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/services/__init__.py +4 -4
  10. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/services/datasource.py +11 -4
  11. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/services/skill.py +15 -9
  12. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/session.py +108 -5
  13. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/tiptap/markdown_parser.py +6 -2
  14. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk.egg-info/PKG-INFO +1 -1
  15. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/tests/test_session.py +4 -6
  16. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/tests/test_utils.py +3 -5
  17. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/pyproject.toml +0 -0
  18. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/setup.cfg +0 -0
  19. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/constants.py +0 -0
  20. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/exceptions.py +0 -0
  21. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/runner/__init__.py +0 -0
  22. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/runner/datasource_factory.py +0 -0
  23. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/runner/schemas/nacos/__init__.py +0 -0
  24. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/runner/schemas/nacos/config.py +0 -0
  25. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/runner/schemas/nacos/constants.py +0 -0
  26. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/runner/schemas/nacos/instance.py +0 -0
  27. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/runner/schemas/nacos/nacos_exception.py +0 -0
  28. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/runner/schemas/nacos/naming_param.py +0 -0
  29. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/runner/schemas/nacos/naming_request.py +0 -0
  30. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/runner/schemas/nacos/naming_response.py +0 -0
  31. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/runner/schemas/nacos/preserved_metadata_key.py +0 -0
  32. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/runner/schemas/nacos/service.py +0 -0
  33. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/runner/utils/__init__.py +0 -0
  34. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/runner/utils/dbConn_base.py +0 -0
  35. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/runner/utils/duckdb_manager.py +0 -0
  36. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/runner/utils/ftp_file_transfer.py +0 -0
  37. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/runner/utils/log.py +0 -0
  38. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/runner/utils/neo4j_sync.py +0 -0
  39. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/runner/utils/queue_kafka.py +0 -0
  40. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/runner/utils/sftp_file_transfer.py +0 -0
  41. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/schemas/__init__.py +0 -0
  42. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/schemas/alarm.py +0 -0
  43. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/schemas/api.py +0 -0
  44. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/schemas/data_table.py +0 -0
  45. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/schemas/dict_.py +0 -0
  46. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/schemas/enums.py +0 -0
  47. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/schemas/group.py +0 -0
  48. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/schemas/hazard.py +0 -0
  49. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/schemas/meta.py +0 -0
  50. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/schemas/query.py +0 -0
  51. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/schemas/report.py +0 -0
  52. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/schemas/skill.py +0 -0
  53. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/schemas/table.py +0 -0
  54. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/schemas/user.py +0 -0
  55. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/schemas/widget.py +0 -0
  56. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/schemas/workflow.py +0 -0
  57. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/services/alarm.py +0 -0
  58. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/services/api.py +0 -0
  59. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/services/auth.py +0 -0
  60. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/services/data_table.py +0 -0
  61. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/services/dataset.py +0 -0
  62. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/services/dict_.py +0 -0
  63. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/services/hazard.py +0 -0
  64. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/services/meta.py +0 -0
  65. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/services/metrics.py +0 -0
  66. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/services/ref.py +0 -0
  67. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/services/report.py +0 -0
  68. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/services/table.py +0 -0
  69. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/services/widget.py +0 -0
  70. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/services/workflow.py +0 -0
  71. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/tiptap/__init__.py +0 -0
  72. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/tiptap/builder.py +0 -0
  73. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/tiptap/constants.py +0 -0
  74. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/tiptap/models.py +0 -0
  75. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/tiptap/parse_utils.py +0 -0
  76. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/tiptap/render_utils.py +0 -0
  77. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/tiptap/renderers.py +0 -0
  78. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/tiptap/tool.py +0 -0
  79. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/utils/__init__.py +0 -0
  80. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/utils/common.py +0 -0
  81. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk/utils/utils.py +0 -0
  82. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk.egg-info/SOURCES.txt +0 -0
  83. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk.egg-info/dependency_links.txt +0 -0
  84. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk.egg-info/requires.txt +0 -0
  85. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/src/dataops_sdk.egg-info/top_level.txt +0 -0
  86. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/tests/test_constants.py +0 -0
  87. {dataops_sdk-0.3.0 → dataops_sdk-0.3.1}/tests/test_exceptions.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dataops-sdk
3
- Version: 0.3.0
3
+ Version: 0.3.1
4
4
  Summary: Python SDK for the DataOps platform.
5
5
  Requires-Python: >=3.11
6
6
  Requires-Dist: pydantic<3,>=2
@@ -14,6 +14,7 @@ from .services import ( # noqa: F401
14
14
  service_count_alarm_rule_matches,
15
15
  service_count_alarm_rules,
16
16
  service_count_alarm_specs,
17
+ service_count_dataset_by_code,
17
18
  service_count_table_by_code,
18
19
  service_count_table_by_name,
19
20
  service_count_widget_by_code,
@@ -48,6 +49,8 @@ from .services import ( # noqa: F401
48
49
  service_get_metrics,
49
50
  service_get_rel_table_columns,
50
51
  service_get_report,
52
+ service_get_skill_by_code,
53
+ service_get_skill_by_name,
51
54
  service_get_table_data_by_code,
52
55
  service_get_table_data_by_name,
53
56
  service_get_table_detail_by_code,
@@ -66,6 +69,8 @@ from .services import ( # noqa: F401
66
69
  service_list_hazard_records,
67
70
  service_list_metrics,
68
71
  service_list_reports,
72
+ service_list_skill_files,
73
+ service_list_skills,
69
74
  service_list_tables,
70
75
  service_list_widgets,
71
76
  service_list_workflows,
@@ -74,6 +79,9 @@ from .services import ( # noqa: F401
74
79
  service_ref_backward,
75
80
  service_ref_forward,
76
81
  service_set_application,
82
+ service_skill_call_by_code,
83
+ service_skill_import,
84
+ service_skill_upload_sub_file,
77
85
  service_start_workflow,
78
86
  service_start_workflow_async,
79
87
  service_trigger_hazard_task,
@@ -81,4 +89,4 @@ from .services import ( # noqa: F401
81
89
  service_update_data_table_record_by_id_list,
82
90
  )
83
91
 
84
- __version__ = "0.3.0"
92
+ __version__ = "0.3.1"
@@ -17,9 +17,10 @@ Example:
17
17
 
18
18
  from base64 import b64decode, b64encode
19
19
  from calendar import monthrange
20
+ from collections.abc import Mapping
20
21
  from datetime import date, datetime, timedelta
21
22
  from email.utils import parsedate_to_datetime
22
- from typing import Any, Literal, Mapping
23
+ from typing import Any, Literal
23
24
  from uuid import uuid4
24
25
 
25
26
  from pydantic import BaseModel, JsonValue
@@ -286,8 +286,7 @@ class DatabaseConn(DatabaseConnBase):
286
286
  mapping: Literal[True] = True,
287
287
  *,
288
288
  log_sql: bool | None = None,
289
- ) -> list[dict[str, Any]]:
290
- ...
289
+ ) -> list[dict[str, Any]]: ...
291
290
 
292
291
  @overload
293
292
  def select(
@@ -298,8 +297,7 @@ class DatabaseConn(DatabaseConnBase):
298
297
  mapping: Literal[False] = False,
299
298
  *,
300
299
  log_sql: bool | None = None,
301
- ) -> list[tuple[Any]]:
302
- ...
300
+ ) -> list[tuple[Any]]: ...
303
301
 
304
302
  def select(
305
303
  self,
@@ -378,7 +376,7 @@ class DatabaseConn(DatabaseConnBase):
378
376
  if hasattr(self, "_engine") and self._engine is not None:
379
377
  self.engine.dispose()
380
378
  self._engine = None
381
- self._logger.info(f"closed")
379
+ self._logger.info("closed")
382
380
 
383
381
  @property
384
382
  def session_factory(self):
@@ -398,21 +396,21 @@ class DatabaseConn(DatabaseConnBase):
398
396
  """
399
397
  提交当前事务。
400
398
  """
401
- self._logger.debug(f"committing")
399
+ self._logger.debug("committing")
402
400
  self.session.commit()
403
401
 
404
402
  def rollback(self):
405
403
  """
406
404
  回滚当前事务。
407
405
  """
408
- self._logger.warning(f"rolling back")
406
+ self._logger.warning("rolling back")
409
407
  self.session.rollback()
410
408
 
411
409
  def begin(self):
412
410
  """
413
411
  开始一个新的事务。
414
412
  """
415
- self._logger.debug(f"beginning")
413
+ self._logger.debug("beginning")
416
414
  if self.session:
417
415
  assert self._session is not None, "session not closed"
418
416
  self._session = self.session_factory()
@@ -428,6 +426,7 @@ class DatabaseConn(DatabaseConnBase):
428
426
  """
429
427
  return self._session
430
428
 
429
+
431
430
  class DatabaseConnDataOps(DatabaseConn):
432
431
  def __init__(self, datasource: str, log_sql: bool | None = None):
433
432
  from dataops_sdk.services.meta import Meta, release_list_get_by_name
@@ -30,7 +30,6 @@ Example:
30
30
  ... ft.upload("/local/file.txt", "remote_file.txt")
31
31
  """
32
32
 
33
- import os
34
33
  from abc import ABC, abstractmethod
35
34
  from logging import Logger
36
35
  from typing import BinaryIO
@@ -15,6 +15,7 @@ import random
15
15
  from collections.abc import Mapping
16
16
 
17
17
  import httpx2
18
+
18
19
  from dataops_sdk.runner.schemas.nacos import NacosSettings, Service
19
20
  from dataops_sdk.runner.schemas.nacos.constants import Constants
20
21
 
@@ -88,7 +89,9 @@ def get_service_instance(
88
89
 
89
90
  instance = random.choice(service.hosts)
90
91
 
91
- http_client = httpx2.Client(base_url=f"http://{instance.ip}:{instance.port}/{service_name}", headers=headers)
92
+ http_client = httpx2.Client(
93
+ base_url=f"http://{instance.ip}:{instance.port}/{service_name}", headers=headers
94
+ )
92
95
 
93
96
  # 主进程结束前执行 http_client.close()
94
97
  atexit.register(http_client.close)
@@ -185,7 +185,6 @@ class QueueBase(ABC):
185
185
  """
186
186
  return self._bootstrap_servers
187
187
 
188
-
189
188
  def __enter__(self):
190
189
  """
191
190
  上下文管理器入口方法。
@@ -1,8 +1,9 @@
1
1
  from typing import Annotated
2
2
 
3
- from dataops_sdk.schemas.enums import DataSourceType
4
3
  from pydantic import BaseModel, BeforeValidator, Field
5
4
 
5
+ from dataops_sdk.schemas.enums import DataSourceType
6
+
6
7
 
7
8
  def str_to_number(v: str):
8
9
  assert v.isnumeric(), "must be number"
@@ -75,15 +75,15 @@ from .metrics import service_get_metrics, service_list_metrics
75
75
  from .ref import service_ref_backward, service_ref_forward
76
76
  from .report import service_get_report, service_list_reports
77
77
  from .skill import (
78
- service_call_skill_by_code,
79
78
  service_delete_skill,
80
- service_delete_sub_file,
81
79
  service_get_skill_by_code,
82
80
  service_get_skill_by_name,
83
- service_import_skill,
84
81
  service_list_skill_files,
85
82
  service_list_skills,
86
- service_upload_sub_file,
83
+ service_skill_call_by_code,
84
+ service_skill_delete_sub_file,
85
+ service_skill_import,
86
+ service_skill_upload_sub_file,
87
87
  )
88
88
  from .table import (
89
89
  service_count_table_by_code,
@@ -1,12 +1,13 @@
1
1
  from dataclasses import dataclass
2
2
 
3
+ from pydantic_core import to_json
4
+
3
5
  from dataops_sdk.exceptions import AuthenticationError, DataOpsError
4
6
  from dataops_sdk.schemas import DataDataSource, Meta
5
7
  from dataops_sdk.schemas.enums import InnerMetaType
6
8
  from dataops_sdk.services.meta import release_list_get_by_name
7
9
  from dataops_sdk.session import get_application, get_session
8
10
  from dataops_sdk.utils import encrypt_body
9
- from pydantic_core import to_json
10
11
 
11
12
 
12
13
  def service_get_datasource_config_by_application_id(
@@ -39,16 +40,22 @@ class DatasourceConfig:
39
40
  hazard_write: Meta[DataDataSource]
40
41
 
41
42
 
42
- def service_get_main_datasource_config_by_application(app_id: str | None = None) -> DatasourceConfig:
43
+ def service_get_main_datasource_config_by_application(
44
+ app_id: str | None = None,
45
+ ) -> DatasourceConfig:
43
46
  if app_id is None:
44
47
  application = get_application()
45
48
  app_id = application.CUID
46
49
  # 主数据源
47
50
  datasource_main = service_get_datasource_config_by_application_id(prod_id=app_id)
48
51
  # 隐患读数据源
49
- datasource_hazard_read = service_get_datasource_config_by_application_id(prod_id=app_id, param_name="datasource_hazard_read")
52
+ datasource_hazard_read = service_get_datasource_config_by_application_id(
53
+ prod_id=app_id, param_name="datasource_hazard_read"
54
+ )
50
55
  # 隐患写数据源
51
- datasource_hazard_write = service_get_datasource_config_by_application_id(prod_id=app_id, param_name="datasource_hazard_write")
56
+ datasource_hazard_write = service_get_datasource_config_by_application_id(
57
+ prod_id=app_id, param_name="datasource_hazard_write"
58
+ )
52
59
  return DatasourceConfig(datasource_main, datasource_hazard_read, datasource_hazard_write)
53
60
 
54
61
 
@@ -4,7 +4,13 @@ from pathlib import Path
4
4
  from pydantic_core import to_json
5
5
 
6
6
  from dataops_sdk.exceptions import AuthenticationError, DataOpsError
7
- from dataops_sdk.schemas import DataSkill, MetaRelease, MetaSkill, MetaType, SkillCallResult
7
+ from dataops_sdk.schemas import (
8
+ DataSkill,
9
+ MetaRelease,
10
+ MetaSkill,
11
+ MetaType,
12
+ SkillCallResult,
13
+ )
8
14
  from dataops_sdk.services.meta import (
9
15
  release_list_get_by_code,
10
16
  release_list_get_by_name,
@@ -14,15 +20,15 @@ from dataops_sdk.session import get_session, post_multipart
14
20
  from dataops_sdk.utils import encrypt_body, filter_nodes_by_pattern
15
21
 
16
22
  __all__ = [
17
- "service_call_skill_by_code",
23
+ "service_skill_call_by_code",
18
24
  "service_delete_skill",
19
- "service_delete_sub_file",
25
+ "service_skill_delete_sub_file",
20
26
  "service_get_skill_by_code",
21
27
  "service_get_skill_by_name",
22
- "service_import_skill",
28
+ "service_skill_import",
23
29
  "service_list_skill_files",
24
30
  "service_list_skills",
25
- "service_upload_sub_file",
31
+ "service_skill_upload_sub_file",
26
32
  ]
27
33
 
28
34
 
@@ -125,7 +131,7 @@ def _post_skill(url: str, body: dict | None = None, *, params: dict | None = Non
125
131
  raise AuthenticationError("认证失败,请先登录") from e
126
132
 
127
133
 
128
- def service_import_skill(
134
+ def service_skill_import(
129
135
  file_path: str | Path,
130
136
  sub_type: str = "llm",
131
137
  name: str | None = None,
@@ -193,7 +199,7 @@ def service_delete_skill(name: str) -> dict:
193
199
  return _post_skill(f"/data/skill/delete/{name}")
194
200
 
195
201
 
196
- def service_upload_sub_file(
202
+ def service_skill_upload_sub_file(
197
203
  skill_name: str,
198
204
  file_path: str | Path,
199
205
  path: str,
@@ -225,7 +231,7 @@ def service_upload_sub_file(
225
231
  resp.json() # 仅校验响应
226
232
 
227
233
 
228
- def service_delete_sub_file(skill_name: str, path: str) -> None:
234
+ def service_skill_delete_sub_file(skill_name: str, path: str) -> None:
229
235
  """删除技能下的指定子文件.
230
236
 
231
237
  Args:
@@ -239,7 +245,7 @@ def service_delete_sub_file(skill_name: str, path: str) -> None:
239
245
  _post_skill(f"/data/skill/{skill_name}/subfile/delete", params={"path": path})
240
246
 
241
247
 
242
- def service_call_skill_by_code(code: str, inputs: Mapping) -> SkillCallResult:
248
+ def service_skill_call_by_code(code: str, inputs: Mapping) -> SkillCallResult:
243
249
  """调用 skill 同步执行,返回 Python 容器运行结果.
244
250
 
245
251
  对应后端 ``POST /data/skill/callByCode/{code}``,入参 ``{"inputs": {...}}``。
@@ -1,16 +1,40 @@
1
1
  import os
2
2
  from collections.abc import Mapping
3
3
  from contextlib import contextmanager
4
+ from contextvars import ContextVar
4
5
  from os import getenv
5
6
  from typing import IO, BinaryIO
6
7
 
7
8
  import httpx2
9
+ from pydantic import BaseModel
10
+ from pydantic_core import from_json, to_json
11
+
8
12
  from dataops_sdk.constants import APPLICATION_FILE, USER_INFO_FILE
9
13
  from dataops_sdk.exceptions import AuthenticationError, DataOpsError
10
14
  from dataops_sdk.schemas.user import Application, UserInfo
11
15
  from dataops_sdk.utils import get_work_dir
12
- from pydantic import BaseModel
13
- from pydantic_core import from_json, to_json
16
+
17
+ __all__ = [
18
+ "DataOpsConfig",
19
+ "configure",
20
+ "get_config",
21
+ "set_request_auth",
22
+ "clear_request_auth",
23
+ "request_context",
24
+ "get_user_info_file_path",
25
+ "get_application_file_path",
26
+ "get_user_info",
27
+ "get_headers",
28
+ "refresh_token",
29
+ "get_application",
30
+ "get_session",
31
+ "post_multipart",
32
+ ]
33
+
34
+ # Request-scoped auth headers context variable
35
+ # 默认 None,表示使用模块级认证(环境变量/file/config)
36
+ # 在 FastAPI/异步环境中,每个 async task 有独立的副本,互不干扰
37
+ REQUEST_HEADERS: ContextVar[dict[str, str] | None] = ContextVar("REQUEST_HEADERS", default=None)
14
38
 
15
39
 
16
40
  class DataOpsConfig(BaseModel):
@@ -81,6 +105,59 @@ def get_config() -> DataOpsConfig:
81
105
  return _config
82
106
 
83
107
 
108
+ def set_request_auth(headers: dict[str, str]) -> None:
109
+ """设置本次请求的认证头。
110
+
111
+ 在 FastAPI 请求处理器开头调用,后续 SDK 调用会使用此认证信息。
112
+ 每个 async task 有独立的上下文副本,支持并发请求。
113
+
114
+ Args:
115
+ headers: 认证相关请求头字典,格式:
116
+ {"Fmind-Auth": "Bearer <token>", "X-App-Code": "xxx", ...}
117
+
118
+ Example:
119
+ # In FastAPI handler:
120
+ def handler(request: Request):
121
+ set_request_auth({"Fmind-Auth": request.headers.get("Fmind-Auth")})
122
+ result = service_get_skill_by_code("my-skill")
123
+ """
124
+ REQUEST_HEADERS.set(headers)
125
+
126
+
127
+ def get_request_auth() -> dict[str, str] | None:
128
+ """获取当前请求的认证头。
129
+
130
+ 通常在请求结束时自动调用(如果使用 request_context 管理器则无需手动调用)。
131
+ """
132
+ return REQUEST_HEADERS.get()
133
+
134
+
135
+ def clear_request_auth() -> None:
136
+ """清除本次请求的认证头。
137
+
138
+ 通常在请求结束时自动调用(如果使用 request_context 管理器则无需手动调用)。
139
+ """
140
+ REQUEST_HEADERS.set(None)
141
+
142
+
143
+ @contextmanager
144
+ def request_context(headers: dict[str, str]):
145
+ """请求级认证上下文管理器。
146
+
147
+ 自动在退出时清理认证上下文。推荐用于包装请求处理器。
148
+
149
+ Example:
150
+ def handler(request: Request):
151
+ with request_context({"Fmind-Auth": request.headers.get("Fmind-Auth")}):
152
+ result = service_get_skill_by_code("my-skill")
153
+ """
154
+ token = REQUEST_HEADERS.set(headers)
155
+ try:
156
+ yield
157
+ finally:
158
+ REQUEST_HEADERS.reset(token)
159
+
160
+
84
161
  def get_user_info_file_path() -> str:
85
162
  """返回用户信息文件路径。"""
86
163
  return get_work_dir(USER_INFO_FILE)
@@ -127,7 +204,13 @@ def get_user_info(strict: bool = True) -> UserInfo | None:
127
204
 
128
205
 
129
206
  def get_headers(strict: bool = True) -> Mapping[str, str]:
130
- # 优先从环境变量获取
207
+ # 最高优先级:请求上下文中的认证头(web app 场景)
208
+ global REQUEST_HEADERS
209
+ request_headers = REQUEST_HEADERS.get()
210
+ if request_headers is not None:
211
+ return request_headers
212
+
213
+ # 降级:原有的 CLI/环境变量/file 认证逻辑
131
214
  fmind_auth_headers = os.getenv("FMIND_AUTH_HEADERS", None)
132
215
  if fmind_auth_headers is not None:
133
216
  headers = from_json(fmind_auth_headers)
@@ -203,12 +286,32 @@ def refresh_token(response: httpx2.Response):
203
286
 
204
287
 
205
288
  @contextmanager
206
- def get_session(strict: bool = True, timeout: int = 10):
289
+ def get_session(
290
+ strict: bool = True,
291
+ timeout: int = 10,
292
+ auth_headers: dict[str, str] | None = None,
293
+ ):
207
294
  """获取请求 Session。
208
295
 
209
296
  使用 httpx2 管理 HTTP 连接,base_url 指向 DataOps 服务。
297
+
298
+ Args:
299
+ strict: 是否要求认证
300
+ timeout: 请求超时秒数,默认 10s
301
+ auth_headers: 可选的认证头,用于一次性认证场景。
302
+ 如果设置,会覆盖 contextvar 和模块级认证。
303
+
304
+ Example:
305
+ # 使用请求上下文认证(推荐):
306
+ set_request_auth({"Fmind-Auth": "Bearer token"})
307
+ with get_session() as session:
308
+ session.get("/api")
309
+
310
+ # 一次性认证(不常用):
311
+ with get_session(auth_headers={"Fmind-Auth": "Bearer token"}) as session:
312
+ session.get("/api")
210
313
  """
211
- headers = get_headers(strict)
314
+ headers = auth_headers if auth_headers is not None else get_headers(strict)
212
315
  with httpx2.Client(
213
316
  headers=headers,
214
317
  base_url=_config.base_url,
@@ -60,7 +60,9 @@ class MarkdownToTipTapParser:
60
60
  node, index = self._parse_table(tokens, index)
61
61
  content.append(node)
62
62
  elif token.type == "html_block":
63
- content.append(parse_utils.parse_paragraph([parse_utils.create_text_node(token.content)]))
63
+ content.append(
64
+ parse_utils.parse_paragraph([parse_utils.create_text_node(token.content)])
65
+ )
64
66
  index += 1
65
67
  else:
66
68
  raise ValueError(f"Unsupported Markdown block token: {token.type}")
@@ -133,7 +135,9 @@ class MarkdownToTipTapParser:
133
135
  if opening.type == "bullet_list_open"
134
136
  else constants.NodeTypes.ORDERED_LIST
135
137
  )
136
- return parse_utils.create_node(node_type, attrs=attrs, content=[item for item, _ in items]), index
138
+ return parse_utils.create_node(
139
+ node_type, attrs=attrs, content=[item for item, _ in items]
140
+ ), index
137
141
 
138
142
  def _convert_task_item(self, paragraph: dict) -> dict | None:
139
143
  if paragraph.get("type") != constants.NodeTypes.PARAGRAPH:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dataops-sdk
3
- Version: 0.3.0
3
+ Version: 0.3.1
4
4
  Summary: Python SDK for the DataOps platform.
5
5
  Requires-Python: >=3.11
6
6
  Requires-Dist: pydantic<3,>=2
@@ -11,24 +11,22 @@ import json
11
11
  from pathlib import Path
12
12
  from unittest.mock import MagicMock
13
13
 
14
+ import dataops_sdk.session as session_module
14
15
  import httpx2
15
16
  import pytest
16
- from pydantic import ValidationError
17
-
18
17
  from dataops_sdk.session import (
19
18
  DataOpsConfig,
20
19
  configure,
21
20
  get_application,
21
+ get_application_file_path,
22
22
  get_config,
23
23
  get_headers,
24
24
  get_session,
25
25
  get_user_info,
26
26
  get_user_info_file_path,
27
- get_application_file_path,
28
27
  refresh_token,
29
28
  )
30
- import dataops_sdk.session as session_module
31
-
29
+ from pydantic import ValidationError
32
30
 
33
31
  # === DataOpsConfig ===
34
32
 
@@ -463,4 +461,4 @@ def test_get_session_closes_on_exception(mocker) -> None:
463
461
  with get_session(strict=False):
464
462
  raise RuntimeError("user code failed")
465
463
 
466
- fake_client.close.assert_called()
464
+ fake_client.close.assert_called()
@@ -12,17 +12,15 @@ from pathlib import Path
12
12
  from typing import ClassVar
13
13
 
14
14
  import pytest
15
- from pydantic import BaseModel
16
-
17
15
  from dataops_sdk.utils import (
18
- deep_merge,
19
16
  decrypt_body,
17
+ deep_merge,
20
18
  encrypt_body,
21
19
  encrypt_hex,
22
20
  filter_nodes_by_pattern,
23
21
  get_work_dir,
24
22
  )
25
-
23
+ from pydantic import BaseModel
26
24
 
27
25
  # === 辅助 fixture:构造 SearchableNode 兼容对象 ===
28
26
 
@@ -314,4 +312,4 @@ def test_deep_merge_deeply_nested() -> None:
314
312
  src = {"a": {"b": {"c": {"d": 1}}}}
315
313
  dst = {"a": {"b": {"c": {"e": 2}}}}
316
314
  merged = deep_merge(src, dst)
317
- assert merged == {"a": {"b": {"c": {"d": 1, "e": 2}}}}
315
+ assert merged == {"a": {"b": {"c": {"d": 1, "e": 2}}}}
File without changes
File without changes