From 28351894368e3e2663c39934029db476a9bea73b Mon Sep 17 00:00:00 2001 From: Rick Wierenga Date: Tue, 12 Aug 2025 13:25:38 -0700 Subject: [PATCH] Allow string indexing in ItemizedResource.row --- CHANGELOG.md | 1 + pylabrobot/resources/itemized_resource.py | 19 +++++++++++++++++-- .../resources/itemized_resource_tests.py | 16 ++++++++++++++++ 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b4c27dd53fe..034f463c04a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -60,6 +60,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). - `location` parameter of `assign_child_resource` is not optional (https://github.com/PyLabRobot/pylabrobot/pull/336) - `Resource.get_absolute_location` raises `NoLocationError` instead of `AssertionError` when absolute location is not defined (https://github.com/PyLabRobot/pylabrobot/pull/338) - `no_trash` and `no_teaching_rack` were renamed to `with_trash` and `with_teaching_rack` to avoid double negatives (https://github.com/PyLabRobot/pylabrobot/pull/347) +- `ItemizedResource.row` accepts a string ("A"-"P") in addition to an integer index. ### Added diff --git a/pylabrobot/resources/itemized_resource.py b/pylabrobot/resources/itemized_resource.py index 5874f14c6df..37501ae944e 100644 --- a/pylabrobot/resources/itemized_resource.py +++ b/pylabrobot/resources/itemized_resource.py @@ -473,6 +473,21 @@ def column(self, column: int) -> List[T]: """Get all items in the given column.""" return self[column * self.num_items_y : (column + 1) * self.num_items_y] - def row(self, row: int) -> List[T]: - """Get all items in the given row.""" + def row(self, row: Union[int, str]) -> List[T]: + """Get all items in the given row. + + Args: + row: The row index. Either an integer starting at ``0`` or a letter + ``"A"``-``"P"`` (case insensitive) corresponding to ``0``-``15``. + + Raises: + ValueError: If ``row`` is a string outside ``"A"``-``"P"``. + """ + + if isinstance(row, str): + letter = row.upper() + if letter not in LETTERS[:16]: + raise ValueError("Row must be between 'A' and 'P'.") + row = LETTERS.index(letter) + return self[row :: self.num_items_y] diff --git a/pylabrobot/resources/itemized_resource_tests.py b/pylabrobot/resources/itemized_resource_tests.py index 53401f8fa35..aff08d1f664 100644 --- a/pylabrobot/resources/itemized_resource_tests.py +++ b/pylabrobot/resources/itemized_resource_tests.py @@ -183,6 +183,22 @@ def test_get_row(self): ], ) + def test_get_row_str(self): + self.assertEqual( + [w.name for w in self.plate.row("A")], + [w.name for w in self.plate.row(0)], + ) + self.assertEqual( + [w.name for w in self.plate.row("d")], + [w.name for w in self.plate.row(3)], + ) + + def test_get_row_str_invalid(self): + with self.assertRaises(ValueError): + self.plate.row("Q") + with self.assertRaises(ValueError): + self.plate.row("AA") + def test_get_column(self): self.assertEqual( [w.name for w in self.plate.column(0)],