Skip to content

Commit

Permalink
Merge branch 'develop' into dependabot/npm_and_yarn/npm_and_yarn-e986…
Browse files Browse the repository at this point in the history
…2e08fa
  • Loading branch information
strickvl authored Mar 9, 2025
2 parents 41e6a01 + 1b2c8f9 commit 49d3aa4
Show file tree
Hide file tree
Showing 38 changed files with 1,073 additions and 481 deletions.
8 changes: 4 additions & 4 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
---
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file

version: 2
updates:
- package-ecosystem: "npm"
directory: "/" # Location of package manifests
- package-ecosystem: npm
directory: / # Location of package manifests
schedule:
interval: "weekly"
interval: weekly
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@
"python.testing.unittestEnabled": false,
"python.testing.pytestEnabled": true,
"python.testing.cwd": "${workspaceFolder}",
"python.analysis.extraPaths": ["bundled/libs", "bundled/tool"]
"python.analysis.extraPaths": ["bundled/libs", "bundled/tool"],
"python.analysis.typeCheckingMode": "off"
}
26 changes: 26 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,32 @@ The project uses [typos](https://github.com/crate-ci/typos) for spellchecking wi

The script automatically uses the repository's default config file `.typos.toml` in the root of the repository. Custom configurations are not supported to ensure consistent spell checking across all contributions. All arguments passed to the script (except `-c/--config`) are forwarded directly to `typos`.

### Formatting and Linting

We use automatic formatting and linting tools to keep our code consistent.

#### Quick Commands

| Task | Command | What it does |
| ----------------- | --------------------- | ---------------------------------------------------- |
| Format everything | `./scripts/format.sh` | Formats all Python, TypeScript, JSON, and YAML files |
| Lint everything | `./scripts/lint.sh` | Checks all files for style/quality issues |

#### Individual Tools

- **Python**: `ruff` for formatting/linting, `mypy` for type checking
- **TypeScript/JSON**: `prettier` for formatting, `eslint` for linting
- **YAML**: `yamlfix` for formatting and checking

#### NPM Scripts

For frontend code only:

- `npm run format` - Format TypeScript and JSON files
- `npm run lint` - Lint TypeScript files

Please run these commands before submitting your PR.

## Contributing Changes

1. **Create a Branch**: Make your changes in a new git branch based on the `develop` branch.
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ this extension and your Python version needs to be 3.8 or greater.
## Requirements

- **ZenML Installation:** ZenML needs to be installed in the local Python environment associated with the Python interpreter selected in the current VS Code workspace. This extension interacts directly with your ZenML environment, so ensuring that ZenML is installed and properly configured is essential.
- **ZenML Version**: To ensure full functionality and compatibility, make sure you have ZenML version 0.63.0 or newer.
- **ZenML Version**: This extension is fully compatible with ZenML versions 0.63.0 through 0.75.0. While newer versions may work, they haven't been officially tested. If you encounter any issues with newer versions, please report them.
- **Python Version**: Python 3.8 or greater is required for the operation of the LSP server, which is a part of this extension.

## Feedback and Contributions
Expand Down
3 changes: 2 additions & 1 deletion bundled/tool/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@

TOOL_MODULE_NAME = "zenml-python"
TOOL_DISPLAY_NAME = "ZenML"
MIN_ZENML_VERSION = "0.55.0"
MIN_ZENML_VERSION = "0.63.0"
MAX_ZENML_VERSION = "0.75.0"

"""Constants for ZenML Notifications and Events"""

Expand Down
4 changes: 2 additions & 2 deletions bundled/tool/lazy_import.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
# or implied. See the License for the specific language governing
# permissions and limitations under the License.
"""
Utilities for lazy importing and temporary suppression of stdout and logging.
Reduces noise when integrating with logging-heavy systems like LSP.
Utilities for lazy importing and temporary suppression of stdout and logging.
Reduces noise when integrating with logging-heavy systems like LSP.
Useful for quieter module loads and command executions.
"""

Expand Down
12 changes: 10 additions & 2 deletions bundled/tool/lsp_jsonrpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@

"""Light-weight JSON-RPC over standard IO."""


import atexit
import io
import json
Expand Down Expand Up @@ -58,14 +57,23 @@ def write(self, data):
raise StreamClosedException()

with self._lock:
content = json.dumps(data)
# Add custom JSON serialization to handle datetime objects
content = json.dumps(data, default=self._json_serializer)
length = len(content.encode("utf-8"))
self._writer.write(f"{CONTENT_LENGTH}{length}\r\n\r\n{content}")
# self._writer.write(
# f"{CONTENT_LENGTH}{length}\r\n\r\n{content}".encode("utf-8")
# )
self._writer.flush()

def _json_serializer(self, obj):
"""Custom JSON serializer to handle datetime and other complex objects."""
# Handle datetime objects
if hasattr(obj, "isoformat"):
return obj.isoformat()
# Handle other non-serializable objects
return str(obj)


class JsonReader:
"""Manages reading JSON-RPC messages from stream."""
Expand Down
4 changes: 3 additions & 1 deletion bundled/tool/lsp_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
# or implied. See the License for the specific language governing
# permissions and limitations under the License.
"""Implementation of tool support over LSP."""

from __future__ import annotations

import json
Expand Down Expand Up @@ -92,7 +93,8 @@ async def initialize(params: lsp.InitializeParams) -> None:
if settings is not None:
_update_workspace_settings(settings)
log_to_output(
f"Settings used to run Server:\r\n{json.dumps(settings, indent=4, ensure_ascii=False)}\r\n"
f"Settings used to run Server:\r\n"
f"{json.dumps(settings, indent=4, ensure_ascii=False)}\r\n"
)

log_to_output(
Expand Down
1 change: 1 addition & 0 deletions bundled/tool/lsp_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
# permissions and limitations under the License.

"""Utility functions and classes for use with running tools over LSP."""

from __future__ import annotations

import contextlib
Expand Down
51 changes: 17 additions & 34 deletions bundled/tool/lsp_zenml.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
updating Python interpreter paths.
"""


import asyncio
import subprocess
import sys
Expand All @@ -32,9 +31,7 @@
from zen_watcher import ZenConfigWatcher
from zenml_client import ZenMLClient

zenml_init_error = {
"error": "ZenML is not initialized. Please check ZenML version requirements."
}
zenml_init_error = {"error": "ZenML is not initialized. Please check ZenML version requirements."}


class ZenLanguageServer(LanguageServer):
Expand All @@ -60,9 +57,7 @@ async def is_zenml_installed(self) -> bool:
if process.returncode == 0:
self.show_message_log("✅ ZenML installation check: Successful.")
return True
self.show_message_log(
"❌ ZenML installation check failed.", lsp.MessageType.Error
)
self.show_message_log("❌ ZenML installation check failed.", lsp.MessageType.Error)
return False
except Exception as e:
self.show_message_log(
Expand Down Expand Up @@ -97,9 +92,7 @@ async def initialize_zenml_client(self):
# initialize watcher
self.initialize_global_config_watcher()
except Exception as e:
self.notify_user(
f"Failed to initialize ZenML client: {str(e)}", lsp.MessageType.Error
)
self.notify_user(f"Failed to initialize ZenML client: {str(e)}", lsp.MessageType.Error)

def initialize_global_config_watcher(self):
"""Sets up and starts the Global Configuration Watcher."""
Expand Down Expand Up @@ -139,9 +132,7 @@ def wrapper(*args, **kwargs):

with suppress_stdout_temporarily():
if wrapper_name:
wrapper_instance = getattr(
self.zenml_client, wrapper_name, None
)
wrapper_instance = getattr(self.zenml_client, wrapper_name, None)
if not wrapper_instance:
return {"error": f"Wrapper '{wrapper_name}' not found."}
return func(wrapper_instance, *args, **kwargs)
Expand Down Expand Up @@ -185,33 +176,25 @@ def _construct_version_validation_response(self, meets_requirement, version_str)

def send_custom_notification(self, method: str, args: dict):
"""Sends a custom notification to the LSP client."""
self.show_message_log(
f"Sending custom notification: {method} with args: {args}"
)
self.show_message_log(f"Sending custom notification: {method} with args: {args}")
self.send_notification(method, args)

def update_python_interpreter(self, interpreter_path):
"""Updates the Python interpreter path and handles errors."""
try:
self.python_interpreter = interpreter_path
self.show_message_log(
f"LSP_Python_Interpreter Updated: {self.python_interpreter}"
)
self.show_message_log(f"LSP_Python_Interpreter Updated: {self.python_interpreter}")
# pylint: disable=broad-exception-caught
except Exception as e:
self.show_message_log(
f"Failed to update Python interpreter: {str(e)}", lsp.MessageType.Error
)

def notify_user(
self, message: str, msg_type: lsp.MessageType = lsp.MessageType.Info
):
def notify_user(self, message: str, msg_type: lsp.MessageType = lsp.MessageType.Info):
"""Logs a message and also notifies the user."""
self.show_message(message, msg_type)

def log_to_output(
self, message: str, msg_type: lsp.MessageType = lsp.MessageType.Log
) -> None:
def log_to_output(self, message: str, msg_type: lsp.MessageType = lsp.MessageType.Log) -> None:
"""Log to output."""
self.show_message_log(message, msg_type)

Expand Down Expand Up @@ -277,55 +260,55 @@ def rename_stack(wrapper_instance, args):
def copy_stack(wrapper_instance, args):
"""Copies a specified ZenML stack to a new stack."""
return wrapper_instance.copy_stack(args)

@self.command(f"{TOOL_MODULE_NAME}.registerStack")
@self.zenml_command(wrapper_name="stacks_wrapper")
def register_stack(wrapper_instance, args):
"""Registers a new ZenML stack."""
return wrapper_instance.register_stack(args)

@self.command(f"{TOOL_MODULE_NAME}.updateStack")
@self.zenml_command(wrapper_name="stacks_wrapper")
def update_stack(wrapper_instance, args):
"""Updates a specified ZenML stack ."""
return wrapper_instance.update_stack(args)

@self.command(f"{TOOL_MODULE_NAME}.deleteStack")
@self.zenml_command(wrapper_name="stacks_wrapper")
def delete_stack(wrapper_instance, args):
"""Deletes a specified ZenML stack ."""
return wrapper_instance.delete_stack(args)

@self.command(f"{TOOL_MODULE_NAME}.registerComponent")
@self.zenml_command(wrapper_name="stacks_wrapper")
def register_component(wrapper_instance, args):
"""Registers a Zenml stack component"""
return wrapper_instance.register_component(args)

@self.command(f"{TOOL_MODULE_NAME}.updateComponent")
@self.zenml_command(wrapper_name="stacks_wrapper")
def update_component(wrapper_instance, args):
"""Updates a ZenML stack component"""
return wrapper_instance.update_component(args)

@self.command(f"{TOOL_MODULE_NAME}.deleteComponent")
@self.zenml_command(wrapper_name="stacks_wrapper")
def delete_component(wrapper_instance, args):
"""Deletes a specified ZenML stack component"""
return wrapper_instance.delete_component(args)

@self.command(f"{TOOL_MODULE_NAME}.listComponents")
@self.zenml_command(wrapper_name="stacks_wrapper")
def list_components(wrapper_instance, args):
"""Get paginated list of stack components from ZenML"""
return wrapper_instance.list_components(args)

@self.command(f"{TOOL_MODULE_NAME}.getComponentTypes")
@self.zenml_command(wrapper_name="stacks_wrapper")
def get_component_types(wrapper_instance, args):
"""Get list of component types from ZenML"""
return wrapper_instance.get_component_types()

@self.command(f"{TOOL_MODULE_NAME}.listFlavors")
@self.zenml_command(wrapper_name="stacks_wrapper")
def list_flavors(wrapper_instance, args):
Expand Down
Loading

0 comments on commit 49d3aa4

Please sign in to comment.