Skip to content
Merged
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
2 changes: 1 addition & 1 deletion mempalace/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
# in file paths, SQLite, or ChromaDB metadata.

MAX_NAME_LENGTH = 128
_SAFE_NAME_RE = re.compile(r"^[a-zA-Z0-9][a-zA-Z0-9_ .'-]{0,126}[a-zA-Z0-9]?$")
_SAFE_NAME_RE = re.compile(r"^(?:[^\W_]|[^\W_][\w .'-]{0,126}[^\W_])$")


def sanitize_name(value: str, field_name: str = "name") -> str:
Expand Down
38 changes: 37 additions & 1 deletion tests/test_config.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import os
import json
import tempfile
from mempalace.config import MempalaceConfig

import pytest
from mempalace.config import MempalaceConfig, sanitize_name


def test_default_config():
Expand Down Expand Up @@ -30,3 +32,37 @@ def test_init():
cfg = MempalaceConfig(config_dir=tmpdir)
cfg.init()
assert os.path.exists(os.path.join(tmpdir, "config.json"))


# --- sanitize_name ---


def test_sanitize_name_ascii():
assert sanitize_name("hello") == "hello"


def test_sanitize_name_latvian():
assert sanitize_name("Jānis") == "Jānis"


def test_sanitize_name_cjk():
assert sanitize_name("太郎") == "太郎"


def test_sanitize_name_cyrillic():
assert sanitize_name("Алексей") == "Алексей"


def test_sanitize_name_rejects_leading_underscore():
with pytest.raises(ValueError):
sanitize_name("_foo")


def test_sanitize_name_rejects_path_traversal():
with pytest.raises(ValueError):
sanitize_name("../etc/passwd")


def test_sanitize_name_rejects_empty():
with pytest.raises(ValueError):
sanitize_name("")