Dev Module (stx.dev)
Development tools and ecosystem management for the SciTeX package family.
Note
stx.dev delegates to the standalone
scitex-dev package.
Install with: pip install scitex-dev.
Overview
The dev module provides utilities for maintaining the SciTeX ecosystem of packages, building documentation, managing versions, and creating MCP/CLI wrappers for scientific tools. It is primarily used by package maintainers and contributors rather than end users.
Ecosystem Management
The SciTeX ecosystem comprises 14+ packages. stx.dev provides a
unified registry and coordination tools.
import scitex as stx
# List all ecosystem packages
stx.dev.list_versions()
# Check version consistency across the ecosystem
stx.dev.check_versions()
# Synchronize local clones
stx.dev.ecosystem_sync()
# Commit across multiple packages
stx.dev.ecosystem_commit("fix: update shared constants")
Package |
Purpose |
|---|---|
|
Hub package (re-exports all modules) |
|
File I/O for 30+ formats |
|
Statistical testing with auto-reporting |
|
AST-based convention checker |
|
Claim-evidence-workflow pipeline |
|
Publication-quality plotting |
|
Development and ecosystem tools |
|
Multi-backend notifications |
|
Runtime SDK for SciTeX applications |
LLM-friendly Types
stx.dev provides structured return types designed for consumption
by both humans and AI agents:
from scitex.dev import Result, ErrorCode
# Wrap function results for consistent handling
result = Result(ok=True, data={"accuracy": 0.95})
result = Result(ok=False, error=ErrorCode.NOT_FOUND, message="File missing")
# Decorator to add return_as= parameter
@stx.dev.supports_return_as
def analyze(data):
return {"mean": data.mean()}
analyze(data, return_as="json") # JSON string
analyze(data, return_as="dict") # Python dict
MCP and CLI Wrappers
Convert Python functions into MCP tools or CLI commands:
from scitex.dev import wrap_as_mcp, wrap_as_cli
def my_tool(path: str, threshold: float = 0.5) -> dict:
"""Analyze a data file."""
...
# Register as MCP tool (for AI agent access)
mcp_tool = wrap_as_mcp(my_tool)
# Register as CLI command (for terminal access)
cli_cmd = wrap_as_cli(my_tool)
Documentation
Build and search unified documentation across the ecosystem:
# Build Sphinx docs for a package
stx.dev.build_docs("scitex-io")
# Get docstring for any public function
stx.dev.get_docs("stx.io.save")
# Full-text search across all packages
results = stx.dev.search("load_configs")
Hot Reload
Reload modules during interactive development:
stx.dev.reload("scitex.io") # Re-import scitex.io from disk
HPC Testing
Submit test suites to HPC clusters and poll results:
scitex dev test-hpc --package scitex-io
scitex dev test-hpc-poll --job-id 12345
Bulk Rename
Rename symbols across an entire codebase safely:
stx.dev.bulk_rename(
root="./src",
old="old_function_name",
new="new_function_name",
dry_run=True, # Preview changes first
)
API Reference
scitex-dev: Shared developer utilities for the SciTeX ecosystem.
Zero-dependency package providing: - Docs aggregation and serving across all scitex packages - Unified search across APIs, CLI, MCP tools, and documentation - Version management and ecosystem registry - Bulk rename with cross-reference updates - LLM-friendly types (Result, ErrorCode, @supports_return_as)
Public API (20 functions):
# Docs
get_docs, build_docs, search_docs
# Search
search
# Versions
list_versions, check_versions, get_mismatches, fix_mismatches
# LLM-friendly types
Result, ErrorCode, supports_return_as, SideEffect,
classify_exception, handle_result, run_as_cli, run_as_mcp,
result_to_mcp, wrap_as_mcp
- scitex.dev.get_docs(package=None, packages=None, format=None, page=None, *, _discover_fn=None, _root_fn=None, _sphinx_fn=None)[source]
Get documentation for one, several, or all installed SciTeX packages.
- Resolution chain per package:
Pre-built _sphinx_html/ in installed package → fastest (production)
Sphinx _build/ available → use existing build
Neither → introspect from docstrings + signatures (always works)
- Parameters:
package (
Optional[str]) – Single package name (returns unwrapped result).packages (
Optional[list[str]]) – List of package names (returns dict keyed by name).format (
Optional[str]) – Output format — None for manifest, “json” for structured, “html” for path to HTML directory.page (
Optional[str]) – Specific page name (only with format=”html” or “json”).
- Returns:
the doc result directly (unwrapped). - If packages=: dict mapping package name → doc result. - If neither: dict of all discovered packages → doc result.
- Return type:
If package=
- Raises:
ValueError – If both package= and packages= are given.
LookupError – If a requested package is not found.
- scitex.dev.build_docs(package=None, output_dir=None, formats=None, *, _discover_fn=None, _sphinx_fn=None)[source]
Build docs from Sphinx source for one or all packages.
- Parameters:
- Return type:
- Returns:
Dict mapping package name → build result (path or error).
- Raises:
LookupError – If package not found.
RuntimeError – If Sphinx is not installed.
- scitex.dev.search_docs(query, package=None, packages=None, max_results=10, *, _discover_fn=None, _get_one_fn=None)[source]
Search documentation across one, several, or all SciTeX packages.
Simple keyword search over page titles and introspected content. Stdlib only — no external search dependencies.
- Parameters:
- Returns:
package, name, title, score, match_type. Sorted by relevance score (descending).
- Return type:
List of dicts with keys
- scitex.dev.search(query, scope='all', package=None, packages=None, max_results=10, fuzzy=True)[source]
Search across the SciTeX ecosystem.
- Query syntax:
“save figure” → match any term ‘“exact phrase”’ → match exact phrase “+required term” → term must appear “-excluded” → results with this term are removed
- Parameters:
query (
str) – Search query (supports +required, -excluded, “phrases”).scope (
Literal['all','api','cli','mcp','docs']) – What to search — “all”, “api”, “cli”, “mcp”, or “docs”.packages (
Optional[list[str]]) – Limit to specific packages.max_results (
int) – Maximum results to return.fuzzy (
bool) – Enable fuzzy matching via difflib (default True).
- Returns:
package, name, title, score, scope, match_type. Sorted by relevance (score descending).
- Return type:
List of dicts with
- scitex.dev.check_versions(packages=None)[source]
Check version consistency and return detailed status.
- scitex.dev.get_mismatches(packages=None)[source]
Return packages with non-ok status and their issues.
- scitex.dev.fix_mismatches(hosts=None, packages=None, local=True, remote=True, confirm=False, config=None)[source]
Detect version mismatches and fix them.
Combines detect + fix_local + fix_remote. Kept for backward compatibility. Prefer using the individual functions for clarity.
Safety: defaults to preview only. Pass confirm=True to execute.
- scitex.dev.get_ecosystem_versions(packages=None)[source]
Return a flat {pkg_name: installed_version} dict for the ecosystem.
Thin wrapper over list_versions for consumers that just need the installed-version string (Django health endpoints, Docker HEALTHCHECK scripts, dashboards). Skips all the git / PyPI / pyproject cross- check detail.
- Parameters:
packages (list[str] | None) – Package names to check. None = all ecosystem packages.
- Returns:
{"scitex": "2.27.3", "figrecipe": "0.28.1", "scitex-io": None}. None means the package is not installed.- Return type:
Examples
>>> from scitex_dev import get_ecosystem_versions >>> vers = get_ecosystem_versions() >>> vers["scitex"] '2.27.3'
- class scitex.dev.Result(success, data=None, error=None, error_code=None, context=<factory>, side_effects=<factory>, hints_on_success=<factory>, hints_on_warning=<factory>, hints_on_error=<factory>, idempotent=False, version=None)[source]
Bases:
Generic[T]Structured result wrapping function output with metadata.
- data
The return value on success; None on failure.
- Type:
T | None
- hints_on_success
Related tools the consumer might want (light, “see also” style). Reserved for future use — currently empty.
- hints_on_warning
Hints for partial success, deprecation, or approaching limits. Reserved for future use — currently empty.
- hints_on_error
Recovery guidance for expected failures (FAQ-style). Accepts None, “”, a single string, or a list.
- class scitex.dev.ErrorCode(value)[source]
-
Machine-readable error codes for structured error responses.
- exception scitex.dev.ScitexError(message, *, code=ErrorCode.INTERNAL, remediation=None)[source]
Bases:
ExceptionCanonical SciTeX exception for structured failures.
Use when the failure crosses an MCP / CLI / HTTP boundary and the caller (often an LLM agent) needs a machine-readable category plus a human remediation hint. For plain Python errors raised inside a script, prefer the standard library exceptions (
ValueError,FileNotFoundError, etc.) — seegeneral/03_interface/01_python-api/09_error-handling.md.- Parameters:
Examples
>>> raise ScitexError( ... "h5py not installed", ... code=ErrorCode.DEPENDENCY, ... remediation="pip install scitex-io[h5]", ... )
- scitex.dev.classify_exception(exc)[source]
Classify an exception into an ErrorCode.
Checks for a
.error_codeattribute first (SciTeXError convention), then falls back to built-in exception type mapping.- Return type:
- scitex.dev.try_import_optional(module_path, attr=None, *, extra=None, pkg=None, package=None)[source]
Import
module_path; returnNoneonImportError.- Parameters:
module_path (str) – Module to import. Leading
.triggers relative resolution againstpackage(mirrorsimportlib.import_module()).attr (str, optional) – If given, return
getattr(module, attr)instead of the module. A missing attribute is treated identically to a failed import.extra (str, optional) – Name of the pip extra that pulls this dependency (used for the install hint surfaced via
last_install_hint()).pkg (str, optional) – Distribution name owning the extra (e.g.
"scitex-io").package (str, optional) – Anchor for relative imports.
- Returns:
The imported module/attribute, or
Noneon failure.- Return type:
object or None
- scitex.dev.last_install_hint(name)[source]
Return the most recently recorded install hint for
name(orNone).- Return type:
- class scitex.dev.InstallHint(module, extra, pkg)[source]
Bases:
objectMetadata to help a caller surface a useful install message.
- scitex.dev.supports_return_as(fn)[source]
Add
return_as="result"support to a function.return_as=None(default): data returned, exceptions raised.return_as="result": wrapped inResult.Any other value: passed through to the original function.
Examples
>>> @supports_return_as ... def add(a: int, b: int) -> int: ... return a + b >>> add(1, 2) 3 >>> result = add(1, 2, return_as="result") >>> result.success True >>> result.data 3
- Return type:
- class scitex.dev.SideEffect(type, target, undoable=False)[source]
Bases:
objectA declared side effect of a function.
- type
Category (file_create, file_modify, file_delete, network, state_change, cache_write).
- Type:
- scitex.dev.handle_result(result, as_json=False, file=None)[source]
Format and print a Result, return the exit code.
- scitex.dev.run_as_cli(fn, as_json=False, **kwargs)[source]
Call a
@supports_return_asfunction and exit with proper code.
- scitex.dev.wrap_as_cli(fn, as_json=False, **kwargs)[source]
Call any function and display its result via CLI.
Like
wrap_as_mcpbut for terminal output. Wraps any plain function in Result, formats based onas_json, and exits with proper exit code.
- scitex.dev.run_as_mcp(fn, **kwargs)[source]
Call a
@supports_return_asfunction and return MCP-ready JSON.
- scitex.dev.wrap_as_mcp(fn, *, side_effects=None, hints_on_error=None, idempotent=False, **kwargs)[source]
Call any function and wrap its return in Result JSON.
Unlike
run_as_mcp(which requires@supports_return_as), this wraps any plain function. Use this to retrofit existing handlers without modifying the underlying function.- Parameters:
fn (Callable) – Any callable returning data or raising exceptions.
side_effects (list[str], optional) – Declared side effects (e.g.
["file_create: /tmp/out.csv"]).hints_on_error (list[str], optional) – Recovery guidance for expected failures (FAQ-style).
idempotent (bool) – Whether the operation is safe to retry.
**kwargs (
Any) – Arguments to pass tofn.
- Returns:
JSON string with Result structure.
- Return type:
- async scitex.dev.async_wrap_as_mcp(coro_fn, *, side_effects=None, hints_on_error=None, idempotent=False, **kwargs)[source]
Async version of
wrap_as_mcpfor async handlers.- Parameters:
- Returns:
JSON string with Result structure.
- Return type:
- scitex.dev.result_to_mcp(result)[source]
Convert an existing Result to MCP-ready JSON.
- Return type:
- scitex.dev.json_option(fn)[source]
Click decorator: adds
--jsonflag asas_jsonparameter.Uses lazy
import clickso scitex-dev stays stdlib-only.- Return type:
- scitex.dev.dry_run_option(fn)[source]
Click decorator: adds
--dry-runflag.Uses lazy
import clickso scitex-dev stays stdlib-only.- Return type:
- scitex.dev.add_dry_run_argument(parser)[source]
Add
--dry-runflag to an argparse parser.- Return type:
- scitex.dev.sync_all(hosts=None, packages=None, stash=True, install=True, safe=True, confirm=False, config=None, *, sync_host_fn=None, enabled_hosts_fn=None)[source]
Sync packages across all enabled hosts.
Safety: defaults to preview only. Pass confirm=True to execute. Parallel: hosts are synced concurrently by default.
- Parameters:
hosts (list[str] | None) – Host names to sync. None = all enabled hosts.
packages (list[str] | None) – Package names. None = host-specific defaults.
stash (bool) – Git stash before pull.
install (bool) – Pip install after pull.
safe (bool) – If True (default), skip packages whose remote working copy is ahead of / diverged from upstream (never clobber unpushed work).
confirm (bool) – If False (default), preview only (dry run). If True, execute the sync operation.
config (DevConfig | None) – Configuration.
- Returns:
{host_name: {package: result}}.
- Return type:
- scitex.dev.sync_host(host, packages=None, stash=True, install=True, safe=True, confirm=False, config=None, *, host_packages_fn=None)[source]
Sync packages to a remote host via SSH.
Safety: defaults to preview only. Pass confirm=True to execute.
Steps per package: ahead-check (if safe), git stash, git pull, pip install -e ., git stash pop.
- Parameters:
host (HostConfig) – Target host configuration.
packages (list[str] | None) – Package names to sync. None = use host’s configured packages.
stash (bool) – Git stash before pull (default True).
install (bool) – Pip install after pull (default True).
safe (bool) – If True (default), pre-check each remote working copy and skip packages whose HEAD is ahead of / diverged from upstream so we never clobber unpushed commits.
confirm (bool) – If False (default), preview only (dry run). If True, execute the sync operation.
config (DevConfig | None) – Configuration. Loaded from default if None.
- Returns:
Per-package results: {package: {status, commands|output, error}}.
statusincludesok,skipped_ahead,skipped_diverged,missing,error,timeout, ordry_run.- Return type:
- scitex.dev.sync_local(packages=None, confirm=False, config=None, jobs=1, on_progress=None)[source]
Install all local editable packages.
Safety: defaults to preview only. Pass confirm=True to execute.
- Parameters:
packages (list[str] | None) – Package names. None = all configured packages.
confirm (bool) – If False (default), preview only. If True, execute pip install -e.
config (DevConfig | None) – Configuration.
jobs (int) – Parallel installs. 1 = serial (default). 0 or negative = all CPUs.
on_progress (callable | None) – Optional callback
f(idx, total, name, status, elapsed)invoked as each package finishes.
- Returns:
{package: {status, output|commands}}.
- Return type:
- scitex.dev.sync_tags(packages=None, confirm=False, config=None)[source]
Push local tags for all packages to origin.
Safety: defaults to preview only. Pass confirm=True to execute.
- scitex.dev.remote_diff(host=None, packages=None, config=None)[source]
Show git diff on remote host(s). Read-only operation.
- scitex.dev.remote_commit(host, packages=None, message=None, push=True, confirm=False, config=None)[source]
Commit dirty changes on a remote host and optionally push to origin.
Safety: defaults to preview only. Pass confirm=True to execute.
- Parameters:
host (str) – Host name (required).
packages (list[str] | None) – Package names. None = host-configured defaults.
message (str | None) – Commit message. Auto-generated if not provided.
push (bool) – Push to origin after commit (default True).
confirm (bool) – If False (default), preview only (dry run).
config (DevConfig | None) – Configuration.
- Returns:
{package: {status, commands|output}}.
- Return type:
- scitex.dev.pull_local(packages=None, confirm=False, stash=True, config=None)[source]
Pull latest from origin to local repos.
Safety: defaults to preview only. Pass confirm=True to execute.
- Parameters:
packages (list[str] | None) – Package names. None = all configured packages.
confirm (bool) – If False (default), preview only.
stash (bool) – If True (default), stash local changes before pull and pop after. If False and repo is dirty, pull proceeds as-is (may fail).
config (DevConfig | None) – Configuration.
- Returns:
{package: {status, output|commands, stashed}}.
- Return type: