Slink/dms/tools/file.py

104 lines
3.1 KiB
Python
Executable File

# Copyright 2020 Antoni Romera
# Copyright 2017-2019 MuK IT GmbH
# Copyright 2024 Subteno - Timothée Vannier (https://www.subteno.com).
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
import mimetypes
import os
import re
import shutil
import tempfile
from odoo.tools.mimetypes import guess_mimetype
def check_name(name):
"""
Check if a file name is valid.
:param str name: The file name to check.
:return: True if the file name is valid, False otherwise.
:rtype: bool
"""
tmp_dir = tempfile.mkdtemp()
try:
open(os.path.join(tmp_dir, name), "a").close()
except OSError:
return False
finally:
shutil.rmtree(tmp_dir)
return True
def compute_name(name, suffix, escape_suffix):
"""
Compute a new name by adding a suffix to the original name.
:param str name: The original name.
:param int suffix: The suffix to add.
:param bool escape_suffix: If True, the suffix is added in between the name and
the file extension.
:return: The new name.
:rtype: str
"""
if escape_suffix:
name, extension = os.path.splitext(name)
return f"{name}({suffix}){extension}"
return f"{name}({suffix})"
def unique_name(name, names, escape_suffix=False):
"""
Generate a unique name by adding a suffix to the original name.
:param str name: The original name.
:param list names: The list of existing names.
:param bool escape_suffix: If True, the suffix is added in between the name and
the file extension.
:return: The unique name.
:rtype: str
"""
if name not in names:
return name
# Extract the suffix from the name
# e.g: "file(1).txt" -> "1"
# "Directory (1)(2)" -> "2"
digits = re.compile(r"\((\d+)\)(\.\w+)?$")
match = digits.search(name)
suffix = 1
if match:
suffix = int(match.group(1)) + 1
# get the name without the suffix and append the extension
name = name[: match.span()[0]] + (match.group(2) or "")
name = compute_name(name, suffix, escape_suffix)
while name in names:
# has to check recursively if the new name is unique because the user can
# rename the file with suffix n+1
# and then duplicate the file n, leading to a new file with suffix n+1 which
# is already used.
return unique_name(name, names, escape_suffix)
return name
def guess_extension(filename=None, mimetype=None, binary=None):
"""
Guess the extension of a file.
:param str filename: The name of the file.
:param str mimetype: The mimetype of the file.
:param str binary: The binary content of the file.
:return: The extension of the file.
:rtype: str
"""
extension = filename and os.path.splitext(filename)[1][1:].strip().lower()
if not extension and mimetype and mimetype != "application/x-empty":
extension = mimetypes.guess_extension(mimetype)[1:].strip().lower()
if not extension and binary:
mimetype = guess_mimetype(binary, default="")
extension = mimetypes.guess_extension(mimetype)[1:].strip().lower()
return extension