fix
This commit is contained in:
parent
9cbfbd041f
commit
ec5ab34686
@ -20,17 +20,18 @@ def validate_file_name(file_name: str) -> bool:
|
||||
return any(pattern.match(file_name) for pattern in FILE_NAME_PATTERNS)
|
||||
|
||||
|
||||
def build_date_parts(now: datetime | None = None) -> tuple[str, str, str]:
|
||||
def build_date_parts(now: datetime | None = None) -> tuple[str, str, str, str]:
|
||||
current = now or datetime.now()
|
||||
year = current.strftime("%Y")
|
||||
month_year = current.strftime("%m_%Y")
|
||||
year = str(current.year)
|
||||
month = str(current.month)
|
||||
day = str(current.day)
|
||||
date_key = current.strftime("%Y%m%d")
|
||||
return year, month_year, date_key
|
||||
return year, month, day, date_key
|
||||
|
||||
|
||||
def build_out_dir(base_dir: str, now: datetime | None = None) -> str:
|
||||
year, month_year, date_key = build_date_parts(now)
|
||||
return join_path(base_dir, DEFAULT_OUTPUT_DIR_NAME, year, month_year, date_key)
|
||||
year, month, day, _ = build_date_parts(now)
|
||||
return join_path(base_dir, DEFAULT_OUTPUT_DIR_NAME, year, month, day)
|
||||
|
||||
|
||||
def build_run_dir(base_dir: str, run_number: int, now: datetime | None = None) -> str:
|
||||
@ -59,8 +60,22 @@ def build_process_log_file_name(date_key: str, run_number: int) -> str:
|
||||
|
||||
|
||||
def join_path(*parts: str) -> str:
|
||||
cleaned = [part.strip("/\\") for part in parts if part.strip("/\\")]
|
||||
return "\\".join(cleaned)
|
||||
raw_parts = [part for part in parts if part and part.strip("/\\")]
|
||||
if not raw_parts:
|
||||
return ""
|
||||
|
||||
first = raw_parts[0]
|
||||
is_unc = (
|
||||
first.startswith("//")
|
||||
or first.startswith("\\\\")
|
||||
or first.startswith("/")
|
||||
or first.startswith("\\")
|
||||
)
|
||||
cleaned = [part.replace("/", "\\").strip("\\") for part in raw_parts]
|
||||
joined = "\\".join(cleaned)
|
||||
if is_unc:
|
||||
return "\\\\" + joined.lstrip("\\")
|
||||
return joined
|
||||
|
||||
|
||||
def get_parent_dir(path: str) -> str:
|
||||
|
||||
@ -67,7 +67,9 @@ class SMBClientConnection:
|
||||
def listdir(self, path: str) -> list[str]:
|
||||
smbclient = _import_smbclient()
|
||||
full_path = self._resolve_path(path)
|
||||
with smbclient.scandir(full_path) as entries:
|
||||
# In some smbclient/smbprotocol versions scandir() returns a generator,
|
||||
# not a context manager, so we iterate directly.
|
||||
entries = smbclient.scandir(full_path)
|
||||
return [entry.name for entry in entries]
|
||||
|
||||
def is_file(self, path: str) -> bool:
|
||||
@ -168,6 +170,8 @@ class SMBClientConnection:
|
||||
def _resolve_path(self, path: str) -> str:
|
||||
if path.startswith("//") or path.startswith("\\\\"):
|
||||
return _normalize_unc_path(path)
|
||||
if _looks_like_unc_without_prefix(path, self.smb_base_path):
|
||||
return _normalize_unc_path("//" + path.lstrip("/\\"))
|
||||
return _normalize_unc_path(join_path(self.smb_base_path, path))
|
||||
|
||||
|
||||
@ -207,7 +211,7 @@ def create_run_context(
|
||||
run_number = next_run_number(out_day_dir, samba_conn)
|
||||
run_dir = join_path(out_day_dir, str(run_number))
|
||||
ensure_dir_exists(run_dir, samba_conn)
|
||||
_, _, date_key = build_date_parts(now)
|
||||
_, _, _, date_key = build_date_parts(now)
|
||||
return RunContext(
|
||||
run_dir=run_dir,
|
||||
out_day_dir=out_day_dir,
|
||||
@ -384,3 +388,11 @@ def _import_smbclient():
|
||||
except ImportError as exc: # noqa: BLE001
|
||||
raise RuntimeError("Библиотека smbprotocol/smbclient не установлена.") from exc
|
||||
return smbclient
|
||||
|
||||
|
||||
def _looks_like_unc_without_prefix(path: str, smb_base_path: str) -> bool:
|
||||
normalized_path = path.replace("/", "\\").lstrip("\\")
|
||||
if not normalized_path:
|
||||
return False
|
||||
server = _extract_server(smb_base_path).lower()
|
||||
return normalized_path.lower().startswith(f"{server}\\")
|
||||
|
||||
@ -25,6 +25,8 @@ from .parser import FileParseResult, parse_xml_content
|
||||
from .protocol import ProtocolRow, write_protocol
|
||||
from .report import ReportRow, write_report
|
||||
|
||||
EMPTY_BATCH_STATUS = "info"
|
||||
|
||||
|
||||
@dataclass
|
||||
class BatchResult:
|
||||
@ -84,7 +86,7 @@ def run_batch(
|
||||
|
||||
scan_result = scan_input_files(input_dir=input_dir, samba_conn=samba_conn)
|
||||
log_lines.append(
|
||||
f"{_now()} scan files: valid={len(scan_result.valid_files)} invalid={len(scan_result.invalid_files)}"
|
||||
f"{_now()} | scan files: valid={len(scan_result.valid_files)} invalid={len(scan_result.invalid_files)}"
|
||||
)
|
||||
|
||||
for remote_file in scan_result.invalid_files:
|
||||
@ -106,7 +108,7 @@ def run_batch(
|
||||
processed_at=datetime.now(),
|
||||
)
|
||||
)
|
||||
log_lines.append(f"{_now()} invalid -> err: {remote_file.path} => {moved_to}")
|
||||
log_lines.append(f"{_now()} | invalid -> err: {remote_file.path} => {moved_to}")
|
||||
|
||||
for remote_file in scan_result.valid_files:
|
||||
parse_result = _parse_remote_xml(remote_file.name, remote_file.path, samba_conn)
|
||||
@ -131,7 +133,7 @@ def run_batch(
|
||||
samba_conn=samba_conn,
|
||||
)
|
||||
log_lines.append(
|
||||
f"{_now()} success -> processed: {remote_file.path} => {moved_to}"
|
||||
f"{_now()} | success -> processed: {remote_file.path} => {moved_to}"
|
||||
)
|
||||
else:
|
||||
moved_to = move_file_to_error(
|
||||
@ -141,14 +143,14 @@ def run_batch(
|
||||
samba_conn=samba_conn,
|
||||
)
|
||||
log_lines.append(
|
||||
f"{_now()} {status} -> err: {remote_file.path} => {moved_to}"
|
||||
f"{_now()} | {status} -> err: {remote_file.path} => {moved_to}"
|
||||
)
|
||||
|
||||
if not protocol_rows:
|
||||
protocol_rows.append(
|
||||
ProtocolRow(
|
||||
file_name="-",
|
||||
status="success",
|
||||
status=EMPTY_BATCH_STATUS,
|
||||
message="Новых файлов для обработки нет.",
|
||||
operations_total=0,
|
||||
rows_written=0,
|
||||
@ -156,7 +158,7 @@ def run_batch(
|
||||
processed_at=datetime.now(),
|
||||
)
|
||||
)
|
||||
log_lines.append(f"{_now()} empty batch")
|
||||
log_lines.append(f"{_now()} | empty batch")
|
||||
|
||||
report_file_name = build_report_file_name(
|
||||
run_context.date_key, run_context.run_number
|
||||
|
||||
12
main.py
12
main.py
@ -43,16 +43,7 @@ def main() -> None:
|
||||
help="Пароль учетной записи для доступа к SMB-шаре.",
|
||||
)
|
||||
if st.button("Изменить путь", use_container_width=True):
|
||||
ok, message, _ = check_access_and_list_files(
|
||||
smb_base_path=SFM_SMB_BASE_PATH,
|
||||
input_dir=resolved_input_dir,
|
||||
samba_user=samba_user,
|
||||
samba_password=samba_password,
|
||||
)
|
||||
if ok:
|
||||
open_path_editor(current_input_dir)
|
||||
else:
|
||||
st.error(f"{message} Обратитесь к {ACCESS_SUPPORT_CONTACT}.")
|
||||
|
||||
edited_path = render_path_editor()
|
||||
if edited_path is not None:
|
||||
@ -78,12 +69,13 @@ def main() -> None:
|
||||
use_container_width=True,
|
||||
):
|
||||
with st.spinner("Выполняется обработка..."):
|
||||
launcher_name = samba_user.strip() or user_id
|
||||
batch_result = run_batch(
|
||||
smb_base_path=SFM_SMB_BASE_PATH,
|
||||
input_dir=resolved_input_dir,
|
||||
samba_user=samba_user,
|
||||
samba_password=samba_password,
|
||||
launcher=user_id,
|
||||
launcher=launcher_name,
|
||||
)
|
||||
if batch_result.status == "success":
|
||||
st.success("Обработка завершена успешно.")
|
||||
|
||||
@ -112,4 +112,4 @@ def test_run_batch_smoke_and_idempotency(tmp_path: Path, monkeypatch) -> None:
|
||||
launcher="tester",
|
||||
)
|
||||
assert second.status == "success"
|
||||
assert second.processed >= 1
|
||||
assert second.processed == 0
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user