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

Create the output directory if its missing and force is used, otherwise raise #295

Merged
merged 6 commits into from
Nov 18, 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
3 changes: 2 additions & 1 deletion conda_pack/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,8 @@ def build_parser():
help="Re-add excluded files matching this pattern")
parser.add_argument("--force", "-f",
action="store_true",
help="Overwrite any existing archive at the output path.")
help=("Overwrite any existing archive at the output path, "
"or create the output directory structure if it's missing."))
parser.add_argument("--quiet", "-q",
action="store_true",
help="Do not report progress")
Expand Down
23 changes: 17 additions & 6 deletions conda_pack/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,18 @@ def _parcel_output(self, parcel_root, parcel_name, parcel_version, parcel_distro
dest_prefix = os.path.join(parcel_root, arcroot)
return dest_prefix, arcroot, triple

def _check_output_location(self, output, force):
if os.path.exists(output) and not force:
raise CondaPackException("File %r already exists" % output)

# `dirname` returns an empty string if the provided `output` is just a filename.
directory = os.path.dirname(output) or "."
if force:
os.makedirs(directory, exist_ok=True)

if not os.path.exists(directory):
raise CondaPackException(f"The target output directory {directory} does not exist")

def pack(
self,
output=None,
Expand Down Expand Up @@ -340,8 +352,8 @@ def pack(
verbose : bool, optional
If True, progress is reported to stdout. Default is False.
force : bool, optional
Whether to overwrite any existing archive at the output path.
Default is False.
Whether to overwrite any existing archive at the output path if present, or
create the output directory structure if it's missing. Default is False.
compress_level : int, optional
The compression level to use, from 0 to 9. Higher numbers decrease
output file size at the expense of compression time. Ignored for
Expand Down Expand Up @@ -386,8 +398,7 @@ def pack(
# Ensure the prefix is a relative path
arcroot = arcroot.strip(os.path.sep) if arcroot else ""

if os.path.exists(output) and not force:
raise CondaPackException("File %r already exists" % output)
self._check_output_location(output, force)

if verbose:
print(f"Packing environment at {self.prefix!r} to {output!r}")
Expand Down Expand Up @@ -518,8 +529,8 @@ def pack(
verbose : bool, optional
If True, progress is reported to stdout. Default is False.
force : bool, optional
Whether to overwrite any existing archive at the output path. Default
is False.
Whether to overwrite any existing archive at the output path if present, or
create the output directory structure if it's missing. Default is False.
compress_level : int, optional
The compression level to use, from 0 to 9. Higher numbers decrease
output file size at the expense of compression time. Ignored for
Expand Down
25 changes: 25 additions & 0 deletions conda_pack/tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,31 @@ def test_ignore_errors_editable_packages():
CondaEnv.from_prefix(py37_editable_path, ignore_editable_packages=True)


def test_errors_when_target_directory_not_exists_and_not_force(tmpdir, py37_env):

target_directory = os.path.join(tmpdir, "not_a_real_directory/")
assert not os.path.exists(target_directory)

target_file = os.path.join(target_directory, "env.tar.gz")

with pytest.raises(CondaPackException) as exc:
py37_env.pack(output=target_file, force=False)

assert "not_a_real_directory" in str(exc.value)


def test_creates_directories_if_missing_and_force(tmpdir, py37_env):

target_directory = os.path.join(tmpdir, "not_a_real_directory/")
assert not os.path.exists(target_directory)

target_file = os.path.join(target_directory, "env.tar.gz")

py37_env.pack(output=target_file, force=True)

assert os.path.exists(target_directory)


def test_errors_pip_overwrites():
with pytest.raises(CondaPackException) as exc:
CondaEnv.from_prefix(py37_broken_path)
Expand Down
21 changes: 21 additions & 0 deletions news/295-create-output-dir-if-missing-and-force
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
### Enhancements

* Creates the output directory if it does not already exist and `force` is used (#295)

* Raise error before packing if the output directory is missing and `force` is not used (#295)

### Bug fixes

* <news item>

### Deprecations

* <news item>

### Docs

* <news item>

### Other

* <news item>