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]
|
||||
if cached.data_type == "e":
|
||||
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
|
||||
finally:
|
||||
formulas.close()
|
||||
|
||||
@@ -30,6 +30,8 @@ def inspect_workbook(path):
|
||||
cached = values[sheet.title][cell.coordinate]
|
||||
if cached.data_type == "e":
|
||||
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
|
||||
finally:
|
||||
formulas.close()
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
import importlib.util
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import types
|
||||
import unittest
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
from unittest.mock import patch
|
||||
|
||||
from openpyxl import Workbook
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
COMMON = ROOT / "config/skill-overrides/common"
|
||||
|
||||
@@ -17,6 +21,16 @@ def load_module(name):
|
||||
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):
|
||||
def test_windows_install_path_and_arguments_with_spaces(self):
|
||||
office = load_module("soffice")
|
||||
@@ -72,6 +86,41 @@ class OfficePortabilityTests(unittest.TestCase):
|
||||
package.unpack(source, root / "unpacked")
|
||||
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__":
|
||||
unittest.main()
|
||||
Reference in new issue
Block a user