Skip to content

Commit

Permalink
Add util function to_record to build records
Browse files Browse the repository at this point in the history
Add a new util function that helps building record values.
Records are list of dictionaries, each dictionary has the same
set of keys, they are set from the given list of headers.
Each key is associated to a value from the given matrix of values.
They are as many dictionaries as they are lines in the matrix.

Each line in the matrix will be associated to a dictionary,
each key is associated to a value from that line in the given order.

Example:
Headers: A B C
Values:
1 2 3
7 8 9
Result: [ { A: 1, B: 2, C: 3}, {A: 7, B: 8, C: 9}]

closes #1367

Signed-off-by: Alexandre Lavigne <[email protected]>
  • Loading branch information
lavigne958 committed Jan 15, 2024
1 parent 63c4c5e commit b491559
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 5 deletions.
10 changes: 10 additions & 0 deletions gspread/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -878,6 +878,16 @@ def get_a1_from_absolute_range(range_name: str) -> str:
return range_name


def to_records(
headers: Sequence[Any] = [], values: Sequence[Sequence[Any]] = [[]]
) -> list[dict[str, Union[str, int, float]]]:
"""Builds the list of dictionaries, all of them have the headers sequence as keys set,
each key is associated to the corresponding value for the same index in the sub-list.
There are as many dictionaries as they are entry in the of given values."""

return [dict(zip(headers, row)) for row in values]


# SHOULD NOT BE NEEDED UNTIL NEXT MAJOR VERSION
# def deprecation_warning(version: str, msg: str) -> None:
# """Emit a deprecation warning.
Expand Down
9 changes: 4 additions & 5 deletions gspread/worksheet.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
is_full_a1_notation,
numericise_all,
rowcol_to_a1,
to_records,
)

CellFormat = TypedDict(
Expand Down Expand Up @@ -498,10 +499,10 @@ def get_all_records(
# Read all rows from the sheet
>>> worksheet.get_all_records()
{
[
{"A1": "A6", "B2": "B7", "C3": "C8"},
{"A1": "A11", "B2": "B12", "C3": "C13"}
}
]
"""
entire_sheet = self.get(
value_render_option=value_render_option,
Expand Down Expand Up @@ -551,9 +552,7 @@ def get_all_records(
for row in values
]

formatted_records = [dict(zip(keys, row)) for row in values]

return formatted_records
return to_records(keys, values)

def get_all_cells(self) -> List[Cell]:
"""Returns a list of all `Cell` of the current sheet."""
Expand Down
38 changes: 38 additions & 0 deletions tests/utils_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -465,3 +465,41 @@ def test_get_a1_from_absolute_range(self):
self.assertEqual(utils.get_a1_from_absolute_range("A1:B2"), "A1:B2")
self.assertEqual(utils.get_a1_from_absolute_range("A1:B"), "A1:B")
self.assertEqual(utils.get_a1_from_absolute_range("2"), "2")

def test_to_records_empty_args(self):
"""Test to_records with empty args"""

self.assertListEqual(utils.to_records([], []), [])
self.assertListEqual(utils.to_records([], [[]]), [{}])
self.assertListEqual(utils.to_records(["a1", "b2"], []), [])
self.assertListEqual(utils.to_records(["a1", "b2"], [[]]), [{}])
self.assertListEqual(utils.to_records([], [["a1"]]), [{}])
self.assertListEqual(utils.to_records([], [["a1"], ["a2"]]), [{}, {}])
self.assertListEqual(utils.to_records([], [[], ["a2"]]), [{}, {}])

def test_to_records(self):
"""Test to_records with values"""

headers = ["HA", "HB", "HC"]
values = [["A2", "B2", "C2"], ["A3", "B3"], ["", "B4", "C4"]]

records = utils.to_records(headers, values)

self.assertEqual(len(values), len(records))

for i in range(len(records)):
record = records[i]
keys = record.keys()

# Some rows have shorter values ("A3", "B3")
# so the list of keys is smaller
# but never bigger than the list of headers
self.assertLessEqual(len(keys), len(headers))

# Each resulting key must be part of the given header
for key in keys:
self.assertIn(key, headers)

# given key are unordered
# but they must match a value from the given input values
self.assertIn(record[key], values[i])

0 comments on commit b491559

Please sign in to comment.