-
-
Notifications
You must be signed in to change notification settings - Fork 644
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
use a template for computing output_path
for packageable targets
#21175
Changes from 8 commits
66594db
80dd7b3
2a766df
03e1ac2
38a6584
2f0f8de
8c84be1
36899ab
9c0d745
926de5c
d15b7c1
b8b512c
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 |
---|---|---|
|
@@ -8,6 +8,7 @@ | |
from pants.core.util_rules.environments import EnvironmentField | ||
from pants.engine.target import ( | ||
COMMON_TARGET_FIELDS, | ||
AsyncFieldMixin, | ||
Dependencies, | ||
OptionalSingleSourceField, | ||
StringField, | ||
|
@@ -40,16 +41,23 @@ class PyOxidizerOutputPathField(OutputPathField): | |
) | ||
|
||
|
||
class PyOxidizerBinaryNameField(OutputPathField): | ||
class PyOxidizerBinaryNameField(StringField, AsyncFieldMixin): | ||
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. This field should not have been subclassing |
||
alias = "binary_name" | ||
default = None | ||
help = help_text( | ||
""" | ||
The name of the binary that will be output by PyOxidizer. If not set, this will default | ||
to the name of this target. | ||
""" | ||
) | ||
|
||
def value_or_default(self) -> str: | ||
if self.value: | ||
return self.value | ||
|
||
return ( | ||
self.address.generated_name if self.address.generated_name else self.address.target_name | ||
) | ||
|
||
|
||
class PyOxidizerEntryPointField(StringField): | ||
alias = "entry_point" | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -66,37 +66,64 @@ class BuiltPackage: | |
|
||
|
||
class OutputPathField(StringField, AsyncFieldMixin): | ||
DEFAULT = "{normalized_spec_path}/{normalized_address}{file_suffix}" | ||
|
||
alias = "output_path" | ||
default = DEFAULT | ||
|
||
help = help_text( | ||
f""" | ||
Where the built asset should be located. | ||
|
||
This field supports the following template replacements: | ||
|
||
- `{{normalized_spec_path}}`: The path to the target's directory ("spec path") with forward slashes replaced by dots. | ||
|
||
- `{{normalized_address}}`: The target's name with paramaterizations escaped by replacing dots with underscores. | ||
|
||
- `{{file_suffix}}`: For target's which produce single file artifacts, this is the file type suffix to use with a leading dot, | ||
and is empty otherwise when not applicable. | ||
|
||
If undefined, this will use the path to the BUILD file, followed by the target name. | ||
For example, `src/python/project:app` would be `src.python.project/app.ext`. | ||
For example, `src/python/project:app` would be `src.python.project/app.ext`. This behavior corresponds to | ||
the default template: `{DEFAULT}` | ||
|
||
When running `{bin_name()} package`, this path will be prefixed by `--distdir` (e.g. `dist/`). | ||
|
||
Warning: setting this value risks naming collisions with other package targets you may have. | ||
""" | ||
) | ||
|
||
def value_or_default(self, *, file_ending: str | None) -> str: | ||
if self.value: | ||
return self.value | ||
def parameters(self, *, file_ending: str | None) -> dict[str, str]: | ||
normalized_spec_path = self.address.spec_path.replace(os.sep, ".") | ||
if not normalized_spec_path: | ||
normalized_spec_path = "." | ||
|
||
target_name_part = ( | ||
self.address.generated_name.replace(".", "_") | ||
if self.address.generated_name | ||
else self.address.target_name | ||
) | ||
params_sanitized = self.address.parameters_repr.replace(".", "_") | ||
file_prefix = f"{target_name_part}{params_sanitized}" | ||
target_params_sanitized = self.address.parameters_repr.replace(".", "_") | ||
normalized_address = f"{target_name_part}{target_params_sanitized}" | ||
|
||
if file_ending is None: | ||
file_name = file_prefix | ||
else: | ||
file_suffix = "" | ||
if file_ending: | ||
assert not file_ending.startswith("."), "`file_ending` should not start with `.`" | ||
file_name = f"{file_prefix}.{file_ending}" | ||
return os.path.join(self.address.spec_path.replace(os.sep, "."), file_name) | ||
file_suffix = f".{file_ending}" | ||
|
||
return dict( | ||
normalized_spec_path=normalized_spec_path, | ||
normalized_address=normalized_address, | ||
file_suffix=file_suffix, | ||
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. Any one: Please propose better names for these. 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. Documenting this is more important than bikeshedding the names... Maybe add docs somewhere in a followup? 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. Sure. Any suggestions as to location? We have several references to |
||
) | ||
|
||
def value_or_default(self, *, file_ending: str | None) -> str: | ||
template = self.value | ||
assert template is not None | ||
params = self.parameters(file_ending=file_ending) | ||
result = template.format(**params) | ||
return os.path.normpath(result) | ||
|
||
|
||
@dataclass(frozen=True) | ||
|
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.
Bug fix: This code should have been calling
.value_or_default
.