diff --git a/winpython/__init__.py b/winpython/__init__.py index 0fe7dcc2..b6c1d768 100644 --- a/winpython/__init__.py +++ b/winpython/__init__.py @@ -28,6 +28,6 @@ OTHER DEALINGS IN THE SOFTWARE. """ -__version__ = '16.5.20250614' +__version__ = '16.6.20250620' __license__ = __doc__ __project_url__ = 'http://winpython.github.io/' diff --git a/winpython/piptree.py b/winpython/piptree.py index 1c61501e..970f4edf 100644 --- a/winpython/piptree.py +++ b/winpython/piptree.py @@ -197,10 +197,12 @@ def _get_dependency_tree(self, package_name: str, extra: str = "", version_req: 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} + #tag downward limiting dependancies + wall = " " if dependency["req_version"].startswith("<") or dependency["req_version"].startswith("==") else "" ret += self._get_dependency_tree( dependency["req_key"], up_req, - f"[requires: {package_name}" + f"[requires{wall}: {package_name}" + (f"[{dependency['req_extra']}]" if dependency["req_extra"] != "" else "") + f'{dependency["req_version"]}]', depth, @@ -242,16 +244,18 @@ def down(self, pp: str = "", extra: str = "", depth: int = 20, indent: int = 5, lines = [l for l in rawtext.split("\n") if len(l.strip()) > 2] return "\n".join(lines).replace('"', "") - def up(self, pp: str, extra: str = "", depth: int = 20, indent: int = 5, version_req: str = "", verbose: bool = False) -> str: + def up(self, ppw: str, extra: str = "", depth: int = 20, indent: int = 5, version_req: str = "", verbose: bool = False) -> str: """Generate upward dependency tree as formatted string.""" + pp = ppw[:-1] if ppw.endswith('!') else ppw + ppend = "!" if ppw.endswith('!') else "" #show only downward limiting dependancies if pp == ".": - results = [self.up(p, extra, depth, indent, version_req, verbose) for p in sorted(self.distro)] + results = [self.up(p + ppend, extra, depth, indent, version_req, verbose) for p in sorted(self.distro)] return '\n'.join(filter(None, results)) if extra == ".": if pp in self.distro: extras = set(self.distro[pp]["provided"]).union(set(self.distro[pp]["provides"])) - results = [self.up(pp, e, depth, indent, version_req, verbose=verbose) for e in sorted(extras)] + results = [self.up(pp + ppend, e, depth, indent, version_req, verbose=verbose) for e in sorted(extras)] return '\n'.join(filter(None, results)) return "" @@ -259,8 +263,8 @@ def up(self, pp: str, extra: str = "", depth: int = 20, indent: int = 5, version return "" rawtext = json.dumps(self._get_dependency_tree(pp, extra, version_req, depth, verbose=verbose, upward=True), indent=indent) - lines = [l for l in rawtext.split("\n") if len(l.strip()) > 2] - return "\n".join(filter(None, lines)).replace('"', "") + lines = [l for l in rawtext.split("\n") if len(l.strip()) > 2 and ( ppend=="" or not "[requires:" in l)] + return "\n".join(filter(None, lines)).replace('"', "").replace('[requires :', '[requires:') def description(self, pp: str) -> None: """Return package description or None if not found.""" diff --git a/winpython/wppm.py b/winpython/wppm.py index 59f14ff8..77a937ac 100644 --- a/winpython/wppm.py +++ b/winpython/wppm.py @@ -278,8 +278,8 @@ def main(test=False): parser.add_argument("-lsa", dest="all", action="store_true",help=f"list details of packages matching [optional] expression: wppm -lsa pandas -l1") parser.add_argument("-md", dest="markdown", action="store_true",help=f"markdown summary of the installation") parser.add_argument("-p",dest="pipdown",action="store_true",help="show Package dependencies of the given package[option], [.]=all: wppm -p pandas[.]") - parser.add_argument("-r", dest="pipup", action="store_true", help=f"show Reverse wppmdependancies of the given package[option]: wppm -r pytest[test]") - parser.add_argument("-l", dest="levels", type=int, default=2, help="show 'LEVELS' levels of dependencies (with -p, -r), default is 2: wppm -p pandas -l1") + parser.add_argument("-r", dest="pipup", action="store_true", help=f"show Reverse (!= constraining) dependancies of the given package[option]: wppm -r pytest![test]") + parser.add_argument("-l", dest="levels", type=int, default=-1, help="show 'LEVELS' levels of dependencies (with -p, -r): wppm -p pandas -l1") parser.add_argument("-t", dest="target", default=sys.prefix, help=f'path to target Python distribution (default: "{sys.prefix}")') parser.add_argument("-i", "--install", action="store_true", help="install a given package wheel or pylock file (use pip for more features)") parser.add_argument("-u", "--uninstall", action="store_true", help="uninstall package (use pip for more features)") @@ -300,13 +300,13 @@ def main(test=False): pip = piptree.PipData(targetpython, args.wheelsource) for args_fname in args.fname: pack, extra, *other = (args_fname + "[").replace("]", "[").split("[") - print(pip.down(pack, extra, args.levels, verbose=args.verbose)) + print(pip.down(pack, extra, args.levels if args.levels>0 else 2, verbose=args.verbose)) sys.exit() elif args.pipup: pip = piptree.PipData(targetpython, args.wheelsource) for args_fname in args.fname: pack, extra, *other = (args_fname + "[").replace("]", "[").split("[") - print(pip.up(pack, extra, args.levels, verbose=args.verbose)) + print(pip.up(pack, extra, args.levels if args.levels>=0 else 1, verbose=args.verbose)) sys.exit() elif args.list: pip = piptree.PipData(targetpython, args.wheelsource)