6
0

LabelProvider.py 3.1 KB

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