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

Allow decimal datatype #631

Merged
merged 1 commit into from
Apr 1, 2022
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
6 changes: 4 additions & 2 deletions snowfakery/data_generator_runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -344,8 +344,10 @@ def __init__(
"snowfakery.standard_plugins.SnowfakeryVersion.snowfakery_version", 2
)
assert snowfakery_version in (2, 3)
native_types = snowfakery_version == 3
self.template_evaluator_factory = JinjaTemplateEvaluatorFactory(native_types)
self.native_types = snowfakery_version == 3
self.template_evaluator_factory = JinjaTemplateEvaluatorFactory(
self.native_types
)

def execute(self):
self.current_context = RuntimeContext(interpreter=self)
Expand Down
6 changes: 5 additions & 1 deletion snowfakery/data_generator_runtime_object_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -333,14 +333,18 @@ def render(self, context: RuntimeContext) -> FieldValue:
if evaluator:
try:
val = evaluator(context)
if hasattr(val, "render"):
val = val.render()
except jinja2.exceptions.UndefinedError as e:
raise DataGenNameError(e.message, self.filename, self.line_num) from e
except Exception as e:
raise DataGenValueError(str(e), self.filename, self.line_num) from e
else:
val = self.definition
context.unique_context_identifier = old_context_identifier
return look_for_number(val) if isinstance(val, str) else val
if isinstance(val, str) and not context.interpreter.native_types:
val = look_for_number(val)
return val

def __repr__(self):
return f"<{self.__class__.__name__ , self.definition}>"
Expand Down
2 changes: 2 additions & 0 deletions snowfakery/output_streams.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import subprocess
import datetime
import sys
from decimal import Decimal
from pathlib import Path
from collections import namedtuple, defaultdict
from typing import Dict, Union, Optional, Mapping, Callable, Sequence
Expand Down Expand Up @@ -54,6 +55,7 @@ class OutputStream(ABC):
datetime.datetime: format_datetime,
type(None): noop,
bool: int,
Decimal: str,
}
uses_folder = False
uses_path = False
Expand Down
3 changes: 3 additions & 0 deletions snowfakery/utils/template_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ def __add__(self, other):
def __radd__(self, other):
return str(other) + str(self)

def render(self):
return self.func()


class FakerTemplateLibrary:
"""A Jinja template library to add the fake.xyz objects to templates"""
Expand Down
17 changes: 17 additions & 0 deletions tests/decimal.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
- snowfakery_version: 3
- object: Foo
fields:
lat: ${{fake.latitude | string}} # jinja2 will still make a number
long: ${{fake.longitude | string}} # https://github.com/pallets/jinja/issues/1200

- object: Bar
fields:
lat2: ${{fake.latitude}}
long2: ${{fake.longitude}}

- object: Baz
fields:
lat3:
fake: latitude
long3:
fake: longitude
9 changes: 7 additions & 2 deletions tests/test_faker.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,19 @@ def test_fake_block_one_param(self, write_row_mock):
generate(StringIO(yaml), {})
assert len(row_values(write_row_mock, 0, "country")) == 2

@pytest.mark.parametrize("snowfakery_version", (2, 3))
@mock.patch(write_row_path)
def test_fake_inline(self, write_row_mock):
def test_fake_inline(self, write_row_mock, snowfakery_version):
yaml = """
- object: OBJ
fields:
country: ${{fake.country_code(representation='alpha-2')}}
"""
generate(StringIO(yaml), {}, None)
generate(
StringIO(yaml),
{},
plugin_options={"snowfakery_version": snowfakery_version},
)
assert len(row_values(write_row_mock, 0, "country")) == 2

@mock.patch(write_row_path)
Expand Down
11 changes: 11 additions & 0 deletions tests/test_types.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import pytest
from unittest import mock
from io import StringIO

Expand Down Expand Up @@ -36,3 +37,13 @@ def test_float(self, generated_rows):
generate(StringIO(yaml))
assert generated_rows.row_values(0, "foo") == 0.1
assert generated_rows.row_values(0, "foo2") == 0.1

@pytest.mark.parametrize("snowfakery_version", (2, 3))
def test_decimal(self, generated_rows, snowfakery_version):
with open("tests/decimal.yml") as f:
generate(f, plugin_options={"snowfakery_version": snowfakery_version})
assert isinstance(
generated_rows.table_values("Foo", 0)["lat"], float
) # Jinja quirk
assert isinstance(generated_rows.table_values("Bar", 0)["lat2"], str)
assert isinstance(generated_rows.table_values("Baz", 0)["lat3"], str)