1"""A CLI to evaluate env markers for requirements files. 2 3A simple script to evaluate the `requirements.txt` files. Currently it is only 4handling environment markers in the requirements files, but in the future it 5may handle more things. We require a `python` interpreter that can run on the 6host platform and then we depend on the [packaging] PyPI wheel. 7 8In order to be able to resolve requirements files for any platform, we are 9re-using the same code that is used in the `whl_library` installer. See 10[here](../whl_installer/wheel.py). 11 12Requirements for the code are: 13- Depends only on `packaging` and core Python. 14- Produces the same result irrespective of the Python interpreter platform or version. 15 16[packaging]: https://packaging.pypa.io/en/stable/ 17""" 18 19import argparse 20import json 21import pathlib 22 23from packaging.requirements import Requirement 24 25from python.private.pypi.whl_installer.platform import Platform 26 27INPUT_HELP = """\ 28Input path to read the requirements as a json file, the keys in the dictionary 29are the requirements lines and the values are strings of target platforms. 30""" 31OUTPUT_HELP = """\ 32Output to write the requirements as a json filepath, the keys in the dictionary 33are the requirements lines and the values are strings of target platforms, which 34got changed based on the evaluated markers. 35""" 36 37 38def main(): 39 parser = argparse.ArgumentParser(description=__doc__) 40 parser.add_argument("input_path", type=pathlib.Path, help=INPUT_HELP.strip()) 41 parser.add_argument("output_path", type=pathlib.Path, help=OUTPUT_HELP.strip()) 42 args = parser.parse_args() 43 44 with args.input_path.open() as f: 45 reqs = json.load(f) 46 47 response = {} 48 for requirement_line, target_platforms in reqs.items(): 49 entry, prefix, hashes = requirement_line.partition("--hash") 50 hashes = prefix + hashes 51 52 req = Requirement(entry) 53 for p in target_platforms: 54 (platform,) = Platform.from_string(p) 55 if not req.marker or req.marker.evaluate(platform.env_markers("")): 56 response.setdefault(requirement_line, []).append(p) 57 58 with args.output_path.open("w") as f: 59 json.dump(response, f) 60 61 62if __name__ == "__main__": 63 main() 64