position_helper.py 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. import logging
  2. import os
  3. from collections import OrderedDict
  4. from collections.abc import Callable
  5. from typing import Any, AnyStr
  6. import yaml
  7. def get_position_map(
  8. folder_path: AnyStr,
  9. file_name: str = '_position.yaml',
  10. ) -> dict[str, int]:
  11. """
  12. Get the mapping from name to index from a YAML file
  13. :param folder_path:
  14. :param file_name: the YAML file name, default to '_position.yaml'
  15. :return: a dict with name as key and index as value
  16. """
  17. try:
  18. position_file_name = os.path.join(folder_path, file_name)
  19. if not os.path.exists(position_file_name):
  20. return {}
  21. with open(position_file_name, encoding='utf-8') as f:
  22. positions = yaml.safe_load(f)
  23. position_map = {}
  24. for index, name in enumerate(positions):
  25. if name and isinstance(name, str):
  26. position_map[name.strip()] = index
  27. return position_map
  28. except:
  29. logging.warning(f'Failed to load the YAML position file {folder_path}/{file_name}.')
  30. return {}
  31. def sort_by_position_map(
  32. position_map: dict[str, int],
  33. data: list[Any],
  34. name_func: Callable[[Any], str],
  35. ) -> list[Any]:
  36. """
  37. Sort the objects by the position map.
  38. If the name of the object is not in the position map, it will be put at the end.
  39. :param position_map: the map holding positions in the form of {name: index}
  40. :param name_func: the function to get the name of the object
  41. :param data: the data to be sorted
  42. :return: the sorted objects
  43. """
  44. if not position_map or not data:
  45. return data
  46. return sorted(data, key=lambda x: position_map.get(name_func(x), float('inf')))
  47. def sort_to_dict_by_position_map(
  48. position_map: dict[str, int],
  49. data: list[Any],
  50. name_func: Callable[[Any], str],
  51. ) -> OrderedDict[str, Any]:
  52. """
  53. Sort the objects into a ordered dict by the position map.
  54. If the name of the object is not in the position map, it will be put at the end.
  55. :param position_map: the map holding positions in the form of {name: index}
  56. :param name_func: the function to get the name of the object
  57. :param data: the data to be sorted
  58. :return: an OrderedDict with the sorted pairs of name and object
  59. """
  60. sorted_items = sort_by_position_map(position_map, data, name_func)
  61. return OrderedDict([(name_func(item), item) for item in sorted_items])