We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
buildpkg doesn't clean up after failed or interrupted downloads
![image](https://user-images.githubusercontent.com/31370756/54251214-8078aa00-4581-11e9-98d3-d9db60b486c6.png)

when I run `make` command in docker environment, it shows this bug. I think it's the network that cause this error. 

We can use `rm -rf /src/packages/numpy/build` to solve this problem 

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `pyodide_build/buildpkg.py`
Content:
```
1 #!/usr/bin/env python3
2 
3 """
4 Builds a Pyodide package.
5 """
6 
7 import argparse
8 import hashlib
9 import os
10 from pathlib import Path
11 import shutil
12 import subprocess
13 
14 
15 from . import common
16 
17 
18 def check_checksum(path, pkg):
19     """
20     Checks that a tarball matches the checksum in the package metadata.
21     """
22     checksum_keys = {'md5', 'sha256'}.intersection(pkg['source'])
23     if not checksum_keys:
24         return
25     elif len(checksum_keys) != 1:
26         raise ValueError('Only one checksum should be included in a package '
27                          'setup; found {}.'.format(checksum_keys))
28     checksum_algorithm = checksum_keys.pop()
29     checksum = pkg['source'][checksum_algorithm]
30     CHUNK_SIZE = 1 << 16
31     h = getattr(hashlib, checksum_algorithm)()
32     with open(path, 'rb') as fd:
33         while True:
34             chunk = fd.read(CHUNK_SIZE)
35             h.update(chunk)
36             if len(chunk) < CHUNK_SIZE:
37                 break
38     if h.hexdigest() != checksum:
39         raise ValueError("Invalid {} checksum".format(checksum_algorithm))
40 
41 
42 def download_and_extract(buildpath, packagedir, pkg, args):
43     tarballpath = buildpath / Path(pkg['source']['url']).name
44     if not tarballpath.is_file():
45         subprocess.run([
46             'wget', '-q', '-O', str(tarballpath), pkg['source']['url']
47         ], check=True)
48         check_checksum(tarballpath, pkg)
49     srcpath = buildpath / packagedir
50     if not srcpath.is_dir():
51         shutil.unpack_archive(str(tarballpath), str(buildpath))
52     return srcpath
53 
54 
55 def patch(path, srcpath, pkg, args):
56     if (srcpath / '.patched').is_file():
57         return
58 
59     # Apply all of the patches
60     orig_dir = Path.cwd()
61     pkgdir = path.parent.resolve()
62     os.chdir(srcpath)
63     try:
64         for patch in pkg['source'].get('patches', []):
65             subprocess.run([
66                 'patch', '-p1', '--binary', '-i', pkgdir / patch
67             ], check=True)
68     finally:
69         os.chdir(orig_dir)
70 
71     # Add any extra files
72     for src, dst in pkg['source'].get('extras', []):
73         shutil.copyfile(pkgdir / src, srcpath / dst)
74 
75     with open(srcpath / '.patched', 'wb') as fd:
76         fd.write(b'\n')
77 
78 
79 def compile(path, srcpath, pkg, args):
80     if (srcpath / '.built').is_file():
81         return
82 
83     orig_dir = Path.cwd()
84     os.chdir(srcpath)
85     env = dict(os.environ)
86     if pkg.get('build', {}).get('skip_host', True):
87         env['SKIP_HOST'] = ''
88 
89     try:
90         subprocess.run([
91             str(Path(args.host) / 'bin' / 'python3'),
92             '-m', 'pyodide_build', 'pywasmcross',
93             '--cflags',
94             args.cflags + ' ' +
95             pkg.get('build', {}).get('cflags', ''),
96             '--ldflags',
97             args.ldflags + ' ' +
98             pkg.get('build', {}).get('ldflags', ''),
99             '--host', args.host,
100             '--target', args.target], env=env, check=True)
101     finally:
102         os.chdir(orig_dir)
103 
104     post = pkg.get('build', {}).get('post')
105     if post is not None:
106         site_packages_dir = (
107             srcpath / 'install' / 'lib' / 'python3.7' / 'site-packages')
108         pkgdir = path.parent.resolve()
109         env = {
110             'SITEPACKAGES': site_packages_dir,
111             'PKGDIR': pkgdir
112         }
113         subprocess.run([
114             'bash', '-c', post], env=env, check=True)
115 
116     with open(srcpath / '.built', 'wb') as fd:
117         fd.write(b'\n')
118 
119 
120 def package_files(buildpath, srcpath, pkg, args):
121     if (buildpath / '.packaged').is_file():
122         return
123 
124     name = pkg['package']['name']
125     install_prefix = (srcpath / 'install').resolve()
126     subprocess.run([
127         'python',
128         common.ROOTDIR / 'file_packager.py',
129         name + '.data',
130         '--abi={0}'.format(args.package_abi),
131         '--lz4',
132         '--preload',
133         '{}@/'.format(install_prefix),
134         '--js-output={}'.format(name + '.js'),
135         '--export-name=pyodide._module',
136         '--exclude', '*.wasm.pre',
137         '--exclude', '*__pycache__*',
138         '--use-preload-plugins'],
139         cwd=buildpath, check=True)
140     subprocess.run([
141         'uglifyjs',
142         buildpath / (name + '.js'),
143         '-o',
144         buildpath / (name + '.js')], check=True)
145 
146     with open(buildpath / '.packaged', 'wb') as fd:
147         fd.write(b'\n')
148 
149 
150 def build_package(path, args):
151     pkg = common.parse_package(path)
152     packagedir = pkg['package']['name'] + '-' + pkg['package']['version']
153     dirpath = path.parent
154     orig_path = Path.cwd()
155     os.chdir(dirpath)
156     try:
157         buildpath = dirpath / 'build'
158         if not buildpath.resolve().is_dir():
159             os.makedirs(buildpath)
160         srcpath = download_and_extract(buildpath, packagedir, pkg, args)
161         patch(path, srcpath, pkg, args)
162         compile(path, srcpath, pkg, args)
163         package_files(buildpath, srcpath, pkg, args)
164     finally:
165         os.chdir(orig_path)
166 
167 
168 def make_parser(parser):
169     parser.description = 'Build a pyodide package.'
170     parser.add_argument(
171         'package', type=str, nargs=1,
172         help="Path to meta.yaml package description")
173     parser.add_argument(
174         '--package_abi', type=int, required=True,
175         help='The ABI number for the package to be built')
176     parser.add_argument(
177         '--cflags', type=str, nargs='?', default=common.DEFAULTCFLAGS,
178         help='Extra compiling flags')
179     parser.add_argument(
180         '--ldflags', type=str, nargs='?', default=common.DEFAULTLDFLAGS,
181         help='Extra linking flags')
182     parser.add_argument(
183         '--host', type=str, nargs='?', default=common.HOSTPYTHON,
184         help='The path to the host Python installation')
185     parser.add_argument(
186         '--target', type=str, nargs='?', default=common.TARGETPYTHON,
187         help='The path to the target Python installation')
188     return parser
189 
190 
191 def main(args):
192     path = Path(args.package[0]).resolve()
193     build_package(path, args)
194 
195 
196 if __name__ == '__main__':
197     parser = make_parser(argparse.ArgumentParser())
198     args = parser.parse_args()
199     main(args)
200
```
--- 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/pyodide_build/buildpkg.py b/pyodide_build/buildpkg.py
--- a/pyodide_build/buildpkg.py
+++ b/pyodide_build/buildpkg.py
@@ -42,10 +42,14 @@
 def download_and_extract(buildpath, packagedir, pkg, args):
     tarballpath = buildpath / Path(pkg['source']['url']).name
     if not tarballpath.is_file():
-        subprocess.run([
-            'wget', '-q', '-O', str(tarballpath), pkg['source']['url']
-        ], check=True)
-        check_checksum(tarballpath, pkg)
+        try:
+            subprocess.run([
+                'wget', '-q', '-O', str(tarballpath), pkg['source']['url']
+            ], check=True)
+            check_checksum(tarballpath, pkg)
+        except Exception:
+            tarballpath.unlink()
+            raise
     srcpath = buildpath / packagedir
     if not srcpath.is_dir():
         shutil.unpack_archive(str(tarballpath), str(buildpath))

{"golden_diff": "diff --git a/pyodide_build/buildpkg.py b/pyodide_build/buildpkg.py\n--- a/pyodide_build/buildpkg.py\n+++ b/pyodide_build/buildpkg.py\n@@ -42,10 +42,14 @@\n def download_and_extract(buildpath, packagedir, pkg, args):\n     tarballpath = buildpath / Path(pkg['source']['url']).name\n     if not tarballpath.is_file():\n-        subprocess.run([\n-            'wget', '-q', '-O', str(tarballpath), pkg['source']['url']\n-        ], check=True)\n-        check_checksum(tarballpath, pkg)\n+        try:\n+            subprocess.run([\n+                'wget', '-q', '-O', str(tarballpath), pkg['source']['url']\n+            ], check=True)\n+            check_checksum(tarballpath, pkg)\n+        except Exception:\n+            tarballpath.unlink()\n+            raise\n     srcpath = buildpath / packagedir\n     if not srcpath.is_dir():\n         shutil.unpack_archive(str(tarballpath), str(buildpath))\n", "issue": "buildpkg doesn't clean up after failed or interrupted downloads\n![image](https://user-images.githubusercontent.com/31370756/54251214-8078aa00-4581-11e9-98d3-d9db60b486c6.png)\r\n\r\nwhen I run `make` command in docker environment, it shows this bug. I think it's the network that cause this error. \r\n\r\nWe can use `rm -rf /src/packages/numpy/build` to solve this problem \n", "before_files": [{"content": "#!/usr/bin/env python3\n\n\"\"\"\nBuilds a Pyodide package.\n\"\"\"\n\nimport argparse\nimport hashlib\nimport os\nfrom pathlib import Path\nimport shutil\nimport subprocess\n\n\nfrom . import common\n\n\ndef check_checksum(path, pkg):\n    \"\"\"\n    Checks that a tarball matches the checksum in the package metadata.\n    \"\"\"\n    checksum_keys = {'md5', 'sha256'}.intersection(pkg['source'])\n    if not checksum_keys:\n        return\n    elif len(checksum_keys) != 1:\n        raise ValueError('Only one checksum should be included in a package '\n                         'setup; found {}.'.format(checksum_keys))\n    checksum_algorithm = checksum_keys.pop()\n    checksum = pkg['source'][checksum_algorithm]\n    CHUNK_SIZE = 1 << 16\n    h = getattr(hashlib, checksum_algorithm)()\n    with open(path, 'rb') as fd:\n        while True:\n            chunk = fd.read(CHUNK_SIZE)\n            h.update(chunk)\n            if len(chunk) < CHUNK_SIZE:\n                break\n    if h.hexdigest() != checksum:\n        raise ValueError(\"Invalid {} checksum\".format(checksum_algorithm))\n\n\ndef download_and_extract(buildpath, packagedir, pkg, args):\n    tarballpath = buildpath / Path(pkg['source']['url']).name\n    if not tarballpath.is_file():\n        subprocess.run([\n            'wget', '-q', '-O', str(tarballpath), pkg['source']['url']\n        ], check=True)\n        check_checksum(tarballpath, pkg)\n    srcpath = buildpath / packagedir\n    if not srcpath.is_dir():\n        shutil.unpack_archive(str(tarballpath), str(buildpath))\n    return srcpath\n\n\ndef patch(path, srcpath, pkg, args):\n    if (srcpath / '.patched').is_file():\n        return\n\n    # Apply all of the patches\n    orig_dir = Path.cwd()\n    pkgdir = path.parent.resolve()\n    os.chdir(srcpath)\n    try:\n        for patch in pkg['source'].get('patches', []):\n            subprocess.run([\n                'patch', '-p1', '--binary', '-i', pkgdir / patch\n            ], check=True)\n    finally:\n        os.chdir(orig_dir)\n\n    # Add any extra files\n    for src, dst in pkg['source'].get('extras', []):\n        shutil.copyfile(pkgdir / src, srcpath / dst)\n\n    with open(srcpath / '.patched', 'wb') as fd:\n        fd.write(b'\\n')\n\n\ndef compile(path, srcpath, pkg, args):\n    if (srcpath / '.built').is_file():\n        return\n\n    orig_dir = Path.cwd()\n    os.chdir(srcpath)\n    env = dict(os.environ)\n    if pkg.get('build', {}).get('skip_host', True):\n        env['SKIP_HOST'] = ''\n\n    try:\n        subprocess.run([\n            str(Path(args.host) / 'bin' / 'python3'),\n            '-m', 'pyodide_build', 'pywasmcross',\n            '--cflags',\n            args.cflags + ' ' +\n            pkg.get('build', {}).get('cflags', ''),\n            '--ldflags',\n            args.ldflags + ' ' +\n            pkg.get('build', {}).get('ldflags', ''),\n            '--host', args.host,\n            '--target', args.target], env=env, check=True)\n    finally:\n        os.chdir(orig_dir)\n\n    post = pkg.get('build', {}).get('post')\n    if post is not None:\n        site_packages_dir = (\n            srcpath / 'install' / 'lib' / 'python3.7' / 'site-packages')\n        pkgdir = path.parent.resolve()\n        env = {\n            'SITEPACKAGES': site_packages_dir,\n            'PKGDIR': pkgdir\n        }\n        subprocess.run([\n            'bash', '-c', post], env=env, check=True)\n\n    with open(srcpath / '.built', 'wb') as fd:\n        fd.write(b'\\n')\n\n\ndef package_files(buildpath, srcpath, pkg, args):\n    if (buildpath / '.packaged').is_file():\n        return\n\n    name = pkg['package']['name']\n    install_prefix = (srcpath / 'install').resolve()\n    subprocess.run([\n        'python',\n        common.ROOTDIR / 'file_packager.py',\n        name + '.data',\n        '--abi={0}'.format(args.package_abi),\n        '--lz4',\n        '--preload',\n        '{}@/'.format(install_prefix),\n        '--js-output={}'.format(name + '.js'),\n        '--export-name=pyodide._module',\n        '--exclude', '*.wasm.pre',\n        '--exclude', '*__pycache__*',\n        '--use-preload-plugins'],\n        cwd=buildpath, check=True)\n    subprocess.run([\n        'uglifyjs',\n        buildpath / (name + '.js'),\n        '-o',\n        buildpath / (name + '.js')], check=True)\n\n    with open(buildpath / '.packaged', 'wb') as fd:\n        fd.write(b'\\n')\n\n\ndef build_package(path, args):\n    pkg = common.parse_package(path)\n    packagedir = pkg['package']['name'] + '-' + pkg['package']['version']\n    dirpath = path.parent\n    orig_path = Path.cwd()\n    os.chdir(dirpath)\n    try:\n        buildpath = dirpath / 'build'\n        if not buildpath.resolve().is_dir():\n            os.makedirs(buildpath)\n        srcpath = download_and_extract(buildpath, packagedir, pkg, args)\n        patch(path, srcpath, pkg, args)\n        compile(path, srcpath, pkg, args)\n        package_files(buildpath, srcpath, pkg, args)\n    finally:\n        os.chdir(orig_path)\n\n\ndef make_parser(parser):\n    parser.description = 'Build a pyodide package.'\n    parser.add_argument(\n        'package', type=str, nargs=1,\n        help=\"Path to meta.yaml package description\")\n    parser.add_argument(\n        '--package_abi', type=int, required=True,\n        help='The ABI number for the package to be built')\n    parser.add_argument(\n        '--cflags', type=str, nargs='?', default=common.DEFAULTCFLAGS,\n        help='Extra compiling flags')\n    parser.add_argument(\n        '--ldflags', type=str, nargs='?', default=common.DEFAULTLDFLAGS,\n        help='Extra linking flags')\n    parser.add_argument(\n        '--host', type=str, nargs='?', default=common.HOSTPYTHON,\n        help='The path to the host Python installation')\n    parser.add_argument(\n        '--target', type=str, nargs='?', default=common.TARGETPYTHON,\n        help='The path to the target Python installation')\n    return parser\n\n\ndef main(args):\n    path = Path(args.package[0]).resolve()\n    build_package(path, args)\n\n\nif __name__ == '__main__':\n    parser = make_parser(argparse.ArgumentParser())\n    args = parser.parse_args()\n    main(args)\n", "path": "pyodide_build/buildpkg.py"}], "after_files": [{"content": "#!/usr/bin/env python3\n\n\"\"\"\nBuilds a Pyodide package.\n\"\"\"\n\nimport argparse\nimport hashlib\nimport os\nfrom pathlib import Path\nimport shutil\nimport subprocess\n\n\nfrom . import common\n\n\ndef check_checksum(path, pkg):\n    \"\"\"\n    Checks that a tarball matches the checksum in the package metadata.\n    \"\"\"\n    checksum_keys = {'md5', 'sha256'}.intersection(pkg['source'])\n    if not checksum_keys:\n        return\n    elif len(checksum_keys) != 1:\n        raise ValueError('Only one checksum should be included in a package '\n                         'setup; found {}.'.format(checksum_keys))\n    checksum_algorithm = checksum_keys.pop()\n    checksum = pkg['source'][checksum_algorithm]\n    CHUNK_SIZE = 1 << 16\n    h = getattr(hashlib, checksum_algorithm)()\n    with open(path, 'rb') as fd:\n        while True:\n            chunk = fd.read(CHUNK_SIZE)\n            h.update(chunk)\n            if len(chunk) < CHUNK_SIZE:\n                break\n    if h.hexdigest() != checksum:\n        raise ValueError(\"Invalid {} checksum\".format(checksum_algorithm))\n\n\ndef download_and_extract(buildpath, packagedir, pkg, args):\n    tarballpath = buildpath / Path(pkg['source']['url']).name\n    if not tarballpath.is_file():\n        try:\n            subprocess.run([\n                'wget', '-q', '-O', str(tarballpath), pkg['source']['url']\n            ], check=True)\n            check_checksum(tarballpath, pkg)\n        except Exception:\n            tarballpath.unlink()\n            raise\n    srcpath = buildpath / packagedir\n    if not srcpath.is_dir():\n        shutil.unpack_archive(str(tarballpath), str(buildpath))\n    return srcpath\n\n\ndef patch(path, srcpath, pkg, args):\n    if (srcpath / '.patched').is_file():\n        return\n\n    # Apply all of the patches\n    orig_dir = Path.cwd()\n    pkgdir = path.parent.resolve()\n    os.chdir(srcpath)\n    try:\n        for patch in pkg['source'].get('patches', []):\n            subprocess.run([\n                'patch', '-p1', '--binary', '-i', pkgdir / patch\n            ], check=True)\n    finally:\n        os.chdir(orig_dir)\n\n    # Add any extra files\n    for src, dst in pkg['source'].get('extras', []):\n        shutil.copyfile(pkgdir / src, srcpath / dst)\n\n    with open(srcpath / '.patched', 'wb') as fd:\n        fd.write(b'\\n')\n\n\ndef compile(path, srcpath, pkg, args):\n    if (srcpath / '.built').is_file():\n        return\n\n    orig_dir = Path.cwd()\n    os.chdir(srcpath)\n    env = dict(os.environ)\n    if pkg.get('build', {}).get('skip_host', True):\n        env['SKIP_HOST'] = ''\n\n    try:\n        subprocess.run([\n            str(Path(args.host) / 'bin' / 'python3'),\n            '-m', 'pyodide_build', 'pywasmcross',\n            '--cflags',\n            args.cflags + ' ' +\n            pkg.get('build', {}).get('cflags', ''),\n            '--ldflags',\n            args.ldflags + ' ' +\n            pkg.get('build', {}).get('ldflags', ''),\n            '--host', args.host,\n            '--target', args.target], env=env, check=True)\n    finally:\n        os.chdir(orig_dir)\n\n    post = pkg.get('build', {}).get('post')\n    if post is not None:\n        site_packages_dir = (\n            srcpath / 'install' / 'lib' / 'python3.7' / 'site-packages')\n        pkgdir = path.parent.resolve()\n        env = {\n            'SITEPACKAGES': site_packages_dir,\n            'PKGDIR': pkgdir\n        }\n        subprocess.run([\n            'bash', '-c', post], env=env, check=True)\n\n    with open(srcpath / '.built', 'wb') as fd:\n        fd.write(b'\\n')\n\n\ndef package_files(buildpath, srcpath, pkg, args):\n    if (buildpath / '.packaged').is_file():\n        return\n\n    name = pkg['package']['name']\n    install_prefix = (srcpath / 'install').resolve()\n    subprocess.run([\n        'python',\n        common.ROOTDIR / 'file_packager.py',\n        name + '.data',\n        '--abi={0}'.format(args.package_abi),\n        '--lz4',\n        '--preload',\n        '{}@/'.format(install_prefix),\n        '--js-output={}'.format(name + '.js'),\n        '--export-name=pyodide._module',\n        '--exclude', '*.wasm.pre',\n        '--exclude', '*__pycache__*',\n        '--use-preload-plugins'],\n        cwd=buildpath, check=True)\n    subprocess.run([\n        'uglifyjs',\n        buildpath / (name + '.js'),\n        '-o',\n        buildpath / (name + '.js')], check=True)\n\n    with open(buildpath / '.packaged', 'wb') as fd:\n        fd.write(b'\\n')\n\n\ndef build_package(path, args):\n    pkg = common.parse_package(path)\n    packagedir = pkg['package']['name'] + '-' + pkg['package']['version']\n    dirpath = path.parent\n    orig_path = Path.cwd()\n    os.chdir(dirpath)\n    try:\n        buildpath = dirpath / 'build'\n        if not buildpath.resolve().is_dir():\n            os.makedirs(buildpath)\n        srcpath = download_and_extract(buildpath, packagedir, pkg, args)\n        patch(path, srcpath, pkg, args)\n        compile(path, srcpath, pkg, args)\n        package_files(buildpath, srcpath, pkg, args)\n    finally:\n        os.chdir(orig_path)\n\n\ndef make_parser(parser):\n    parser.description = 'Build a pyodide package.'\n    parser.add_argument(\n        'package', type=str, nargs=1,\n        help=\"Path to meta.yaml package description\")\n    parser.add_argument(\n        '--package_abi', type=int, required=True,\n        help='The ABI number for the package to be built')\n    parser.add_argument(\n        '--cflags', type=str, nargs='?', default=common.DEFAULTCFLAGS,\n        help='Extra compiling flags')\n    parser.add_argument(\n        '--ldflags', type=str, nargs='?', default=common.DEFAULTLDFLAGS,\n        help='Extra linking flags')\n    parser.add_argument(\n        '--host', type=str, nargs='?', default=common.HOSTPYTHON,\n        help='The path to the host Python installation')\n    parser.add_argument(\n        '--target', type=str, nargs='?', default=common.TARGETPYTHON,\n        help='The path to the target Python installation')\n    return parser\n\n\ndef main(args):\n    path = Path(args.package[0]).resolve()\n    build_package(path, args)\n\n\nif __name__ == '__main__':\n    parser = make_parser(argparse.ArgumentParser())\n    args = parser.parse_args()\n    main(args)\n", "path": "pyodide_build/buildpkg.py"}]}