-
Notifications
You must be signed in to change notification settings - Fork 43
Preserve case when parsing boolean like strings #1634
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
base: develop
Are you sure you want to change the base?
Changes from all commits
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 | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -189,7 +189,10 @@ def experiment_variant(self, name: str, value: Any): | |||||||
| default_var = self.default_variants[name] | ||||||||
|
|
||||||||
| # If the default value is a boolean, convert the experiment value to a boolean | ||||||||
| if default_var and isinstance(default_var.default, bool): | ||||||||
| if default_var and ( | ||||||||
| isinstance(default_var.default, bool) | ||||||||
| or type(default_var.default).__name__ == "syaml_bool" | ||||||||
| ): | ||||||||
| if isinstance(value, str): | ||||||||
| value = value.lower() == "true" | ||||||||
|
|
||||||||
|
|
@@ -403,7 +406,7 @@ def __init__( | |||||||
| self._definitions = self._build_definitions() | ||||||||
|
|
||||||||
| def _build_definitions(self) -> tuple: | ||||||||
| if isinstance(self.default, bool): | ||||||||
| if isinstance(self.default, bool) or type(self.default).__name__ == "syaml_bool": | ||||||||
|
Contributor
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. Using
Suggested change
|
||||||||
| val_str = str(self.default) | ||||||||
| return ( | ||||||||
| self._definition, | ||||||||
|
|
@@ -419,7 +422,7 @@ def copy(self): | |||||||
|
|
||||||||
| def format_value(self, value: Any) -> str: | ||||||||
| """Format a value for this variant into Spack-like syntax""" | ||||||||
| if isinstance(self.default, bool): | ||||||||
| if isinstance(self.default, bool) or type(self.default).__name__ == "syaml_bool": | ||||||||
|
Contributor
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. Using
Suggested change
|
||||||||
| prefix = "+" if value else "~" | ||||||||
| return f"{prefix}{self.name}" | ||||||||
| else: | ||||||||
|
|
||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -50,10 +50,25 @@ class syaml_int(int): | |
| __repr__ = int.__repr__ | ||
|
|
||
|
|
||
| class syaml_bool(int): | ||
| def __new__(cls, val, string_val=None): | ||
| obj = super(syaml_bool, cls).__new__(cls, val) | ||
| obj.string_val = string_val | ||
| return obj | ||
|
|
||
| def __repr__(self): | ||
| return self.string_val if self.string_val else ('True' if self else 'False') | ||
|
|
||
| def __str__(self): | ||
| return self.string_val if self.string_val else ('True' if self else 'False') | ||
|
|
||
|
|
||
|
|
||
| #: mapping from syaml type -> primitive type | ||
| syaml_types = { | ||
| syaml_str: str, | ||
| syaml_int: int, | ||
| syaml_bool: bool, | ||
| syaml_dict: dict, | ||
| syaml_list: list, | ||
| } | ||
|
|
@@ -121,6 +136,13 @@ class OrderedLineLoader(RoundTripLoader): | |
| # and fill in with mappings later. We preserve this behavior. | ||
| # | ||
|
|
||
|
|
||
| def construct_yaml_bool(self, node): | ||
| value = super(OrderedLineLoader, self).construct_yaml_bool(node) | ||
| b = syaml_bool(value, string_val=node.value) | ||
| mark(b, node) | ||
| return b | ||
|
|
||
| def construct_yaml_str(self, node): | ||
| value = super(OrderedLineLoader, self).construct_yaml_str(node) | ||
| # There is no specific marker to indicate that we are parsing a key, | ||
|
|
@@ -156,6 +178,8 @@ def construct_yaml_map(self, node): | |
|
|
||
|
|
||
| # register above new constructors | ||
| OrderedLineLoader.add_constructor( | ||
| 'tag:yaml.org,2002:bool', OrderedLineLoader.construct_yaml_bool) | ||
| OrderedLineLoader.add_constructor( | ||
| 'tag:yaml.org,2002:map', OrderedLineLoader.construct_yaml_map) | ||
| OrderedLineLoader.add_constructor( | ||
|
|
@@ -178,12 +202,23 @@ def ignore_aliases(self, _data): | |
| """Make the dumper NEVER print YAML aliases.""" | ||
| return True | ||
|
|
||
| def represent_bool(self, data): | ||
| if hasattr(data, 'string_val') and data.string_val: | ||
| return self.represent_scalar('tag:yaml.org,2002:bool', data.string_val) | ||
| return super(SafeDumper, self).represent_bool(bool(data)) | ||
|
|
||
|
Comment on lines
+205
to
+209
Contributor
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. There is a duplicate definition of |
||
| def represent_data(self, data): | ||
| result = super(OrderedLineDumper, self).represent_data(data) | ||
| if data is None: | ||
| result.value = syaml_str("null") | ||
| return result | ||
|
|
||
|
|
||
| def represent_bool(self, data): | ||
| if hasattr(data, 'string_val') and data.string_val: | ||
| return self.represent_scalar('tag:yaml.org,2002:bool', data.string_val) | ||
| return super(OrderedLineDumper, self).represent_bool(bool(data)) | ||
|
|
||
| def represent_str(self, data): | ||
| if hasattr(data, 'override') and data.override: | ||
| data = data + ':' | ||
|
|
@@ -198,12 +233,19 @@ def ignore_aliases(self, _data): | |
| """Make the dumper NEVER print YAML aliases.""" | ||
| return True | ||
|
|
||
| def represent_bool(self, data): | ||
| if hasattr(data, 'string_val') and data.string_val: | ||
| return self.represent_scalar('tag:yaml.org,2002:bool', data.string_val) | ||
| return super(SafeDumper, self).represent_bool(bool(data)) | ||
|
|
||
|
|
||
| # Make our special objects look like normal YAML ones. | ||
| RoundTripDumper.add_representer(syaml_dict, RoundTripDumper.represent_dict) | ||
| RoundTripDumper.add_representer(syaml_list, RoundTripDumper.represent_list) | ||
| RoundTripDumper.add_representer(syaml_int, RoundTripDumper.represent_int) | ||
| RoundTripDumper.add_representer(syaml_bool, RoundTripDumper.represent_bool) | ||
| RoundTripDumper.add_representer(syaml_str, RoundTripDumper.represent_str) | ||
| OrderedLineDumper.add_representer(syaml_bool, OrderedLineDumper.represent_bool) | ||
| OrderedLineDumper.add_representer(syaml_str, OrderedLineDumper.represent_str) | ||
|
|
||
|
|
||
|
|
||
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.
Using
type(default_var.default).__name__ == "syaml_bool"is a fragile string-based type check. It is more robust and idiomatic to importsyaml_booland useisinstanceto check the type, which also correctly handles subclasses.