cycls 0.0.2.94__py3-none-any.whl → 0.0.2.96__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.
cycls/__init__.py CHANGED
@@ -1,14 +1,6 @@
1
- from . import function as _function_module
2
1
  from .function import function, Function
3
2
  from .app import app, App
4
3
 
5
- def __getattr__(name):
6
- if name in ("api_key", "base_url"):
7
- return getattr(_function_module, name)
8
- raise AttributeError(f"module 'cycls' has no attribute '{name}'")
9
-
10
- def __setattr__(name, value):
11
- if name in ("api_key", "base_url"):
12
- setattr(_function_module, name, value)
13
- else:
14
- raise AttributeError(f"module 'cycls' has no attribute '{name}'")
4
+ # Module-level config
5
+ api_key = None
6
+ base_url = None
cycls/app.py CHANGED
@@ -15,13 +15,14 @@ class App(Function):
15
15
 
16
16
  def __init__(self, func, name, theme="default", pip=None, apt=None, copy=None, copy_public=None,
17
17
  auth=False, org=None, header=None, intro=None, title=None, plan="free", analytics=False,
18
- state=False):
18
+ state=False, memory="1Gi"):
19
19
  if theme not in THEMES:
20
20
  raise ValueError(f"Unknown theme: {theme}. Available: {THEMES}")
21
21
  self.user_func = func
22
22
  self.theme = theme
23
23
  self.copy_public = copy_public or []
24
24
  self.state = state
25
+ self.memory = memory
25
26
 
26
27
  self.config = Config(
27
28
  header=header,
@@ -79,12 +80,12 @@ class App(Function):
79
80
  self._prepare_func(prod=True)
80
81
  return super().deploy(port=port)
81
82
 
82
- def _deploy(self, port=8080):
83
+ def _deploy(self, port=8080, memory=None):
83
84
  """Deploy to testing infrastructure."""
84
85
  if self.api_key is None:
85
86
  raise RuntimeError("Missing API key. Set cycls.api_key or CYCLS_API_KEY environment variable.")
86
87
  self._prepare_func(prod=True)
87
- return super()._deploy(port=port)
88
+ return super()._deploy(port=port, memory=memory or self.memory)
88
89
 
89
90
 
90
91
  def app(name=None, **kwargs):
cycls/function.py CHANGED
@@ -46,10 +46,14 @@ api_key = None
46
46
  base_url = None
47
47
 
48
48
  def _get_api_key():
49
- return api_key or os.getenv("CYCLS_API_KEY")
49
+ import sys
50
+ cycls_pkg = sys.modules.get('cycls')
51
+ return api_key or (cycls_pkg and cycls_pkg.__dict__.get('api_key')) or os.getenv("CYCLS_API_KEY")
50
52
 
51
53
  def _get_base_url():
52
- return base_url or os.getenv("CYCLS_BASE_URL")
54
+ import sys
55
+ cycls_pkg = sys.modules.get('cycls')
56
+ return base_url or (cycls_pkg and cycls_pkg.__dict__.get('base_url')) or os.getenv("CYCLS_BASE_URL")
53
57
 
54
58
  def _hash_path(path_str: str) -> str:
55
59
  h = hashlib.sha256()
@@ -91,8 +95,8 @@ class Function:
91
95
  self.apt = sorted(apt or [])
92
96
  self.run_commands = sorted(run_commands or [])
93
97
  self.copy = {f: f for f in copy} if isinstance(copy, list) else (copy or {})
94
- self.base_url = base_url or "https://service-core-280879789566.me-central1.run.app"
95
- self.api_key = api_key
98
+ self._base_url = base_url
99
+ self._api_key = api_key
96
100
  self.pip = sorted(set(pip or []) | {"cloudpickle"})
97
101
 
98
102
  self.image_prefix = f"cycls/{self.name}"
@@ -100,6 +104,14 @@ class Function:
100
104
  self._docker_client = None
101
105
  self._container = None
102
106
 
107
+ @property
108
+ def api_key(self):
109
+ return self._api_key or _get_api_key()
110
+
111
+ @property
112
+ def base_url(self):
113
+ return self._base_url or _get_base_url() or "https://service-core-280879789566.me-central1.run.app"
114
+
103
115
  @property
104
116
  def docker_client(self):
105
117
  if self._docker_client is None:
@@ -399,7 +411,31 @@ CMD ["python", "entrypoint.py"]
399
411
  def _deploy(self, *args, **kwargs):
400
412
  import requests
401
413
 
414
+ base_url = self.base_url
402
415
  port = kwargs.pop('port', 8080)
416
+ memory = kwargs.pop('memory', '1Gi')
417
+
418
+ # Check name availability before uploading
419
+ print(f"Checking '{self.name}'...")
420
+ try:
421
+ check_resp = requests.get(
422
+ f"{base_url}/v1/deployment/check-name",
423
+ params={"name": self.name},
424
+ headers={"X-API-Key": self.api_key},
425
+ timeout=30,
426
+ )
427
+ if check_resp.status_code == 401:
428
+ print("Error: Invalid API key")
429
+ return None
430
+ check_resp.raise_for_status()
431
+ check_data = check_resp.json()
432
+ if not check_data.get("available"):
433
+ print(f"Error: {check_data.get('reason', 'Name unavailable')}")
434
+ return None
435
+ except requests.exceptions.RequestException as e:
436
+ print(f"Error checking name: {e}")
437
+ return None
438
+
403
439
  print(f"Deploying '{self.name}'...")
404
440
 
405
441
  payload = cloudpickle.dumps((self.func, args, {**kwargs, 'port': port}))
@@ -418,14 +454,22 @@ CMD ["python", "entrypoint.py"]
418
454
  print("Uploading...")
419
455
  with open(archive_path, 'rb') as f:
420
456
  response = requests.post(
421
- "https://api-572247013948.me-central1.run.app/v1/deploy",
422
- data={"function_name": self.name, "port": port},
457
+ f"{base_url}/v1/deploy",
458
+ data={"function_name": self.name, "port": port, "memory": memory},
423
459
  files={'source_archive': (archive_name, f, 'application/gzip')},
424
460
  headers={"X-API-Key": self.api_key},
425
461
  timeout=9000,
426
462
  stream=True,
427
463
  )
428
464
 
465
+ if not response.ok:
466
+ print(f"Deploy failed: {response.status_code}")
467
+ try:
468
+ print(f" {response.json()['detail']}")
469
+ except (json.JSONDecodeError, KeyError):
470
+ print(f" {response.text}")
471
+ return None
472
+
429
473
  # Parse NDJSON stream
430
474
  url = None
431
475
  for line in response.iter_lines(decode_unicode=True):
@@ -436,6 +480,7 @@ CMD ["python", "entrypoint.py"]
436
480
  print(f" [{status}] {msg}")
437
481
  if status == "DONE":
438
482
  url = event.get("url")
483
+ print(f"Deployed: {url}")
439
484
  elif status == "ERROR":
440
485
  return None
441
486
  return url
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cycls
3
- Version: 0.0.2.94
3
+ Version: 0.0.2.96
4
4
  Summary: Distribute Intelligence
5
5
  Author-email: "Mohammed J. AlRujayi" <mj@cycls.com>
6
6
  Requires-Python: >=3.10
@@ -1,15 +1,15 @@
1
- cycls/__init__.py,sha256=efbq0vRijGOByKtz9bRF8WQFYmnPSgZV1DH-54s6iwQ,493
2
- cycls/app.py,sha256=1i0cZ6EeSJMpSrB_qUtc7TxWjqcFrtwF7owbWBKpI0I,3547
1
+ cycls/__init__.py,sha256=XnLv709ktYzCVON0PwwFZFe6_m54pXfXZH9-niTxYxU,121
2
+ cycls/app.py,sha256=0SbXFok7im-xyZwum67gxuuP0Hqn3LkHD6HJ-WQJ1LY,3633
3
3
  cycls/auth.py,sha256=xkndHZyCfnlertMMEKerCJjf23N3fVcTRVTTSXTTuzg,247
4
4
  cycls/cli.py,sha256=cVbIkTDnVofohvByyYUrXF_RYDQZVQECJqo7cPBPJfs,4781
5
- cycls/function.py,sha256=-brasxTyfa9HxhZTO0OlV7gA1-cVLqMKNsbXTVQ6alg,16596
5
+ cycls/function.py,sha256=3W5rQzAXtkL4nOC5shTH2vRnW54NhvKzYiR0Q9nzIDM,18250
6
6
  cycls/state.py,sha256=3RL_BqcbfiAkJ6byeEo4Q9L99VurYyYKYJJhJhEVmAo,210
7
7
  cycls/web.py,sha256=v-hyWL9nlh4SyqAVgRzOkx96YuBntxqw6Q6phpAMDv0,6172
8
8
  cycls/themes/default/index.html,sha256=bZ3hJ4gPpDv9Jk2m2Eo8AaPAnf-96CE7LyvL5FJNl5Y,1082
9
9
  cycls/themes/default/assets/index-CTZe1T7l.js,sha256=srbFzhFFHhllhr9ewEbtDWp0oRt9aDAmeeAsTlltO9g,1357164
10
10
  cycls/themes/default/assets/index-oGkkm3Z8.css,sha256=xHhbrJvvz8mIN_Otrl6nawKJcA41L3tCFhVEOstGhVU,6498
11
11
  cycls/themes/dev/index.html,sha256=QJBHkdNuMMiwQU7o8dN8__8YQeQB45D37D-NCXIWB2Q,11585
12
- cycls-0.0.2.94.dist-info/METADATA,sha256=TpdHz5UtHK9EKZku7w4GU3TLtA9KRSbUwXTnE4zt39A,8869
13
- cycls-0.0.2.94.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
14
- cycls-0.0.2.94.dist-info/entry_points.txt,sha256=CktT5eNvW_Qxomf7L_Ez_GdUbL6qAfx_Utm6_HtUJwE,41
15
- cycls-0.0.2.94.dist-info/RECORD,,
12
+ cycls-0.0.2.96.dist-info/METADATA,sha256=-Yr_fdovBssU3aUW3rwIANu1G1--_uf4dZsxjKaY8II,8869
13
+ cycls-0.0.2.96.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
14
+ cycls-0.0.2.96.dist-info/entry_points.txt,sha256=CktT5eNvW_Qxomf7L_Ez_GdUbL6qAfx_Utm6_HtUJwE,41
15
+ cycls-0.0.2.96.dist-info/RECORD,,