6
0

LabelProvider.py 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  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. database class 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. for folder, conf_path in _find_files(root):
  28. with open(conf_path) as f:
  29. config = json.load(f)
  30. provider, _ = cls.get_or_create(
  31. root_folder=str(folder),
  32. configuration_file=conf_path.name
  33. )
  34. provider.name = config['name']
  35. # returns None if not present
  36. provider.description = config.get('description')
  37. provider.flush()
  38. db.session.commit()
  39. @property
  40. def root(self) -> Path:
  41. return Path(self.root_folder)
  42. @property
  43. def configuration_file_path(self) -> str:
  44. return str(self.root / self.configuration_file)
  45. def load(self) -> LabelProviderInterface:
  46. """
  47. load configuration.json and create an instance from the included code object
  48. :return: LabelProvider instance
  49. """
  50. # load configuration.json
  51. with open(self.configuration_file_path) as configuration_file:
  52. configuration = json.load(configuration_file)
  53. # load code
  54. code_path = str(self.root / configuration['code']['module'])
  55. module_name = code_path.replace('/', '.').replace('\\', '.')
  56. class_name = configuration['code']['class']
  57. imported_module = __import__(module_name, fromlist=[class_name])
  58. class_attr = getattr(imported_module, class_name)
  59. # return instance
  60. return class_attr(self.root_folder, configuration)
  61. def _find_files(root: str, config_regex=re.compile(r'^configuration(\d+)?\.json$')):
  62. # list folders in labels/
  63. for folder in Path(root).glob('*'):
  64. # list files
  65. for file_path in folder.iterdir():
  66. # filter configuration files
  67. if not file_path.is_file():
  68. continue
  69. if config_regex.match(file_path.name) is None:
  70. continue
  71. # yield element
  72. yield folder, file_path