Publish current ComfyUI O1Key code baseline
Replace the prior release tree with the current plugin, frontend, tests, and documentation. Document retired node IDs and the public Gitea update source.
This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
import importlib.util
|
||||
import json
|
||||
import sys
|
||||
import types
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
from unittest.mock import patch
|
||||
|
||||
import aiohttp
|
||||
from PIL import Image
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
|
||||
|
||||
def _load_uploader():
|
||||
package = types.ModuleType("comfyui_o1key")
|
||||
package.__path__ = [str(ROOT)]
|
||||
utils_package = types.ModuleType("comfyui_o1key.utils")
|
||||
utils_package.__path__ = [str(ROOT / "utils")]
|
||||
sys.modules[package.__name__] = package
|
||||
sys.modules[utils_package.__name__] = utils_package
|
||||
|
||||
config = types.ModuleType("comfyui_o1key.utils.config")
|
||||
config.get_api_key_or_raise = lambda *_args, **_kwargs: "secret"
|
||||
config.get_api_base_url = lambda: "https://api.o1key.cn"
|
||||
sys.modules[config.__name__] = config
|
||||
|
||||
video_task = types.ModuleType("comfyui_o1key.utils.video_task")
|
||||
video_task.check_interrupt = lambda: None
|
||||
|
||||
async def run_with_interrupt(coro):
|
||||
return await coro
|
||||
|
||||
video_task.run_with_interrupt = run_with_interrupt
|
||||
sys.modules[video_task.__name__] = video_task
|
||||
|
||||
spec = importlib.util.spec_from_file_location(
|
||||
"comfyui_o1key.utils.r2_uploader",
|
||||
ROOT / "utils" / "r2_uploader.py",
|
||||
)
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
sys.modules[spec.name] = module
|
||||
spec.loader.exec_module(module)
|
||||
return module
|
||||
|
||||
|
||||
UPLOADER = _load_uploader()
|
||||
|
||||
|
||||
class _FakeResponse:
|
||||
def __init__(self, status, payload, headers=None):
|
||||
self.status = status
|
||||
self.payload = payload
|
||||
self.headers = headers or {}
|
||||
|
||||
async def __aenter__(self):
|
||||
return self
|
||||
|
||||
async def __aexit__(self, _exc_type, _exc, _tb):
|
||||
return False
|
||||
|
||||
async def text(self):
|
||||
return json.dumps(self.payload)
|
||||
|
||||
|
||||
class _FakeSession:
|
||||
def __init__(self, factory):
|
||||
self.factory = factory
|
||||
|
||||
async def __aenter__(self):
|
||||
return self
|
||||
|
||||
async def __aexit__(self, _exc_type, _exc, _tb):
|
||||
return False
|
||||
|
||||
def post(self, url, **kwargs):
|
||||
self.factory.calls.append((url, kwargs))
|
||||
return self.factory.responses.pop(0)
|
||||
|
||||
|
||||
class _SessionFactory:
|
||||
def __init__(self, responses):
|
||||
self.responses = list(responses)
|
||||
self.calls = []
|
||||
|
||||
def __call__(self, **_kwargs):
|
||||
return _FakeSession(self)
|
||||
|
||||
|
||||
class TempMediaUploadTests(unittest.IsolatedAsyncioTestCase):
|
||||
async def test_upload_uses_new_multipart_endpoint(self):
|
||||
expected_url = "https://cf-api.o1key.com/tmp/input/reference.png"
|
||||
factory = _SessionFactory([
|
||||
_FakeResponse(200, {
|
||||
"url": expected_url,
|
||||
"filename": "reference.png",
|
||||
"content_type": "image/png",
|
||||
"size": 12,
|
||||
"expires_at": 1_787_495_062,
|
||||
})
|
||||
])
|
||||
|
||||
with (
|
||||
patch.object(UPLOADER.aiohttp, "ClientSession", factory),
|
||||
patch.object(UPLOADER.aiohttp, "TCPConnector", return_value=object()),
|
||||
patch("builtins.print") as print_mock,
|
||||
):
|
||||
result = await UPLOADER._upload_file(
|
||||
b"png-bytes",
|
||||
"reference.png",
|
||||
"image/png",
|
||||
base_url="https://cf-api.o1key.com/",
|
||||
)
|
||||
|
||||
self.assertEqual(result, expected_url)
|
||||
rendered_log = "\n".join(
|
||||
" ".join(str(arg) for arg in call.args)
|
||||
for call in print_mock.call_args_list
|
||||
)
|
||||
self.assertNotIn(expected_url, rendered_log)
|
||||
self.assertEqual(len(factory.calls), 1)
|
||||
url, kwargs = factory.calls[0]
|
||||
self.assertEqual(url, "https://cf-api.o1key.com/v1/o1key/uploads")
|
||||
self.assertEqual(kwargs["headers"], {"Authorization": "Bearer secret"})
|
||||
self.assertNotIn("Content-Type", kwargs["headers"])
|
||||
self.assertIsInstance(kwargs["data"], aiohttp.FormData)
|
||||
field_options, field_headers, field_value = kwargs["data"]._fields[0]
|
||||
self.assertEqual(field_options["name"], "file")
|
||||
self.assertEqual(field_options["filename"], "reference.png")
|
||||
self.assertEqual(field_headers["Content-Type"], "image/png")
|
||||
self.assertEqual(field_value, b"png-bytes")
|
||||
|
||||
async def test_non_retryable_upload_error_is_not_retried(self):
|
||||
factory = _SessionFactory([
|
||||
_FakeResponse(413, {"error": "attachment too large"})
|
||||
])
|
||||
|
||||
with (
|
||||
patch.object(UPLOADER.aiohttp, "ClientSession", factory),
|
||||
patch.object(UPLOADER.aiohttp, "TCPConnector", return_value=object()),
|
||||
):
|
||||
with self.assertRaisesRegex(RuntimeError, "HTTP 413"):
|
||||
await UPLOADER._upload_file(
|
||||
b"data",
|
||||
"video.mp4",
|
||||
"video/mp4",
|
||||
)
|
||||
|
||||
self.assertEqual(len(factory.calls), 1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main(verbosity=2)
|
||||
Reference in New Issue
Block a user