import importlib.util
import ntpath
import os
from typing import Optional
__all__ = ['CONFIGS', 'OpenCC', '__version__']
_this_dir = os.path.dirname(os.path.abspath(__file__))
_opencc_share_dir = os.path.join(_this_dir, 'clib', 'share', 'opencc')
_opencc_rootdir = os.path.abspath(os.path.join(_this_dir, '..', '..'))
_opencc_configdir = os.path.join(_opencc_rootdir, 'data', 'config')
if os.path.isdir(_opencc_share_dir):
CONFIGS = [f for f in os.listdir(_opencc_share_dir) if f.endswith('.json')]
elif os.path.isdir(_opencc_configdir):
CONFIGS = [f for f in os.listdir(_opencc_configdir) if f.endswith('.json')]
else:
CONFIGS = []
_CONFIG_STEMS = {config[:-5] for config in CONFIGS}
def _append_path_to_env(name: str, path: str) -> None:
value = os.environ.get(name, '')
if path in value: return
if value == '':
value = path
else:
value += f'{os.pathsep}{path}'
os.environ[name] = value
def _load_opencc_clib_from_runfiles():
candidate_dirs = [
os.path.join(_opencc_rootdir, 'src', 'pyd'),
os.path.join(_opencc_rootdir, 'src'),
]
candidate_names = [
'opencc_clib.pyd',
'opencc_clib.so',
]
for directory in candidate_dirs:
if not os.path.isdir(directory):
continue
for entry in os.listdir(directory):
if entry == 'opencc_clib.pyd' or entry.startswith('opencc_clib.') or entry.startswith('opencc_clib.cpython-'):
candidate_names.append(entry)
candidate_paths = []
for directory in candidate_dirs:
for name in candidate_names:
candidate_paths.append(os.path.join(directory, name))
for candidate in candidate_paths:
if not os.path.isfile(candidate):
continue
spec = importlib.util.spec_from_file_location('opencc_clib', candidate)
if spec is None or spec.loader is None:
continue
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
raise ImportError('opencc_clib not found in Bazel runfiles')
try:
import opencc_clib
except ImportError:
try:
from opencc.clib import opencc_clib
except ImportError:
opencc_clib = _load_opencc_clib_from_runfiles()
__version__ = opencc_clib.__version__
def _normalize_config_name(config: str) -> str:
basename = ntpath.basename(os.path.basename(config))
if basename != config:
return config
if '.' in basename:
return config
if config in _CONFIG_STEMS:
return config + '.json'
return config
class OpenCC(opencc_clib._OpenCC):
def __init__(self,
config: str = 't2s',
include_tofu_risk_dictionaries: bool = True,
resource_zip: Optional[str] = None) -> None:
config = _normalize_config_name(config)
if resource_zip is None and not os.path.isfile(config):
config_under_share_dir = os.path.join(_opencc_share_dir, config)
if os.path.isfile(config_under_share_dir):
config = config_under_share_dir
super().__init__(config, include_tofu_risk_dictionaries, resource_zip)
self.config = config
def convert(self, text: str):
byte_text = text.encode('utf-8')
return super().convert(byte_text, len(byte_text))