def _get_dependency_tree(self, package_name: str, extra: str = "", version_req: str = "", depth: int = 20, path: Optional[List[str]] = None, verbose: bool = False, upward: bool = False) -> List[List[str]]:
        """Recursive function to build dependency tree."""
        path = path or []
        extras = extra.split(",")
        pkg_key = self.normalize(package_name)
        ret_all = []

        full_name = f"{package_name}[{extra}]" if extra else package_name
        if full_name in path:
            logger.warning(f"Cycle detected: {' -> '.join(path + [full_name])}")
            return []

        pkg_data = self.distro[pkg_key]
        if pkg_data and len(path) <= depth:
            for extra in extras:
                environment = {"extra": extra, **self.environment}
                summary = f'  {pkg_data["summary"]}' if verbose else ''
                base_name = f'{package_name}[{extra}]' if extra else package_name
                ret = [f'{base_name}=={pkg_data["version"]} {version_req}{summary}']

                dependencies = pkg_data["requires_dist"] if not upward else pkg_data["reverse_dependencies"]

                for dependency in dependencies:
                    if dependency["req_key"] in self.distro:
                        next_path = path + [base_name]
                        if upward:     
                            up_req = (dependency.get("req_marker", "").split('extra == ')+[""])[1].strip("'\"")
                            if dependency["req_key"] in self.distro and dependency["req_key"]+"["+up_req+"]" not in path:
                                # upward dependancy taken if:
                                # - if extra "" demanded, and no marker from upward package: like pandas[] ==> numpy
                                # - or the extra is in the upward package, like pandas[test] ==> pytest, for 'test' extra
                                # - or an extra "array" is demanded, and indeed in the req_extra list: array,dataframe,diagnostics,distributer 
                                if (not dependency.get("req_marker") and extra == "") or \
                                   ("req_marker" in dependency and extra == up_req and \
                                    dependency["req_key"] != pkg_key and \
                                    Marker(dependency["req_marker"]).evaluate(environment=environment)) or \
                                   ("req_marker" in dependency and extra != "" and \
                                    extra + ',' in dependency["req_extra"] + ',' and \
                                    Marker(dependency["req_marker"]).evaluate(environment=environment | {"extra": up_req})):
                                    # IA risk error: # dask[array] go upwards as dask[dataframe], so {"extra": up_req} , not {"extra": extra}
                                    ret += self._get_dependency_tree(
                                        dependency["req_key"],
                                        up_req,
                                        f"[requires: {package_name}"
                                        + (f"[{dependency['req_extra']}]" if dependency["req_extra"] != "" else "")
                                        + f'{dependency["req_version"]}]',
                                        depth,
                                        next_path,
                                        verbose=verbose,
                                        upward=upward,
                                    )
                        elif not dependency.get("req_marker") or Marker(dependency["req_marker"]).evaluate(environment=environment):
                            ret += self._get_dependency_tree(
                                dependency["req_key"],
                                dependency["req_extra"],
                                dependency["req_version"],
                                depth,
                                next_path,
                                verbose=verbose,
                                upward=upward,
                            )

                ret_all.append(ret)
        return ret_all
Recursive function to build dependency tree.
winpython/piptree.py