-
Notifications
You must be signed in to change notification settings - Fork 414
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
NEW: Better package splitting for multi-output recipes with negative glob in outputs/files #5216
base: main
Are you sure you want to change the base?
Changes from 7 commits
a545986
14e3548
7fbc142
67904ce
e56c573
be19766
b667724
063ff89
1ab7638
de7715d
f56e201
0537c19
30a5e1b
a92964f
a2e3963
bfac4e0
3c0b090
fd5e956
4c04d49
e16c470
e598d6a
8dd906d
642906b
d1b12a1
9dbd17c
c3a26dd
84aad48
249a065
55248d4
e42b6f0
a62e4b9
e28565f
ee89c04
b0645c2
822b477
475c0ec
4f988f9
b33f6f6
256017a
e5fdcbf
606ee08
6d33054
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -14,6 +14,7 @@ | |||||
import subprocess | ||||||
import sys | ||||||
import time | ||||||
import typing | ||||||
import warnings | ||||||
from collections import OrderedDict, deque | ||||||
from os.path import dirname, isdir, isfile, islink, join | ||||||
|
@@ -1802,7 +1803,7 @@ def post_process_files(m: MetaData, initial_prefix_files): | |||||
return new_files | ||||||
|
||||||
|
||||||
def bundle_conda(output, metadata: MetaData, env, stats, **kw): | ||||||
def bundle_conda(output, metadata: MetaData, env, stats, new_prefix_files: typing.Set[str], **kw): | ||||||
log = utils.get_logger(__name__) | ||||||
log.info("Packaging %s", metadata.dist()) | ||||||
get_all_replacements(metadata.config) | ||||||
|
@@ -1915,10 +1916,26 @@ def bundle_conda(output, metadata: MetaData, env, stats, **kw): | |||||
if files: | ||||||
# Files is specified by the output | ||||||
# we exclude the list of files that we want to keep, so post-process picks them up as "new" | ||||||
keep_files = { | ||||||
os.path.normpath(pth) | ||||||
for pth in utils.expand_globs(files, metadata.config.host_prefix) | ||||||
} | ||||||
if isinstance(files, dict): | ||||||
# When file matching with include/exclude lists, only | ||||||
# new_prefix_files are considered. Files in the PREFIX from other | ||||||
# recipes (dependencies) are ignored | ||||||
include = files.get("include", []) | ||||||
exclude = files.get("exclude", []) | ||||||
exclude_files = { | ||||||
os.path.normpath(pth) | ||||||
for pth in utils.expand_globs(exclude, metadata.config.host_prefix) | ||||||
} | ||||||
keep_files = { | ||||||
os.path.normpath(pth) | ||||||
for pth in utils.expand_globs(include, metadata.config.host_prefix) | ||||||
} | ||||||
keep_files = new_prefix_files.intersection(keep_files) - exclude_files | ||||||
jaimergp marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
else: | ||||||
keep_files = { | ||||||
os.path.normpath(pth) | ||||||
for pth in utils.expand_globs(files, metadata.config.host_prefix) | ||||||
} | ||||||
pfx_files = set(utils.prefix_files(metadata.config.host_prefix)) | ||||||
initial_files = { | ||||||
item | ||||||
|
@@ -2093,7 +2110,7 @@ def bundle_conda(output, metadata: MetaData, env, stats, **kw): | |||||
return final_outputs | ||||||
|
||||||
|
||||||
def bundle_wheel(output, metadata: MetaData, env, stats): | ||||||
def bundle_wheel(output, metadata: MetaData, env, stats, new_prefix_files: typing.Set[str]): | ||||||
ext = ".bat" if utils.on_win else ".sh" | ||||||
with TemporaryDirectory() as tmpdir, utils.tmp_chdir(metadata.config.work_dir): | ||||||
dest_file = os.path.join(metadata.config.work_dir, "wheel_output" + ext) | ||||||
|
@@ -2817,7 +2834,7 @@ def build( | |||||
# This is wrong, files has not been expanded at this time and could contain | ||||||
# wildcards. Also well, I just do not understand this, because when this | ||||||
# does contain wildcards, the files in to_remove will slip back in. | ||||||
if "files" in output_d: | ||||||
if "files" in output_d and not isinstance(output_d["files"], dict): | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have updated this condition to: if (
"files" in output_d
and output_d["files"] is not None
and not isinstance(output_d["files"], dict)
): |
||||||
output_d["files"] = set(output_d["files"]) - to_remove | ||||||
|
||||||
# copies the backed-up new prefix files into the newly created host env | ||||||
|
@@ -2833,7 +2850,7 @@ def build( | |||||
with utils.path_prepended(m.config.build_prefix): | ||||||
env = environ.get_dict(m=m) | ||||||
pkg_type = "conda" if not hasattr(m, "type") else m.type | ||||||
newly_built_packages = bundlers[pkg_type](output_d, m, env, stats) | ||||||
newly_built_packages = bundlers[pkg_type](output_d, m, env, stats, new_prefix_files) | ||||||
# warn about overlapping files. | ||||||
if "checksums" in output_d: | ||||||
for file, csum in output_d["checksums"].items(): | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
Enhancements: | ||
------------- | ||
|
||
* implemented negative matching for `files` for `outputs` | ||
|
||
Bug fixes: | ||
---------- | ||
|
||
* <news item> | ||
|
||
Deprecations: | ||
------------- | ||
|
||
* <news item> | ||
|
||
Docs: | ||
----- | ||
|
||
* <news item> | ||
|
||
Other: | ||
------ | ||
|
||
* <news item> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,9 +9,12 @@ requirements: | |
outputs: | ||
- name: my_script_subpackage | ||
files: | ||
- subpackage_file1 | ||
- somedir | ||
- "*.ext" | ||
include: | ||
- subpackage_file1 | ||
- somedir | ||
- "*.ext" | ||
exclude: | ||
- "*3.ext" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we replace the old test with a new one instead of adding a new case? Maybe I would add a new output in this meta.yaml and then test the different behaviors differently, if possible (e.g. how the list-of-str behaviour does copy anything in PREFIX, but include/exclude doesn't?). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have updated the test recipe to include multiple outputs: one uses the old file matching and one uses the new file matching. |
||
test: | ||
script: subpackage_test.py | ||
script_interpreter: python |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This syntax will be affected by the "key is set to an empty block, which means None in YAML" kind of issue. We should change it to:
It might also be a good opportunity to sneak @jakirkham's changes added by #4971.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See line 1818:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My understanding is that
files.get("include")
may returnNone
, butinclude
must be a list. So we use the falsiness ofNone
to replace it with[]
. Equivalent to:There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You might have
and then you'll have
files["exclude"] = None
on macOS, for example (linux is false). Not sure at what point we are ensuring thatinclude
is a list.Under that circumstance
files.get("exclude", [])
will beNone
instead of the expected[]
. Is that what you mean? I think we are saying the same 😬There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. We are saying the same thing. I'm just trying to figure out if we should be doing something stronger than converting Falsy values into the empty list. Perhaps convert any non-list into a list? Something like:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That might silence errors when users populate it with a dict or something accidentally. I think we can just play it simple with falsy promotions.