Merge pull request #1826 from apache/tristan/downloadable-source

Stop passing URL opener across process boundaries
diff --git a/MANIFEST.in b/MANIFEST.in
index 3a8a044..a0deafa 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -23,7 +23,6 @@
 # Cython files
 recursive-include src/buildstream *.pyx
 recursive-include src/buildstream *.pxd
-recursive-include src/buildstream *.c
 
 # Data files required by BuildStream's generic source tests
 graft src/buildstream/_testing/_sourcetests/project
diff --git a/doc/source/main_install.rst b/doc/source/main_install.rst
index 819c124..aca7781 100644
--- a/doc/source/main_install.rst
+++ b/doc/source/main_install.rst
@@ -236,11 +236,15 @@
 Installing completions
 ----------------------
 
-BuildStream integrates with Bash to provide helpful tab-completion. These
-are provided by the `bst` completion script, available online
-`here <https://raw.githubusercontent.com/apache/buildstream/master/src/buildstream/data/bst>`_
-and in your local Git clone at ``src/buildstream/data/bst``. The completion
-script requires manaul installation.
+BuildStream integrates with Bash and Zsh to provide helpful tab-completion.
+These completion scripts require manual installation.
+
+Bash completions
+~~~~~~~~~~~~~~~~
+
+Bash completions are provided by the ``bst`` completion script, available online
+(`src/buildstream/data/bst <https://raw.githubusercontent.com/apache/buildstream/master/src/buildstream/data/bst>`_)
+and in your local Git clone at ``src/buildstream/data/bst``.
 
 To install for the current user, paste the contents of the completion script
 into the file ``~/.bash_completion``.
@@ -252,3 +256,43 @@
 
 See the `bash-completion FAQ <https://github.com/scop/bash-completion#faq>`_
 for more information.
+
+Zsh completions
+~~~~~~~~~~~~~~~~
+
+Zsh completions are provided by the ``_bst`` completion script, available online
+(`src/buildstream/data/zsh/_bst <https://raw.githubusercontent.com/apache/buildstream/master/src/buildstream/data/zsh/_bst>`_)
+and in your local Git clone at ``src/buildstream/data/zsh/_bst``.
+
+Copy the above file to your Zsh completions location. Here are some instructions
+for vanilla Zsh, as well as the *Prezto* and *Oh My Zsh* frameworks:
+
+**Zsh**::
+
+    cp src/buildstream/data/zsh/_bst ~/.zfunc/_bst
+
+You must then add the following lines in your ``~/.zshrc``, if they do not already exist::
+
+    fpath+=~/.zfunc
+    autoload -Uz compinit && compinit
+
+
+**Prezto**::
+
+    cp src/buildstream/data/zsh/_bst ~/.zprezto/modules/completion/external/src/_bst
+
+You may have to reset your zcompdump cache, if you have one, and then restart your shell::
+
+    rm ~/.zcompdump ${XDG_CACHE_HOME:-$HOME/.cache}/prezto/zcompdump
+
+**Oh My Zsh**::
+
+    mkdir $ZSH_CUSTOM/plugins/bst
+    cp src/buildstream/data/zsh/_bst $ZSH_CUSTOM/plugins/bst/_bst
+
+You must then add ``bst`` to your plugins array in ``~/.zshrc``::
+
+    plugins(
+      bst
+      ...
+    )
diff --git a/setup.py b/setup.py
index e26ba09..017b046 100755
--- a/setup.py
+++ b/setup.py
@@ -313,23 +313,6 @@
 #####################################################
 #            Setup Cython and extensions            #
 #####################################################
-# We want to ensure that source distributions always
-# include the .c files, in order to allow users to
-# not need cython when building.
-def assert_cython_required():
-    if "sdist" not in sys.argv:
-        return
-
-    print(
-        "Cython is required when building 'sdist' in order to "
-        "ensure source distributions can be built without Cython. "
-        "Please install it using your package manager (usually 'python3-cython') "
-        "or pip (pip install cython).",
-        file=sys.stderr,
-    )
-
-    raise SystemExit(1)
-
 
 try:
     ENABLE_CYTHON_TRACE = int(os.environ.get("BST_CYTHON_TRACE", "0"))
@@ -342,29 +325,27 @@
 
 
 def cythonize(extensions, **kwargs):
+    # We want to make sure that generated Cython code is never
+    # included in the source distribution.
+    #
+    # This is because Cython will generate some code which accesses
+    # internal API from CPython, as such we cannot guarantee that
+    # the C code we generated when creating the distribution will
+    # be valid for the target CPython interpretor.
+    #
+    if "sdist" in sys.argv:
+        return extensions
+
     try:
         from Cython.Build import cythonize as _cythonize
     except ImportError:
-        assert_cython_required()
-
-        print("Cython not found. Using preprocessed c files instead")
-
-        missing_c_sources = []
-
-        for extension in extensions:
-            for source in extension.sources:
-                if source.endswith(".pyx"):
-                    c_file = source.replace(".pyx", ".c")
-
-                    if not os.path.exists(c_file):
-                        missing_c_sources.append((extension, c_file))
-
-        if missing_c_sources:
-            for extension, source in missing_c_sources:
-                print("Missing '{}' for building extension '{}'".format(source, extension.name))
-
-            raise SystemExit(1)
-        return extensions
+        print(
+            "Cython is required when building BuildStream from sources. "
+            "Please install it using your package manager (usually 'python3-cython') "
+            "or pip (pip install cython).",
+            file=sys.stderr,
+        )
+        raise SystemExit(1)
 
     return _cythonize(extensions, **kwargs)
 
diff --git a/src/buildstream/data/zsh/_bst b/src/buildstream/data/zsh/_bst
new file mode 100644
index 0000000..b8b0d31
--- /dev/null
+++ b/src/buildstream/data/zsh/_bst
@@ -0,0 +1,21 @@
+#compdef bst
+_bst_cmpl() {
+    local idx completions name
+    idx="${#words[@]}"
+    # ZSH arrays start at 1
+    let idx=idx-1
+    completions=( $( env COMP_WORDS="$words" \
+                     COMP_CWORD=$idx \
+                     _BST_COMPLETION=complete bst ) )
+    for name in ${completions[@]}; do
+        # For items that are an incomplete path, do not add trailing space
+        if [[ $name = */ ]]; then
+            compadd -S '' $name
+        else
+            A=($name)
+            compadd -a A
+        fi
+    done
+    return 0
+}
+_bst_cmpl "$@"
diff --git a/src/buildstream/downloadablefilesource.py b/src/buildstream/downloadablefilesource.py
index 16f6604..e310335 100644
--- a/src/buildstream/downloadablefilesource.py
+++ b/src/buildstream/downloadablefilesource.py
@@ -133,7 +133,7 @@
 class DownloadableFileSource(Source):
     # pylint: disable=attribute-defined-outside-init
 
-    COMMON_CONFIG_KEYS = Source.COMMON_CONFIG_KEYS + ["url", "ref", "etag"]
+    COMMON_CONFIG_KEYS = Source.COMMON_CONFIG_KEYS + ["url", "ref"]
 
     __default_mirror_file = None
 
@@ -142,7 +142,6 @@
         self.ref = node.get_str("ref", None)
         self.url = self.translate_url(self.original_url)
         self._mirror_dir = os.path.join(self.get_mirror_directory(), utils.url_directory_name(self.original_url))
-        self._warn_deprecated_etag(node)
 
     def preflight(self):
         return
@@ -155,7 +154,6 @@
 
     def load_ref(self, node):
         self.ref = node.get_str("ref", None)
-        self._warn_deprecated_etag(node)
 
     def get_ref(self):
         return self.ref
@@ -199,12 +197,6 @@
                 "File downloaded from {} has sha256sum '{}', not '{}'!".format(self.url, sha256, self.ref)
             )
 
-    def _warn_deprecated_etag(self, node):
-        etag = node.get_str("etag", None)
-        if etag:
-            provenance = node.get_scalar(etag).get_provenance()
-            self.warn('{} "etag" is deprecated and ignored.'.format(provenance))
-
     def _get_etag(self, ref):
         etagfilename = os.path.join(self._mirror_dir, "{}.etag".format(ref))
         if os.path.exists(etagfilename):
diff --git a/tox.ini b/tox.ini
index c6998a9..df878d8 100644
--- a/tox.ini
+++ b/tox.ini
@@ -170,6 +170,7 @@
 deps =
     -rrequirements/requirements.txt
     -rrequirements/dev-requirements.txt
+    Cython
 
 #
 # Running static type checkers