Given a requirement, return its cache key. This behavior is a little weird in order to allow backwards
        compatibility with cache files. For a requirement without extras, this will return, for example:

        ("ipython", "2.1.0")

        For a requirement with extras, the extras will be comma-separated and appended to the version, inside brackets,
        like so:

        ("ipython", "2.1.0[nbconvert,notebook]")

def as_cache_key(self, ireq):
        """
        Given a requirement, return its cache key. This behavior is a little weird in order to allow backwards
        compatibility with cache files. For a requirement without extras, this will return, for example:

        ("ipython", "2.1.0")

        For a requirement with extras, the extras will be comma-separated and appended to the version, inside brackets,
        like so:

        ("ipython", "2.1.0[nbconvert,notebook]")
        """
        name, version, extras = as_tuple(ireq)
        if not extras:
            extras_string = ""
        else:
            extras_string = "[{}]".format(",".join(extras))
        return name, "{}{}".format(version, extras_string)