cycls 0.0.2.93__py3-none-any.whl → 0.0.2.94__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/app.py +7 -0
- cycls/function.py +44 -0
- cycls/themes/default/assets/{index-Xh0IeurI.js → index-CTZe1T7l.js} +66 -66
- cycls/themes/default/index.html +1 -1
- {cycls-0.0.2.93.dist-info → cycls-0.0.2.94.dist-info}/METADATA +1 -1
- {cycls-0.0.2.93.dist-info → cycls-0.0.2.94.dist-info}/RECORD +8 -8
- {cycls-0.0.2.93.dist-info → cycls-0.0.2.94.dist-info}/WHEEL +0 -0
- {cycls-0.0.2.93.dist-info → cycls-0.0.2.94.dist-info}/entry_points.txt +0 -0
cycls/app.py
CHANGED
|
@@ -79,6 +79,13 @@ class App(Function):
|
|
|
79
79
|
self._prepare_func(prod=True)
|
|
80
80
|
return super().deploy(port=port)
|
|
81
81
|
|
|
82
|
+
def _deploy(self, port=8080):
|
|
83
|
+
"""Deploy to testing infrastructure."""
|
|
84
|
+
if self.api_key is None:
|
|
85
|
+
raise RuntimeError("Missing API key. Set cycls.api_key or CYCLS_API_KEY environment variable.")
|
|
86
|
+
self._prepare_func(prod=True)
|
|
87
|
+
return super()._deploy(port=port)
|
|
88
|
+
|
|
82
89
|
|
|
83
90
|
def app(name=None, **kwargs):
|
|
84
91
|
"""Decorator that transforms a function into a deployable App."""
|
cycls/function.py
CHANGED
|
@@ -396,6 +396,50 @@ CMD ["python", "entrypoint.py"]
|
|
|
396
396
|
print(f"Connection error: {e}")
|
|
397
397
|
return None
|
|
398
398
|
|
|
399
|
+
def _deploy(self, *args, **kwargs):
|
|
400
|
+
import requests
|
|
401
|
+
|
|
402
|
+
port = kwargs.pop('port', 8080)
|
|
403
|
+
print(f"Deploying '{self.name}'...")
|
|
404
|
+
|
|
405
|
+
payload = cloudpickle.dumps((self.func, args, {**kwargs, 'port': port}))
|
|
406
|
+
archive_name = f"{self.name}-{hashlib.sha256(payload).hexdigest()[:16]}.tar.gz"
|
|
407
|
+
|
|
408
|
+
with tempfile.TemporaryDirectory() as tmpdir:
|
|
409
|
+
workdir = Path(tmpdir)
|
|
410
|
+
self._prepare_deploy_context(workdir, port, args, kwargs)
|
|
411
|
+
|
|
412
|
+
archive_path = workdir / archive_name
|
|
413
|
+
with tarfile.open(archive_path, "w:gz") as tar:
|
|
414
|
+
for f in workdir.glob("**/*"):
|
|
415
|
+
if f.is_file() and f != archive_path:
|
|
416
|
+
tar.add(f, arcname=f.relative_to(workdir))
|
|
417
|
+
|
|
418
|
+
print("Uploading...")
|
|
419
|
+
with open(archive_path, 'rb') as f:
|
|
420
|
+
response = requests.post(
|
|
421
|
+
"https://api-572247013948.me-central1.run.app/v1/deploy",
|
|
422
|
+
data={"function_name": self.name, "port": port},
|
|
423
|
+
files={'source_archive': (archive_name, f, 'application/gzip')},
|
|
424
|
+
headers={"X-API-Key": self.api_key},
|
|
425
|
+
timeout=9000,
|
|
426
|
+
stream=True,
|
|
427
|
+
)
|
|
428
|
+
|
|
429
|
+
# Parse NDJSON stream
|
|
430
|
+
url = None
|
|
431
|
+
for line in response.iter_lines(decode_unicode=True):
|
|
432
|
+
if line:
|
|
433
|
+
event = json.loads(line)
|
|
434
|
+
status = event.get("status", "")
|
|
435
|
+
msg = event.get("message", "")
|
|
436
|
+
print(f" [{status}] {msg}")
|
|
437
|
+
if status == "DONE":
|
|
438
|
+
url = event.get("url")
|
|
439
|
+
elif status == "ERROR":
|
|
440
|
+
return None
|
|
441
|
+
return url
|
|
442
|
+
|
|
399
443
|
def __del__(self):
|
|
400
444
|
self._cleanup_container()
|
|
401
445
|
|