Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

__init__.py 3.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. #
  2. # Copyright 2024 The InfiniFlow Authors. All Rights Reserved.
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. #
  16. import re
  17. from pathlib import PurePath
  18. from .user_service import UserService as UserService
  19. def split_name_counter(filename: str) -> tuple[str, int | None]:
  20. """
  21. Splits a filename into main part and counter (if present in parentheses).
  22. Args:
  23. filename: Input filename string to be parsed
  24. Returns:
  25. A tuple containing:
  26. - The main filename part (string)
  27. - The counter from parentheses (integer) or None if no counter exists
  28. """
  29. pattern = re.compile(r"^(.*?)\((\d+)\)$")
  30. match = pattern.search(filename)
  31. if match:
  32. main_part = match.group(1).rstrip()
  33. bracket_part = match.group(2)
  34. return main_part, int(bracket_part)
  35. return filename, None
  36. def duplicate_name(query_func, **kwargs) -> str:
  37. """
  38. Generates a unique filename by appending/incrementing a counter when duplicates exist.
  39. Continuously checks for name availability using the provided query function,
  40. automatically appending (1), (2), etc. until finding an available name or
  41. reaching maximum retries.
  42. Args:
  43. query_func: Callable that accepts keyword arguments and returns:
  44. - True if name exists (should be modified)
  45. - False if name is available
  46. **kwargs: Must contain 'name' key with original filename to check
  47. Returns:
  48. str: Available filename, either:
  49. - Original name (if available)
  50. - Modified name with counter (e.g., "file(1).txt")
  51. Raises:
  52. KeyError: If 'name' key not provided in kwargs
  53. RuntimeError: If unable to generate unique name after maximum retries
  54. Example:
  55. >>> def name_exists(name): return name in existing_files
  56. >>> duplicate_name(name_exists, name="document.pdf")
  57. 'document(1).pdf' # If original exists
  58. """
  59. MAX_RETRIES = 1000
  60. if "name" not in kwargs:
  61. raise KeyError("Arguments must contain 'name' key")
  62. original_name = kwargs["name"]
  63. current_name = original_name
  64. retries = 0
  65. while retries < MAX_RETRIES:
  66. if not query_func(**kwargs):
  67. return current_name
  68. path = PurePath(current_name)
  69. stem = path.stem
  70. suffix = path.suffix
  71. main_part, counter = split_name_counter(stem)
  72. counter = counter + 1 if counter else 1
  73. new_name = f"{main_part}({counter}){suffix}"
  74. kwargs["name"] = new_name
  75. current_name = new_name
  76. retries += 1
  77. raise RuntimeError(f"Failed to generate unique name within {MAX_RETRIES} attempts. Original: {original_name}")