Source code for commonutil.pathtag
# -*- coding: utf-8 -*-
""" 路徑為基礎的標記或巨集支援 / Path-based Tag or Macro Support """
# 注意: 這個模組參考到了其他 commonutil 內的模組。
# 當製作 commonutil 模組時如果引用此模組,必須小心不要製造出遞迴的參考。
# Caution: as this module includes other modules from commonutil package.
# be careful, do not make circular reference if building commonutil module base on this module.
import re
import datetime
from commonutil.convert import to_text
_PTAG_TYPE_FILE = 1
_PTAG_TYPE_PATH = 2
_PTAG_TYPE_CURRENT = 3
_PTAG_TYPE_MTIME = 4
_PTAG_KEY_MAP = {
'F': _PTAG_TYPE_FILE,
'P': _PTAG_TYPE_PATH,
'N': _PTAG_TYPE_CURRENT,
'M': _PTAG_TYPE_MTIME,
}
_ptag_trap_regex = re.compile(u'([PFNM])\$((\{([0-9]+)\})|([0-9]))')
[docs]def parse_template(v):
# type: (str) -> Any
"""
將輸入的檔名與路徑關鍵字代換字串轉換為後續供代換作業的物件
Translate given string which contained path-tag macros into match object
Args:
v: 要轉換的代換字串 / Macro string
Return:
供代換作業使用的物件 / Match object for substitute operation
"""
if v is None:
return None
v = str(v)
remain_s = 0
remain_e = len(v)
rule_q = [] # result container
# {{{ search substitute keyword
m = _ptag_trap_regex.search(v, remain_s, remain_e)
while m is not None:
# {{{ get text before rule-string
left_e = m.start(0)
if left_e > remain_s:
rule_q.append(v[remain_s:left_e])
# }}} get text before rule-string
# {{{ create rule object
try:
type_code = _PTAG_KEY_MAP[str(m.group(1))]
g_idx = m.group(4)
if g_idx is None:
g_idx = m.group(5)
g_idx = int(g_idx)
rule_q.append((
type_code,
g_idx,
))
except Exception as e:
rule_q.append("?/ERR:%r/" % (e, ))
# }}} create rule object
remain_s = m.end(0)
if remain_s < remain_e:
m = _ptag_trap_regex.search(v, remain_s, remain_e)
else:
m = None
# }}} search substitute keyword
if remain_s < remain_e:
rule_q.append(v[remain_s:remain_e])
return rule_q if rule_q else None
def _datetime_prop_by_index(dtobj, idx):
if idx == 1:
return str(dtobj.year).zfill(4)
elif idx == 2:
return str(dtobj.month).zfill(2)
elif idx == 3:
return str(dtobj.day).zfill(2)
elif idx == 4:
return str(dtobj.hour).zfill(2)
elif idx == 5:
return str(dtobj.minute).zfill(2)
elif idx == 6:
return str(dtobj.second).zfill(2)
return u'?/ERR:datetime-index/'
[docs]def replace(xtrule, f_mobj, p_mobj, filemtime_dtobj=None):
# type: (Any, re.MatchObject, re.MatchObject, datetime.datetime) -> str
"""
執行檔名與路徑關鍵字代換字串作業
Perform tag replacement by given match rule object
Args:
xtrule: 從 parse_time_tag_template() 函數取得的代換作業參數物件 / Match rule object get from parse_time_tag_template() function
f_mobj: 檔案名稱的 regex match object / regex match object of file name
p_mobj: 檔案路徑的 regex match object / regex match object of file path (folder part)
filemtime_dtobj=None: 檔案的變更時間物件 (已經偏移完成) / datetime.datetime object of the file modify time (must shift to desired time zone before pass in)
Return:
經過代換的字串 / Result string
"""
result_q = []
for xtitem in xtrule:
elem = None
# {{{ 決定字串片段 (elem)
if isinstance(xtitem, tuple):
try:
subs_type, subs_idx, = xtitem
if _PTAG_TYPE_FILE == subs_type:
elem = f_mobj.group(subs_idx)
elif _PTAG_TYPE_PATH == subs_type:
elem = p_mobj.group(subs_idx)
elif _PTAG_TYPE_CURRENT == subs_type:
elem = _datetime_prop_by_index(datetime.datetime.now(), subs_idx)
elif (_PTAG_TYPE_MTIME == subs_type) and (filemtime_dtobj is not None):
elem = _datetime_prop_by_index(filemtime_dtobj, subs_idx)
except Exception as _e:
# elem = default_value
elem = u"?/ERR:%r/" % (_e, )
else:
elem = xtitem
# }}} 決定字串片段
if (elem is not None) and (not isinstance(elem, unicode)):
elem = to_text(elem, None)
if elem is not None:
result_q.append(elem)
return u''.join(result_q) if result_q else None
# vim: ts=4 sw=4 ai nowrap