osci/datalake/reports/__init__.py (52 lines of code) (raw):

"""Copyright since 2020, EPAM Systems This file is part of OSCI. OSCI is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. OSCI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OSCI. If not, see <http://www.gnu.org/licenses/>.""" import abc import datetime import pandas as pd from typing import Type, Dict from osci.utils import MetaSingleton class BaseReport(metaclass=abc.ABCMeta): base_name = None date_period = None schema = None __date_suffix_pattern = "%Y-%m-%d" __data = None @property def name(self) -> str: """ Return the base_name of the report with date period type """ return f'{self.base_name}{"_" + self.date_period if self.date_period else ""}' def _get_name_with_date(self, date: datetime) -> str: """ Return the name of the report with date :param date: :return: """ return f'{self.name}_{date.strftime(self.__date_suffix_pattern)}.csv' @property def full_name(self) -> str: """ Return the full name of the report including file extension """ raise NotImplementedError() @property def url(self) -> str: """ Return the report url with prefix """ raise NotImplementedError() @property def path(self) -> str: """ Return the full path to report """ raise NotImplementedError() @property def df(self) -> pd.DataFrame: """ Return report data as pandas DataFrame """ if self.__data is None: self.__data = self.read() return self.__data def save(self, df: pd.DataFrame): """ Save pandas DataFrame as file :param df: """ raise NotImplementedError() def read(self) -> pd.DataFrame: """ Read report to pandas DataFrame from file """ raise NotImplementedError() class BaseReportFactory(metaclass=MetaSingleton): report_base_cls: Type[BaseReport] = BaseReport __date_period_cls_map__: Dict[str, report_base_cls] = None def __create_period_cls_map(self) -> Dict[str, report_base_cls]: return { cls.date_period: cls for cls in self.report_base_cls.__subclasses__() } @property def _date_period_cls_map(self) -> Dict[str, report_base_cls]: if self.__date_period_cls_map__ is None: self.__date_period_cls_map__ = self.__create_period_cls_map() return self.__date_period_cls_map__ def get_cls(self, date_period: str) -> report_base_cls: if date_period not in self._date_period_cls_map: raise NotImplementedError(f'Subclass of {self.report_base_cls} not implemented for ' f'date period `{date_period}`') return self._date_period_cls_map[date_period]