Skip to content

Commit

Permalink
Add support for binding to constant values (#37)
Browse files Browse the repository at this point in the history
  • Loading branch information
cariad authored Jul 21, 2023
1 parent 6e36718 commit af0dc5f
Show file tree
Hide file tree
Showing 14 changed files with 101 additions and 13 deletions.
2 changes: 1 addition & 1 deletion docs/source/cook-book/conditional-translating.rst
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ This code is similar to :doc:`the Translating example <translating>` but note th

columns = Columns()
columns.add("Name", "name")
columns.add("Address", Source("address.planet", translator=censor))
columns.add("Address", Source(path="address.planet", translator=censor))

renderer = RowsRenderer(columns)
rows = renderer.render(data)
Expand Down
62 changes: 62 additions & 0 deletions docs/source/cook-book/constants.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
.. py:module:: rolumns
:noindex:

Constants
=========

The Problem
-----------

Sometimes you want to bind a column to a static constant that doesn't exist within your source data.

We'll achieve this by binding the constant to the column's :class:`Source`.

Code Sample
-----------

.. testcode::

from rolumns import Columns, Source
from rolumns.renderers import RowsRenderer

data = [
{
"name": "Robert Pringles",
"address": {
"planet": "Earth"
}
},
{
"name": "Daniel Sausage",
"address": {
"planet": "Mars"
}
},
{
"name": "Charlie Marmalade",
"address": {
"planet": "Pluto"
}
}
]

columns = Columns()
columns.add("Name", "name")
columns.add("Address", "address.planet")
columns.add("Lives on a Planet?", Source(constant="Yes"))

renderer = RowsRenderer(columns)
rows = renderer.render(data)

print(list(rows))

Result
------

.. testoutput::
:options: +NORMALIZE_WHITESPACE

[['Name', 'Address', 'Lives on a Planet?'],
['Robert Pringles', 'Earth', 'Yes'],
['Daniel Sausage', 'Mars', 'Yes'],
['Charlie Marmalade', 'Pluto', 'Yes']]
1 change: 1 addition & 0 deletions docs/source/cook-book/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ These articles describe common scenarios and solutions, starting with the simple
grouping-dictionary-lists
translating
conditional-translating
constants
udfs
udfs-with-repeating
choosing-columns
Expand Down
2 changes: 1 addition & 1 deletion docs/source/cook-book/translating.rst
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ This code is similar to :doc:`the Flat Table example <flat>` except for the :cla

columns = Columns()
columns.add("Name", "name")
columns.add("Email", Source("email", translator=censor))
columns.add("Email", Source(path="email", translator=censor))

renderer = RowsRenderer(columns)
rows = renderer.render(data)
Expand Down
2 changes: 1 addition & 1 deletion docs/source/cook-book/udfs-with-repeating.rst
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ This code is similar to :doc:`User-Defined Fields <udfs>`, but note that the new
by_udf = ByUserDefinedFields()
by_udf.append("Email", "email")
by_udf.append("Title", "title")
by_udf.append("Company", Source("company.name", cursor=columns.cursor))
by_udf.append("Company", Source(path="company.name", cursor=columns.cursor))

udfs = staff.group(by_udf)
udfs.add("Property", ByUserDefinedFields.NAME)
Expand Down
2 changes: 1 addition & 1 deletion rolumns/by_key.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ class ByKey(Group):
_VALUE = "value"

def __init__(self, source: Optional[Union[Source, str]] = None) -> None:
self._source = source if isinstance(source, Source) else Source(source)
self._source = source if isinstance(source, Source) else Source(path=source)

@classmethod
def key(cls) -> str:
Expand Down
2 changes: 1 addition & 1 deletion rolumns/by_user_defined_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class UserDefinedField:

def __init__(self, name: str, source: Union[Source, str]) -> None:
self.name = name
self.source = source if isinstance(source, Source) else Source(source)
self.source = source if isinstance(source, Source) else Source(path=source)


class ByUserDefinedFields(Group):
Expand Down
4 changes: 2 additions & 2 deletions rolumns/columns.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,14 @@ def add(
columns = Columns()
columns.add("Name", "name")
columns.add("Email", Source("email"))
columns.add("Email", Source(path="email"))
awards = columns.group("awards")
# "awards" is also a column set
awards.add("Awards")
"""

source = source if isinstance(source, Source) else Source(source)
source = source if isinstance(source, Source) else Source(path=source)
column = Column(name, source)
self._columns.append(column)

Expand Down
12 changes: 11 additions & 1 deletion rolumns/source.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,20 @@ class Source:
]
- The path :code:`None` iterates over the values
:code:`constant` describes any static constant to bind to.
:code:`cursor` describes any cursor to bind to.
"""

def __init__(
self,
path: Optional[str],
constant: Optional[Any] = None,
cursor: Optional[Cursor] = None,
path: Optional[str] = None,
translator: Optional[Translator] = None,
) -> None:
self._constant = constant
self._cursor = cursor
self._path = path
self._translator = translator
Expand All @@ -53,6 +59,10 @@ def read(self, record: Any) -> Iterable[Any]:
Yields each prescribed value of :code:`record`.
"""

if self._constant is not None:
yield self._constant
return

if self._cursor is not None:
record = self._cursor.current

Expand Down
6 changes: 6 additions & 0 deletions tests/data/0001-expect-constant.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[
["Name", "Favourite Colour", "Delightful?"],
["alice", "green", "Yes"],
["bob", "magenta", "Yes"],
["charlie", "orange", "Yes"]
]
2 changes: 1 addition & 1 deletion tests/renderers/test_markdown.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def fire(state: TranslationState) -> Optional[str]:
cs = Columns()
cs.add("Name", "name")
cs.add("Favourite Colour", "favourite_colour")
cs.add("?", Source("favourite_colour", translator=fire))
cs.add("?", Source(path="favourite_colour", translator=fire))
t = MarkdownRenderer(cs)

assert t.render_string(inp) == "\n".join(exp) + "\n"
Expand Down
13 changes: 11 additions & 2 deletions tests/renderers/test_rows.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ def to_upper(state: TranslationState) -> str:
]

cs = Columns()
cs.add("Name", Source("name", translator=to_upper))
cs.add("Name", Source(path="name", translator=to_upper))

assert list(RowsRenderer(cs).render(inp)) == exp

Expand Down Expand Up @@ -243,7 +243,7 @@ def test_udf_repeat_static() -> None:
UserDefinedField(
"Emergency",
Source(
ByKey.value("static.emergency_phone.value"),
path=ByKey.value("static.emergency_phone.value"),
cursor=cs.cursor,
),
),
Expand All @@ -254,3 +254,12 @@ def test_udf_repeat_static() -> None:
udfs.add("Number", "value")

assert list(RowsRenderer(cs).render(inp)) == exp


def test_constant() -> None:
(inp, exp) = load_test_case(1, expect_variant="constant")
cs = Columns()
cs.add("Name", "name")
cs.add("Favourite Colour", "favourite_colour")
cs.add("Delightful?", Source(constant="Yes"))
assert list(RowsRenderer(cs).render(inp)) == exp
2 changes: 1 addition & 1 deletion tests/test_readme.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ def censor(state: TranslationState) -> str:

columns = rolumns.Columns()
columns.add("Name", "name")
columns.add("Email", rolumns.Source("email", translator=censor))
columns.add("Email", rolumns.Source(path="email", translator=censor))

renderer = rolumns.renderers.MarkdownRenderer(columns)

Expand Down
2 changes: 1 addition & 1 deletion tests/test_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ def test_fail() -> None:
def fail(state: TranslationState) -> str:
raise Exception("failed")

source = Source("date", translator=fail)
source = Source(path="date", translator=fail)

with raises(TranslationFailed) as ex:
list(source.read({"date": "pringles"}))
Expand Down

0 comments on commit af0dc5f

Please sign in to comment.