class ProviderManagerTestCase(unittest.TestCase): """ Unit test case for provider manager. """ def setUp(self): self.provider_manager = ProviderManager() def test_add(self): """ Test add method for provider manager. """ self.provider_manager.add('dummy', DummyProvider) self.assertTrue('dummy' in self.provider_manager._providers) self.assertEqual(self.provider_manager.get('dummy'), DummyProvider) def test_get(self): """ Test application get method. """ self.provider_manager.add('dummy', DummyProvider) self.assertEqual(self.provider_manager.get('dummy'), DummyProvider) def test_contain(self): """ Test if '__contains__' method is working. """ self.provider_manager.add('dummy', DummyProvider) self.assertTrue('dummy' in self.provider_manager._providers) self.assertFalse('bar' in self.provider_manager._providers)
class ProviderManagerTestCase(unittest.TestCase): """ Test case for ProviderManager """ def setUp(self): self.provider_manager = ProviderManager() def test_add(self): """ :return: """ self.provider_manager.add('dummy', DummyProvider) self.assertTrue('dummy' in self.provider_manager._providers) self.assertEqual(self.provider_manager.get('dummy'), DummyProvider) def test_get(self): """ :return: """ self.provider_manager.add('dummy', DummyProvider) self.assertEqual(self.provider_manager.get('dummy'), DummyProvider) self.assertIsNone(self.provider_manager.get('any')) def test_contains(self): """ :return: """ self.provider_manager.add('dummy', DummyProvider) self.assertTrue('dummy' in self.provider_manager) self.assertFalse('any' in self.provider_manager) def test_iter(self): """ :return: """ self.provider_manager.add('dummy', DummyProvider) for name in self.provider_manager: self.assertTrue(name in self.provider_manager)
class ProviderManagerTestCase(unittest.TestCase): """ Unit test case for providers manager. """ def setUp(self): self.provider_manager = ProviderManager() def test_load_commands(self): """ Test load commands method for providers manager. """ self.provider_manager.add('dummy', DummyCommand) self.assertTrue('dummy' in self.provider_manager._commands) self.assertEqual(self.provider_manager.get('dummy'), DummyCommand) self.assertFalse('bar' in self.provider_manager) self.assertIsNone(self.provider_manager.get('bar'))
class ProviderManagerTestCase(unittest.TestCase): """Unit test case for provider manager.""" def setUp(self): """Contain set up info for every single test.""" self.provider_manager = ProviderManager() self.provider_manager.add('example', ExampleCommand) def test_load_providers(self): """Test _load_providers method for provider manager.""" message = 'An error occurs during the _load_providers method.' self.assertTrue('accu' in self.provider_manager._providers, msg=message) self.assertTrue('rp5' in self.provider_manager._providers, msg=message) self.assertTrue('sinoptik' in self.provider_manager._providers, msg=message) def test_add(self): """Test add method for provider manager.""" self.assertTrue('example' in self.provider_manager._providers, msg="Command 'example' is missing in provider manager.") def test_get(self): """Test get method for provider manager.""" self.assertEqual(self.provider_manager.get('example'), ExampleCommand) self.assertIsNone(self.provider_manager.get('bar'), ExampleCommand) def test_contains(self): """Test if '__contains__' method is working.""" self.assertTrue('example' in self.provider_manager) self.assertFalse('bar' in self.provider_manager) def test_len(self): """Test if '__len__' method is working.""" self.assertEqual(4, len(self.provider_manager._providers))
class App: """ WeatherApp agregator """ logger = logging.getLogger(__name__) LOG_LEVEL_MAP = {0: logging.WARNING, 1: logging.INFO, 2: logging.DEBUG} def __init__(self, stdin=None, stdout=None, stderr=None): self.stdin = stdin or sys.stdin self.stdout = stdout or sys.stdout self.stderr = stderr or sys.stderr self.arg_parser = self._arg_parse() self.providermanager = ProviderManager() self.formatters = self._load_formatter() self.commandmanager = CommandManager() def place_settings(self): """ information about current settings :return: info about change settings """ flag = False for site_name in config.sites: self.stdout.write( 'The site {} have installed place {} \n'.format(site_name, self.providermanager.get( site_name).read_settings()[ 1])) while True: self.stdout.write( 'If you will change place for site - input "sitename"') self.stdout.write('If you will exit? input "exit"') site_name = input('If not need - input "No"') if site_name.lower() == 'no': break elif site_name.lower() == 'exit': sys.exit(1) elif site_name in config.sites: self.providermanager.get(site_name).chose_place() flag = True break else: print('Not correct data') return flag def _arg_parse(self): """ Initialize argument parser """ arg_parser = ArgumentParser(add_help=False) arg_parser.add_argument('command', help='Command', nargs="?") arg_parser.add_argument('-r', '--refresh', help='Bypass caches', action='store_true') arg_parser.add_argument('--debug', action='store_true') arg_parser.add_argument('-v', '--verbose', action='count', dest='verbose_level', default=0, help='Increase verbosity of output.') arg_parser.add_argument('-f', '--formatter', action='store', nargs='*', default=['table'], help="Output format, defaults to table") arg_parser.add_argument('-time', action='store', help="Change time cache") return arg_parser def configure_logging(self): """ Create logging handlers for any log output """ root_logger = logging.getLogger('') root_logger.setLevel(App.LOG_LEVEL_MAP[0]) console_handler = logging.StreamHandler() console_handler.setLevel( App.LOG_LEVEL_MAP.get(self.options.verbose_level, App.LOG_LEVEL_MAP[0])) info_formater = logging.Formatter( '%(asctime)s - %(levelname)s - %(funcName)s - %(message)s') console_handler.setFormatter(info_formater) root_logger.addHandler(console_handler) @staticmethod def _load_formatter(): return {'table': TableFormatter, 'csv': CSV_Formatter, 'txt': TXT_Formatter} def produce_output(self, data): """ Print results. """ formatter = self.formatters.get(self.options.formatter[0], 'table')() self.stdout.write(formatter.emit(data)) self.stdout.write('\n') def run_command(self, name, argv): """ Run command """ command = self.commandmanager.get(name) try: command(self).run(argv) except Exception: msg = "Error during command: %s run" if self.options.debug: self.logger.exception(msg, name) else: self.logger.error(msg, name) def run_provider(self, name): """ Run specified provider """ provider = self.providermanager.get(name) data = list() if provider: data.append(provider.data_for_table()) self.produce_output(data) def run_providers(self): """ Execute all available providers. data for table = list(site_name, temperature, place, cond) """ data = list() for name, provider in self.providermanager._providers.items(): provider = provider.data_for_table() data.append(provider) self.produce_output(data) def run(self, argv): self.options, remaining_args = self.arg_parser.parse_known_args(argv) command_name = self.options.command self.configure_logging() if self.options.refresh == True: Cache_controller.refresh_cache() if self.options.time != None and self.options.time.isnumeric() == True: Cache_controller.change_time_cache(self.options.time) if not command_name: # run all weather providers by default self.run_providers() if command_name in self.providermanager: # run specific provider self.run_provider(command_name) if command_name in self.commandmanager: # run specific provider self.run_command(command_name, remaining_args) def __del__(self): pass
class App: """ Weather aggregator application. """ logger = logging.getLogger(__name__) LOG_LEVEL_MAP = {0: logging.WARNING, 1: logging.INFO, 2: logging.DEBUG} def __init__(self, stdin=None, stdout=None, stderr=None): self.stdin = stdin or sys.stdin self.stdout = stdout or sys.stdout self.stderr = stderr or sys.stderr self.arg_parser = self._arg_parse() self.providermanager = ProviderManager() self.commandmanager = CommandManager() self.formatters = self._load_formatters() @staticmethod def _arg_parse(): """ Initializes argument parser. """ arg_parser = ArgumentParser(add_help=False) arg_parser.add_argument('command', help="Command", nargs='?') arg_parser.add_argument('--refresh', help="Bypass caches", action='store_true') arg_parser.add_argument('-f', '--formatter', action='store', default='table', help="Output format, defaults to table") arg_parser.add_argument('-v', '--verbose', action='count', dest='verbose_level', default=config.DEFAULT_VERBOSE_LEVEL, help='Increase verbosity of output') arg_parser.add_argument('--debug', action='store_true', default=False, help='Show tracebacks on errors') return arg_parser @staticmethod def _load_formatters(): return {'table': TableFormatter} def configure_logging(self): """ Creates logging handlers for any log output. """ root_logger = logging.getLogger('') root_logger.setLevel(logging.DEBUG) console = logging.StreamHandler() console_level = self.LOG_LEVEL_MAP.get(self.options.verbose_level, logging.WARNING) console.setLevel(console_level) formatter = logging.Formatter(config.DEFAULT_MESSAGE_FORMAT) console.setFormatter(formatter) root_logger.addHandler(console) def produce_output(self, title, location, data): """ Prints results. """ formatter = self.formatters.get(self.options.formatter, 'table')() columns = [title, location] self.stdout.write(formatter.emit(columns, data)) self.stdout.write('\n') def run_command(self, name, argv): """ Runs command. """ command = self.commandmanager.get(name) try: command(self).run(argv) except Exception: msg = "Error during command: %s run" if self.options.debug: self.logger.exception(msg, name) else: self.logger.error(msg, name) def run_provider(self, name, argv): """ Runs specified provider. """ provider = self.providermanager.get(name) if provider: provider = provider(self) self.produce_output(provider.title, provider.location, provider.run(argv)) def run_providers(self, argv): """ Executes all available providers. """ for name, provider in self.providermanager: provider = provider(self) self.produce_output(provider.title, provider.location, provider.run(argv)) def run(self, argv): """ Runs application. :param argv: list of passed arguments """ self.options, remaining_args = self.arg_parser.parse_known_args(argv) self.configure_logging() command_name = self.options.command if not command_name: # runs all providers return self.run_providers(remaining_args) if command_name in self.commandmanager: return self.run_command(command_name, remaining_args) if command_name in self.providermanager: return self.run_provider(command_name, remaining_args) else: self.stdout.write('Unknown command provided. \n') sys.exit(1)
class App: """Weather aggregator application.""" def __init__(self, stdin=None, stdout=None, stderr=None): self.stdin = stdin or sys.stdin self.stdout = stdout or sys.stdout self.stderr = stderr or sys.stderr self.arg_parser = self._arg_parse() self.providermanager = ProviderManager() self.commandmanager = CommandManager() self.formatters = self._load_formatters() @staticmethod def _arg_parse(): """Initialize argument parser.""" arg_parser = ArgumentParser(description='Application information', add_help=False) arg_parser.add_argument('command', help='Command', nargs='?') arg_parser.add_argument('--refresh', help='Bypass caches', action='store_true') arg_parser.add_argument('--debug', help='Info for developer', action='store_true', default=False) arg_parser.add_argument('-f', '--formatter', help='Output format, defaults to table', action='store', default='table') return arg_parser @staticmethod def configure_logging(fname='weatheapp'): """Set up logging for any log output.""" logger.add(f'{fname}_{{time:MM:DD}}.log', retention='5 days') @staticmethod def get_cache_directory(): """Return path to the cache directory.""" return Path.home() / config.CACHE_DIR def clear_app_cache(self): """Delete directory with cache.""" cache_dir = self.get_cache_directory() try: shutil.rmtree(cache_dir) except FileNotFoundError: msg = 'The cache directory is empty or not found' if self.options.debug: logger.exception(msg) else: logger.error(msg) def delete_invalid_cache(self): """Delete all invalid (old) cache. The time during which the cache is valid can be changed in config.py """ cache_dir = self.get_cache_directory() if cache_dir.exists(): path = Path(cache_dir) dirs = os.listdir(path) for file in dirs: life_time = time.time() - (path / file).stat().st_mtime if life_time > config.DAY_IN_SECONDS: os.remove(path / file) def get_weather_info_to_save(self, weather_site: str) -> dict: """Return information from weather site to save.""" if weather_site in self.providermanager: provider = self.providermanager[weather_site] provider_obj = provider(self) _, content = self.get_city_name_page_content(weather_site) weather_info = provider_obj.get_weather_info(content) return weather_info def write_info_to_csv(self, weather_site: str): """Write data to a CSV file.""" info = self.get_weather_info_to_save(weather_site) with open('weather_data.csv', 'w', newline='') as output_file: field_names = ['Parameters', 'Description'] writer = csv.DictWriter(output_file, fieldnames=field_names) writer.writeheader() for key, value in info.items(): writer.writerow({'Parameters': key, 'Description': value}) def get_city_name_page_content(self, weather_site: str, refresh: bool = False): """Return name of the city and page content.""" PlaceInfo = namedtuple('PlaceInfo', 'place_name page_content') if weather_site in self.providermanager: provider = self.providermanager[weather_site] provider_obj = provider(self) city_name, city_url = provider_obj.get_configuration() content = provider_obj.get_page_from_server(city_url, refresh=refresh) place_info = PlaceInfo(city_name, content) return place_info @staticmethod def _load_formatters(): return {'table': TableFormatter} def program_output(self, title: str, city: str, info: dict): """Print the application output in readable form.""" formatter = self.formatters.get(self.options.formatter, 'table')() columns = [title, city] self.stdout.write(formatter.emit(columns, info)) self.stdout.write('\n') def run_command(self, name, argv): """Run command""" command = self.commandmanager.get(name) try: command(self).run(argv) except Exception: msg = f'Error during command: {name} run' if self.options.debug: logger.exception(msg) else: logger.error(msg) def run_provider(self, name, argv): """Run specified provider.""" provider = self.providermanager.get(name) if provider: provider = provider(self) self.program_output(provider.title, provider.location, provider.run(argv)) def run_providers(self, argv): """Execute all available providers.""" for _, provider in self.providermanager: provider = provider(self) self.program_output(provider.title, provider.location, provider.run(argv)) def run(self, argv): """Run application. :param argv: list of passed arguments """ self.delete_invalid_cache() self.options, remaining_args = self.arg_parser.parse_known_args(argv) self.configure_logging() logger.debug(f'Got the following args: {argv}') command_name = self.options.command if not command_name: # run all providers return self.run_providers(remaining_args) if command_name in self.commandmanager: return self.run_command(command_name, remaining_args) if command_name in self.providermanager: return self.run_provider(command_name, remaining_args) if remaining_args: weather_site = remaining_args[0] if command_name == 'clear-cache': self.clear_app_cache() elif command_name == 'save-to-csv': self.write_info_to_csv(weather_site) else: self.stdout.write('Unknown command provided. \n') sys.exit(1)