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 19, 2024
1 parent 1075572 commit de307cb
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 5 deletions.
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 @@ -507,10 +508,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 @@ -560,9 +561,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 de307cb

Please sign in to comment.