-
Notifications
You must be signed in to change notification settings - Fork 119
Install with pip #1478
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Install with pip #1478
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
eccf81c
add click
tomvanmele 21cb865
update install script
tomvanmele f85d184
add script to repo config
tomvanmele 143e939
docstring
tomvanmele 6767f64
log
tomvanmele e7e0c3f
add clear option
tomvanmele c216cdd
rewrite without click
tomvanmele 495ff06
log
tomvanmele d91c5a4
docs and rename
tomvanmele c7e8434
Merge branch 'main' into install-with-pip
tomvanmele File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,20 +1,169 @@ | ||
| import argparse | ||
| import pathlib | ||
| import random | ||
| import shutil | ||
| import string | ||
| import subprocess | ||
| from typing import Optional | ||
|
|
||
| import compas_rhino | ||
| import compas | ||
|
|
||
| executable = "python" if compas.WINDOWS else "python3.9" | ||
| rhinocode = pathlib.Path().home() / ".rhinocode" | ||
| rhinopython = rhinocode / "py39-rh8" / executable | ||
| site_envs = rhinocode / "py39-rh8" / "site-envs" | ||
|
|
||
| def install(args): | ||
| subprocess.check_call([compas_rhino._get_default_rhino_cpython_path("8.0"), "-m", "pip", "install"] + args) | ||
|
|
||
| def random_string(length=8) -> str: | ||
| return "".join(random.choices(string.ascii_letters + string.digits, k=length)) | ||
|
tomvanmele marked this conversation as resolved.
|
||
|
|
||
| if __name__ == "__main__": | ||
| import argparse | ||
|
|
||
| parser = argparse.ArgumentParser() | ||
| def find_full_env_name(name: str) -> str: | ||
| for filepath in site_envs.iterdir(): | ||
| if filepath.stem.startswith(name): | ||
| return filepath.stem | ||
| raise ValueError(f"No environment with this name exists: {name}") | ||
|
|
||
|
|
||
| def ensure_site_env(name: str) -> str: | ||
| try: | ||
| fullname = find_full_env_name(name) | ||
| except ValueError: | ||
| fullname = f"{name}-{random_string()}" | ||
| return fullname | ||
|
|
||
|
|
||
| def install_in_rhino_with_pip( | ||
| packages: list[str], | ||
| requirements: Optional[str] = None, | ||
| env: str = "default", | ||
| upgrade: bool = False, | ||
| deps: bool = True, | ||
| clear: bool = False, | ||
| ): | ||
| """Install a package with Rhino's CPython pip. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| packages : list of str | ||
| The package(s) to install (PyPI names or local package paths). | ||
| requirements : str, optional | ||
| Path to a requirements file. | ||
| env : str, optional | ||
| Name of the site env, without the random suffix. | ||
| upgrade : bool, optional | ||
| Attempt to upgrade packages already installed. | ||
| deps : bool, optional | ||
| If False, do not install dependencies. | ||
| clear : bool, optional | ||
| If True, clear the environment before installing. | ||
|
|
||
| Returns | ||
| ------- | ||
| int | ||
| The return code from the pip install command. | ||
|
|
||
| Raises | ||
| ------ | ||
| ValueError | ||
| If both packages and requirements are provided, or if neither are provided. | ||
|
|
||
| Examples | ||
| -------- | ||
| >>> install_in_rhino_with_pip(packages=["requests"], env="myenv", upgrade=True) | ||
| >>> install_in_rhino_with_pip(requirements="requirements.txt", env="myenv") | ||
| >>> install_in_rhino_with_pip(packages=["."], env="myenv") | ||
| >>> install_in_rhino_with_pip(packages=[".."], env="myenv") | ||
|
|
||
| Notes | ||
| ----- | ||
| This function is made available as a command line script under the name `install_in_rhino`. | ||
| On the command line you can use the following syntax | ||
|
|
||
| .. code-block:: bash | ||
|
|
||
| install_in_rhino requests numpy | ||
| install_in_rhino -r requirements.txt --env myenv --upgrade | ||
| install_in_rhino . --env myenv | ||
| install_in_rhino .. --env myenv | ||
| install_in_rhino -r requirements.txt --env myenv --no-deps | ||
| install_in_rhino requests --env myenv --clear | ||
|
|
||
| """ | ||
|
|
||
| parser.add_argument("pipargs", help="Arguments to be passed on to pip as a string") | ||
| if requirements and packages: | ||
| raise ValueError("You must provide either packages or a requirements file, not both.") | ||
|
|
||
| if requirements: | ||
| params = ["-r", str(pathlib.Path(requirements).resolve())] | ||
| elif packages: | ||
| params = [] | ||
| for p in packages: | ||
| if p == ".": | ||
| p = str(pathlib.Path().cwd()) | ||
| elif p == "..": | ||
| p = str(pathlib.Path().cwd().parent) | ||
| params.append(p) | ||
| else: | ||
| raise ValueError("You must provide either packages or a requirements file.") | ||
|
|
||
| env = env or "default" | ||
|
|
||
| if clear: | ||
| try: | ||
| fullname = find_full_env_name(env) | ||
| except ValueError: | ||
| pass | ||
| else: | ||
| target = site_envs / fullname | ||
| shutil.rmtree(target, ignore_errors=True) | ||
|
|
||
| target = site_envs / ensure_site_env(env) | ||
| target.mkdir(exist_ok=True) | ||
|
|
||
| args = [ | ||
| str(rhinopython), | ||
| "-m", | ||
| "pip", | ||
| "install", | ||
| *params, | ||
| "--target", | ||
| str(target), | ||
| "--no-warn-script-location", | ||
| ] | ||
|
|
||
| if upgrade: | ||
| args.append("--upgrade") | ||
| if not deps: | ||
| args.append("--no-deps") | ||
|
|
||
| return subprocess.check_call(args) | ||
|
|
||
|
|
||
| def main(): | ||
| parser = argparse.ArgumentParser(description="Install a package with Rhino's CPython pip.") | ||
| parser.add_argument("packages", help="The package(s) to install (PyPI names or local package paths)", nargs="*") | ||
| parser.add_argument("-r", "--requirements", help="Path to a requirements file") | ||
| parser.add_argument("--env", default="default", help="Name of the site env, without the random suffix") | ||
| parser.add_argument("--upgrade", action="store_true", help="Attempt to upgrade packages already installed") | ||
| parser.add_argument("--no-deps", dest="deps", action="store_false", help="Do not install dependencies") | ||
| parser.add_argument("--clear", action="store_true", help="Clear the environment before installing") | ||
| parser.set_defaults(deps=True) | ||
| args = parser.parse_args() | ||
| pipargs = args.pipargs.split() | ||
|
|
||
| install(pipargs) | ||
| install_in_rhino_with_pip( | ||
| packages=args.packages, | ||
| requirements=args.requirements, | ||
| env=args.env, | ||
| upgrade=args.upgrade, | ||
| deps=args.deps, | ||
| clear=args.clear, | ||
| ) | ||
|
|
||
|
|
||
| # ============================================================================= | ||
| # Main | ||
| # ============================================================================= | ||
|
|
||
| if __name__ == "__main__": | ||
| main() | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.