Coverage for src / openenv / core / utils.py: 100.00%

22 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-03-25 13:36 +0000

1"""Utility helpers.""" 

2 

3from __future__ import annotations 

4 

5import base64 

6import hashlib 

7import json 

8import re 

9from typing import Any 

10 

11 

12_NAME_NORMALIZER = re.compile(r"[^a-z0-9]+") 

13_HOME_OPENCLAW_WORKSPACE_PATTERN = re.compile( 

14 r"(?:/home/[A-Za-z0-9._-]+|/root|\$HOME|\$\{HOME\}|~)/\.openclaw/workspace(?=(?:/|\b|$))" 

15) 

16_HOME_OPENCLAW_STATE_PATTERN = re.compile( 

17 r"(?:/home/[A-Za-z0-9._-]+|/root|\$HOME|\$\{HOME\}|~)/\.openclaw(?=(?:/|\b|$))" 

18) 

19 

20 

21def stable_json_dumps(value: Any, *, indent: int | None = None) -> str: 

22 """Serialize data deterministically.""" 

23 return json.dumps(value, indent=indent, sort_keys=True, ensure_ascii=True) 

24 

25 

26def sha256_text(text: str) -> str: 

27 """Return the SHA-256 digest of UTF-8 text.""" 

28 return hashlib.sha256(text.encode("utf-8")).hexdigest() 

29 

30 

31def slugify_name(value: str) -> str: 

32 """Normalize a project name for file and image tags.""" 

33 normalized = _NAME_NORMALIZER.sub("-", value.strip().lower()).strip("-") 

34 return normalized or "openclawenv-agent" 

35 

36 

37def encode_payload(value: Any) -> str: 

38 """Encode JSON payload as base64 for embedding in Dockerfile.""" 

39 encoded = stable_json_dumps(value, indent=None).encode("utf-8") 

40 return base64.b64encode(encoded).decode("ascii") 

41 

42 

43def rewrite_openclaw_home_paths(text: str, *, state_dir: str, workspace: str) -> str: 

44 """Rewrite hard-coded home-based OpenClaw paths to runtime-specific directories.""" 

45 rewritten = _HOME_OPENCLAW_WORKSPACE_PATTERN.sub(workspace, text) 

46 return _HOME_OPENCLAW_STATE_PATTERN.sub(state_dir, rewritten)