From 796fe9da0bcc2149872decf5d4dce8e8a7744241 Mon Sep 17 00:00:00 2001 From: soustruh Date: Thu, 17 Jul 2025 16:47:35 +0200 Subject: [PATCH 1/3] venv parameter has no default value now - This should help users realize this feature is new and make them deliberately pick one of the choices available. - The red warning when creating a new configuration seems like an acceptable trade-off for users not breaking their configurations unintentionally when making unrelated changes to their configurations. --- component_config/configSchema.json | 52 ++++++++++++++++-------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/component_config/configSchema.json b/component_config/configSchema.json index 66517ba..fa21b29 100644 --- a/component_config/configSchema.json +++ b/component_config/configSchema.json @@ -2,16 +2,39 @@ "type": "object", "title": "Configuration", "required": [ + "venv", "user_properties", - "code", - "packages" + "source" ], "properties": { + "venv": { + "enum": [ + "3.14", + "3.13", + "3.12", + "base" + ], + "type": "string", + "format": "radio", + "title": "Python Version & Environment Isolation", + "default": null, + "options": { + "tooltip": "- **Isolated environment** takes a couple of seconds to start, but gives you the opportuninty to pick one of the latest versions of Python. It's also a safer choice as it prevents package collisions.\n- Non-isolated environment (used to be the default choice) might start a bit faster, but can lead to issues mentioned above. It will also become a subject to deprecation in the future.\n- We recommmend you **update the code regularly** to make sure it runs with the latest versions of all packages. This will help you avoid issues with abandoned packages and **security vulnerabilities**.", + "enum_titles": [ + "Python 3.14 beta – Isolated environment (just the packages of your choice)", + "Python 3.13 – Isolated environment (just the packages of your choice) – This is the recommended choice 🐙", + "Python 3.12 – Isolated environment (just the packages of your choice)", + "Python 3.10 – Shared environment (contains many pre-installed packages in legacy versions) – This used to be the default choice" + ] + }, + "required": false, + "propertyOrder": 10 + }, "user_properties": { "type": "object", "title": "User Parameters", "format": "editor", - "propertyOrder": 10, + "propertyOrder": 20, "default": { "debug": false }, @@ -25,30 +48,9 @@ } } }, - "venv": { - "enum": [ - "base", - "3.12", - "3.13", - "3.14" - ], - "type": "string", - "title": "Python Version & Environment Isolation", - "default": "3.13", - "options": { - "tooltip": "- Isolated environment takes a couple of seconds to start, but gives you the opportuninty to pick one of the latest versions of Python. It's also a safer choice as it prevents package collisions.\n- Non-isolated environment (used to be the default choice) might start a bit faster, but can lead to issues mentioned above.", - "enum_titles": [ - "Python 3.10 – Shared environment (contains many pre-installed packages in legacy versions)", - "Python 3.12 – Isolated environment (just the packages of your choice)", - "Python 3.13 – Isolated environment (just the packages of your choice)", - "Python 3.14 beta – Isolated environment (just the packages of your choice)" - ] - }, - "required": false, - "propertyOrder": 30 - }, "source": { "type": "string", + "format": "radio", "title": "Source Code & Dependencies", "propertyOrder": 30, "enum": [ From ca1e6ba29d7fb802de3ce4e30f8f6659167d833d Mon Sep 17 00:00:00 2001 From: soustruh Date: Thu, 17 Jul 2025 16:50:39 +0200 Subject: [PATCH 2/3] =?UTF-8?q?live=20view=20of=20the=20custom=20code=20ou?= =?UTF-8?q?tput=20&=20logging=20=F0=9F=8F=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/subprocess_runner.py | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/src/subprocess_runner.py b/src/subprocess_runner.py index 94c8b27..c40fcc1 100644 --- a/src/subprocess_runner.py +++ b/src/subprocess_runner.py @@ -1,5 +1,6 @@ import logging import subprocess +import threading from keboola.component.exceptions import UserException @@ -16,18 +17,36 @@ def run( args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, - text=False, + text=True, ) - stdout, stderr = process.communicate() - if stdout: - logging.info("Command output:\n%s", stdout.decode()) + stderr_output = [] - process.poll() - if process.poll() != 0: - stderr_str = stderr.decode() if stderr else "Unknown error." + def read_stderr(): + if process.stderr: + for line in iter(process.stderr.readline, ""): + stderr_output.append(line.strip()) + logging.info("Command stderr: %s", line.strip()) + process.stderr.close() + + # Start stderr reader thread + stderr_thread = threading.Thread(target=read_stderr) + stderr_thread.start() + + # Read stdout in main thread + stdout_lines = [] + if process.stdout: + for line in iter(process.stdout.readline, ""): + stdout_lines.append(line.strip()) + logging.info("Command output: %s", line.strip()) + process.stdout.close() + stderr_thread.join() + + process.wait() + stderr_str = "\n".join(stderr_output) if stderr_output else "Unknown error." + if process.returncode != 0: raise UserException(f"{err_message} Log in event detail.", stderr_str) - elif stderr: - logging.info("%s Full log in detail.", ok_message, extra={"full_message": stderr.decode()}) + elif stderr_str: + logging.info("%s Full log in detail.", ok_message, extra={"full_message": stderr_str}) else: logging.info(ok_message) From d2917516c0cf72ae0038978c3ea78248a796bf85 Mon Sep 17 00:00:00 2001 From: soustruh Date: Fri, 18 Jul 2025 15:17:42 +0200 Subject: [PATCH 3/3] =?UTF-8?q?reordered=20git=20preferences=20to=20better?= =?UTF-8?q?=20match=20natural=20user=20workflow=20=F0=9F=8C=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- component_config/configSchema.json | 83 +++++++++++++++--------------- 1 file changed, 41 insertions(+), 42 deletions(-) diff --git a/component_config/configSchema.json b/component_config/configSchema.json index fa21b29..19effd1 100644 --- a/component_config/configSchema.json +++ b/component_config/configSchema.json @@ -27,7 +27,6 @@ "Python 3.10 – Shared environment (contains many pre-installed packages in legacy versions) – This used to be the default choice" ] }, - "required": false, "propertyOrder": 10 }, "user_properties": { @@ -64,8 +63,7 @@ "Get from Git repository" ] }, - "default": "code", - "required": false + "default": "code" }, "packages": { "type": "array", @@ -112,8 +110,7 @@ }, "required": [ "url", - "branch", - "filename" + "auth" ], "properties": { "url": { @@ -121,42 +118,11 @@ "title": "Repository URL", "propertyOrder": 70 }, - "branch": { - "type": "string", - "enum": [], - "title": "Branch Name", - "propertyOrder": 80, - "options": { - "async": { - "label": "List Branches", - "action": "listBranches", - "autoload": [ - "git.url" - ], - "cache": false - } - } - }, - "filename": { - "type": "string", - "enum": [], - "title": "Script Filename", - "propertyOrder": 90, - "options": { - "async": { - "label": "List Files", - "action": "listFiles", - "autoload": [ - "git.branch" - ], - "cache": false - } - } - }, "auth": { "type": "string", + "format": "radio", "title": "Repository Visibility & Authentication", - "propertyOrder": 100, + "propertyOrder": 80, "enum": [ "none", "pat", @@ -169,13 +135,12 @@ "Private – SSH Key" ] }, - "default": "none", - "required": false + "default": "none" }, "#token": { "type": "string", "title": "Personal Access Token", - "propertyOrder": 110, + "propertyOrder": 90, "options": { "dependencies": { "auth": "pat" @@ -185,13 +150,47 @@ "ssh_keys": { "type": "object", "format": "ssh-editor", - "propertyOrder": 120, + "propertyOrder": 100, "options": { "only_keys": true, "dependencies": { "auth": "ssh" } } + }, + "branch": { + "type": "string", + "enum": [], + "title": "Branch Name", + "propertyOrder": 110, + "options": { + "tooltip": "If left empty, the default value `main` will be used.", + "async": { + "label": "List Branches", + "action": "listBranches", + "autoload": [ + "git.url" + ], + "cache": false + } + } + }, + "filename": { + "type": "string", + "enum": [], + "title": "Script Filename", + "propertyOrder": 120, + "options": { + "tooltip": "If left empty, the default value `main.py` will be used.", + "async": { + "label": "List Files", + "action": "listFiles", + "autoload": [ + "git.branch" + ], + "cache": false + } + } } } }