def test_add_linking_success(mocker: MockerFixture): api = mocker.Mock(spec=TransmissionApi) api.add_torrent_with_files.return_value = CommandResult(success=True) api.add_torrent.return_value = CommandResult(success=True) add_service = AddService(api) fs = MockFilesystem({"test_path"}) locator: TorrentDataLocator = DefaultTorrentDataLocator(fs) find_service = FindService(locator) path = Path("/", "test_path") file = MetainfoFile( { "name": "meaningless", "info_hash": "meaningless and necessary", "info": { "length": 5 }, }, path, ) command = LinkingAddCommand(add_service, fs, {TorrentData(file, Path("/some/place"))}) output: LinkingAddOutput = command.run() assert not fs.exists(path) assert output.linked_torrents == {file: Path("/some/place")}
def test_linking_add_run_display_failed(mocker: MockerFixture, capsys): api = mocker.Mock(spec=TransmissionApi) api.add_torrent_with_files.return_value = CommandResult(error="unknown", success=False) api.add_torrent.return_value = CommandResult(error="unknown", success=False) add_service = AddService(api) fs = MockFilesystem({"test_path"}) locator: TorrentDataLocator = DefaultTorrentDataLocator(fs) find_service = FindService(locator) path = Path("/", "test_path") file = MetainfoFile( { "name": "meaningless", "info_hash": "meaningless and necessary", "info": { "length": 5 }, }, path, ) command = LinkingAddCommand(add_service, fs, {TorrentData(file, Path("/some/place"))}) output: LinkingAddOutput = command.run() output.display() result = capsys.readouterr().out assert result == "\n".join(["1 failed:", "meaningless because: unknown" ]) + "\n"
def test_find_missing(): metainfo_path = Path("/", "metainfo.torrent") properties = { "info_hash": "meaningless and necessary", "name": "test_name", "info": { "files": [ { "path": ["file1"], "length": 0 }, { "path": ["file2"], "length": 0 }, ] }, } metainfo_file = MetainfoFile(properties, metainfo_path) fs = MockFilesystem({"data"}) locator = DefaultTorrentDataLocator(fs) find_service = FindService(locator) command = FindCommand(find_service, {metainfo_file}) output = command.run() assert output.found == set() assert output.missing == {metainfo_file}
def find_factory(argv: Sequence[str], dependencies: Mapping) -> CommandFactoryResult: reader = dependencies["metainfo_reader"] fs: Filesystem = dependencies["fs"] locator: FileLocator = dependencies["locator"] # parse arguments from clutchless.spec import find as find_command args = docopt(doc=find_command.__doc__, argv=argv) find_args = FindArgs(args, reader, fs, locator) data_directories = find_args.get_data_dirs() file_locator = MultipleDirectoryFileLocator(data_directories, fs) data_reader = DefaultTorrentDataReader(fs) data_locator = CustomTorrentDataLocator(file_locator, data_reader) service = FindService(data_locator) metainfo_files = find_args.get_torrent_files() if not metainfo_files: raise RuntimeError("Did not find any metainfo files") else: print(f"Found {len(metainfo_files)} metainfo files:") for file in metainfo_files: print(f"{file.name} at {file.path.parent}") return FindCommand(service, metainfo_files), args
def test_find_run_output(capsys): metainfo_path = Path("/", "metainfo.torrent") properties = { "info_hash": "meaningless and necessary", "name": "test_name", "info": { "files": [ { "path": ["file1"], "length": 0 }, { "path": ["file2"], "length": 0 }, ] }, } metainfo_file = MetainfoFile(properties, metainfo_path) missing_properties = { "info_hash": "meaningless and necessary", "name": "another_name", "info": { "files": [ { "path": ["file3"], "length": 0 }, { "path": ["file4"], "length": 0 }, ] }, } missing_metainfo_file = MetainfoFile(missing_properties, Path("/missing.torrent")) fs = MockFilesystem({"data": {"test_name": {"file1", "file2"}}}) locator = DefaultTorrentDataLocator(fs) find_service = FindService(locator) command = FindCommand(find_service, {metainfo_file, missing_metainfo_file}) output = command.run() output.display() result = capsys.readouterr().out assert (result == "\n".join([ "Starting search - press Ctrl+C to cancel", "1/2 test_name found at /data", "Found 1 torrents:", "\x1b[32m✓ test_name at /data", "Did not find 1 torrents:", "\x1b[31m✗ another_name", ]) + "\n")
def add_factory(argv: Sequence[str], dependencies: Mapping) -> CommandFactoryResult: client = dependencies["client"] reader: MetainfoIO = dependencies["metainfo_reader"] # parse arguments from clutchless.spec import add as add_command args = docopt(doc=add_command.__doc__, argv=argv) fs: Filesystem = dependencies["fs"] if not args["--delete"]: fs = DryRunFilesystem() metainfo_file_paths = collect_metainfo_paths(fs, args["<metainfo>"]) metainfo_files = {reader.from_path(path) for path in metainfo_file_paths} data_directories = get_valid_directories(fs, args["-d"]) file_locator = MultipleDirectoryFileLocator(data_directories, fs) data_reader = DefaultTorrentDataReader(fs) data_locator = CustomTorrentDataLocator(file_locator, data_reader) add_service = AddService(client) # action command: Command = AddCommand(add_service, fs, metainfo_files) if len(data_directories) > 0: find_service = FindService(data_locator) if not args["--force"]: add_service = LinkOnlyAddService(client) torrent_data: Iterable[TorrentData] = find_service.find(metainfo_files) response = input("Continue? [Y/N]:") if response.strip().lower() != "y": raise RuntimeError("User decided not to continue") command = LinkingAddCommand(add_service, fs, torrent_data) return command, args
def link_factory(argv: Sequence[str], dependencies: Mapping) -> CommandFactoryResult: reader = dependencies["metainfo_reader"] client = dependencies["client"] fs = dependencies["fs"] data_service = LinkDataService(client, reader) link_service = LinkService(reader, data_service) # parse from clutchless.spec import link as link_command link_args = docopt(doc=link_command.__doc__, argv=argv) data_dirs: Set[Path] = get_valid_directories(fs, link_args.get("<data>")) file_locator = MultipleDirectoryFileLocator(data_dirs, fs) data_reader = DefaultTorrentDataReader(fs) data_locator = CustomTorrentDataLocator(file_locator, data_reader) find_service = FindService(data_locator) if link_args.get("--list"): return ListLinkCommand(link_service), link_args return LinkCommand(link_service, find_service), link_args