-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
tags/typeconv: add ToInteger, ToString, ToBoolean, ToFloat tags (closes
#49)
- Loading branch information
Showing
3 changed files
with
91 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
from numbers import Number | ||
from collections.abc import Mapping | ||
from typing import Optional, Type, Union | ||
|
||
from ..context import Context | ||
from ..void import Void, VoidType | ||
from .base import BaseTag | ||
|
||
|
||
class _BaseToType(BaseTag): | ||
""" | ||
arguments: Data to convert. | ||
example: "`!{name} ...`" | ||
description: Converts the input to the desired type. | ||
""" | ||
|
||
value_types = (object,) | ||
target_type: Type | ||
|
||
def enrich(self, context: Context): | ||
return self.target_type(context.enrich(self.data)) | ||
|
||
|
||
class ToBoolean(_BaseToType): | ||
__doc__ = _BaseToType.__doc__ | ||
target_type = bool | ||
|
||
|
||
class ToInteger(_BaseToType): | ||
""" | ||
arguments: Either single argument containing the data to convert, or an object with `value:` and `radix:`. | ||
example: `!ToInteger "50"`, `!ToInteger value: "C0FFEE", radix: 16` | ||
description: Converts the input to Python `int`. Radix is never inferred from input: if not supplied, it is always 10. | ||
""" | ||
|
||
target_type = int | ||
|
||
def enrich(self, context: Context): | ||
data = context.enrich(self.data) | ||
|
||
if isinstance(data, Mapping): | ||
value = data["value"] | ||
radix = data.get("radix", 10) | ||
return self.target_type(value, radix) | ||
else: | ||
return self.target_type(data) | ||
|
||
|
||
class ToFloat(_BaseToType): | ||
__doc__ = _BaseToType.__doc__ | ||
target_type = float | ||
|
||
|
||
class ToString(_BaseToType): | ||
__doc__ = _BaseToType.__doc__ | ||
target_type = str |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import pytest | ||
|
||
from emrichen import Template, Context | ||
from emrichen.void import Void | ||
|
||
|
||
@pytest.mark.parametrize( | ||
'tag, val, result', | ||
[ | ||
('ToBoolean', 0, False), | ||
# ('ToBoolean', "false", False), | ||
('ToBoolean', "TRUE", True), | ||
('ToInteger', "8", 8), | ||
('ToInteger', {"value": "0644", "radix": 8}, 420), | ||
('ToFloat', "8.2", 8.2), | ||
('ToFloat', 8, 8.0), | ||
('ToFloat', True, 1.0), | ||
('ToString', True, "True"), # TODO too pythonic? should we return lowercase instead? | ||
('ToString', 8, "8"), | ||
# ('ToString', {'a': 5, 'b': 6}, "{'a': 5, 'b': 6}"), # TODO OrderedDict([('a', 5), ('b', 6)]) | ||
], | ||
) | ||
def test_typeop(tag, val, result): | ||
resolved = Template.parse(f"!{tag},Lookup 'a'").enrich(Context({'a': val}))[0] | ||
assert resolved == result, f'{tag}({val!r}) returned {resolved}, expected {result}' | ||
|
||
# type equivalence instead of isinstance is intended: want strict conformance | ||
assert type(resolved) == type( | ||
result | ||
), f'{tag}({val!r}) returned type {type(resolved)}, expected {type(result)}' |