{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "![alt text](https://braincircuits.centreforbrainhealth.ca/sites/default/files/braincircuits_reverse_0.png)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# OSFCLIENT\n", "\n", "![alt text](https://raw.githubusercontent.com/osfclient/osfclient/master/LOGO/osf-cli-logo-v1-small.png)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Introduction" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The [osfclient](https://github.com/osfclient/osfclient) is a Python module and a command-line program for implementing simple actions in OSF, such as uploading files and downloading projects.\n", "\n", "This notebook demonstrates the use of osfclient's command-line interface* and Python library by using an [OSF Project](https://osf.io/qf9n8/) created specifically to be used in examples here. \n", "\n", "Make sure to check out the [documentation](https://osfclient.readthedocs.io/) for osfclient.\n", "\n", "Extensive documentation for OSF is available through the [OSF Guides](https://help.osf.io/hc/en-us). For a quick introduction, check out the [OSF page](https://ubcbraincircuits.readthedocs.io/en/latest/data_sharing/open_science_framework.html) of the Brain Circuits Cluster Data Management White Paper. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Installation " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`osfclient` is no longer an active project (see this [comment](https://github.com/osfclient/osfclient/issues/169#issuecomment-524444154) from a former maintainer) so I created a fork of this repository to fix bugs and make improvements. \n", "\n", "To install my version of osfclient (which is used in this notebook), run the following command:\n", "\n", "```console\n", "pip install git+https://github.com/BrainUBC/osfclient\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Command-line\n", "\n", "---\n", "\n", "*Run all commands in Terminal or Command Prompt.*" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Help" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "This particular command can be executed in a Jupyter Notebook (run the cell below!) by adding `!`. " ] }, { "cell_type": "code", "execution_count": 80, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "usage: osf [-h] [-u USERNAME] [-p PROJECT] [-v]\n", " {clone,init,fetch,list,ls,upload,remove,rm} ...\n", "\n", "osf is a command-line program to up and download\n", "files from osf.io.\n", "\n", "These are common osf commands:\n", "\n", " init Set up a .osfcli.config file\n", " clone Copy all files from all storages of a project\n", " fetch Fetch an individual file from a project\n", " list List all files from all storages for a project\n", " upload Upload a new file to an existing project\n", " remove Remove a file from a project's storage\n", "\n", "See 'osf -h' to read about a specific command.\n", "\n", "positional arguments:\n", " {clone,init,fetch,list,ls,upload,remove,rm}\n", "\n", "optional arguments:\n", " -h, --help show this help message and exit\n", " -u USERNAME, --username USERNAME\n", " OSF username. Provide your password via OSF_PASSWORD\n", " environment variable\n", " -p PROJECT, --project PROJECT\n", " OSF project ID\n", " -v, --version show program's version number and exit\n" ] } ], "source": [ "! osf -h" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "*Note*: The OSF **project ID** is contained within the URL of the project. The project ID of the example is `qf9n8` as given by its URL, https://osf.io/qf9n8/." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ``list``" ] }, { "cell_type": "code", "execution_count": 81, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "usage: osf list [-h]\n", "\n", "list() -> new empty list\n", "list(iterable) -> new list initialized from iterable's items\n", "\n", "optional arguments:\n", " -h, --help show this help message and exit\n" ] } ], "source": [ "! osf list -h" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "\n", "The following command provides a list of files of a project:\n", "\n", "```console\n", "osf -p qf9n8 list\n", "```\n", "\n", "Notice the `-p` argument followed by the project ID. \n", "\n", "\n", "Output:\n", "\n", "```console\n", "github\\osf_addon.txt\n", "osfstorage\\osf/osf_3.txt\n", "osfstorage\\osf/osf_2.txt\n", "osfstorage\\osf/osf_1.txt\n", "osfstorage\\osf.txt\n", "osfstorage\\folder/osf_folder.txt\n", "```\n", "\n", "Note that `list` only provides files within add-ons and within the OSF Storage of the project. It does *not* list files within components." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## `init`\n" ] }, { "cell_type": "code", "execution_count": 82, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "usage: osf init [-h]\n", "\n", "Initialize or edit an existing .osfcli.config file.\n", "\n", "optional arguments:\n", " -h, --help show this help message and exit\n" ] } ], "source": [ "! osf init -h" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "\n", "The `init` command initializes a configutation file `.osfcli.config` in the current directory.\n", "\n", "```console\n", "osf init\n", "```\n", "\n", "This gives the following prompts (I included my inputs for clarity):\n", "\n", "```console\n", "Provide a username for the config gile [current username: ]:\n", "g.alejo@alumni.ubc.ca\n", "```\n", "\n", "```console\n", "Provide a project for the config file [current project: ]:\n", "qf9n8\n", "```\n", "\n", "The configuration file sets default values for username and project so you won't need to specify these arguments when you run commands. For example, the `list` command from a few cells above becomes:\n", "\n", "```console\n", "osf list\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## `clone`" ] }, { "cell_type": "code", "execution_count": 83, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "usage: osf clone [-h] [-U] [output]\n", "\n", "Copy all files from all storages of a project.\n", "\n", " The output directory defaults to the current directory.\n", "\n", " If the project is private you need to specify a username.\n", "\n", " If args.update is True, overwrite any existing local files only if local and\n", " remote files differ.\n", " \n", "\n", "positional arguments:\n", " output Write files to this directory\n", "\n", "optional arguments:\n", " -h, --help show this help message and exit\n", " -U, --update Overwrite only if local and remote files differ\n" ] } ], "source": [ "! osf clone -h" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "\n", "This is the download command - it creates a copy of a project or component. \n", "\n", "```console\n", "osf clone\n", "```\n", "\n", "If you've already created a configuration file, the command above will clone the project you've specified in that file. To clone other projects/components, use the same `-p` argument as before.\n", "\n", "```console\n", "osf -p q5mt7 clone \\Users\\User\\\n", "```\n", "\n", "This command creates a copy of `component` (component ID = `q5mt7`). A folder named after the storage type `osfstorage` appears within the specified directory containing a single file `osf_component.txt`. \n", "\n", "If an `output` argument is not specified, a folder named after the project or component ID is created in the working directory with storages as subfolders.\n", "\n", "A couple of things to note:\n", "- File hierarchy is maintained upon download.\n", "- **Components are not cloned along with the project** and therefore must be cloned separately." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## `upload`" ] }, { "cell_type": "code", "execution_count": 84, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "usage: osf upload [-h] [-f] [-U] [-r] source destination\n", "\n", "Upload a new file to an existing project.\n", "\n", " The first part of the remote path is interpreted as the name of the\n", " storage provider. If there is no match the default (osfstorage) is\n", " used.\n", "\n", " If the project is private you need to specify a username.\n", "\n", " To upload a whole directory (and all its sub-directories) use the `-r`\n", " command-line option. If your source directory name ends in a / then\n", " files will be created directly in the remote directory. If it does not\n", " end in a slash an extra sub-directory with the name of the local directory\n", " will be created.\n", "\n", " To place contents of local directory `foo` in remote directory `bar/foo`:\n", " $ osf upload -r foo bar\n", " To place contents of local directory `foo` in remote directory `bar`:\n", " $ osf upload -r foo/ bar\n", " \n", "\n", "positional arguments:\n", " source Local file\n", " destination Remote file path\n", "\n", "optional arguments:\n", " -h, --help show this help message and exit\n", " -f, --force Force overwriting of remote file\n", " -U, --update Overwrite only if local and remote files differ\n", " -r, --recursive Recursively upload entire directories\n" ] } ], "source": [ "! osf upload -h" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "\n", "### To upload a single file into OSF Storage:\n", "\n", "The command below uploads a text file called `test.txt` (`source` argument) from my current directory into the OSF Storage of the project and renames it as `osf.txt` (`destination` argument).\n", "\n", "```console\n", "osf -p qf9n8 -u g.alejo@alumni.ubc.ca upload test.txt osf.txt\n", "```\n", "\n", "Note that this is followed by the prompt: `Please input your password:`." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### To upload a single file into a pre-existing or non-existent folder within OSF Storage:\n", "\n", "The command below uploads the test file as `osf_folder.txt` into a new folder called `folder` within OSF Storage. \n", "\n", "```console\n", "osf -p qf9n8 -u g.alejo@alumni.ubc.ca upload test.txt folder\\osf_folder.txt \n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### To upload a single file into a storage add-on:\n", "\n", "This command uploads the test file into the connected Github repository as `osf_addon.txt`.\n", "\n", "```console\n", "osf -p qf9n8 -u g.alejo@alumni.ubc.ca upload test.txt github\\osf_addon.txt\n", "```\n", "\n", "Note that the only add-ons accessible through osfclient are `github`, `figshare`, and `googledrive`." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### To upload an entire directory:\n", "\n", "Use the recursive argument, `-r`.\n", "\n", "This command uploads the contents of the local folder `osf` (`osf_1.txt`, `osf_2.txt`, `osf_3.txt`) into OSF Storage.\n", "\n", "```console\n", "osf -p qf9n8 -u g.alejo@alumni.ubc.ca upload -r osf\\ \\\n", "```\n", "\n", "The ouput of the `list` command will include:\n", "\n", "```\n", "osfstorage\\osf_1.txt\n", "osfstorage\\osf_2.txt\n", "osfstorage\\osf_3.txt\n", "```\n", "\n", "To create a folder with the name of the local directory, remove the slash in the `source` argument.\n", "\n", "```console\n", "osf -p qf9n8 -u g.alejo@alumni.ubc.ca upload -r osf \\\n", "```\n", "\n", "In this case, the `list` command will output:\n", "\n", "```\n", "osfstorage\\osf/osf_3.txt\n", "osfstorage\\osf/osf_2.txt\n", "osfstorage\\osf/osf_1.txt\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## `fetch`" ] }, { "cell_type": "code", "execution_count": 85, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "usage: osf fetch [-h] [-f] [-U] remote [local]\n", "\n", "Fetch an individual file from a project.\n", "\n", " The first part of the remote path is interpreted as the name of the\n", " storage provider. If there is no match the default (osfstorage) is\n", " used.\n", "\n", " The local path defaults to the name of the remote file.\n", "\n", " If the project is private you need to specify a username.\n", "\n", " If args.force is True, write local file even if that file already exists.\n", " If args.force is False but args.update is True, overwrite an existing local\n", " file only if local and remote files differ.\n", " \n", "\n", "positional arguments:\n", " remote Remote path\n", " local Local path\n", "\n", "optional arguments:\n", " -h, --help show this help message and exit\n", " -f, --force Force overwriting of local file\n", " -U, --update Overwrite only if local and remote files differ\n" ] } ], "source": [ "! osf fetch -h" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "\n", "To download a single file, use `fetch`.\n", "\n", "```console\n", "osf -p qf9n8 fetch \\osf.txt test.txt\n", "```\n", "\n", "Here, we downloaded `osf.txt` into the working directory as `test.txt`.\n", "\n", "Note that the `remote` argument must be a *file path*. In this case, the file is stored in the default storage (osfstorage) therefore a slash before the file name is sufficient. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## `remove`" ] }, { "cell_type": "code", "execution_count": 86, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "usage: osf remove [-h] target\n", "\n", "Remove a file from the project's storage.\n", "\n", " The first part of the remote path is interpreted as the name of the\n", " storage provider. If there is no match the default (osfstorage) is\n", " used.\n", " \n", "\n", "positional arguments:\n", " target Remote file path\n", "\n", "optional arguments:\n", " -h, --help show this help message and exit\n" ] } ], "source": [ "! osf remove -h" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "\n", "The `remove` command deletes files.\n", "\n", "To delete `osf.txt` which was uploaded earlier, use:\n", "\n", "```console\n", "osf -p qf9n8 -u g.alejo@alumni.ubc.ca remove \\osf.txt\n", "```\n", "\n", "The `target` argument must be a path. Like upload, a password is required for this command. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Python Library\n", "\n", "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The examples from above are recreated using the equivalent function to each command. Click on the headers to jump back to the corresponding section under Command-line." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import osfclient\n", "from osfclient import cli\n", "import os" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Note**: `cli` contains the upload, clone, etc. functions ([source code](https://osfclient.readthedocs.io/en/latest/_modules/osfclient/cli.html)). It is imported separately because otherwise we don't have access to it." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Basic features" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "osf = osfclient.OSF()" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "proj = osf.project('qf9n8')" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'osfclient'" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "proj.title" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'A dummy project created to demonstrate the use of osfclient, a command-line program and Python library for uploading and downloading files to and from OSF.'" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "proj.description" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Set password as an environment variable (optional)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "os.environ[\"OSF_PASSWORD\"] = \"\" # insert your password as a string " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If the password is not set as an environment variable, a password prompt will appear every time `upload` and `remove` are used (for public projects)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Define a class for command arguments" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [], "source": [ "class args:\n", "\n", " def __init__(self, project, username=None, update=False, force=False, destination=None, source=None, recursive=False, target=None, output=None, remote=None, local=None):\n", " self.project = project\n", " self.username = username\n", " self.update = update # applies to upload, clone, and fetch\n", " self.force = force # applies to fetch and upload \n", " # upload arguments:\n", " self.destination = destination\n", " self.source = source\n", " self.recursive = recursive\n", " # remove argument:\n", " self.target = target\n", " # clone argument:\n", " self.output = output\n", " # fetch arguments:\n", " self.remote = remote\n", " self.local = local " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's initialize the arguments. We can change them later as needed." ] }, { "cell_type": "code", "execution_count": 59, "metadata": {}, "outputs": [], "source": [ "arguments = args(\n", " username='g.alejo@alumni.ubc.ca',\n", " project='qf9n8',\n", " # upload arguments:\n", " destination='', \n", " source='',\n", " # remove argument:\n", " target='',\n", " # clone argument:\n", " output='',\n", " # fetch arguments:\n", " remote='',\n", " local=''\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## `list_` " ] }, { "cell_type": "code", "execution_count": 75, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "github\\osf_addon.txt\n", "osfstorage\\osf/osf_3.txt\n", "osfstorage\\osf/osf_2.txt\n", "osfstorage\\osf/osf_1.txt\n", "osfstorage\\osf.txt\n", "osfstorage\\folder/osf_folder.txt\n" ] } ], "source": [ "cli.list_(arguments)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This project has one component which `list_` does not show. Set the `project` argument equal to the component ID to see its contents." ] }, { "cell_type": "code", "execution_count": 57, "metadata": {}, "outputs": [], "source": [ "arguments.project = 'q5mt7'" ] }, { "cell_type": "code", "execution_count": 58, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "osfstorage\\osf_component.txt\n" ] } ], "source": [ "cli.list_(arguments)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## `init`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can pass any string to `init` but it will not accept no arguments. " ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "ename": "TypeError", "evalue": "init() missing 1 required positional argument: 'args'", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)", "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mcli\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0minit\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[1;31mTypeError\u001b[0m: init() missing 1 required positional argument: 'args'" ] } ], "source": [ "cli.init()" ] }, { "cell_type": "code", "execution_count": 54, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Provide a username for the config file [current username: ]:\n", "g.alejo@alumni.ubc.ca\n", "Provide a project for the config file [current project: ]:\n", "qf9n8\n" ] } ], "source": [ "cli.init('blah')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## `upload`" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "arguments.project = 'qf9n8'" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### To upload a single file into OSF Storage:" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [], "source": [ "arguments.source = '\\\\Users\\\\User\\\\osf.txt'" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [], "source": [ "arguments.destination = '' # leave as as an empty string to maintain file name " ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [], "source": [ "cli.upload(arguments)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### To upload a single file into a pre-existing or non-existent folder within OSF Storage:" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [], "source": [ "arguments.source = '\\\\Users\\\\User\\\\test.txt'" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [], "source": [ "arguments.destination = 'folder\\\\osf_folder.txt' # indicate the name of the folder as the first part of the path" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [], "source": [ "cli.upload(arguments)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### To upload a single file into a storage add-on:" ] }, { "cell_type": "code", "execution_count": 73, "metadata": {}, "outputs": [], "source": [ "arguments.source = '\\\\Users\\\\User\\\\test.txt'" ] }, { "cell_type": "code", "execution_count": 72, "metadata": {}, "outputs": [], "source": [ "arguments.destination = 'github\\\\osf_addon.txt' # specify the add-on as the first part of the path " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "*Note*: If uploading to an add-on and the file name is to be maintained, make sure that the `destination` argument is a **path**! (i.e., `\"github\\\\\"`)" ] }, { "cell_type": "code", "execution_count": 74, "metadata": {}, "outputs": [], "source": [ "cli.upload(arguments)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "*Notes*: \n", "- The only accessible add-ons are `github`, `figshare`, and `googledrive`.\n", "- If the file name is unspecified in the `destination` argument, the local file is uploaded with its original name." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### To upload an entire directory:" ] }, { "cell_type": "code", "execution_count": 64, "metadata": {}, "outputs": [], "source": [ "arguments.recursive = True" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To upload files from a directory directly into OSF Storage (or other add-on), the path must end with backslashes (or a forward slash for Mac OS):" ] }, { "cell_type": "code", "execution_count": 66, "metadata": {}, "outputs": [], "source": [ "arguments.source = \"\\\\Users\\\\User\\\\osf\\\\\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To create a folder with the name of the local directory, do not end the path with slashes." ] }, { "cell_type": "code", "execution_count": 62, "metadata": {}, "outputs": [], "source": [ "arguments.source = \"\\\\Users\\\\User\\\\osf\"" ] }, { "cell_type": "code", "execution_count": 65, "metadata": {}, "outputs": [], "source": [ "arguments.destination = '' # an empty string indicates OSF Storage; can also be a storage add-on" ] }, { "cell_type": "code", "execution_count": 67, "metadata": {}, "outputs": [], "source": [ "cli.upload(arguments)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "*Reminder*: To upload a file into a component, set the project argument equal to the component ID, i.e. `arguments.project = `." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## `clone`" ] }, { "cell_type": "code", "execution_count": 87, "metadata": {}, "outputs": [], "source": [ "arguments.project = 'q5mt7' # component ID" ] }, { "cell_type": "code", "execution_count": 88, "metadata": {}, "outputs": [], "source": [ "arguments.output = '\\\\Users\\\\User'" ] }, { "cell_type": "code", "execution_count": 89, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "0files [00:00, ?files/s]\n", " 0%| | 0.00/5.20k [00:00