state.py 3.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. # coding: utf-8
  2. import importlib
  3. import typing
  4. from io import StringIO
  5. import sys
  6. from lxml import etree
  7. from synergine2.config import Config
  8. from synergine2.log import get_logger
  9. from synergine2.simulation import Subject
  10. from opencombat.exception import StateLoadError
  11. class StateLoader(object):
  12. def __init__(
  13. self,
  14. config: Config,
  15. state_file_path: str,
  16. ) -> None:
  17. self.logger = get_logger('StateLoader', config)
  18. self.config = config
  19. self.state_file_path = state_file_path
  20. self._validate()
  21. def _validate(self) -> None:
  22. # open and read schema file
  23. schema_file_path = self.config.get(
  24. 'global.state_schema',
  25. 'opencombat/state.xsd',
  26. )
  27. with open(schema_file_path, 'r') as schema_file:
  28. schema_to_check = schema_file.read()
  29. # open and read xml file
  30. with open(self.state_file_path, 'r') as xml_file:
  31. xml_to_check = xml_file.read()
  32. xmlschema_doc = etree.parse(StringIO(schema_to_check))
  33. xmlschema = etree.XMLSchema(xmlschema_doc)
  34. try:
  35. doc = etree.parse(StringIO(xml_to_check))
  36. # check for file IO error
  37. except IOError as exc:
  38. self.logger.error(exc)
  39. raise StateLoadError('Invalid File "{}": {}'.format(
  40. self.state_file_path,
  41. str(exc),
  42. ))
  43. # check for XML syntax errors
  44. except etree.XMLSyntaxError as exc:
  45. self.logger.error(exc)
  46. raise StateLoadError('XML Syntax Error in "{}": {}'.format(
  47. self.state_file_path,
  48. str(exc.error_log),
  49. ))
  50. except Exception as exc:
  51. self.logger.error(exc)
  52. raise StateLoadError('Unknown error with "{}": {}'.format(
  53. self.state_file_path,
  54. str(exc),
  55. ))
  56. # validate against schema
  57. try:
  58. xmlschema.assertValid(doc)
  59. except etree.DocumentInvalid as exc:
  60. self.logger.error(exc)
  61. raise StateLoadError(
  62. 'Schema validation error with "{}": {}'.format(
  63. self.state_file_path,
  64. str(exc),
  65. )
  66. )
  67. except Exception as exc:
  68. self.logger.error(exc)
  69. raise StateLoadError(
  70. 'Unknown validation error with "{}": {}'.format(
  71. self.state_file_path,
  72. str(exc),
  73. )
  74. )
  75. def get_subjects(self) -> typing.List[Subject]:
  76. raise NotImplementedError('TODO')
  77. class StateLoaderBuilder(object):
  78. def __init__(
  79. self,
  80. config: Config,
  81. ) -> None:
  82. self.logger = get_logger('StateLoader', config)
  83. self.config = config
  84. def get_state_loader(
  85. self,
  86. state_file_path: str,
  87. ) -> StateLoader:
  88. class_address = self.config.get(
  89. 'global.state_loader',
  90. 'opencombat.state.StateLoader',
  91. )
  92. module_address = '.'.join(class_address.split('.')[:-1])
  93. class_name = class_address.split('.')[-1]
  94. module_ = importlib.import_module(module_address)
  95. state_loader_class = getattr(module_, class_name)
  96. return state_loader_class(self.config, state_file_path)