dc-python-sdk 1.5.20__tar.gz → 1.5.22__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 (35) hide show
  1. {dc_python_sdk-1.5.20/src/dc_python_sdk.egg-info → dc_python_sdk-1.5.22}/PKG-INFO +1 -1
  2. {dc_python_sdk-1.5.20 → dc_python_sdk-1.5.22}/pyproject.toml +1 -1
  3. {dc_python_sdk-1.5.20 → dc_python_sdk-1.5.22}/setup.cfg +1 -1
  4. {dc_python_sdk-1.5.20 → dc_python_sdk-1.5.22/src/dc_python_sdk.egg-info}/PKG-INFO +1 -1
  5. {dc_python_sdk-1.5.20 → dc_python_sdk-1.5.22}/src/dc_sdk/cli.py +11 -2
  6. {dc_python_sdk-1.5.20 → dc_python_sdk-1.5.22}/src/dc_sdk/src/ai_http.py +110 -15
  7. {dc_python_sdk-1.5.20 → dc_python_sdk-1.5.22}/src/dc_sdk/src/server.py +3 -2
  8. {dc_python_sdk-1.5.20 → dc_python_sdk-1.5.22}/LICENSE +0 -0
  9. {dc_python_sdk-1.5.20 → dc_python_sdk-1.5.22}/README.md +0 -0
  10. {dc_python_sdk-1.5.20 → dc_python_sdk-1.5.22}/src/dc_python_sdk.egg-info/SOURCES.txt +0 -0
  11. {dc_python_sdk-1.5.20 → dc_python_sdk-1.5.22}/src/dc_python_sdk.egg-info/dependency_links.txt +0 -0
  12. {dc_python_sdk-1.5.20 → dc_python_sdk-1.5.22}/src/dc_python_sdk.egg-info/entry_points.txt +0 -0
  13. {dc_python_sdk-1.5.20 → dc_python_sdk-1.5.22}/src/dc_python_sdk.egg-info/requires.txt +0 -0
  14. {dc_python_sdk-1.5.20 → dc_python_sdk-1.5.22}/src/dc_python_sdk.egg-info/top_level.txt +0 -0
  15. {dc_python_sdk-1.5.20 → dc_python_sdk-1.5.22}/src/dc_sdk/__init__.py +0 -0
  16. {dc_python_sdk-1.5.20 → dc_python_sdk-1.5.22}/src/dc_sdk/app.py +0 -0
  17. {dc_python_sdk-1.5.20 → dc_python_sdk-1.5.22}/src/dc_sdk/errors.py +0 -0
  18. {dc_python_sdk-1.5.20 → dc_python_sdk-1.5.22}/src/dc_sdk/handler.py +0 -0
  19. {dc_python_sdk-1.5.20 → dc_python_sdk-1.5.22}/src/dc_sdk/src/__init__.py +0 -0
  20. {dc_python_sdk-1.5.20 → dc_python_sdk-1.5.22}/src/dc_sdk/src/ai.py +0 -0
  21. {dc_python_sdk-1.5.20 → dc_python_sdk-1.5.22}/src/dc_sdk/src/mapping.py +0 -0
  22. {dc_python_sdk-1.5.20 → dc_python_sdk-1.5.22}/src/dc_sdk/src/models/__init__.py +0 -0
  23. {dc_python_sdk-1.5.20 → dc_python_sdk-1.5.22}/src/dc_sdk/src/models/enums.py +0 -0
  24. {dc_python_sdk-1.5.20 → dc_python_sdk-1.5.22}/src/dc_sdk/src/models/errors.py +0 -0
  25. {dc_python_sdk-1.5.20 → dc_python_sdk-1.5.22}/src/dc_sdk/src/models/log_templates.py +0 -0
  26. {dc_python_sdk-1.5.20 → dc_python_sdk-1.5.22}/src/dc_sdk/src/models/pipeline_details.py +0 -0
  27. {dc_python_sdk-1.5.20 → dc_python_sdk-1.5.22}/src/dc_sdk/src/pipeline.py +0 -0
  28. {dc_python_sdk-1.5.20 → dc_python_sdk-1.5.22}/src/dc_sdk/src/services/__init__.py +0 -0
  29. {dc_python_sdk-1.5.20 → dc_python_sdk-1.5.22}/src/dc_sdk/src/services/api.py +0 -0
  30. {dc_python_sdk-1.5.20 → dc_python_sdk-1.5.22}/src/dc_sdk/src/services/aws.py +0 -0
  31. {dc_python_sdk-1.5.20 → dc_python_sdk-1.5.22}/src/dc_sdk/src/services/environment.py +0 -0
  32. {dc_python_sdk-1.5.20 → dc_python_sdk-1.5.22}/src/dc_sdk/src/services/loader.py +0 -0
  33. {dc_python_sdk-1.5.20 → dc_python_sdk-1.5.22}/src/dc_sdk/src/services/logger.py +0 -0
  34. {dc_python_sdk-1.5.20 → dc_python_sdk-1.5.22}/src/dc_sdk/src/services/session.py +0 -0
  35. {dc_python_sdk-1.5.20 → dc_python_sdk-1.5.22}/src/dc_sdk/types.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dc-python-sdk
3
- Version: 1.5.20
3
+ Version: 1.5.22
4
4
  Summary: Data Connector Python SDK
5
5
  Home-page: https://github.com/data-connector/dc-python-sdk
6
6
  Author: DataConnector
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "dc-python-sdk"
7
- version = "1.5.20"
7
+ version = "1.5.22"
8
8
  description = "Data Connector Python SDK"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.6"
@@ -1,6 +1,6 @@
1
1
  [metadata]
2
2
  name = dc-python-sdk
3
- version = 1.5.20
3
+ version = 1.5.22
4
4
  author = DataConnector
5
5
  author_email = josh@dataconnector.com
6
6
  description = A small example package
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dc-python-sdk
3
- Version: 1.5.20
3
+ Version: 1.5.22
4
4
  Summary: Data Connector Python SDK
5
5
  Home-page: https://github.com/data-connector/dc-python-sdk
6
6
  Author: DataConnector
@@ -1,6 +1,13 @@
1
1
  import sys
2
2
  from importlib.metadata import version
3
3
 
4
+ def get_arg(name, default=None):
5
+ if name in sys.argv:
6
+ idx = sys.argv.index(name)
7
+ if idx + 1 < len(sys.argv):
8
+ return sys.argv[idx + 1]
9
+ return default
10
+
4
11
  def main():
5
12
  if len(sys.argv) < 2:
6
13
  print("Usage: dc-sdk [http|ai|ai-http]")
@@ -8,13 +15,15 @@ def main():
8
15
 
9
16
  command = sys.argv[1]
10
17
 
18
+ port = int(get_arg("--port", 5000))
19
+
11
20
  print("version: ", version("dc-python-sdk"))
12
21
 
13
22
  print(f"[DC SDK] Command: {command}")
14
23
 
15
24
  if command == "http":
16
25
  from dc_sdk.src.server import start_server
17
- start_server()
26
+ start_server(port)
18
27
 
19
28
  elif command == "ai":
20
29
  from dc_sdk.src.ai import start_ai
@@ -22,7 +31,7 @@ def main():
22
31
 
23
32
  elif command == "ai-http":
24
33
  from dc_sdk.src.ai_http import start_ai_http
25
- start_ai_http()
34
+ start_ai_http(connector_port=port)
26
35
 
27
36
  else:
28
37
  print(f"Unknown command: {command}")
@@ -10,6 +10,7 @@ from openai import OpenAI
10
10
  import atexit
11
11
  import signal
12
12
  import shutil
13
+ import threading
13
14
 
14
15
  logger = logging.getLogger(__name__)
15
16
 
@@ -19,6 +20,12 @@ app = FastAPI()
19
20
 
20
21
  client = None
21
22
  workspace = os.getenv("WORKSPACE", "/workspace")
23
+ port_for_connector = 5000
24
+
25
+ # Process-wide TTL for ai-http (see DC_SDK_TTL_SECONDS); exposed in /session-info.
26
+ process_ttl_seconds: Optional[float] = None
27
+ process_ttl_deadline_unix: Optional[float] = None
28
+ _process_ttl_timer: Optional[threading.Timer] = None
22
29
 
23
30
  # -----------------------------
24
31
  # MODELS
@@ -70,12 +77,39 @@ def get_free_port():
70
77
  return port
71
78
 
72
79
 
80
+ _DEFAULT_PROCESS_TTL_SECONDS = 600.0
81
+
82
+
83
+ def _parse_process_ttl_seconds() -> float:
84
+ """
85
+ Wall-clock lifetime for the whole ai-http process from start_ai_http() entry.
86
+ Env DC_SDK_TTL_SECONDS: positive seconds; unset or empty → 600 (10m); 0 → disabled.
87
+ """
88
+ raw = os.environ.get("DC_SDK_TTL_SECONDS")
89
+ if raw is None:
90
+ return _DEFAULT_PROCESS_TTL_SECONDS
91
+ raw = raw.strip()
92
+ if raw == "":
93
+ return _DEFAULT_PROCESS_TTL_SECONDS
94
+ try:
95
+ v = float(raw)
96
+ except ValueError:
97
+ logger.warning(
98
+ "Invalid DC_SDK_TTL_SECONDS=%r; using default %s",
99
+ raw,
100
+ _DEFAULT_PROCESS_TTL_SECONDS,
101
+ )
102
+ return _DEFAULT_PROCESS_TTL_SECONDS
103
+ if v <= 0:
104
+ return 0.0
105
+ return v
106
+
107
+
73
108
  def start_connector():
74
109
  global workspace
75
- port = int(os.getenv("PORT", 6060))
76
-
110
+ global port_for_connector
77
111
  proc = subprocess.Popen(
78
- ["dc-sdk", "http"],
112
+ ["dc-sdk", "http", "--port", str(port_for_connector)],
79
113
  cwd=workspace,
80
114
  stdout=subprocess.DEVNULL,
81
115
  stderr=subprocess.DEVNULL
@@ -84,15 +118,15 @@ def start_connector():
84
118
  # wait for health
85
119
  for _ in range(50):
86
120
  try:
87
- res = requests.get(f"http://localhost:{port}/health")
121
+ res = requests.get(f"http://localhost:{port_for_connector}/health")
88
122
  if res.status_code == 200:
89
- logger.info("Connector ready on port %s", port)
90
- return {"process": proc, "port": port}
123
+ logger.info("Connector ready on port %s", port_for_connector)
124
+ return {"process": proc, "port": port_for_connector}
91
125
  except Exception:
92
- logger.debug("Health check not ready yet on port %s", port)
126
+ logger.debug("Health check not ready yet on port %s", port_for_connector)
93
127
  time.sleep(0.1)
94
128
 
95
- logger.error("Connector failed to become healthy on port %s within timeout", port)
129
+ logger.error("Connector failed to become healthy on port %s within timeout", port_for_connector)
96
130
  proc.terminate()
97
131
  raise Exception("Failed to start connector")
98
132
 
@@ -704,9 +738,52 @@ def clone_repo():
704
738
  subprocess.run(["git", "-C", workspace, "checkout", branch], check=True)
705
739
  subprocess.run(["git", "-C", workspace, "pull"], check=True)
706
740
 
707
- def start_ai_http():
741
+ def start_ai_http(connector_port=5000):
708
742
  global client
709
743
  global workspace
744
+ global port_for_connector
745
+ global process_ttl_seconds
746
+ global process_ttl_deadline_unix
747
+ global _process_ttl_timer
748
+
749
+ port_for_connector = connector_port
750
+
751
+ process_ttl_seconds = None
752
+ process_ttl_deadline_unix = None
753
+ _process_ttl_timer = None
754
+
755
+ ttl_sec = _parse_process_ttl_seconds()
756
+ ttl_shutdown_holder: Dict[str, Any] = {"fn": None}
757
+
758
+ if ttl_sec > 0:
759
+ process_ttl_seconds = ttl_sec
760
+ process_ttl_deadline_unix = time.time() + ttl_sec
761
+
762
+ def on_process_ttl():
763
+ logger.warning(
764
+ "DC_SDK_TTL_SECONDS (%s s) elapsed; stopping and exiting process",
765
+ ttl_sec,
766
+ )
767
+ fn = ttl_shutdown_holder.get("fn")
768
+ if callable(fn):
769
+ try:
770
+ fn()
771
+ except Exception:
772
+ logger.exception("Process TTL shutdown hook failed")
773
+ os._exit(0)
774
+
775
+ _process_ttl_timer = threading.Timer(ttl_sec, on_process_ttl)
776
+ _process_ttl_timer.daemon = True
777
+ _process_ttl_timer.start()
778
+ logger.info(
779
+ "Process TTL active: exit after %s s wall clock (DC_SDK_TTL_SECONDS)",
780
+ ttl_sec,
781
+ )
782
+ else:
783
+ logger.info(
784
+ "Process TTL disabled (DC_SDK_TTL_SECONDS=%r)",
785
+ os.environ.get("DC_SDK_TTL_SECONDS"),
786
+ )
710
787
 
711
788
  api_key = os.getenv("OPENAI_API_KEY")
712
789
  ai_port = int(os.getenv("AI_PORT", 5050))
@@ -721,9 +798,13 @@ def start_ai_http():
721
798
 
722
799
  # ✅ Write code-server config
723
800
  with open("/root/.config/code-server/config.yaml", "w") as f:
724
- f.write(f"""bind-addr: 0.0.0.0:{code_port}
725
- auth: none
726
- """)
801
+ f.write(
802
+ f"bind-addr: 0.0.0.0:{code_port}\n"
803
+ "auth: none\n"
804
+ )
805
+
806
+ with open("/root/.config/code-server/config.yaml", "r") as f:
807
+ logger.info("code-server config:\n%s", f.read())
727
808
 
728
809
  # ✅ Ensure workspace + vscode dir exists
729
810
  os.makedirs(workspace, exist_ok=True)
@@ -752,10 +833,17 @@ auth: none
752
833
  raise Exception("code-server failed to start")
753
834
 
754
835
  def shutdown():
836
+ global _process_ttl_timer
837
+ tm = _process_ttl_timer
838
+ _process_ttl_timer = None
839
+ if tm is not None:
840
+ tm.cancel()
755
841
  logger.info("Shutting down code-server...")
756
842
  if code_server_proc:
757
843
  code_server_proc.terminate()
758
844
 
845
+ ttl_shutdown_holder["fn"] = shutdown
846
+
759
847
  atexit.register(shutdown)
760
848
 
761
849
  def handle_signal(sig, frame):
@@ -777,9 +865,16 @@ auth: none
777
865
 
778
866
  @app.get("/session-info")
779
867
  def session_info():
780
- return {
868
+ out: Dict[str, Any] = {
781
869
  "workspace": workspace,
782
870
  "ai_port": int(os.getenv("AI_PORT", 5050)),
783
871
  "code_server_port": int(os.getenv("CODE_SERVER_PORT", 5002)),
784
- "api_base": f"http://localhost:{os.getenv('AI_PORT', 5050)}"
785
- }
872
+ "api_base": f"http://localhost:{os.getenv('AI_PORT', 5050)}",
873
+ }
874
+ if process_ttl_seconds is not None and process_ttl_deadline_unix is not None:
875
+ out["ttl_seconds"] = process_ttl_seconds
876
+ out["ttl_deadline_unix"] = process_ttl_deadline_unix
877
+ out["ttl_remaining_seconds"] = max(
878
+ 0.0, process_ttl_deadline_unix - time.time()
879
+ )
880
+ return out
@@ -88,10 +88,11 @@ def invoke(req: InvokeRequest):
88
88
  }
89
89
 
90
90
 
91
- def start_server():
91
+ def start_server(port: Optional[int] = None):
92
92
  import uvicorn
93
+ listen = int(os.getenv("PORT", 5000)) if port is None else int(port)
93
94
  uvicorn.run(
94
95
  "dc_sdk.src.server:app",
95
96
  host="0.0.0.0",
96
- port=int(os.getenv("PORT", 5000))
97
+ port=listen,
97
98
  )
File without changes
File without changes