Skip to content
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

Feature multiple collection installs #55

Merged
merged 5 commits into from
Sep 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions src/pip4a/arg_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,13 +136,12 @@ def parse() -> argparse.Namespace:
)

level2 = ArgumentParser(add_help=False, parents=[level1])
spec_or_req = level2.add_mutually_exclusive_group(required=True)
spec_or_req.add_argument(
level2.add_argument(
"collection_specifier",
help="Collection name or path to collection with extras.",
nargs="?",
nargs="*",
)
spec_or_req.add_argument(
level2.add_argument(
"-r",
"--requirement <file>",
dest="requirement",
Expand Down
63 changes: 49 additions & 14 deletions src/pip4a/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,52 +57,87 @@ def init_output(self: Cli) -> None:

def args_sanity(self: Cli) -> None:
"""Perform some sanity checking on the args."""
# Missing args
if (
hasattr(self.args, "requirement")
and self.args.requirement
and not self.args.requirement.exists()
):
err = f"Requirements file not found: {self.args.requirement}"
self.output.error(err)
self.output.critical(err)

# Multiple editable collections
if (
hasattr(self.args, "collection_specifier")
and len(self.args.collection_specifier) > 1
and hasattr(self.args, "editable")
and self.args.editable
):
err = "Editable can only be used with a single collection specifier."
self.output.critical(err)

# Editable with requirements file
if (
hasattr(self.args, "requirement")
and self.args.requirement
and hasattr(self.args, "editable")
and self.args.editable
):
err = "Editable can not be used with a requirements file."
self.output.critical(err)

def ensure_isolated(self: Cli) -> None:
"""Ensure the environment is isolated."""
env_vars = os.environ
errors = []
errored = False
if "ANSIBLE_COLLECTIONS_PATHS" in env_vars:
err = "ANSIBLE_COLLECTIONS_PATHS is set"
errors.append(err)
self.output.error(err)
hint = "Run `unset ANSIBLE_COLLECTIONS_PATHS` to unset it."
self.output.hint(hint)
errored = True
if "ANSIBLE_COLLECTION_PATH" in env_vars:
err = "ANSIBLE_COLLECTION_PATH is set"
errors.append(err)
self.output.error(err)
hint = "Run `unset ANSIBLE_COLLECTION_PATH` to unset it."
self.output.hint(hint)
errored = True

home_coll = Path.home() / ".ansible/collections/ansible_collections"
if home_coll.exists() and tuple(home_coll.iterdir()):
err = f"Collections found in {home_coll}"
errors.append(err)
self.output.error(err)
hint = "Run `rm -rf ~/.ansible/collections` to remove them."
self.output.hint(hint)
errored = True

usr_coll = Path("/usr/share/ansible/collections")
if usr_coll.exists() and tuple(usr_coll.iterdir()):
err = f"Collections found in {usr_coll}"
errors.append(err)
self.output.error(err)
hint = "Run `sudo rm -rf /usr/share/ansible/collections` to remove them."
self.output.hint(hint)
errored = True

if "VIRTUAL_ENV" not in env_vars and not self.args.venv:
err = (
"Unable to use user site packages directory:"
f" {site.getusersitepackages()}, please activate or specify a virtual environment"
)
errors.append(err)
self.output.error(err)
hint = (
"Use `--venv <directory>` to specify a virtual environment"
" or enable an existing one."
)
self.output.hint(hint)
errored = True

if errors:
if errored:
err = (
"The development environment is not isolated,"
" please resolve the following errors:"
" please resolve the above errors."
)
self.output.error(err)
for error in errors:
err = f"- {error}"
self.output.error(err)
err = "Exiting."

self.output.critical(err)

def run(self: Cli) -> None:
Expand Down
5 changes: 3 additions & 2 deletions src/pip4a/collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@


@dataclass
class Collection:
class Collection: # pylint: disable=too-many-instance-attributes
"""A collection request specification."""

config: Config
Expand All @@ -27,6 +27,7 @@ class Collection:
cnamespace: str | None = None
cname: str | None = None
specifier: str | None = None
original: str | None = None

@property
def name(self: Collection) -> str:
Expand Down Expand Up @@ -72,7 +73,7 @@ def parse_collection_request( # noqa: PLR0915
Returns:
A collection object
"""
collection = Collection(config=config)
collection = Collection(config=config, original=string)
# spec with dep, local
if "[" in string and "]" in string:
msg = f"Found optional dependencies in collection request: {string}"
Expand Down
4 changes: 2 additions & 2 deletions src/pip4a/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ def _set_interpreter(
command=command,
verbose=self.args.verbose,
msg=work,
term_features=self.term_features,
output=self._output,
)
msg = f"Created virtual environment: {self.venv}"
self._output.info(msg)
Expand Down Expand Up @@ -149,7 +149,7 @@ def _set_site_pkg_path(self: Config) -> None:
command=command,
verbose=self.args.verbose,
msg=work,
term_features=self.term_features,
output=self._output,
)
except subprocess.CalledProcessError as exc:
err = f"Failed to find site packages path: {exc}"
Expand Down
6 changes: 3 additions & 3 deletions src/pip4a/subcommands/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def __init__(self: Checker, config: Config, output: Output) -> None:

def run(self: Checker) -> None:
"""Run the checker."""
builder_introspect(config=self._config)
builder_introspect(config=self._config, output=self._output)
self._collection_deps()
self.system_deps()
self._python_deps()
Expand Down Expand Up @@ -151,7 +151,7 @@ def _python_deps(self: Checker) -> None:
command=command,
verbose=self._config.args.verbose,
msg=work,
term_features=self._config.term_features,
output=self._output,
)
except subprocess.CalledProcessError as exc:
err = f"Failed to check python dependencies: {exc}"
Expand Down Expand Up @@ -191,7 +191,7 @@ def system_deps(self: Checker) -> None:
command=command,
verbose=self._config.args.verbose,
msg=work,
term_features=self._config.term_features,
output=self._output,
)
except subprocess.CalledProcessError as exc:
if exc.stderr:
Expand Down
Loading