We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Very long, CPU-intensive process after asking to import selected Khan Academy resources
### Observed behavior

Need more info on this, but this is the best I can produce right now.. observe the 566m of CPU usage:

```
top - 01:39:58 up 2 days, 11:30,  1 user,  load average: 2.10, 2.17, 2.17
Tasks: 287 total,   1 running, 286 sleeping,   0 stopped,   0 zombie
%Cpu(s): 45.6 us, 12.9 sy,  0.0 ni, 41.5 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  8054696 total,   904492 free,  5504828 used,  1645376 buff/cache
KiB Swap: 16381948 total, 14482384 free,  1899564 used.  1499508 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                                                            
15123 kolibri   20   0 3474360 1.112g  10440 S 201.0 14.5 566:35.82 kolibri                         
```

### Steps to reproduce

Not sure, but I have asked to download a select sub-part of the KA resources, and my laptop is stuck for hours.


### Context

Kolibri 0.9.0, debian installation source, Ubuntu 16.04


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `kolibri/content/management/commands/importcontent.py`
Content:
```
1 import logging as logger
2 import os
3 
4 from django.conf import settings
5 from django.core.management.base import CommandError
6 from requests.exceptions import HTTPError
7 
8 from ...utils import annotation
9 from ...utils import import_export_content
10 from ...utils import paths
11 from ...utils import transfer
12 from kolibri.tasks.management.commands.base import AsyncCommand
13 
14 # constants to specify the transfer method to be used
15 DOWNLOAD_METHOD = "download"
16 COPY_METHOD = "copy"
17 
18 logging = logger.getLogger(__name__)
19 
20 
21 class Command(AsyncCommand):
22 
23     def add_arguments(self, parser):
24         # let's save the parser in case we need to print a help statement
25         self._parser = parser
26 
27         # we want two groups of arguments. One group is when the
28         # 'importcontent disk' command is given, where we'll expect a file
29         # directory to be given. Another is the 'importcontent network'
30         # command to be given, where we'll expect a channel.
31 
32         # However, some optional arguments apply to both groups. Add them here!
33         node_ids_help_text = """
34         Specify one or more node IDs to import. Only the files associated to those node IDs will be imported.
35 
36         e.g.
37 
38         kolibri manage importcontent --node_ids <id1>,<id2>, [<ids>,...] {network, disk} <channel id>
39         """
40         parser.add_argument(
41             "--node_ids", "-n",
42             # Split the comma separated string we get, into a list of strings
43             type=lambda x: x.split(","),
44             default=[],
45             required=False,
46             dest="node_ids",
47             help=node_ids_help_text,
48         )
49 
50         exclude_node_ids_help_text = """
51         Specify one or more node IDs to exclude. Files associated to those node IDs will be not be imported.
52 
53         e.g.
54 
55         kolibri manage importcontent --exclude_node_ids <id1>,<id2>, [<ids>,...] {network, disk} <channel id>
56         """
57         parser.add_argument(
58             "--exclude_node_ids",
59             # Split the comma separated string we get, into a list of string
60             type=lambda x: x.split(","),
61             default=[],
62             required=False,
63             dest="exclude_node_ids",
64             help=exclude_node_ids_help_text
65         )
66 
67         parser.add_argument(
68             "--include-unrenderable-content",
69             action='store_false',
70             default=True,
71             dest="renderable_only",
72             help="Import all content, not just that which this Kolibri instance can render"
73         )
74 
75         # to implement these two groups of commands and their corresponding
76         # arguments, we'll need argparse.subparsers.
77         subparsers = parser.add_subparsers(dest='command', help="The following subcommands are available.")
78 
79         # the network command has a channel id required positional argument,
80         # and some optional content_id arguments.
81 
82         # TODO: implement a --content-domain parameter, for optionally
83         # specifying the domain for the curation server.
84 
85         # Note: cmd should be the management command instance, as though the
86         # interface for adding arguments is argparse, Django overrides the
87         # parser object with its own thing, hence why we need to add cmd. See
88         # http://stackoverflow.com/questions/36706220/is-it-possible-to-create-subparsers-in-a-django-management-command
89         network_subparser = subparsers.add_parser(
90             name='network',
91             cmd=self,
92             help="Download the given channel through the network.",
93         )
94         network_subparser.add_argument('channel_id', type=str)
95 
96         default_studio_url = settings.CENTRAL_CONTENT_DOWNLOAD_BASE_URL
97         network_subparser.add_argument(
98             "--baseurl",
99             type=str,
100             default=default_studio_url,
101             dest="baseurl",
102         )
103 
104         disk_subparser = subparsers.add_parser(
105             name='disk',
106             cmd=self,
107             help='Copy the content from the given folder.'
108         )
109         disk_subparser.add_argument('channel_id', type=str)
110         disk_subparser.add_argument('directory', type=str)
111 
112     def download_content(self, channel_id, node_ids=None, exclude_node_ids=None, baseurl=None, renderable_only=True):
113         self._transfer(DOWNLOAD_METHOD, channel_id, node_ids=node_ids, exclude_node_ids=exclude_node_ids, baseurl=baseurl, renderable_only=renderable_only)
114 
115     def copy_content(self, channel_id, path, node_ids=None, exclude_node_ids=None, renderable_only=True):
116         self._transfer(COPY_METHOD, channel_id, path=path, node_ids=node_ids, exclude_node_ids=exclude_node_ids, renderable_only=renderable_only)
117 
118     def _transfer(self, method, channel_id, path=None, node_ids=None, exclude_node_ids=None, baseurl=None, renderable_only=True):  # noqa: max-complexity=16
119 
120         files_to_download, total_bytes_to_transfer = import_export_content.get_files_to_transfer(
121             channel_id, node_ids, exclude_node_ids, False, renderable_only=renderable_only)
122 
123         number_of_skipped_files = 0
124         file_checksums_to_annotate = []
125 
126         with self.start_progress(total=total_bytes_to_transfer) as overall_progress_update:
127 
128             for f in files_to_download:
129 
130                 if self.is_cancelled():
131                     break
132 
133                 filename = f.get_filename()
134                 dest = paths.get_content_storage_file_path(filename)
135 
136                 # if the file already exists, add its size to our overall progress, and skip
137                 if os.path.isfile(dest) and os.path.getsize(dest) == f.file_size:
138                     overall_progress_update(f.file_size)
139                     file_checksums_to_annotate.append(f.id)
140                     continue
141 
142                 # determine where we're downloading/copying from, and create appropriate transfer object
143                 if method == DOWNLOAD_METHOD:
144                     url = paths.get_content_storage_remote_url(filename, baseurl=baseurl)
145                     filetransfer = transfer.FileDownload(url, dest)
146                 elif method == COPY_METHOD:
147                     srcpath = paths.get_content_storage_file_path(filename, datafolder=path)
148                     filetransfer = transfer.FileCopy(srcpath, dest)
149 
150                 try:
151 
152                     with filetransfer:
153 
154                         with self.start_progress(total=filetransfer.total_size) as file_dl_progress_update:
155 
156                             for chunk in filetransfer:
157                                 if self.is_cancelled():
158                                     filetransfer.cancel()
159                                     break
160                                 length = len(chunk)
161                                 overall_progress_update(length)
162                                 file_dl_progress_update(length)
163 
164                     file_checksums_to_annotate.append(f.id)
165 
166                 except HTTPError:
167                     overall_progress_update(f.file_size)
168 
169                 except OSError:
170                     number_of_skipped_files += 1
171                     overall_progress_update(f.file_size)
172 
173             annotation.set_availability(channel_id, file_checksums_to_annotate)
174 
175             if number_of_skipped_files > 0:
176                 logging.warning(
177                     "{} files are skipped, because they are not found in the given external drive.".format(
178                         number_of_skipped_files))
179 
180             if self.is_cancelled():
181                 self.cancel()
182 
183     def handle_async(self, *args, **options):
184         if options['command'] == 'network':
185             self.download_content(options["channel_id"],
186                                   node_ids=options["node_ids"],
187                                   exclude_node_ids=options['exclude_node_ids'],
188                                   baseurl=options["baseurl"],
189                                   renderable_only=options["renderable_only"])
190         elif options['command'] == 'disk':
191             self.copy_content(options["channel_id"],
192                               options["directory"],
193                               node_ids=options["node_ids"],
194                               exclude_node_ids=options["exclude_node_ids"],
195                               renderable_only=options["renderable_only"])
196         else:
197             self._parser.print_help()
198             raise CommandError("Please give a valid subcommand. You gave: {}".format(options["command"]))
199
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/kolibri/content/management/commands/importcontent.py b/kolibri/content/management/commands/importcontent.py
--- a/kolibri/content/management/commands/importcontent.py
+++ b/kolibri/content/management/commands/importcontent.py
@@ -67,7 +67,7 @@
         parser.add_argument(
             "--include-unrenderable-content",
             action='store_false',
-            default=True,
+            default=False,
             dest="renderable_only",
             help="Import all content, not just that which this Kolibri instance can render"
         )

{"golden_diff": "diff --git a/kolibri/content/management/commands/importcontent.py b/kolibri/content/management/commands/importcontent.py\n--- a/kolibri/content/management/commands/importcontent.py\n+++ b/kolibri/content/management/commands/importcontent.py\n@@ -67,7 +67,7 @@\n         parser.add_argument(\n             \"--include-unrenderable-content\",\n             action='store_false',\n-            default=True,\n+            default=False,\n             dest=\"renderable_only\",\n             help=\"Import all content, not just that which this Kolibri instance can render\"\n         )\n", "issue": "Very long, CPU-intensive process after asking to import selected Khan Academy resources\n### Observed behavior\r\n\r\nNeed more info on this, but this is the best I can produce right now.. observe the 566m of CPU usage:\r\n\r\n```\r\ntop - 01:39:58 up 2 days, 11:30,  1 user,  load average: 2.10, 2.17, 2.17\r\nTasks: 287 total,   1 running, 286 sleeping,   0 stopped,   0 zombie\r\n%Cpu(s): 45.6 us, 12.9 sy,  0.0 ni, 41.5 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st\r\nKiB Mem :  8054696 total,   904492 free,  5504828 used,  1645376 buff/cache\r\nKiB Swap: 16381948 total, 14482384 free,  1899564 used.  1499508 avail Mem \r\n\r\n  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                                                            \r\n15123 kolibri   20   0 3474360 1.112g  10440 S 201.0 14.5 566:35.82 kolibri                         \r\n```\r\n\r\n### Steps to reproduce\r\n\r\nNot sure, but I have asked to download a select sub-part of the KA resources, and my laptop is stuck for hours.\r\n\r\n\r\n### Context\r\n\r\nKolibri 0.9.0, debian installation source, Ubuntu 16.04\r\n\n", "before_files": [{"content": "import logging as logger\nimport os\n\nfrom django.conf import settings\nfrom django.core.management.base import CommandError\nfrom requests.exceptions import HTTPError\n\nfrom ...utils import annotation\nfrom ...utils import import_export_content\nfrom ...utils import paths\nfrom ...utils import transfer\nfrom kolibri.tasks.management.commands.base import AsyncCommand\n\n# constants to specify the transfer method to be used\nDOWNLOAD_METHOD = \"download\"\nCOPY_METHOD = \"copy\"\n\nlogging = logger.getLogger(__name__)\n\n\nclass Command(AsyncCommand):\n\n    def add_arguments(self, parser):\n        # let's save the parser in case we need to print a help statement\n        self._parser = parser\n\n        # we want two groups of arguments. One group is when the\n        # 'importcontent disk' command is given, where we'll expect a file\n        # directory to be given. Another is the 'importcontent network'\n        # command to be given, where we'll expect a channel.\n\n        # However, some optional arguments apply to both groups. Add them here!\n        node_ids_help_text = \"\"\"\n        Specify one or more node IDs to import. Only the files associated to those node IDs will be imported.\n\n        e.g.\n\n        kolibri manage importcontent --node_ids <id1>,<id2>, [<ids>,...] {network, disk} <channel id>\n        \"\"\"\n        parser.add_argument(\n            \"--node_ids\", \"-n\",\n            # Split the comma separated string we get, into a list of strings\n            type=lambda x: x.split(\",\"),\n            default=[],\n            required=False,\n            dest=\"node_ids\",\n            help=node_ids_help_text,\n        )\n\n        exclude_node_ids_help_text = \"\"\"\n        Specify one or more node IDs to exclude. Files associated to those node IDs will be not be imported.\n\n        e.g.\n\n        kolibri manage importcontent --exclude_node_ids <id1>,<id2>, [<ids>,...] {network, disk} <channel id>\n        \"\"\"\n        parser.add_argument(\n            \"--exclude_node_ids\",\n            # Split the comma separated string we get, into a list of string\n            type=lambda x: x.split(\",\"),\n            default=[],\n            required=False,\n            dest=\"exclude_node_ids\",\n            help=exclude_node_ids_help_text\n        )\n\n        parser.add_argument(\n            \"--include-unrenderable-content\",\n            action='store_false',\n            default=True,\n            dest=\"renderable_only\",\n            help=\"Import all content, not just that which this Kolibri instance can render\"\n        )\n\n        # to implement these two groups of commands and their corresponding\n        # arguments, we'll need argparse.subparsers.\n        subparsers = parser.add_subparsers(dest='command', help=\"The following subcommands are available.\")\n\n        # the network command has a channel id required positional argument,\n        # and some optional content_id arguments.\n\n        # TODO: implement a --content-domain parameter, for optionally\n        # specifying the domain for the curation server.\n\n        # Note: cmd should be the management command instance, as though the\n        # interface for adding arguments is argparse, Django overrides the\n        # parser object with its own thing, hence why we need to add cmd. See\n        # http://stackoverflow.com/questions/36706220/is-it-possible-to-create-subparsers-in-a-django-management-command\n        network_subparser = subparsers.add_parser(\n            name='network',\n            cmd=self,\n            help=\"Download the given channel through the network.\",\n        )\n        network_subparser.add_argument('channel_id', type=str)\n\n        default_studio_url = settings.CENTRAL_CONTENT_DOWNLOAD_BASE_URL\n        network_subparser.add_argument(\n            \"--baseurl\",\n            type=str,\n            default=default_studio_url,\n            dest=\"baseurl\",\n        )\n\n        disk_subparser = subparsers.add_parser(\n            name='disk',\n            cmd=self,\n            help='Copy the content from the given folder.'\n        )\n        disk_subparser.add_argument('channel_id', type=str)\n        disk_subparser.add_argument('directory', type=str)\n\n    def download_content(self, channel_id, node_ids=None, exclude_node_ids=None, baseurl=None, renderable_only=True):\n        self._transfer(DOWNLOAD_METHOD, channel_id, node_ids=node_ids, exclude_node_ids=exclude_node_ids, baseurl=baseurl, renderable_only=renderable_only)\n\n    def copy_content(self, channel_id, path, node_ids=None, exclude_node_ids=None, renderable_only=True):\n        self._transfer(COPY_METHOD, channel_id, path=path, node_ids=node_ids, exclude_node_ids=exclude_node_ids, renderable_only=renderable_only)\n\n    def _transfer(self, method, channel_id, path=None, node_ids=None, exclude_node_ids=None, baseurl=None, renderable_only=True):  # noqa: max-complexity=16\n\n        files_to_download, total_bytes_to_transfer = import_export_content.get_files_to_transfer(\n            channel_id, node_ids, exclude_node_ids, False, renderable_only=renderable_only)\n\n        number_of_skipped_files = 0\n        file_checksums_to_annotate = []\n\n        with self.start_progress(total=total_bytes_to_transfer) as overall_progress_update:\n\n            for f in files_to_download:\n\n                if self.is_cancelled():\n                    break\n\n                filename = f.get_filename()\n                dest = paths.get_content_storage_file_path(filename)\n\n                # if the file already exists, add its size to our overall progress, and skip\n                if os.path.isfile(dest) and os.path.getsize(dest) == f.file_size:\n                    overall_progress_update(f.file_size)\n                    file_checksums_to_annotate.append(f.id)\n                    continue\n\n                # determine where we're downloading/copying from, and create appropriate transfer object\n                if method == DOWNLOAD_METHOD:\n                    url = paths.get_content_storage_remote_url(filename, baseurl=baseurl)\n                    filetransfer = transfer.FileDownload(url, dest)\n                elif method == COPY_METHOD:\n                    srcpath = paths.get_content_storage_file_path(filename, datafolder=path)\n                    filetransfer = transfer.FileCopy(srcpath, dest)\n\n                try:\n\n                    with filetransfer:\n\n                        with self.start_progress(total=filetransfer.total_size) as file_dl_progress_update:\n\n                            for chunk in filetransfer:\n                                if self.is_cancelled():\n                                    filetransfer.cancel()\n                                    break\n                                length = len(chunk)\n                                overall_progress_update(length)\n                                file_dl_progress_update(length)\n\n                    file_checksums_to_annotate.append(f.id)\n\n                except HTTPError:\n                    overall_progress_update(f.file_size)\n\n                except OSError:\n                    number_of_skipped_files += 1\n                    overall_progress_update(f.file_size)\n\n            annotation.set_availability(channel_id, file_checksums_to_annotate)\n\n            if number_of_skipped_files > 0:\n                logging.warning(\n                    \"{} files are skipped, because they are not found in the given external drive.\".format(\n                        number_of_skipped_files))\n\n            if self.is_cancelled():\n                self.cancel()\n\n    def handle_async(self, *args, **options):\n        if options['command'] == 'network':\n            self.download_content(options[\"channel_id\"],\n                                  node_ids=options[\"node_ids\"],\n                                  exclude_node_ids=options['exclude_node_ids'],\n                                  baseurl=options[\"baseurl\"],\n                                  renderable_only=options[\"renderable_only\"])\n        elif options['command'] == 'disk':\n            self.copy_content(options[\"channel_id\"],\n                              options[\"directory\"],\n                              node_ids=options[\"node_ids\"],\n                              exclude_node_ids=options[\"exclude_node_ids\"],\n                              renderable_only=options[\"renderable_only\"])\n        else:\n            self._parser.print_help()\n            raise CommandError(\"Please give a valid subcommand. You gave: {}\".format(options[\"command\"]))\n", "path": "kolibri/content/management/commands/importcontent.py"}], "after_files": [{"content": "import logging as logger\nimport os\n\nfrom django.conf import settings\nfrom django.core.management.base import CommandError\nfrom requests.exceptions import HTTPError\n\nfrom ...utils import annotation\nfrom ...utils import import_export_content\nfrom ...utils import paths\nfrom ...utils import transfer\nfrom kolibri.tasks.management.commands.base import AsyncCommand\n\n# constants to specify the transfer method to be used\nDOWNLOAD_METHOD = \"download\"\nCOPY_METHOD = \"copy\"\n\nlogging = logger.getLogger(__name__)\n\n\nclass Command(AsyncCommand):\n\n    def add_arguments(self, parser):\n        # let's save the parser in case we need to print a help statement\n        self._parser = parser\n\n        # we want two groups of arguments. One group is when the\n        # 'importcontent disk' command is given, where we'll expect a file\n        # directory to be given. Another is the 'importcontent network'\n        # command to be given, where we'll expect a channel.\n\n        # However, some optional arguments apply to both groups. Add them here!\n        node_ids_help_text = \"\"\"\n        Specify one or more node IDs to import. Only the files associated to those node IDs will be imported.\n\n        e.g.\n\n        kolibri manage importcontent --node_ids <id1>,<id2>, [<ids>,...] {network, disk} <channel id>\n        \"\"\"\n        parser.add_argument(\n            \"--node_ids\", \"-n\",\n            # Split the comma separated string we get, into a list of strings\n            type=lambda x: x.split(\",\"),\n            default=[],\n            required=False,\n            dest=\"node_ids\",\n            help=node_ids_help_text,\n        )\n\n        exclude_node_ids_help_text = \"\"\"\n        Specify one or more node IDs to exclude. Files associated to those node IDs will be not be imported.\n\n        e.g.\n\n        kolibri manage importcontent --exclude_node_ids <id1>,<id2>, [<ids>,...] {network, disk} <channel id>\n        \"\"\"\n        parser.add_argument(\n            \"--exclude_node_ids\",\n            # Split the comma separated string we get, into a list of string\n            type=lambda x: x.split(\",\"),\n            default=[],\n            required=False,\n            dest=\"exclude_node_ids\",\n            help=exclude_node_ids_help_text\n        )\n\n        parser.add_argument(\n            \"--include-unrenderable-content\",\n            action='store_false',\n            default=False,\n            dest=\"renderable_only\",\n            help=\"Import all content, not just that which this Kolibri instance can render\"\n        )\n\n        # to implement these two groups of commands and their corresponding\n        # arguments, we'll need argparse.subparsers.\n        subparsers = parser.add_subparsers(dest='command', help=\"The following subcommands are available.\")\n\n        # the network command has a channel id required positional argument,\n        # and some optional content_id arguments.\n\n        # TODO: implement a --content-domain parameter, for optionally\n        # specifying the domain for the curation server.\n\n        # Note: cmd should be the management command instance, as though the\n        # interface for adding arguments is argparse, Django overrides the\n        # parser object with its own thing, hence why we need to add cmd. See\n        # http://stackoverflow.com/questions/36706220/is-it-possible-to-create-subparsers-in-a-django-management-command\n        network_subparser = subparsers.add_parser(\n            name='network',\n            cmd=self,\n            help=\"Download the given channel through the network.\",\n        )\n        network_subparser.add_argument('channel_id', type=str)\n\n        default_studio_url = settings.CENTRAL_CONTENT_DOWNLOAD_BASE_URL\n        network_subparser.add_argument(\n            \"--baseurl\",\n            type=str,\n            default=default_studio_url,\n            dest=\"baseurl\",\n        )\n\n        disk_subparser = subparsers.add_parser(\n            name='disk',\n            cmd=self,\n            help='Copy the content from the given folder.'\n        )\n        disk_subparser.add_argument('channel_id', type=str)\n        disk_subparser.add_argument('directory', type=str)\n\n    def download_content(self, channel_id, node_ids=None, exclude_node_ids=None, baseurl=None, renderable_only=True):\n        self._transfer(DOWNLOAD_METHOD, channel_id, node_ids=node_ids, exclude_node_ids=exclude_node_ids, baseurl=baseurl, renderable_only=renderable_only)\n\n    def copy_content(self, channel_id, path, node_ids=None, exclude_node_ids=None, renderable_only=True):\n        self._transfer(COPY_METHOD, channel_id, path=path, node_ids=node_ids, exclude_node_ids=exclude_node_ids, renderable_only=renderable_only)\n\n    def _transfer(self, method, channel_id, path=None, node_ids=None, exclude_node_ids=None, baseurl=None, renderable_only=True):  # noqa: max-complexity=16\n\n        files_to_download, total_bytes_to_transfer = import_export_content.get_files_to_transfer(\n            channel_id, node_ids, exclude_node_ids, False, renderable_only=renderable_only)\n\n        number_of_skipped_files = 0\n        file_checksums_to_annotate = []\n\n        with self.start_progress(total=total_bytes_to_transfer) as overall_progress_update:\n\n            for f in files_to_download:\n\n                if self.is_cancelled():\n                    break\n\n                filename = f.get_filename()\n                dest = paths.get_content_storage_file_path(filename)\n\n                # if the file already exists, add its size to our overall progress, and skip\n                if os.path.isfile(dest) and os.path.getsize(dest) == f.file_size:\n                    overall_progress_update(f.file_size)\n                    file_checksums_to_annotate.append(f.id)\n                    continue\n\n                # determine where we're downloading/copying from, and create appropriate transfer object\n                if method == DOWNLOAD_METHOD:\n                    url = paths.get_content_storage_remote_url(filename, baseurl=baseurl)\n                    filetransfer = transfer.FileDownload(url, dest)\n                elif method == COPY_METHOD:\n                    srcpath = paths.get_content_storage_file_path(filename, datafolder=path)\n                    filetransfer = transfer.FileCopy(srcpath, dest)\n\n                try:\n\n                    with filetransfer:\n\n                        with self.start_progress(total=filetransfer.total_size) as file_dl_progress_update:\n\n                            for chunk in filetransfer:\n                                if self.is_cancelled():\n                                    filetransfer.cancel()\n                                    break\n                                length = len(chunk)\n                                overall_progress_update(length)\n                                file_dl_progress_update(length)\n\n                    file_checksums_to_annotate.append(f.id)\n\n                except HTTPError:\n                    overall_progress_update(f.file_size)\n\n                except OSError:\n                    number_of_skipped_files += 1\n                    overall_progress_update(f.file_size)\n\n            annotation.set_availability(channel_id, file_checksums_to_annotate)\n\n            if number_of_skipped_files > 0:\n                logging.warning(\n                    \"{} files are skipped, because they are not found in the given external drive.\".format(\n                        number_of_skipped_files))\n\n            if self.is_cancelled():\n                self.cancel()\n\n    def handle_async(self, *args, **options):\n        if options['command'] == 'network':\n            self.download_content(options[\"channel_id\"],\n                                  node_ids=options[\"node_ids\"],\n                                  exclude_node_ids=options['exclude_node_ids'],\n                                  baseurl=options[\"baseurl\"],\n                                  renderable_only=options[\"renderable_only\"])\n        elif options['command'] == 'disk':\n            self.copy_content(options[\"channel_id\"],\n                              options[\"directory\"],\n                              node_ids=options[\"node_ids\"],\n                              exclude_node_ids=options[\"exclude_node_ids\"],\n                              renderable_only=options[\"renderable_only\"])\n        else:\n            self._parser.print_help()\n            raise CommandError(\"Please give a valid subcommand. You gave: {}\".format(options[\"command\"]))\n", "path": "kolibri/content/management/commands/importcontent.py"}]}