LabelProvider.py 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. import json
  2. import re
  3. from pathlib import Path
  4. from pycs import db
  5. from pycs.database.base import NamedBaseModel
  6. from pycs.interfaces.LabelProvider import LabelProvider as LabelProviderInterface
  7. class LabelProvider(NamedBaseModel):
  8. """
  9. DB model for label providers
  10. """
  11. description = db.Column(db.String)
  12. root_folder = db.Column(db.String, nullable=False)
  13. configuration_file = db.Column(db.String, nullable=False)
  14. # relationships to other models
  15. projects = db.relationship("Project", backref="label_provider", lazy="dynamic")
  16. # contraints
  17. __table_args__ = (
  18. db.UniqueConstraint('root_folder', 'configuration_file'),
  19. )
  20. serialize_only = NamedBaseModel.serialize_only + (
  21. "description",
  22. "root_folder",
  23. "configuration_file",
  24. )
  25. @classmethod
  26. def discover(cls, root: Path):
  27. """
  28. searches for label providers under the given path
  29. and stores them in the database
  30. """
  31. for folder, conf_path in _find_files(root):
  32. with open(conf_path) as conf_file:
  33. config = json.load(conf_file)
  34. provider, _ = cls.get_or_create(
  35. root_folder=str(folder),
  36. configuration_file=conf_path.name
  37. )
  38. provider.name = config['name']
  39. # returns None if not present
  40. provider.description = config.get('description')
  41. provider.flush()
  42. db.session.commit()
  43. @property
  44. def root(self) -> Path:
  45. """ returns the root folder as Path object """
  46. return Path(self.root_folder)
  47. @property
  48. def configuration_file_path(self) -> str:
  49. """ return the configuration file as Path object """
  50. return str(self.root / self.configuration_file)
  51. def load(self) -> LabelProviderInterface:
  52. """
  53. load configuration.json and create an instance from the included code object
  54. :return: LabelProvider instance
  55. """
  56. # load configuration.json
  57. with open(self.configuration_file_path) as configuration_file:
  58. configuration = json.load(configuration_file)
  59. # load code
  60. code_path = str(self.root / configuration['code']['module'])
  61. module_name = code_path.replace('/', '.').replace('\\', '.')
  62. class_name = configuration['code']['class']
  63. imported_module = __import__(module_name, fromlist=[class_name])
  64. class_attr = getattr(imported_module, class_name)
  65. # return instance
  66. return class_attr(self.root_folder, configuration)
  67. def _find_files(root: str, config_regex=re.compile(r'^configuration(\d+)?\.json$')):
  68. """ generator for config files found under the given path """
  69. for folder in Path(root).glob('*'):
  70. # list files
  71. for file_path in folder.iterdir():
  72. # filter configuration files
  73. if not file_path.is_file():
  74. continue
  75. if config_regex.match(file_path.name) is None:
  76. continue
  77. # yield element
  78. yield folder, file_path