Sync third-party and MCP marketplace plugins
Constraint: Public skills are published only by explicit administrator action unless they are tracked third-party market sources. Confidence: high Scope-risk: narrow Directive: Keep private/internal skills out of the public marketplace and preserve normal incremental market Git history. Tested: Marketplace validation passed.
This commit is contained in:
1 parent
598c8df2cd
commit
ee2b89a64b
3 files changed
+53
No files matched your search
@@ -30,6 +30,8 @@ def inspect_workbook(path):
|
|||||||
cached = values[sheet.title][cell.coordinate]
|
cached = values[sheet.title][cell.coordinate]
|
||||||
if cached.data_type == "e":
|
if cached.data_type == "e":
|
||||||
errors.setdefault(str(cached.value), []).append(location)
|
errors.setdefault(str(cached.value), []).append(location)
|
||||||
|
elif cell.data_type == "f" and cached.value is None:
|
||||||
|
errors.setdefault("MISSING_FORMULA_CACHE", []).append(location)
|
||||||
return formula_cells, errors
|
return formula_cells, errors
|
||||||
finally:
|
finally:
|
||||||
formulas.close()
|
formulas.close()
|
||||||
|
|||||||
@@ -30,6 +30,8 @@ def inspect_workbook(path):
|
|||||||
cached = values[sheet.title][cell.coordinate]
|
cached = values[sheet.title][cell.coordinate]
|
||||||
if cached.data_type == "e":
|
if cached.data_type == "e":
|
||||||
errors.setdefault(str(cached.value), []).append(location)
|
errors.setdefault(str(cached.value), []).append(location)
|
||||||
|
elif cell.data_type == "f" and cached.value is None:
|
||||||
|
errors.setdefault("MISSING_FORMULA_CACHE", []).append(location)
|
||||||
return formula_cells, errors
|
return formula_cells, errors
|
||||||
finally:
|
finally:
|
||||||
formulas.close()
|
formulas.close()
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
import importlib.util
|
import importlib.util
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
|
import types
|
||||||
import unittest
|
import unittest
|
||||||
import zipfile
|
import zipfile
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from openpyxl import Workbook
|
||||||
|
|
||||||
ROOT = Path(__file__).resolve().parents[2]
|
ROOT = Path(__file__).resolve().parents[2]
|
||||||
COMMON = ROOT / "config/skill-overrides/common"
|
COMMON = ROOT / "config/skill-overrides/common"
|
||||||
|
|
||||||
@@ -17,6 +21,16 @@ def load_module(name):
|
|||||||
return module
|
return module
|
||||||
|
|
||||||
|
|
||||||
|
def load_recalc():
|
||||||
|
office = types.ModuleType("office.soffice")
|
||||||
|
office.run_soffice = lambda *args, **kwargs: None
|
||||||
|
spec = importlib.util.spec_from_file_location("market_recalc", ROOT / "config/skill-overrides/xlsx/recalc.py")
|
||||||
|
module = importlib.util.module_from_spec(spec)
|
||||||
|
with patch.dict(sys.modules, {"office.soffice": office}):
|
||||||
|
spec.loader.exec_module(module)
|
||||||
|
return module
|
||||||
|
|
||||||
|
|
||||||
class OfficePortabilityTests(unittest.TestCase):
|
class OfficePortabilityTests(unittest.TestCase):
|
||||||
def test_windows_install_path_and_arguments_with_spaces(self):
|
def test_windows_install_path_and_arguments_with_spaces(self):
|
||||||
office = load_module("soffice")
|
office = load_module("soffice")
|
||||||
@@ -72,6 +86,41 @@ class OfficePortabilityTests(unittest.TestCase):
|
|||||||
package.unpack(source, root / "unpacked")
|
package.unpack(source, root / "unpacked")
|
||||||
self.assertFalse((root / "escape.txt").exists())
|
self.assertFalse((root / "escape.txt").exists())
|
||||||
|
|
||||||
|
def test_formula_without_cache_is_not_success(self):
|
||||||
|
recalc = load_recalc()
|
||||||
|
with tempfile.TemporaryDirectory() as temporary:
|
||||||
|
source = Path(temporary) / "中文.xlsx"
|
||||||
|
workbook = Workbook()
|
||||||
|
workbook.active["A1"] = "=1+1"
|
||||||
|
workbook.save(source)
|
||||||
|
formulas, errors = recalc.inspect_workbook(source)
|
||||||
|
self.assertEqual(formulas, {"Sheet!A1"})
|
||||||
|
self.assertEqual(errors, {"MISSING_FORMULA_CACHE": ["Sheet!A1"]})
|
||||||
|
|
||||||
|
def test_recalc_timeout_preserves_original(self):
|
||||||
|
recalc = load_recalc()
|
||||||
|
with tempfile.TemporaryDirectory() as temporary:
|
||||||
|
source = Path(temporary) / "中文.xlsx"
|
||||||
|
Workbook().save(source)
|
||||||
|
before = source.read_bytes()
|
||||||
|
with patch.object(recalc, "run_soffice", side_effect=subprocess.TimeoutExpired("soffice", 1)):
|
||||||
|
report = recalc.recalc(source, 1)
|
||||||
|
self.assertIn("error", report)
|
||||||
|
self.assertEqual(source.read_bytes(), before)
|
||||||
|
|
||||||
|
def test_recalc_external_links_refused_without_conversion(self):
|
||||||
|
recalc = load_recalc()
|
||||||
|
with tempfile.TemporaryDirectory() as temporary:
|
||||||
|
source = Path(temporary) / "linked.xlsx"
|
||||||
|
with zipfile.ZipFile(source, "w") as archive:
|
||||||
|
archive.writestr("xl/externalLinks/externalLink1.xml", "<externalLink/>")
|
||||||
|
before = source.read_bytes()
|
||||||
|
with patch.object(recalc, "run_soffice") as convert:
|
||||||
|
report = recalc.recalc(source)
|
||||||
|
self.assertIn("error", report)
|
||||||
|
convert.assert_not_called()
|
||||||
|
self.assertEqual(source.read_bytes(), before)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
Reference in new issue
Block a user