Function bodies 257 total
should_exclude? function · ruby · L63-L72 (10 LOC)docgen/scripts/build_sketchup_api_index.rb
def should_exclude?(obj, excluded_namespaces, excluded_patterns)
# Check top-level namespace
top_namespace = obj.path.split('::').first
return true if excluded_namespaces.include?(top_namespace)
# Check patterns
return true if excluded_patterns.any? { |regex| regex.match?(obj.path) }
false
endcategorize_classes function · ruby · L75-L91 (17 LOC)docgen/scripts/build_sketchup_api_index.rb
def categorize_classes(classes, categories)
categorized = Hash.new { |h, k| h[k] = [] }
uncategorized = []
classes.each do |cls|
class_name = cls[:path].split('::').last
found = false
categories.each do |category, class_names|
next if category == 'Other'
next unless class_names.include?(class_name)
categorized[category] << cls
found = true
break
endgenerate_namespace_index function · ruby · L101-L119 (19 LOC)docgen/scripts/build_sketchup_api_index.rb
def generate_namespace_index(namespace, objects, methods_by_parent, categories)
output_dir = "generated-sketchup-api-docs/#{namespace}"
FileUtils.mkdir_p(output_dir)
output_path = "#{output_dir}/INDEX.md"
# Separate classes/modules from the main namespace object
classes_and_modules = objects.select { |o| %w[class module].include?(o[:type]) }
main_obj = classes_and_modules.find { |obj| obj[:path] == namespace }
other_classes = classes_and_modules.reject { |obj| obj[:path] == namespace }
File.open(output_path, 'w') do |f|
f.puts "# #{namespace} Namespace"
f.puts ''
# Module description if exists
if main_obj && !main_obj[:summary].empty?
f.puts main_obj[:summary]
f.puts ''
endDocHelpers.convert_yard_references method · ruby · L15-L24 (10 LOC)docgen/scripts/doc_helpers.rb
def self.convert_yard_references(text)
return text if text.nil? || text.empty?
# Convert {ClassName}, {#method}, {.class_method} to markdown code
# Remove leading # or . from references (YARD syntax, not part of name)
text = text.gsub(/\{([#.]?)([^}]+)\}/, '`\2`')
# Convert +text+ to markdown code (YARD inline code format)
text.gsub(/\+([^+]+)\+/, '`\1`')
endDocHelpers.normalize_text method · ruby · L36-L69 (34 LOC)docgen/scripts/doc_helpers.rb
def self.normalize_text(text)
return text if text.nil? || text.empty?
# Split by paragraph breaks (one or more blank lines)
paragraphs = text.split(/\n\s*\n/)
# Normalize each paragraph
normalized = paragraphs.map do |para|
lines = para.split("\n")
# Remove empty lines within paragraph
lines = lines.reject { |line| line.strip.empty? }
result = []
current = ''
lines.each do |line|
stripped = line.strip
# Check if line has intentional formatting:
# 1. Leading whitespace (indentation)
# 2. Starts with list marker (-, *, +, or number followed by . or ))
is_formatted = line =~ /^\s+/ || stripped =~ /^[-*+]|\d+[.)]/
if is_formatted
# Formatted line - finish current accumulated text and start new line
result << current.strip unless current.strip.empty?
current = stripped
elsif current.empty?
# Regular text - join with previous (removeprocess_yard_text function · ruby · L87-L94 (8 LOC)docgen/scripts/doc_helpers.rb
def self.process_yard_text(text)
return text if text.nil? || text.empty?
# First normalize (remove line wrapping, preserve paragraphs)
normalized = normalize_text(text)
# Then convert YARD cross-references to markdown code
convert_yard_references(normalized)
endshould_exclude? function · ruby · L35-L41 (7 LOC)docgen/scripts/generate_sketchup_api_docs.rb
def should_exclude?(obj, excluded_namespaces, excluded_patterns)
top_namespace = obj.path.split('::').first
return true if excluded_namespaces.include?(top_namespace)
return true if excluded_patterns.any? { |regex| regex.match?(obj.path) }
false
endRepobility · severity-and-effort ranking · https://repobility.com
format_tag function · ruby · L44-L49 (6 LOC)docgen/scripts/generate_sketchup_api_docs.rb
def format_tag(tag) return nil unless tag text = tag.text.to_s.strip text.empty? ? nil : text end
format_param function · ruby · L52-L62 (11 LOC)docgen/scripts/generate_sketchup_api_docs.rb
def format_param(param)
parts = []
parts << "`#{param.name}`" if param.name
if param.types && !param.types.empty?
# Add "as" separator if we have a parameter name
parts << 'as' if param.name
# Wrap each type in backticks
types_formatted = param.types.map { |t| "`#{t}`" }.join(', ')
# Only use parentheses if there's more than one type
parts << (param.types.length > 1 ? "(#{types_formatted})" : types_formatted)
endformat_return function · ruby · L68-L75 (8 LOC)docgen/scripts/generate_sketchup_api_docs.rb
def format_return(tag)
parts = []
if tag.types && !tag.types.empty?
# Wrap each type in backticks
types_formatted = tag.types.map { |t| "`#{t}`" }.join(', ')
# Only use parentheses if there's more than one type
parts << (tag.types.length > 1 ? "(#{types_formatted})" : types_formatted)
endgenerate_class_markdown function · ruby · L81-L92 (12 LOC)docgen/scripts/generate_sketchup_api_docs.rb
def generate_class_markdown(obj)
md = []
# Header
md << "# #{obj.type.to_s.capitalize}: #{obj.path}"
md << ''
# Inheritance information
if obj.type == :class && obj.superclass && obj.superclass.path != 'Object'
md << "**Inherits:** `#{obj.superclass.path}`"
md << ''
endgenerate_method_markdown function · ruby · L161-L179 (19 LOC)docgen/scripts/generate_sketchup_api_docs.rb
def generate_method_markdown(method)
md = []
# Method signature
sig = method.signature || "def #{method.name}"
md << "### #{method.name}"
md << ''
md << '```ruby'
md << sig
md << '```'
md << ''
# Method description
if method.docstring && !method.docstring.empty?
# Process YARD text (normalize and convert references)
description = DocHelpers.process_yard_text(method.docstring.to_s.strip)
md << description
md << ''
end_setup_logging function · python · L14-L32 (19 LOC)driver/src/supex_driver/cli/main.py
def _setup_logging():
"""Configure logging to file only (lazy initialization).
Called once when first needed. Fails gracefully if log directory
cannot be created.
"""
log_dir = os.environ.get("SUPEX_LOG_DIR", os.path.expanduser("~/.supex/logs"))
try:
os.makedirs(log_dir, exist_ok=True)
log_file = os.path.join(log_dir, "cli.log")
logging.basicConfig(
level=logging.DEBUG,
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
filename=log_file,
filemode="a",
)
except OSError:
# If we can't create log directory, configure null handler
logging.basicConfig(level=logging.WARNING, handlers=[logging.NullHandler()])_ensure_logging function · python · L39-L44 (6 LOC)driver/src/supex_driver/cli/main.py
def _ensure_logging():
"""Ensure logging is configured (lazy init)."""
global _logging_configured
if not _logging_configured:
_setup_logging()
_logging_configured = Truehandle_error function · python · L71-L88 (18 LOC)driver/src/supex_driver/cli/main.py
def handle_error(e: Exception, exit_code: int = 1):
"""Handle and display errors."""
out = get_output()
if isinstance(e, SketchUpRemoteError):
out.error(f"SketchUp error [{e.code}]: {e.message}")
if e.data:
if "file" in e.data:
out.info(f"File: {e.data['file']}", dim=True)
if "line" in e.data:
out.info(f"Line: {e.data['line']}", dim=True)
if "hint" in e.data:
out.info(f"Hint: {e.data['hint']}", dim=True)
elif isinstance(e, SketchUpConnectionError):
out.error(f"Connection error: {e}")
out.info("Make sure SketchUp is running with the Supex runtime.", dim=True)
else:
out.error(str(e))
raise typer.Exit(exit_code)Repobility — same analyzer, your code, free for public repos · /scan/
print_result function · python · L91-L100 (10 LOC)driver/src/supex_driver/cli/main.py
def print_result(result: dict, as_json: bool = False) -> None:
"""Print command result to console."""
out = get_output()
if as_json:
out.json(result)
# Pretty print based on content
elif "success" in result and not result.get("success"):
out.error(f"Failed: {result.get('error', 'Unknown error')}")
else:
out.json(result)get_project_root function · python · L103-L109 (7 LOC)driver/src/supex_driver/cli/main.py
def get_project_root() -> Path:
"""Find project root by looking for CLAUDE.md or .git."""
current = Path(__file__).resolve()
for parent in current.parents:
if (parent / "CLAUDE.md").exists() or (parent / ".git").exists():
return parent
return Path.cwd()check_docs_available function · python · L112-L117 (6 LOC)driver/src/supex_driver/cli/main.py
def check_docs_available() -> tuple[bool, Path]:
"""Check if SketchUp API docs are available."""
project_root = get_project_root()
docs_path = project_root / "docgen" / "generated-sketchup-api-docs"
index_path = docs_path / "INDEX.md"
return index_path.exists(), docs_pathstatus function · python · L121-L156 (36 LOC)driver/src/supex_driver/cli/main.py
def status(
host: HostOption = "localhost",
port: PortOption = 9876,
):
"""Check SketchUp connection and system status."""
out = get_output()
sketchup_connected = False
# SketchUp connection status
try:
conn = get_connection(host, port)
result = conn.send_command("ping")
version = result.get('version', 'unknown')
out.panel(
f"[green]Connected[/green]\nVersion: {version}",
title="SketchUp Status",
)
sketchup_connected = True
except Exception as e:
out.panel(
f"[red]Disconnected[/red]\n{e}",
title="SketchUp Status",
)
out.info("Make sure SketchUp is running with the Supex runtime.", dim=True)
# Documentation status
docs_available, docs_path = check_docs_available()
if docs_available:
out.print(f"\n[dim]API Docs:[/dim] [green]Available[/green] at {docs_path}")
else:
out.print("\n[dim]API Docs:[/dim] [yelloreload function · python · L160-L182 (23 LOC)driver/src/supex_driver/cli/main.py
def reload(
host: HostOption = "localhost",
port: PortOption = 9876,
):
"""Reload the SketchUp extension without restarting SketchUp."""
out = get_output()
try:
out.warning("Reloading SketchUp extension...")
conn = get_connection(host, port)
result = conn.send_command("reload_extension")
if result.get("success"):
out.success("Extension reloaded successfully")
if "message" in result:
out.print(result["message"])
else:
out.error("Failed to reload extension")
error_msg = result.get("error", "Unknown error")
out.print(error_msg)
raise typer.Exit(1)
except Exception as e:
handle_error(e)eval_ruby function · python · L186-L209 (24 LOC)driver/src/supex_driver/cli/main.py
def eval_ruby(
code: Annotated[str, typer.Argument(help="Ruby code to execute")],
host: HostOption = "localhost",
port: PortOption = 9876,
raw: Annotated[bool, typer.Option("--raw", "-r", help="Output raw JSON")] = False,
):
"""Evaluate Ruby code in SketchUp context."""
out = get_output()
try:
conn = get_connection(host, port)
result = conn.send_command("eval_ruby", {"code": code})
if raw:
print(json.dumps(result))
else:
# Extract the actual result text
content = result.get("content", [])
if isinstance(content, list) and content:
text = content[0].get("text", str(result))
out.print(text)
else:
out.print(result.get("result", str(result)))
except Exception as e:
handle_error(e)eval_ruby_file function · python · L213-L244 (32 LOC)driver/src/supex_driver/cli/main.py
def eval_ruby_file(
file_path: Annotated[Path, typer.Argument(help="Path to Ruby file")],
host: HostOption = "localhost",
port: PortOption = 9876,
raw: Annotated[bool, typer.Option("--raw", "-r", help="Output raw JSON")] = False,
):
"""Evaluate Ruby code from a file in SketchUp context."""
out = get_output()
# Resolve to absolute path
abs_path = file_path.resolve()
if not abs_path.exists():
out.error(f"File not found: {abs_path}")
raise typer.Exit(1)
try:
conn = get_connection(host, port)
result = conn.send_command("eval_ruby_file", {"file_path": str(abs_path)})
if raw:
print(json.dumps(result))
elif result.get("success"):
out.success(f"Executed {abs_path.name}")
content = result.get("content", [])
if isinstance(content, list) and content:
text = content[0].get("text", "")
if text:
out.print(text)
info function · python · L248-L270 (23 LOC)driver/src/supex_driver/cli/main.py
def info(
host: HostOption = "localhost",
port: PortOption = 9876,
raw: Annotated[bool, typer.Option("--raw", "-r", help="Output raw JSON")] = False,
):
"""Get information about the current SketchUp model."""
out = get_output()
try:
conn = get_connection(host, port)
result = conn.send_command("get_model_info")
if raw:
print(json.dumps(result))
else:
content = result.get("content", [{}])
if isinstance(content, list) and content:
data = json.loads(content[0].get("text", "{}"))
else:
data = result
out.table(data, title="Model Info")
except Exception as e:
handle_error(e)Methodology: Repobility · https://repobility.com/research/state-of-ai-code-2026/
entities function · python · L274-L290 (17 LOC)driver/src/supex_driver/cli/main.py
def entities(
entity_type: Annotated[str, typer.Argument(help="Type: all, faces, edges, groups, components")] = "all",
host: HostOption = "localhost",
port: PortOption = 9876,
raw: Annotated[bool, typer.Option("--raw", "-r", help="Output raw JSON")] = False,
):
"""List entities in the model."""
try:
conn = get_connection(host, port)
result = conn.send_command("list_entities", {"entity_type": entity_type})
if raw:
print(json.dumps(result))
else:
print_result(result)
except Exception as e:
handle_error(e)selection function · python · L294-L309 (16 LOC)driver/src/supex_driver/cli/main.py
def selection(
host: HostOption = "localhost",
port: PortOption = 9876,
raw: Annotated[bool, typer.Option("--raw", "-r", help="Output raw JSON")] = False,
):
"""Get currently selected entities in SketchUp."""
try:
conn = get_connection(host, port)
result = conn.send_command("get_selection")
if raw:
print(json.dumps(result))
else:
print_result(result)
except Exception as e:
handle_error(e)layers function · python · L313-L328 (16 LOC)driver/src/supex_driver/cli/main.py
def layers(
host: HostOption = "localhost",
port: PortOption = 9876,
raw: Annotated[bool, typer.Option("--raw", "-r", help="Output raw JSON")] = False,
):
"""List layers (tags) in the model."""
try:
conn = get_connection(host, port)
result = conn.send_command("get_layers")
if raw:
print(json.dumps(result))
else:
print_result(result)
except Exception as e:
handle_error(e)materials function · python · L332-L347 (16 LOC)driver/src/supex_driver/cli/main.py
def materials(
host: HostOption = "localhost",
port: PortOption = 9876,
raw: Annotated[bool, typer.Option("--raw", "-r", help="Output raw JSON")] = False,
):
"""List materials in the model."""
try:
conn = get_connection(host, port)
result = conn.send_command("get_materials")
if raw:
print(json.dumps(result))
else:
print_result(result)
except Exception as e:
handle_error(e)camera function · python · L351-L366 (16 LOC)driver/src/supex_driver/cli/main.py
def camera(
host: HostOption = "localhost",
port: PortOption = 9876,
raw: Annotated[bool, typer.Option("--raw", "-r", help="Output raw JSON")] = False,
):
"""Get current camera position and settings."""
try:
conn = get_connection(host, port)
result = conn.send_command("get_camera_info")
if raw:
print(json.dumps(result))
else:
print_result(result)
except Exception as e:
handle_error(e)screenshot function · python · L370-L401 (32 LOC)driver/src/supex_driver/cli/main.py
def screenshot(
output: Annotated[Path | None, typer.Option("--output", "-o", help="Output file path")] = None,
width: Annotated[int, typer.Option("--width", "-w", help="Image width")] = 1920,
height: Annotated[int, typer.Option("--height", help="Image height")] = 1080,
transparent: Annotated[bool, typer.Option("--transparent", "-t", help="Transparent background")] = False,
host: HostOption = "localhost",
port: PortOption = 9876,
):
"""Take a screenshot of the current SketchUp view."""
out = get_output()
try:
conn = get_connection(host, port)
params: dict[str, int | bool | str] = {
"width": width,
"height": height,
"transparent": transparent,
}
if output:
params["output_path"] = str(output.resolve())
result = conn.send_command("take_screenshot", params)
content = result.get("content", [{}])
if isinstance(content, list) and content:
daopen_model function · python · L405-L423 (19 LOC)driver/src/supex_driver/cli/main.py
def open_model(
path: Annotated[Path, typer.Argument(help="Path to .skp file")],
host: HostOption = "localhost",
port: PortOption = 9876,
):
"""Open a SketchUp model file."""
out = get_output()
abs_path = path.resolve()
if not abs_path.exists():
out.error(f"File not found: {abs_path}")
raise typer.Exit(1)
try:
conn = get_connection(host, port)
conn.send_command("open_model", {"path": str(abs_path)})
out.success(f"Opened: {abs_path.name}")
except Exception as e:
handle_error(e)save function · python · L427-L443 (17 LOC)driver/src/supex_driver/cli/main.py
def save(
path: Annotated[Path | None, typer.Argument(help="Path to save to (optional)")] = None,
host: HostOption = "localhost",
port: PortOption = 9876,
):
"""Save the current SketchUp model."""
out = get_output()
try:
conn = get_connection(host, port)
params = {}
if path:
params["path"] = str(path.resolve())
conn.send_command("save_model", params)
out.success("Model saved")
except Exception as e:
handle_error(e)Want this analysis on your repo? https://repobility.com/scan/
export function · python · L447-L468 (22 LOC)driver/src/supex_driver/cli/main.py
def export(
format: Annotated[str, typer.Argument(help="Export format: skp, obj, dae, stl, png, jpg")] = "skp",
host: HostOption = "localhost",
port: PortOption = 9876,
):
"""Export the current SketchUp scene."""
out = get_output()
try:
conn = get_connection(host, port)
result = conn.send_command("export_scene", {"format": format})
# Handle both MCP format (content array) and direct format (file_path)
content = result.get("content")
if isinstance(content, list) and content:
data = json.loads(content[0].get("text", "{}"))
else:
data = result
file_path = data.get("file_path", "unknown")
out.success(f"Exported to: {file_path}")
except Exception as e:
handle_error(e)main function · python · L471-L477 (7 LOC)driver/src/supex_driver/cli/main.py
def main():
"""Main entry point."""
_ensure_logging()
try:
app()
except KeyboardInterrupt:
raise SystemExit(130)_should_use_plain_output function · python · L15-L41 (27 LOC)driver/src/supex_driver/cli/output.py
def _should_use_plain_output() -> bool:
"""Determine if plain (non-rich) output should be used.
Priority order (highest first):
1. SUPEX_PLAIN=1 -> plain mode (project-specific)
2. SUPEX_COLOR=1 -> rich mode (project-specific)
3. NO_COLOR (any non-empty value) -> plain mode (standard)
4. FORCE_COLOR (any non-empty value) -> rich mode (standard)
5. TTY detection -> rich if TTY, plain otherwise
"""
# Project-specific overrides (highest priority)
if os.environ.get("SUPEX_PLAIN") == "1":
return True
if os.environ.get("SUPEX_COLOR") == "1":
return False
# Standard environment variables
no_color = os.environ.get("NO_COLOR", "")
if no_color: # Any non-empty value
return True
force_color = os.environ.get("FORCE_COLOR", "")
if force_color: # Any non-empty value
return False
# TTY detection fallback
return not sys.stdout.isatty()_strip_markup function · python · L44-L50 (7 LOC)driver/src/supex_driver/cli/output.py
def _strip_markup(text: str) -> str:
"""Remove Rich markup tags from text.
Handles tags like [green], [/green], [red], [dim], etc.
Preserves unicode characters (checkmarks, etc.).
"""
return re.sub(r"\[/?[a-zA-Z_]+\]", "", text)Output.__init__ method · python · L56-L62 (7 LOC)driver/src/supex_driver/cli/output.py
def __init__(self) -> None:
self._plain_mode = _should_use_plain_output()
if not self._plain_mode:
# Use wide console to prevent truncation in non-terminal contexts
self._console: Console | None = Console(width=200)
else:
self._console = NoneOutput.print method · python · L69-L77 (9 LOC)driver/src/supex_driver/cli/output.py
def print(self, *args: Any, **kwargs: Any) -> None:
"""Print text, stripping Rich markup in plain mode."""
if self._plain_mode:
# Convert args to plain text
text = " ".join(_strip_markup(str(arg)) for arg in args)
print(text)
else:
assert self._console is not None
self._console.print(*args, **kwargs)Output.success method · python · L79-L85 (7 LOC)driver/src/supex_driver/cli/output.py
def success(self, message: str) -> None:
"""Print success message with checkmark."""
if self._plain_mode:
print(f"[OK] {message}")
else:
assert self._console is not None
self._console.print(f"[green]\u2713[/green] {message}")Output.error method · python · L87-L93 (7 LOC)driver/src/supex_driver/cli/output.py
def error(self, message: str) -> None:
"""Print error message."""
if self._plain_mode:
print(f"[ERROR] {message}", file=sys.stderr)
else:
assert self._console is not None
self._console.print(f"[red]Error:[/red] {message}")Repobility · severity-and-effort ranking · https://repobility.com
Output.warning method · python · L95-L101 (7 LOC)driver/src/supex_driver/cli/output.py
def warning(self, message: str) -> None:
"""Print warning message."""
if self._plain_mode:
print(f"[WARN] {message}")
else:
assert self._console is not None
self._console.print(f"[yellow]{message}[/yellow]")Output.info method · python · L103-L112 (10 LOC)driver/src/supex_driver/cli/output.py
def info(self, message: str, dim: bool = False) -> None:
"""Print informational message."""
if self._plain_mode:
print(message)
else:
assert self._console is not None
if dim:
self._console.print(f"[dim]{message}[/dim]")
else:
self._console.print(message)Output.panel method · python · L114-L128 (15 LOC)driver/src/supex_driver/cli/output.py
def panel(self, content: str, title: str | None = None) -> None:
"""Print content in a panel (or plain section in plain mode)."""
if self._plain_mode:
# Strip markup from content
plain_content = _strip_markup(content)
if title:
separator = "-" * (len(title) + 8)
print(f"--- {title} ---")
print(plain_content)
print(separator)
else:
print(plain_content)
else:
assert self._console is not None
self._console.print(Panel(content, title=title))Output.table method · python · L130-L145 (16 LOC)driver/src/supex_driver/cli/output.py
def table(self, data: dict[str, Any], title: str | None = None) -> None:
"""Print key-value data as table or plain text."""
if self._plain_mode:
if title:
print(f"{title}:")
max_key_len = max(len(str(k)) for k in data) if data else 0
for key, value in data.items():
print(f" {key:<{max_key_len}} {value}")
else:
assert self._console is not None
table = Table(title=title)
table.add_column("Property", style="cyan")
table.add_column("Value")
for key, value in data.items():
table.add_row(str(key), str(value))
self._console.print(table)Output.json method · python · L147-L153 (7 LOC)driver/src/supex_driver/cli/output.py
def json(self, data: Any) -> None:
"""Print JSON data with or without syntax highlighting."""
if self._plain_mode:
print(json_module.dumps(data, indent=2))
else:
assert self._console is not None
self._console.print(JSON(json_module.dumps(data)))get_output function · python · L160-L165 (6 LOC)driver/src/supex_driver/cli/output.py
def get_output() -> Output:
"""Get the global Output instance."""
global _output
if _output is None:
_output = Output()
return _output_next_request_id function · python · L44-L49 (6 LOC)driver/src/supex_driver/connection/connection.py
def _next_request_id() -> int:
"""Generate next request ID (thread-safe monotonic counter)."""
global _request_id_counter
with _request_id_lock:
_request_id_counter += 1
return _request_id_counterSketchupConnection.connect method · python · L74-L102 (29 LOC)driver/src/supex_driver/connection/connection.py
def connect(self) -> bool:
"""Connect to the SketchUp runtime socket server and send hello handshake.
Returns:
True if connection and identification successful, False otherwise.
"""
# Always create fresh connections
self.disconnect()
try:
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.settimeout(self.timeout)
self.sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
self.sock.connect((self.host, self.port))
logger.debug(f"Created connection to SketchUp at {self.host}:{self.port}")
# Send hello handshake
if not self._send_hello():
logger.error("Failed to identify with SketchUp server")
self.disconnect()
return False
self._identified = True
return True
except Exception as e:
logger.error(f"Failed to connect to SketchURepobility — same analyzer, your code, free for public repos · /scan/
SketchupConnection._send_hello method · python · L104-L147 (44 LOC)driver/src/supex_driver/connection/connection.py
def _send_hello(self) -> bool:
"""Send hello handshake to identify this client.
Returns:
True if identification successful, False otherwise.
"""
if not self.sock:
return False
hello_params = {
"name": CLIENT_NAME,
"version": CLIENT_VERSION,
"agent": self.agent,
"pid": os.getpid(),
}
# Add token if configured
if self.token:
hello_params["token"] = self.token
hello_request = {
"jsonrpc": "2.0",
"method": "hello",
"params": hello_params,
"id": "hello",
}
try:
request_bytes = json.dumps(hello_request).encode("utf-8") + b"\n"
self.sock.sendall(request_bytes)
response_data = self.receive_full_response(self.sock)
response = json.loads(response_data.decode("utf-8"))
if "error" in response:
erSketchupConnection.disconnect method · python · L149-L158 (10 LOC)driver/src/supex_driver/connection/connection.py
def disconnect(self) -> None:
"""Disconnect from the SketchUp runtime."""
if self.sock:
try:
self.sock.close()
except Exception as e:
logger.error(f"Error disconnecting from SketchUp: {e}")
finally:
self.sock = None
self._identified = FalseSketchupConnection.receive_full_response method · python · L160-L208 (49 LOC)driver/src/supex_driver/connection/connection.py
def receive_full_response(
self, sock: socket.socket, buffer_size: int = 4096
) -> bytes:
"""Receive a complete newline-delimited JSON response.
Reads from socket until a newline character is encountered,
enforcing maximum response size limits.
Args:
sock: The socket to receive from.
buffer_size: Size of receive buffer.
Returns:
Complete response as bytes (including trailing newline).
Raises:
SketchUpTimeoutError: If socket times out with no data.
SketchUpConnectionError: If connection is lost.
SketchUpProtocolError: If response exceeds size limit or is incomplete.
"""
data = bytearray()
sock.settimeout(self.timeout)
try:
while True:
chunk = sock.recv(buffer_size)
if not chunk:
if not data:
raise SketchUpConnectionError("Connectipage 1 / 6next ›