steamfiles.py 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. """Parses steam ACF files.
  2. Straight up ripped from https://github.com/leovp/steamfiles.
  3. (I was having issues building with cx_Freeze)
  4. """
  5. def loads(data, wrapper=dict):
  6. """
  7. Loads ACF content into a Python object.
  8. :param data: An UTF-8 encoded content of an ACF file.
  9. :param wrapper: A wrapping object for key-value pairs.
  10. :return: An Ordered Dictionary with ACF data.
  11. """
  12. if not isinstance(data, str):
  13. raise TypeError("can only load a str as an ACF but got " + type(data).__name__)
  14. parsed = wrapper()
  15. current_section = parsed
  16. sections = []
  17. lines = (line.strip() for line in data.splitlines())
  18. for line in lines:
  19. try:
  20. key, value = line.split(None, 1)
  21. key = key.replace('"', "").lstrip()
  22. value = value.replace('"', "").rstrip()
  23. except ValueError:
  24. if line == "{":
  25. # Initialize the last added section.
  26. current_section = _prepare_subsection(parsed, sections, wrapper)
  27. elif line == "}":
  28. # Remove the last section from the queue.
  29. sections.pop()
  30. else:
  31. # Add a new section to the queue.
  32. sections.append(line.replace('"', ""))
  33. continue
  34. current_section[key] = value
  35. return parsed
  36. def load(fp, wrapper=dict):
  37. """
  38. Loads the contents of an ACF file into a Python object.
  39. :param fp: A file object.
  40. :param wrapper: A wrapping object for key-value pairs.
  41. :return: An Ordered Dictionary with ACF data.
  42. """
  43. return loads(fp.read(), wrapper=wrapper)
  44. def _prepare_subsection(data, sections, wrapper):
  45. """
  46. Creates a subsection ready to be filled.
  47. :param data: Semi-parsed dictionary.
  48. :param sections: A list of sections.
  49. :param wrapper: A wrapping object for key-value pairs.
  50. :return: A newly created subsection.
  51. """
  52. current = data
  53. for i in sections[:-1]:
  54. current = current[i]
  55. current[sections[-1]] = wrapper()
  56. return current[sections[-1]]