Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 7 additions & 13 deletions .github/workflows/import-smoke-on-ubuntu-py3-12.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ name: import-smoke
# the bare package (no extras) is `pip install -e .`-able and
# `import scitex` succeeds. Catches `[project] dependencies`
# drift that the test matrix masks because it installs `[all,dev]`.
#
# Thin caller over the org reusable (PS-231): the local steps were
# equivalent to the reusable's install (no extras) + import check.
# `runs_on` stays explicit so the runner choice remains locally visible.

on:
push:
Expand All @@ -19,16 +23,6 @@ on:
jobs:
install-check:
name: import-smoke-on-ubuntu-py3-12
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install (no extras)
run: |
python -m venv .venv
.venv/bin/pip install --upgrade pip
.venv/bin/pip install -e .
- name: Import smoke
run: .venv/bin/python -c "import scitex; print(scitex.__version__)"
uses: scitex-ai/.github/.github/workflows/import-smoke.yml@main
with:
runs_on: '["ubuntu-latest"]'
9 changes: 4 additions & 5 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -942,11 +942,10 @@ docs/sphinx/_build/

# Generated Sphinx HTML — NOT committed for the umbrella. RTD
# (readthedocs.io) builds and hosts the docs from docs/sphinx/; committing
# ~120MB of generated HTML is pure repo bloat. The PyPI wheel does not need
# it (the SIF installs the wheel, which excludes docs). NOTE: this conflicts
# with scitex-dev rules PS-121/PS-128, which currently require the umbrella
# to commit src/<pkg>/_sphinx_html/ for scitex-cloud's in-wheel doc serving
# — flagged to scitex-dev for the umbrella to accept RTD-built docs instead.
# ~120MB of generated HTML is pure repo bloat. The bundle still reaches the
# wheel via [tool.hatch.build.targets.wheel] `artifacts` (PS-121/PS-128 read
# that declaration, so this exclusion is compliant) — CI's rtd workflow
# refreshes the dir before release builds.
src/scitex/_sphinx_html/
.playwright-cli/
.venv/
Expand Down
11 changes: 11 additions & 0 deletions .scitex/dev/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,14 @@
project-type:
- pip
- deferred

# Reasoned PS-231 exemptions (rule-prescribed path for leaf-unique workflows).
audit:
exemptions:
PS-231:
- path: .github/workflows/pytest-matrix-on-ubuntu-py3-11-3-12-3-13.yml
line: 0
reason: "Leaf-unique segfault-hardened matrix: CPU-only torch pre-install (CUDA wheels segfault GPU-less runners, exit 139), mid-extraction peer standalones install, PS-170 pin-freshness gate, JUnit-verdict pass/fail (shutdown segfault after last PASS must not fail the job), retry-on-segfault, tests/e2e + cross-package-import quarantines. The org pytest-matrix reusable provides none of these; converting would lose the hardening."
- path: .github/workflows/rtd-sphinx-build-on-ubuntu-latest.yml
line: 0
reason: "Vendoring publisher (rule BLOCKER 2): builds Sphinx HTML and refreshes src/scitex/_sphinx_html/ for the in-wheel docs bundle served by scitex-cloud. The org rtd-sphinx-build reusable is build-only; converting stops the bundle refresh while the wheel still declares the artifact."
2 changes: 1 addition & 1 deletion docs/sphinx/source/mcp.rst
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ Or install the MCP server globally:

.. code-block:: bash

scitex mcp installation
scitex mcp show-installation

Tool Categories
---------------
Expand Down
62 changes: 35 additions & 27 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,13 @@ dependencies = [
# ModuleNotFoundError. PS-213 console-script-deps-must-be-core
# (scitex-dev v0.17.10+) enforces this rule ecosystem-wide.
#
# The sibling `scitex` entry-point (`scitex.__main__:main`) uses the
# LAZY-EXTRA pattern — function-scope `import click` in
# `_check_cli_dependencies()` with a `pip install scitex[cli]` install
# hint — and would qualify for the PS-213i lazy-pass on its own, BUT
# `scitex-pkg` lives in the same package so the moment we ship a
# console-script that loads click unconditionally we have to make
# click a hard core dep.
# The sibling `scitex` entry-point is now the click group itself
# (`scitex.cli.main:cli`) — audit-cli requires a click/argparse object
# behind the entry point. `python -m scitex` keeps the LAZY-EXTRA
# pattern (function-scope `import click` in `_check_cli_dependencies()`
# with a `pip install scitex[cli]` install hint). Either way, shipping a
# console-script that loads click unconditionally keeps click a hard
# core dep.
"click>=8.0.0",
"tqdm",
"packaging",
Expand Down Expand Up @@ -128,7 +128,12 @@ Repository = "https://github.com/ywatanabe1989/scitex-python"
"Bug Tracker" = "https://github.com/ywatanabe1989/scitex-python/issues"

[project.scripts]
scitex = "scitex.__main__:main"
# Main CLI: the click group directly (audit-cli requires a click/argparse
# object behind the entry point; a plain-function wrapper reads as
# not-auditable). Top imports of scitex.cli.main are stdlib + click (core),
# subcommands stay lazy, so a bare `pip install scitex` still works.
# `python -m scitex` keeps the friendly _check_cli_dependencies() path.
scitex = "scitex.cli.main:cli"
# Package-management CLI (venv drift detector for mgr-pkg autonomous ops)
scitex-pkg = "scitex.cli.pkg:pkg"
# Unified MCP Server (all modules in one). Use `scitex serve` (preferred)
Expand Down Expand Up @@ -275,7 +280,7 @@ config = [

# Context Module - Context managers
# Use: pip install scitex[context]
context = []
context = ["scitex-context==0.1.4"]

# CV Module - Computer vision
# Use: pip install scitex[cv]
Expand All @@ -298,7 +303,7 @@ dataset = ["scitex-dataset==0.5.0"]

# Datetime Module - Date and time utilities
# Use: pip install scitex[datetime]
datetime = []
datetime = ["scitex-datetime==0.1.3"]

# Decorators Module - Caching and utilities
# Use: pip install scitex[decorators]
Expand Down Expand Up @@ -388,7 +393,7 @@ etc = [

# Events Module - Event system
# Use: pip install scitex[events]
events = []
events = ["scitex-events==0.1.6"]

# Gists Module - Code snippet management
# Use: pip install scitex[gists]
Expand Down Expand Up @@ -443,7 +448,7 @@ io = [

# Introspect Module - Code introspection
# Use: pip install scitex[introspect]
introspect = []
introspect = ["scitex-introspect==0.1.7"]

# Linalg Module - Linear algebra
# Use: pip install scitex[linalg]
Expand All @@ -467,7 +472,7 @@ logging = [

# Media Module - Media display utilities (always available: scitex-etc is a
# core dep). scitex.media re-exports scitex_etc.media (shipped in >=0.2.0).
media = []
media = ["scitex-etc==0.2.1"]

# ML Module - Machine learning
# Use: pip install scitex[ml]
Expand Down Expand Up @@ -523,7 +528,7 @@ notification = [

# OS Module - OS utilities
# Use: pip install scitex[os]
os = []
os = ["scitex-os==0.1.8"]

# Parallel Module - Parallel processing
# Use: pip install scitex[parallel]
Expand Down Expand Up @@ -609,9 +614,11 @@ rng = [

# Scholar GUI - Minimal deps for Flask citation graph viewer
# Use: pip install scitex[scholar-gui]
# NOTE: `click` is a hard core dep (see [project.dependencies]), so it is
# NOT repeated here — repeating it trips PS-148 (optional-dep imported
# unguarded at module top) across src/scitex/cli/.
scholar-gui = [
"flask>=2.0.0",
"click",
"crossref-local==0.7.6",
"openalex-local==0.7.6",
]
Expand Down Expand Up @@ -661,9 +668,8 @@ scholar = [
"scitex-scholar==1.4.2"
]

# Schema Module - Data schema validation
# Use: pip install scitex[schema]
schema = []
# Schema Module - Data schema validation (planned; no standalone peer yet,
# so no install handle is declared until the module ships).

# Security Module - Security utilities. Absorbed into scitex-audit
# per ADR-0001 (scitex-dev #139, Accepted 2026-06-07); `scitex.security`
Expand Down Expand Up @@ -949,16 +955,13 @@ dev = [
"scitex-audit==0.2.0",
"scitex-browser==0.1.15",
"scitex-clew==0.17.0",
# NOTE: scitex-hub (optional peer powering cloud/module/project; formerly
# scitex-cloud) is intentionally NOT in [dev] — it is unreleased, so listing
# it here would break CI's `.[all,dev]` resolve. Install explicitly via
# `pip install scitex[cloud]` when scitex-hub is available.
"scitex-container==0.2.1",
"scitex-dataset==0.5.0",
"scitex-dev==0.28.0",
"scitex-dev>=0.28.0",
"scitex-etc==0.2.1",
"scitex-genai==0.1.1",
"scitex-io==0.3.3",
"scitex-logging==0.1.7",
"scitex-notification==0.2.9",
"scitex-scholar==1.4.2",
"scitex-ssh==1.0.1",
Expand Down Expand Up @@ -1022,9 +1025,10 @@ all = [
"scitex[capture]",
"scitex[clew]",
"scitex[cli]",
# NOTE: scitex[cloud] / scitex[module] / scitex[project] (scitex-hub) are
# OPTIONAL peers deliberately kept OUT of [all] so CI's matrix runs without
# the unreleased scitex-hub. Install explicitly: pip install scitex[cloud].
"scitex[cloud]",
"scitex[hub]",
"scitex[module]",
"scitex[project]",
"scitex[compat]",
"scitex[config]",
"scitex[container]",
Expand Down Expand Up @@ -1064,7 +1068,6 @@ all = [
"scitex[reproduce]",
"scitex[resource]",
"scitex[rng]",
"scitex[schema]",
"scitex[scholar]",
"scitex[scholar-gui]",
"scitex[security]",
Expand Down Expand Up @@ -1100,6 +1103,11 @@ path = "src/scitex/__version__.py"
pattern = '__version__ = "(?P<version>[^"]+)"'

[tool.hatch.build.targets.wheel]
# In-wheel Sphinx bundle for scitex-cloud docs serving (PS-121/PS-128):
# `artifacts` (not `force-include`) so local builds without the generated
# bundle still succeed — CI's rtd workflow refreshes src/scitex/_sphinx_html/
# before release builds. The dir stays gitignored (see .gitignore note).
artifacts = ["src/scitex/_sphinx_html"]
exclude = [
# Scholar development symlinks
"src/scitex/scholar/.env",
Expand Down
15 changes: 9 additions & 6 deletions src/scitex/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,17 @@
"""

# Suppress SQLAlchemy verbose logging (SQL queries, BEGIN/COMMIT)
# Must happen early, before any module imports sqlalchemy
import logging as _stdlib_logging
# Must happen early, before any module imports sqlalchemy.
# NOTE: scitex_logging.getLogger shares the stdlib logger registry, so
# setLevel here behaves exactly like logging.getLogger(...).setLevel(...)
# while satisfying PS-220 (shippable output must use scitex_logging).
import scitex_logging as _slogging
import warnings

_stdlib_logging.getLogger("sqlalchemy").setLevel(_stdlib_logging.WARNING)
_stdlib_logging.getLogger("sqlalchemy.engine").setLevel(_stdlib_logging.WARNING)
_stdlib_logging.getLogger("sqlalchemy.engine.Engine").setLevel(_stdlib_logging.WARNING)
_stdlib_logging.getLogger("sqlalchemy.pool").setLevel(_stdlib_logging.WARNING)
_slogging.getLogger("sqlalchemy").setLevel(_slogging.WARNING)
_slogging.getLogger("sqlalchemy.engine").setLevel(_slogging.WARNING)
_slogging.getLogger("sqlalchemy.engine.Engine").setLevel(_slogging.WARNING)
_slogging.getLogger("sqlalchemy.pool").setLevel(_slogging.WARNING)

# Show deprecation warnings from scitex modules (educational for migration)
warnings.filterwarnings("default", category=DeprecationWarning, module="scitex.*")
Expand Down
12 changes: 8 additions & 4 deletions src/scitex/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@

import sys

import scitex_logging as slogging

log = slogging.getLogger(__name__)


def _check_cli_dependencies():
"""Check CLI dependencies and return missing ones."""
Expand All @@ -23,18 +27,18 @@ def main():
# Check dependencies first
missing = _check_cli_dependencies()
if missing:
print("SciTeX CLI missing dependencies:")
log.error("SciTeX CLI missing dependencies:")
for pkg, install in missing:
print(f" - {pkg}: {install}")
print("\nOr install all CLI deps: pip install scitex[cli]")
log.error(f" - {pkg}: {install}")
log.error("Or install all CLI deps: pip install scitex[cli]")
sys.exit(1)

try:
from scitex.cli.main import cli

cli()
except ImportError as e:
print(f"SciTeX CLI import error: {e}")
log.error(f"SciTeX CLI import error: {e}")
import traceback

traceback.print_exc()
Expand Down
17 changes: 9 additions & 8 deletions src/scitex/_mcp/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,13 @@
from __future__ import annotations

import importlib
import logging
import os
import threading
import warnings
from typing import Iterable

import scitex_logging as slogging

# Load environment variables from SCITEX_ENV_SRC early.
from scitex.helpers import load_scitex_env

Expand All @@ -43,7 +44,7 @@

from ._compat import get_tools_sync, mounted_namespaces, safe_mount

logger = logging.getLogger(__name__)
logger = slogging.getLogger(__name__)

FastMCP = try_import_optional("fastmcp", "FastMCP", pkg="scitex")
FASTMCP_AVAILABLE = FastMCP is not None
Expand Down Expand Up @@ -439,19 +440,19 @@ def run_server(
if not FASTMCP_AVAILABLE:
import sys

print("=" * 60)
print("Requires 'fastmcp' package: pip install fastmcp")
print("=" * 60)
logger.error("=" * 60)
logger.error("Requires 'fastmcp' package: pip install fastmcp")
logger.error("=" * 60)
sys.exit(1)

if transport == "stdio":
mcp.run(transport="stdio")
elif transport == "sse":
print(f"Starting scitex MCP (SSE) on {host}:{port}")
print(f"Remote: ssh -R {port}:localhost:{port} remote-host")
logger.info(f"Starting scitex MCP (SSE) on {host}:{port}")
logger.info(f"Remote: ssh -R {port}:localhost:{port} remote-host")
mcp.run(transport="sse", host=host, port=port)
elif transport == "http":
print(f"Starting scitex MCP (HTTP) on {host}:{port}")
logger.info(f"Starting scitex MCP (HTTP) on {host}:{port}")
mcp.run(transport="streamable-http", host=host, port=port)
else:
raise ValueError(f"Unknown transport: {transport}")
Expand Down
4 changes: 2 additions & 2 deletions src/scitex/_mcp/_peer_extras.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@

from __future__ import annotations

import logging
import scitex_logging as slogging

logger = logging.getLogger(__name__)
logger = slogging.getLogger(__name__)

__all__ = ["register_peer_extras"]

Expand Down
8 changes: 7 additions & 1 deletion src/scitex/cli/browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,13 @@ def open(url, stealth, timeout, background):
# Add https:// if no scheme provided
if url != "about:blank" and not url.startswith(("http://", "https://", "about:")):
url = f"https://{url}"
from playwright.async_api import async_playwright
try:
from playwright.async_api import async_playwright
except ImportError as exc:
raise ImportError(
"playwright is required for browser automation: "
"pip install scitex[browser]"
) from exc

from scitex.browser.core import BrowserMixin

Expand Down
Loading
Loading