Files
py_enjoy/kit/Prop.py
2026-02-27 14:37:10 +08:00

167 lines
5.6 KiB
Python

#!/usr/bin/env python3.9
# -*- coding: utf-8 -*-
"""
JFinal Prop - Properties File Handler
"""
import os
from typing import Optional
class Prop:
"""Properties file handler"""
DEFAULT_ENCODING = "UTF-8"
def __init__(self, file_name_or_content=None, encoding: str = DEFAULT_ENCODING, is_file: bool = True):
"""
Initialize Prop
Args:
file_name_or_content: file name (if is_file=True) or content string
encoding: encoding for reading properties file
is_file: True if first parameter is file name, False if it's content string
"""
self._properties = {}
if file_name_or_content is None:
return
if is_file:
self._load_from_file(file_name_or_content, encoding)
else:
self._load_from_content(file_name_or_content, encoding)
def _load_from_file(self, file_name: str, encoding: str):
"""Load properties from file"""
try:
# Try to find file in classpath first
import importlib.resources
try:
with importlib.resources.open_text(file_name, encoding=encoding) as f:
self._parse_properties(f.read())
return
except (FileNotFoundError, TypeError):
pass
# Try as absolute file path
if os.path.isabs(file_name):
file_path = file_name
else:
file_path = os.path.join(os.getcwd(), file_name)
if not os.path.exists(file_path):
raise FileNotFoundError(f"Properties file not found: {file_name}")
with open(file_path, 'r', encoding=encoding) as f:
self._parse_properties(f.read())
except Exception as e:
raise RuntimeError(f"Error loading properties file: {e}")
def _load_from_content(self, content: str, encoding: str):
"""Load properties from content string"""
try:
self._parse_properties(content)
except Exception as e:
raise RuntimeError(f"Error parsing properties content: {e}")
def _parse_properties(self, content: str):
"""Parse properties content"""
for line in content.split('\n'):
line = line.strip()
# Skip empty lines and comments
if not line or line.startswith('#') or line.startswith('!'):
continue
# Handle line continuation
while line.endswith('\\'):
line = line[:-1].strip()
# This is a simplified implementation
# Find the first separator
separator_idx = -1
for sep in ['=', ':']:
idx = line.find(sep)
if idx != -1:
if separator_idx == -1 or idx < separator_idx:
separator_idx = idx
if separator_idx == -1:
# No separator, treat as key with empty value
key = line.strip()
value = ""
else:
key = line[:separator_idx].strip()
value = line[separator_idx + 1:].strip()
if key:
self._properties[key] = value
def get(self, key: str, default_value: str = None) -> Optional[str]:
"""Get property value"""
value = self._properties.get(key)
if value is not None and len(value) != 0:
return value.strip()
return default_value
def get_int(self, key: str, default_value: int = None) -> Optional[int]:
"""Get property as integer"""
value = self.get(key)
if value is not None:
return int(value)
return default_value
def get_long(self, key: str, default_value: int = None) -> Optional[int]:
"""Get property as long integer"""
value = self.get(key)
if value is not None:
return int(value)
return default_value
def get_double(self, key: str, default_value: float = None) -> Optional[float]:
"""Get property as double"""
value = self.get(key)
if value is not None:
return float(value)
return default_value
def get_boolean(self, key: str, default_value: bool = None) -> Optional[bool]:
"""Get property as boolean"""
value = self.get(key)
if value is not None:
value_lower = value.lower().strip()
if value_lower == "true":
return True
elif value_lower == "false":
return False
else:
raise ValueError(f"Cannot parse boolean value: {value}")
return default_value
def contains_key(self, key: str) -> bool:
"""Check if key exists"""
return key in self._properties
def is_empty(self) -> bool:
"""Check if properties is empty"""
return len(self._properties) == 0
def not_empty(self) -> bool:
"""Check if properties is not empty"""
return not self.is_empty()
def append(self, prop) -> 'Prop':
"""Append properties from another Prop"""
if prop is None:
raise ValueError("prop cannot be None")
for key, value in prop.get_properties().items():
self._properties[key] = value
return self
def get_properties(self) -> dict:
"""Get all properties"""
return self._properties.copy()