scitex 2.11.0__py3-none-any.whl → 2.13.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- scitex/__main__.py +24 -5
- scitex/__version__.py +1 -1
- scitex/_optional_deps.py +33 -0
- scitex/ai/classification/reporters/_ClassificationReporter.py +1 -1
- scitex/ai/classification/timeseries/_TimeSeriesBlockingSplit.py +2 -2
- scitex/ai/classification/timeseries/_TimeSeriesCalendarSplit.py +2 -2
- scitex/ai/classification/timeseries/_TimeSeriesSlidingWindowSplit.py +2 -2
- scitex/ai/classification/timeseries/_TimeSeriesSlidingWindowSplit_v01-not-using-n_splits.py +2 -2
- scitex/ai/classification/timeseries/_TimeSeriesStratifiedSplit.py +2 -2
- scitex/ai/classification/timeseries/_normalize_timestamp.py +1 -1
- scitex/ai/metrics/_calc_seizure_prediction_metrics.py +1 -1
- scitex/ai/plt/_plot_feature_importance.py +1 -1
- scitex/ai/plt/_plot_learning_curve.py +1 -1
- scitex/ai/plt/_plot_optuna_study.py +1 -1
- scitex/ai/plt/_plot_pre_rec_curve.py +1 -1
- scitex/ai/plt/_plot_roc_curve.py +1 -1
- scitex/ai/plt/_stx_conf_mat.py +1 -1
- scitex/ai/training/_LearningCurveLogger.py +1 -1
- scitex/audio/mcp_server.py +38 -8
- scitex/browser/automation/CookieHandler.py +1 -1
- scitex/browser/core/BrowserMixin.py +1 -1
- scitex/browser/core/ChromeProfileManager.py +1 -1
- scitex/browser/debugging/_browser_logger.py +1 -1
- scitex/browser/debugging/_highlight_element.py +1 -1
- scitex/browser/debugging/_show_grid.py +1 -1
- scitex/browser/interaction/click_center.py +1 -1
- scitex/browser/interaction/click_with_fallbacks.py +1 -1
- scitex/browser/interaction/close_popups.py +1 -1
- scitex/browser/interaction/fill_with_fallbacks.py +1 -1
- scitex/browser/pdf/click_download_for_chrome_pdf_viewer.py +1 -1
- scitex/browser/pdf/detect_chrome_pdf_viewer.py +1 -1
- scitex/browser/stealth/HumanBehavior.py +1 -1
- scitex/browser/stealth/StealthManager.py +1 -1
- scitex/canvas/_mcp_handlers.py +372 -0
- scitex/canvas/_mcp_tool_schemas.py +219 -0
- scitex/canvas/mcp_server.py +151 -0
- scitex/capture/mcp_server.py +41 -12
- scitex/cli/audio.py +233 -0
- scitex/cli/capture.py +307 -0
- scitex/cli/main.py +27 -4
- scitex/cli/repro.py +233 -0
- scitex/cli/resource.py +240 -0
- scitex/cli/stats.py +325 -0
- scitex/cli/template.py +236 -0
- scitex/cli/tex.py +286 -0
- scitex/cli/web.py +11 -12
- scitex/dev/__init__.py +3 -0
- scitex/dev/_pyproject.py +405 -0
- scitex/dev/plt/__init__.py +2 -2
- scitex/dev/plt/mpl/get_dir_ax.py +1 -1
- scitex/dev/plt/mpl/get_signatures.py +1 -1
- scitex/dev/plt/mpl/get_signatures_details.py +1 -1
- scitex/diagram/_mcp_handlers.py +400 -0
- scitex/diagram/_mcp_tool_schemas.py +157 -0
- scitex/diagram/mcp_server.py +151 -0
- scitex/dsp/_demo_sig.py +51 -5
- scitex/dsp/_mne.py +13 -2
- scitex/dsp/_modulation_index.py +15 -3
- scitex/dsp/_pac.py +23 -5
- scitex/dsp/_psd.py +16 -4
- scitex/dsp/_resample.py +24 -4
- scitex/dsp/_transform.py +16 -3
- scitex/dsp/add_noise.py +15 -1
- scitex/dsp/norm.py +17 -2
- scitex/dsp/reference.py +17 -1
- scitex/dsp/utils/_differential_bandpass_filters.py +20 -2
- scitex/dsp/utils/_zero_pad.py +18 -4
- scitex/dt/_normalize_timestamp.py +1 -1
- scitex/git/_session.py +1 -1
- scitex/io/_load_modules/_con.py +12 -1
- scitex/io/_load_modules/_eeg.py +12 -1
- scitex/io/_load_modules/_optuna.py +21 -63
- scitex/io/_load_modules/_torch.py +11 -3
- scitex/io/_save_modules/_optuna_study_as_csv_and_pngs.py +13 -2
- scitex/io/_save_modules/_torch.py +11 -3
- scitex/mcp_server.py +159 -0
- scitex/plt/_mcp_handlers.py +361 -0
- scitex/plt/_mcp_tool_schemas.py +169 -0
- scitex/plt/mcp_server.py +205 -0
- scitex/repro/README_RandomStateManager.md +3 -3
- scitex/repro/_RandomStateManager.py +14 -14
- scitex/repro/_gen_ID.py +1 -1
- scitex/repro/_gen_timestamp.py +1 -1
- scitex/repro/_hash_array.py +4 -4
- scitex/scholar/__main__.py +24 -2
- scitex/scholar/_mcp_handlers.py +685 -0
- scitex/scholar/_mcp_tool_schemas.py +339 -0
- scitex/scholar/docs/template.py +1 -1
- scitex/scholar/examples/07_storage_integration.py +1 -1
- scitex/scholar/impact_factor/jcr/ImpactFactorJCREngine.py +1 -1
- scitex/scholar/impact_factor/jcr/build_database.py +1 -1
- scitex/scholar/mcp_server.py +315 -0
- scitex/scholar/pdf_download/ScholarPDFDownloader.py +1 -1
- scitex/scholar/pipelines/ScholarPipelineBibTeX.py +1 -1
- scitex/scholar/pipelines/ScholarPipelineParallel.py +1 -1
- scitex/scholar/pipelines/ScholarPipelineSingle.py +1 -1
- scitex/scholar/storage/PaperIO.py +1 -1
- scitex/session/README.md +4 -4
- scitex/session/__init__.py +1 -1
- scitex/session/_decorator.py +9 -9
- scitex/session/_lifecycle.py +5 -5
- scitex/session/template.py +1 -1
- scitex/stats/__main__.py +281 -0
- scitex/stats/_mcp_handlers.py +1191 -0
- scitex/stats/_mcp_tool_schemas.py +384 -0
- scitex/stats/correct/_correct_bonferroni.py +1 -1
- scitex/stats/correct/_correct_fdr.py +1 -1
- scitex/stats/correct/_correct_fdr_.py +1 -1
- scitex/stats/correct/_correct_holm.py +1 -1
- scitex/stats/correct/_correct_sidak.py +1 -1
- scitex/stats/effect_sizes/_cliffs_delta.py +1 -1
- scitex/stats/effect_sizes/_cohens_d.py +1 -1
- scitex/stats/effect_sizes/_epsilon_squared.py +1 -1
- scitex/stats/effect_sizes/_eta_squared.py +1 -1
- scitex/stats/effect_sizes/_prob_superiority.py +1 -1
- scitex/stats/mcp_server.py +405 -0
- scitex/stats/posthoc/_dunnett.py +1 -1
- scitex/stats/posthoc/_games_howell.py +1 -1
- scitex/stats/posthoc/_tukey_hsd.py +1 -1
- scitex/stats/power/_power.py +1 -1
- scitex/stats/utils/_effect_size.py +1 -1
- scitex/stats/utils/_formatters.py +1 -1
- scitex/stats/utils/_power.py +1 -1
- scitex/template/_mcp_handlers.py +259 -0
- scitex/template/_mcp_tool_schemas.py +112 -0
- scitex/template/mcp_server.py +186 -0
- scitex/utils/_verify_scitex_format.py +2 -2
- scitex/utils/template.py +1 -1
- scitex/web/__init__.py +12 -11
- scitex/web/_scraping.py +26 -265
- scitex/web/download_images.py +316 -0
- scitex/writer/Writer.py +1 -1
- scitex/writer/_clone_writer_project.py +1 -1
- scitex/writer/_validate_tree_structures.py +1 -1
- scitex/writer/dataclasses/config/_WriterConfig.py +1 -1
- scitex/writer/dataclasses/contents/_ManuscriptContents.py +1 -1
- scitex/writer/dataclasses/core/_Document.py +1 -1
- scitex/writer/dataclasses/core/_DocumentSection.py +1 -1
- scitex/writer/dataclasses/results/_CompilationResult.py +1 -1
- scitex/writer/dataclasses/results/_LaTeXIssue.py +1 -1
- scitex/writer/utils/.legacy_git_retry.py +7 -5
- scitex/writer/utils/_parse_latex_logs.py +1 -1
- {scitex-2.11.0.dist-info → scitex-2.13.0.dist-info}/METADATA +431 -269
- {scitex-2.11.0.dist-info → scitex-2.13.0.dist-info}/RECORD +147 -118
- scitex-2.13.0.dist-info/entry_points.txt +11 -0
- scitex-2.11.0.dist-info/entry_points.txt +0 -2
- {scitex-2.11.0.dist-info → scitex-2.13.0.dist-info}/WHEEL +0 -0
- {scitex-2.11.0.dist-info → scitex-2.13.0.dist-info}/licenses/LICENSE +0 -0
scitex/dev/_pyproject.py
ADDED
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# Timestamp: 2025-01-08
|
|
3
|
+
# File: /home/ywatanabe/proj/scitex-code/src/scitex/dev/_pyproject.py
|
|
4
|
+
|
|
5
|
+
"""
|
|
6
|
+
Utility for programmatically managing pyproject.toml dependencies.
|
|
7
|
+
|
|
8
|
+
Usage:
|
|
9
|
+
from scitex.dev import pyproject
|
|
10
|
+
|
|
11
|
+
# Load and inspect
|
|
12
|
+
pp = pyproject.load()
|
|
13
|
+
extras = pyproject.get_extras(pp)
|
|
14
|
+
|
|
15
|
+
# Audit dependencies
|
|
16
|
+
pyproject.print_report()
|
|
17
|
+
pyproject.validate_heavy_sync()
|
|
18
|
+
|
|
19
|
+
# Find issues
|
|
20
|
+
duplicates = pyproject.find_duplicates()
|
|
21
|
+
missing = pyproject.find_missing_heavy_deps()
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
import re
|
|
25
|
+
from collections import defaultdict
|
|
26
|
+
from pathlib import Path
|
|
27
|
+
from typing import Dict, List, Optional, Set
|
|
28
|
+
|
|
29
|
+
try:
|
|
30
|
+
import tomlkit
|
|
31
|
+
|
|
32
|
+
TOMLKIT_AVAILABLE = True
|
|
33
|
+
except ImportError:
|
|
34
|
+
TOMLKIT_AVAILABLE = False
|
|
35
|
+
tomlkit = None
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _get_default_path() -> Path:
|
|
39
|
+
"""Get default pyproject.toml path (project root)."""
|
|
40
|
+
# Navigate from this file to project root
|
|
41
|
+
current = Path(__file__).resolve()
|
|
42
|
+
# src/scitex/dev/_pyproject.py -> project root
|
|
43
|
+
for _ in range(4):
|
|
44
|
+
current = current.parent
|
|
45
|
+
return current / "pyproject.toml"
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def load(path: Optional[Path] = None) -> dict:
|
|
49
|
+
"""
|
|
50
|
+
Load pyproject.toml preserving comments and formatting.
|
|
51
|
+
|
|
52
|
+
Parameters
|
|
53
|
+
----------
|
|
54
|
+
path : Path, optional
|
|
55
|
+
Path to pyproject.toml. Defaults to project root.
|
|
56
|
+
|
|
57
|
+
Returns
|
|
58
|
+
-------
|
|
59
|
+
dict
|
|
60
|
+
Parsed TOML document (tomlkit.TOMLDocument)
|
|
61
|
+
"""
|
|
62
|
+
if not TOMLKIT_AVAILABLE:
|
|
63
|
+
raise ImportError(
|
|
64
|
+
"tomlkit is required for pyproject utilities. "
|
|
65
|
+
"Install with: pip install tomlkit"
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
path = path or _get_default_path()
|
|
69
|
+
with open(path) as f:
|
|
70
|
+
return tomlkit.load(f)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def save(doc: dict, path: Optional[Path] = None) -> None:
|
|
74
|
+
"""
|
|
75
|
+
Save pyproject.toml preserving comments and formatting.
|
|
76
|
+
|
|
77
|
+
Parameters
|
|
78
|
+
----------
|
|
79
|
+
doc : dict
|
|
80
|
+
TOML document to save
|
|
81
|
+
path : Path, optional
|
|
82
|
+
Path to pyproject.toml. Defaults to project root.
|
|
83
|
+
"""
|
|
84
|
+
if not TOMLKIT_AVAILABLE:
|
|
85
|
+
raise ImportError("tomlkit is required")
|
|
86
|
+
|
|
87
|
+
path = path or _get_default_path()
|
|
88
|
+
with open(path, "w") as f:
|
|
89
|
+
tomlkit.dump(doc, f)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def get_extras(doc: Optional[dict] = None) -> Dict[str, List[str]]:
|
|
93
|
+
"""
|
|
94
|
+
Get all optional dependency extras.
|
|
95
|
+
|
|
96
|
+
Returns
|
|
97
|
+
-------
|
|
98
|
+
dict
|
|
99
|
+
Mapping of extra name to list of dependencies
|
|
100
|
+
"""
|
|
101
|
+
doc = doc or load()
|
|
102
|
+
return dict(doc.get("project", {}).get("optional-dependencies", {}))
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def get_core_deps(doc: Optional[dict] = None) -> List[str]:
|
|
106
|
+
"""Get core dependencies."""
|
|
107
|
+
doc = doc or load()
|
|
108
|
+
return list(doc.get("project", {}).get("dependencies", []))
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def get_heavy_deps(doc: Optional[dict] = None) -> Set[str]:
|
|
112
|
+
"""Get dependencies in the [heavy] extra."""
|
|
113
|
+
extras = get_extras(doc)
|
|
114
|
+
return set(extras.get("heavy", []))
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def parse_commented_deps(path: Optional[Path] = None) -> Dict[str, List[str]]:
|
|
118
|
+
"""
|
|
119
|
+
Parse commented-out dependencies from pyproject.toml.
|
|
120
|
+
|
|
121
|
+
Looks for patterns like:
|
|
122
|
+
# "torch",
|
|
123
|
+
# "mne",
|
|
124
|
+
|
|
125
|
+
Returns
|
|
126
|
+
-------
|
|
127
|
+
dict
|
|
128
|
+
Mapping of extra name to list of commented dependencies
|
|
129
|
+
"""
|
|
130
|
+
path = path or _get_default_path()
|
|
131
|
+
|
|
132
|
+
commented_deps = defaultdict(list)
|
|
133
|
+
current_extra = None
|
|
134
|
+
|
|
135
|
+
with open(path) as f:
|
|
136
|
+
for line in f:
|
|
137
|
+
# Detect extra section
|
|
138
|
+
match = re.match(r"^(\w+)\s*=\s*\[", line)
|
|
139
|
+
if match:
|
|
140
|
+
current_extra = match.group(1)
|
|
141
|
+
continue
|
|
142
|
+
|
|
143
|
+
# Detect end of section
|
|
144
|
+
if line.strip() == "]":
|
|
145
|
+
current_extra = None
|
|
146
|
+
continue
|
|
147
|
+
|
|
148
|
+
# Detect commented dependency
|
|
149
|
+
if current_extra:
|
|
150
|
+
match = re.match(r'^\s*#\s*"([^"]+)"', line)
|
|
151
|
+
if match:
|
|
152
|
+
dep = match.group(1)
|
|
153
|
+
commented_deps[current_extra].append(dep)
|
|
154
|
+
|
|
155
|
+
return dict(commented_deps)
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def find_duplicates(doc: Optional[dict] = None) -> Dict[str, List[str]]:
|
|
159
|
+
"""
|
|
160
|
+
Find dependencies that appear in multiple extras.
|
|
161
|
+
|
|
162
|
+
Returns
|
|
163
|
+
-------
|
|
164
|
+
dict
|
|
165
|
+
Mapping of dependency to list of extras containing it
|
|
166
|
+
"""
|
|
167
|
+
extras = get_extras(doc)
|
|
168
|
+
dep_locations = defaultdict(list)
|
|
169
|
+
|
|
170
|
+
for extra_name, deps in extras.items():
|
|
171
|
+
if extra_name in ("all", "dev", "heavy"):
|
|
172
|
+
continue # Skip meta-extras
|
|
173
|
+
for dep in deps:
|
|
174
|
+
# Normalize dep name (strip version specifiers)
|
|
175
|
+
dep_name = re.split(r"[<>=\[]", dep)[0].strip().lower()
|
|
176
|
+
dep_locations[dep_name].append(extra_name)
|
|
177
|
+
|
|
178
|
+
# Return only duplicates
|
|
179
|
+
return {dep: extras for dep, extras in dep_locations.items() if len(extras) > 1}
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def find_missing_heavy_deps(path: Optional[Path] = None) -> List[str]:
|
|
183
|
+
"""
|
|
184
|
+
Find commented deps that are NOT in [heavy] extra.
|
|
185
|
+
|
|
186
|
+
Returns
|
|
187
|
+
-------
|
|
188
|
+
list
|
|
189
|
+
Dependencies that should be added to [heavy]
|
|
190
|
+
"""
|
|
191
|
+
doc = load(path)
|
|
192
|
+
heavy_deps = get_heavy_deps(doc)
|
|
193
|
+
commented = parse_commented_deps(path)
|
|
194
|
+
|
|
195
|
+
# Normalize heavy deps
|
|
196
|
+
heavy_normalized = {re.split(r"[<>=\[]", d)[0].strip().lower() for d in heavy_deps}
|
|
197
|
+
|
|
198
|
+
missing = set()
|
|
199
|
+
for extra, deps in commented.items():
|
|
200
|
+
for dep in deps:
|
|
201
|
+
dep_normalized = re.split(r"[<>=\[]", dep)[0].strip().lower()
|
|
202
|
+
if dep_normalized not in heavy_normalized:
|
|
203
|
+
missing.add(dep)
|
|
204
|
+
|
|
205
|
+
return sorted(missing)
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def validate_heavy_sync(path: Optional[Path] = None, verbose: bool = True) -> bool:
|
|
209
|
+
"""
|
|
210
|
+
Validate that all commented deps are in [heavy] extra.
|
|
211
|
+
|
|
212
|
+
Parameters
|
|
213
|
+
----------
|
|
214
|
+
path : Path, optional
|
|
215
|
+
Path to pyproject.toml
|
|
216
|
+
verbose : bool
|
|
217
|
+
Print validation results
|
|
218
|
+
|
|
219
|
+
Returns
|
|
220
|
+
-------
|
|
221
|
+
bool
|
|
222
|
+
True if all commented deps are in [heavy]
|
|
223
|
+
"""
|
|
224
|
+
missing = find_missing_heavy_deps(path)
|
|
225
|
+
|
|
226
|
+
if verbose:
|
|
227
|
+
if missing:
|
|
228
|
+
print(f"Missing from [heavy] extra ({len(missing)}):")
|
|
229
|
+
for dep in missing:
|
|
230
|
+
print(f" - {dep}")
|
|
231
|
+
else:
|
|
232
|
+
print("All commented deps are in [heavy] extra")
|
|
233
|
+
|
|
234
|
+
return len(missing) == 0
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
def get_extra_stats(doc: Optional[dict] = None) -> Dict[str, dict]:
|
|
238
|
+
"""
|
|
239
|
+
Get statistics for each extra.
|
|
240
|
+
|
|
241
|
+
Returns
|
|
242
|
+
-------
|
|
243
|
+
dict
|
|
244
|
+
Mapping of extra name to stats dict
|
|
245
|
+
"""
|
|
246
|
+
extras = get_extras(doc)
|
|
247
|
+
stats = {}
|
|
248
|
+
|
|
249
|
+
for name, deps in extras.items():
|
|
250
|
+
stats[name] = {
|
|
251
|
+
"count": len(deps),
|
|
252
|
+
"deps": deps,
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
return stats
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
def print_report(path: Optional[Path] = None) -> None:
|
|
259
|
+
"""Print a comprehensive dependency report."""
|
|
260
|
+
doc = load(path)
|
|
261
|
+
extras = get_extras(doc)
|
|
262
|
+
core = get_core_deps(doc)
|
|
263
|
+
commented = parse_commented_deps(path)
|
|
264
|
+
duplicates = find_duplicates(doc)
|
|
265
|
+
missing = find_missing_heavy_deps(path)
|
|
266
|
+
|
|
267
|
+
print("=" * 60)
|
|
268
|
+
print("PYPROJECT.TOML DEPENDENCY REPORT")
|
|
269
|
+
print("=" * 60)
|
|
270
|
+
|
|
271
|
+
# Core deps
|
|
272
|
+
print(f"\nCore dependencies: {len(core)}")
|
|
273
|
+
for dep in core:
|
|
274
|
+
print(f" - {dep}")
|
|
275
|
+
|
|
276
|
+
# Extras summary
|
|
277
|
+
print(f"\nExtras ({len(extras)}):")
|
|
278
|
+
for name, deps in sorted(extras.items()):
|
|
279
|
+
commented_count = len(commented.get(name, []))
|
|
280
|
+
suffix = f" (+{commented_count} commented)" if commented_count else ""
|
|
281
|
+
print(f" {name}: {len(deps)} deps{suffix}")
|
|
282
|
+
|
|
283
|
+
# Duplicates
|
|
284
|
+
if duplicates:
|
|
285
|
+
print(f"\nDuplicates ({len(duplicates)}):")
|
|
286
|
+
for dep, locations in sorted(duplicates.items()):
|
|
287
|
+
print(f" {dep}: {', '.join(locations)}")
|
|
288
|
+
else:
|
|
289
|
+
print("\nNo duplicates found")
|
|
290
|
+
|
|
291
|
+
# Heavy sync status
|
|
292
|
+
print("\nHeavy sync: ", end="")
|
|
293
|
+
if missing:
|
|
294
|
+
print(f"MISSING {len(missing)} deps")
|
|
295
|
+
for dep in missing:
|
|
296
|
+
print(f" - {dep}")
|
|
297
|
+
else:
|
|
298
|
+
print("OK")
|
|
299
|
+
|
|
300
|
+
print("=" * 60)
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
def add_to_extra(
|
|
304
|
+
extra_name: str,
|
|
305
|
+
deps: List[str],
|
|
306
|
+
path: Optional[Path] = None,
|
|
307
|
+
save_file: bool = False,
|
|
308
|
+
) -> dict:
|
|
309
|
+
"""
|
|
310
|
+
Add dependencies to an extra.
|
|
311
|
+
|
|
312
|
+
Parameters
|
|
313
|
+
----------
|
|
314
|
+
extra_name : str
|
|
315
|
+
Name of the extra
|
|
316
|
+
deps : list
|
|
317
|
+
Dependencies to add
|
|
318
|
+
path : Path, optional
|
|
319
|
+
Path to pyproject.toml
|
|
320
|
+
save_file : bool
|
|
321
|
+
If True, save changes to file
|
|
322
|
+
|
|
323
|
+
Returns
|
|
324
|
+
-------
|
|
325
|
+
dict
|
|
326
|
+
Updated document
|
|
327
|
+
"""
|
|
328
|
+
doc = load(path)
|
|
329
|
+
extras = doc["project"]["optional-dependencies"]
|
|
330
|
+
|
|
331
|
+
if extra_name not in extras:
|
|
332
|
+
extras[extra_name] = []
|
|
333
|
+
|
|
334
|
+
existing = set(extras[extra_name])
|
|
335
|
+
for dep in deps:
|
|
336
|
+
if dep not in existing:
|
|
337
|
+
extras[extra_name].append(dep)
|
|
338
|
+
|
|
339
|
+
if save_file:
|
|
340
|
+
save(doc, path)
|
|
341
|
+
|
|
342
|
+
return doc
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
def remove_from_extra(
|
|
346
|
+
extra_name: str,
|
|
347
|
+
deps: List[str],
|
|
348
|
+
path: Optional[Path] = None,
|
|
349
|
+
save_file: bool = False,
|
|
350
|
+
) -> dict:
|
|
351
|
+
"""
|
|
352
|
+
Remove dependencies from an extra.
|
|
353
|
+
|
|
354
|
+
Parameters
|
|
355
|
+
----------
|
|
356
|
+
extra_name : str
|
|
357
|
+
Name of the extra
|
|
358
|
+
deps : list
|
|
359
|
+
Dependencies to remove
|
|
360
|
+
path : Path, optional
|
|
361
|
+
Path to pyproject.toml
|
|
362
|
+
save_file : bool
|
|
363
|
+
If True, save changes to file
|
|
364
|
+
|
|
365
|
+
Returns
|
|
366
|
+
-------
|
|
367
|
+
dict
|
|
368
|
+
Updated document
|
|
369
|
+
"""
|
|
370
|
+
doc = load(path)
|
|
371
|
+
extras = doc["project"]["optional-dependencies"]
|
|
372
|
+
|
|
373
|
+
if extra_name in extras:
|
|
374
|
+
deps_set = set(deps)
|
|
375
|
+
extras[extra_name] = [d for d in extras[extra_name] if d not in deps_set]
|
|
376
|
+
|
|
377
|
+
if save_file:
|
|
378
|
+
save(doc, path)
|
|
379
|
+
|
|
380
|
+
return doc
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
# CLI interface
|
|
384
|
+
if __name__ == "__main__":
|
|
385
|
+
import sys
|
|
386
|
+
|
|
387
|
+
if len(sys.argv) > 1:
|
|
388
|
+
cmd = sys.argv[1]
|
|
389
|
+
if cmd == "report":
|
|
390
|
+
print_report()
|
|
391
|
+
elif cmd == "validate":
|
|
392
|
+
valid = validate_heavy_sync()
|
|
393
|
+
sys.exit(0 if valid else 1)
|
|
394
|
+
elif cmd == "duplicates":
|
|
395
|
+
dups = find_duplicates()
|
|
396
|
+
for dep, extras in sorted(dups.items()):
|
|
397
|
+
print(f"{dep}: {', '.join(extras)}")
|
|
398
|
+
else:
|
|
399
|
+
print(f"Unknown command: {cmd}")
|
|
400
|
+
print("Commands: report, validate, duplicates")
|
|
401
|
+
else:
|
|
402
|
+
print_report()
|
|
403
|
+
|
|
404
|
+
|
|
405
|
+
# EOF
|
scitex/dev/plt/__init__.py
CHANGED
|
@@ -16,8 +16,8 @@ Usage:
|
|
|
16
16
|
from scitex.dev.plt import PLOTTERS_STX, PLOTTERS_SNS, PLOTTERS_MPL
|
|
17
17
|
|
|
18
18
|
@stx.session
|
|
19
|
-
def main(plt=stx.INJECTED,
|
|
20
|
-
rng =
|
|
19
|
+
def main(plt=stx.INJECTED, rng=stx.INJECTED):
|
|
20
|
+
rng = rng("demo")
|
|
21
21
|
|
|
22
22
|
# stx_* API (ArrayLike)
|
|
23
23
|
for name, plotter in PLOTTERS_STX.items():
|
scitex/dev/plt/mpl/get_dir_ax.py
CHANGED