def test_configparser_copy(self): ccp = CallbackConfigParser() ccp.read_file(self.CONFIG_FILES_DIR / 'config1.conf') copy_ccp = ccp.copy() self.assertEqual(copy_ccp.get('general', 'version'), 11) self.assertTrue(copy_ccp.get('search_community', 'enabled'))
def test_configparser_copy(): ccp = CallbackConfigParser() ccp.read_file(CONFIG_FILES_DIR / 'config1.conf') copy_ccp = ccp.copy() assert copy_ccp.get('general', 'version') == 11 assert copy_ccp.get('search_community', 'enabled')
def test_configparser_config1(): ccp = CallbackConfigParser() ccp.read_file(CONFIG_FILES_DIR / 'config1.conf') assert ccp.get('general', 'version') == 11 assert ccp.get('search_community', 'enabled') assert isinstance(ccp.get('tunnel_community', 'socks5_listen_ports'), list) assert not ccp.get('foo', 'bar')
def test_configparser_false_callback(self): def parser_callback(section, option, old_value, new_value): return False ccp = CallbackConfigParser() ccp.read_file(self.CONFIG_FILES_DIR / 'config1.conf') ccp.set_callback(parser_callback) ccp.set('search_community', 'enabled', False)
def test_configparser_config1(self): ccp = CallbackConfigParser() ccp.read_file(self.CONFIG_FILES_DIR / 'config1.conf') self.assertEqual(ccp.get('general', 'version'), 11) self.assertTrue(ccp.get('search_community', 'enabled')) self.assertIsInstance(ccp.get('tunnel_community', 'socks5_listen_ports'), list) self.assertFalse(ccp.get('foo', 'bar'))
def convert_state_file_to_conf_74(filename, refactoring_tool=None): """ Converts .pstate file (pre-7.4.0) to .conf file. :param filename: .pstate file :param refactoring_tool: RefactoringTool instance if using Python3 :return: None """ def _fix_state_config(config): for section, option in [('state', 'metainfo'), ('state', 'engineresumedata')]: value = config.get(section, option, literal_eval=False) try: value = str(refactoring_tool.refactor_string(value + '\n', option + '_2to3')) ungarbled_dict = recursive_ungarble_metainfo(ast.literal_eval(value)) value = ungarbled_dict or ast.literal_eval(value) config.set(section, option, base64.b64encode(lt.bencode(value)).decode('utf-8')) except (ValueError, SyntaxError, ParseError) as ex: logger.error("Config could not be fixed, probably corrupted. Exception: %s %s", type(ex), str(ex)) return None return config old_config = CallbackConfigParser() try: old_config.read_file(str(filename)) except MissingSectionHeaderError: logger.error("Removing download state file %s since it appears to be corrupt", filename) os.remove(filename) # We first need to fix the .state file such that it has the correct metainfo/resumedata. # If the config cannot be fixed, it is likely corrupted in which case we simply remove the file. fixed_config = _fix_state_config(old_config) if not fixed_config: logger.error("Removing download state file %s since it could not be fixed", filename) os.remove(filename) return # Remove dlstate since the same information is already stored in the resumedata if old_config.has_option('state', 'dlstate'): old_config.remove_option('state', 'dlstate') new_config = ConfigObj(infile=str(filename)[:-6] + '.conf', encoding='utf8') for section in old_config.sections(): for key, _ in old_config.items(section): val = old_config.get(section, key) if section not in new_config: new_config[section] = {} new_config[section][key] = val new_config.write() os.remove(filename)
def test_configparser_false_callback(): def parser_callback(*_): return False with pytest.raises(OperationNotPossibleAtRuntimeException): ccp = CallbackConfigParser() ccp.read_file(CONFIG_FILES_DIR / 'config1.conf') ccp.set_callback(parser_callback) ccp.set('search_community', 'enabled', False)
def test_delete_noncompliant_state(tmpdir): state_dir = TESTS_DATA_DIR / 'noncompliant_state_dir' shutil.copytree(str(state_dir), str(tmpdir / "test")) cleanup_noncompliant_channel_torrents(Path(tmpdir) / "test") # Check cleanup of the channels dir dir_listing = list((Path(tmpdir) / "test" / "channels").iterdir()) assert len(dir_listing) == 3 for f in (Path(tmpdir) / "test" / "channels").iterdir(): assert CHANNEL_DIR_NAME_LENGTH == len(f.stem) # Check cleanup of torrent state dir checkpoints_dir = tmpdir / "test" / "dlcheckpoints" dir_listing = os.listdir(checkpoints_dir) assert len(dir_listing) == 1 file_path = checkpoints_dir / dir_listing[0] pstate = CallbackConfigParser() pstate.read_file(file_path) assert CHANNEL_DIR_NAME_LENGTH == len(pstate.get('state', 'metainfo')['info']['name'])
def test_configparser_write_file_defaults(tmpdir): ccp = CallbackConfigParser(defaults={'foo': 'bar'}) new_path = Path(tmpdir) / 'config_new.conf' ccp.write_file(new_path) assert new_path.is_file() ccp.read_file(new_path) assert ccp.get('DEFAULT', 'foo') == 'bar'
def test_configparser_write_file_defaults(self): ccp = CallbackConfigParser(defaults={'foo': 'bar'}) new_path = self.session_base_dir / 'config_new.conf' ccp.write_file(new_path) self.assertTrue(new_path.is_file()) ccp.read_file(new_path) self.assertEqual(ccp.get('DEFAULT', 'foo'), 'bar')
def test_delete_noncompliant_state(self): STATE_DIR = TESTS_DATA_DIR / 'noncompliant_state_dir' tmpdir = self.temporary_directory() / STATE_DIR.name shutil.copytree(str_path(STATE_DIR), str_path(tmpdir)) cleanup_noncompliant_channel_torrents(tmpdir) # Check cleanup of the channels dir dir_listing = list((tmpdir / "channels").iterdir()) self.assertEqual(3, len(dir_listing)) for f in (tmpdir / "channels").iterdir(): self.assertEqual(CHANNEL_DIR_NAME_LENGTH, len(f.stem)) # Check cleanup of torrent state dir checkpoints_dir = tmpdir / "dlcheckpoints" dir_listing = os.listdir(checkpoints_dir) self.assertEqual(1, len(dir_listing)) file_path = checkpoints_dir / dir_listing[0] pstate = CallbackConfigParser() pstate.read_file(file_path) self.assertEqual(CHANNEL_DIR_NAME_LENGTH, len(pstate.get('state', 'metainfo')['info']['name']))
def cleanup_noncompliant_channel_torrents(state_dir): logger = logging.getLogger(__name__) channels_dir = state_dir / "channels" # Remove torrents contents if channels_dir.exists(): for d in channels_dir.iterdir(): if len(d.stem) != CHANNEL_DIR_NAME_LENGTH: dir_path = channels_dir / d # We remove both malformed channel dirs and .torrent and .mdblob files for personal channel if dir_path.is_dir(): shutil.rmtree(str(dir_path), ignore_errors=True) elif dir_path.is_file(): os.unlink(str(dir_path)) # Remove .state torrent resume files resume_dir = state_dir / "dlcheckpoints" if resume_dir.exists(): for f in resume_dir.iterdir(): if not str(f).endswith('.state'): continue file_path = resume_dir / f pstate = CallbackConfigParser() try: pstate.read_file(file_path) except (ParsingError, MissingSectionHeaderError): logger.warning( "Parsing channel torrent resume file %s failed, deleting", file_path) os.unlink(file_path) continue if pstate and pstate.has_option('download_defaults', 'channel_download') and \ pstate.get('download_defaults', 'channel_download'): try: name = pstate.get('state', 'metainfo')['info']['name'] if name and len(name) != CHANNEL_DIR_NAME_LENGTH: os.unlink(file_path) except (TypeError, KeyError, ValueError): logger.debug( "Malfored .pstate file %s found during cleanup of non-compliant channel torrents.", file_path)
def test_configparser_write_file(tmpdir): ccp = CallbackConfigParser() ccp.read_file(CONFIG_FILES_DIR / 'config1.conf') new_path = Path(tmpdir) / 'config_new.conf' ccp.write_file(new_path) assert new_path.is_file() ccp.read_file(new_path) assert ccp.get('general', 'version') == 11 assert ccp.get('search_community', 'enabled') assert isinstance(ccp.get('tunnel_community', 'socks5_listen_ports'), list) assert not ccp.get('foo', 'bar')
def test_configparser_set_callback(): def parser_callback(*_): return True ccp = CallbackConfigParser() ccp.set_callback(parser_callback) ccp.read_file(CONFIG_FILES_DIR / 'config1.conf') ccp.set('search_community', 'enabled', False) ccp.set('search_community', 'bar', 42) assert not ccp.get('search_community', 'enabled') assert ccp.get('search_community', 'bar') == 42
def test_configparser_write_file(self): ccp = CallbackConfigParser() ccp.read_file(self.CONFIG_FILES_DIR / 'config1.conf') new_path = self.session_base_dir / 'config_new.conf' ccp.write_file(new_path) self.assertTrue(new_path.is_file()) ccp.read_file(new_path) self.assertEqual(ccp.get('general', 'version'), 11) self.assertTrue(ccp.get('search_community', 'enabled')) self.assertIsInstance(ccp.get('tunnel_community', 'socks5_listen_ports'), list) self.assertFalse(ccp.get('foo', 'bar'))
def test_configparser_set_callback(self): def parser_callback(section, option, old_value, new_value): return True ccp = CallbackConfigParser() ccp.set_callback(parser_callback) ccp.read_file(self.CONFIG_FILES_DIR / 'config1.conf') ccp.set('search_community', 'enabled', False) ccp.set('search_community', 'bar', 42) self.assertFalse(ccp.get('search_community', 'enabled')) self.assertEqual(ccp.get('search_community', 'bar'), 42)