mirror of
https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git
synced 2026-10-28 13:55:08 +03:00
Since their inclusion in Python 3.6, f-strings have become the preferred way to format strings with variable values as they are generally more readable as the value substitution is in place and doesn't have to be parsed from the list or arguments to `.format()`. Where it does not impact readability (when the line is <120 characters), swap usage of `.format()` to an f-string. For lines that are not converted, inform the linter to ignore attempts to upgrade those instances to f-strings [0] [0]: https://docs.astral.sh/ruff/rules/f-string/ Signed-off-by: Vincent Fazio <vfazio@xes-inc.com> Link: https://lore.kernel.org/r/20241114145116.2123714-23-vfazio@xes-inc.com Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
645 lines
23 KiB
Python
645 lines
23 KiB
Python
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
# SPDX-FileCopyrightText: 2022 Bartosz Golaszewski <brgl@bgdev.pl>
|
|
|
|
from unittest import TestCase
|
|
|
|
import gpiod
|
|
from gpiod.line import Clock, Direction, Drive, Edge, Value
|
|
|
|
from . import gpiosim
|
|
|
|
Pull = gpiosim.Chip.Pull
|
|
SimVal = gpiosim.Chip.Value
|
|
|
|
|
|
class ChipLineRequestsBehaveCorrectlyWithInvalidArguments(TestCase):
|
|
def setUp(self) -> None:
|
|
self.sim = gpiosim.Chip(num_lines=8)
|
|
self.chip = gpiod.Chip(self.sim.dev_path)
|
|
|
|
def tearDown(self) -> None:
|
|
self.chip.close()
|
|
del self.chip
|
|
del self.sim
|
|
|
|
def test_passing_invalid_types_as_configs(self) -> None:
|
|
with self.assertRaises(AttributeError):
|
|
self.chip.request_lines("foobar") # type: ignore[arg-type]
|
|
|
|
with self.assertRaises(AttributeError):
|
|
self.chip.request_lines(None, "foobar") # type: ignore[arg-type]
|
|
|
|
def test_offset_out_of_range(self) -> None:
|
|
with self.assertRaises(ValueError):
|
|
self.chip.request_lines(config={(1, 0, 4, 8): None})
|
|
|
|
def test_line_name_not_found(self) -> None:
|
|
with self.assertRaises(FileNotFoundError):
|
|
self.chip.request_lines(config={"foo": None})
|
|
|
|
def test_request_no_arguments(self) -> None:
|
|
with self.assertRaises(TypeError):
|
|
self.chip.request_lines() # type: ignore[call-arg]
|
|
|
|
|
|
class ModuleLineRequestsBehaveCorrectlyWithInvalidArguments(TestCase):
|
|
def setUp(self) -> None:
|
|
self.sim = gpiosim.Chip(num_lines=8)
|
|
|
|
def tearDown(self) -> None:
|
|
del self.sim
|
|
|
|
def test_passing_invalid_types_as_configs(self) -> None:
|
|
with self.assertRaises(AttributeError):
|
|
gpiod.request_lines(self.sim.dev_path, "foobar") # type: ignore[arg-type]
|
|
|
|
with self.assertRaises(AttributeError):
|
|
gpiod.request_lines(self.sim.dev_path, None, "foobar") # type: ignore[arg-type]
|
|
|
|
def test_offset_out_of_range(self) -> None:
|
|
with self.assertRaises(ValueError):
|
|
gpiod.request_lines(self.sim.dev_path, config={(1, 0, 4, 8): None})
|
|
|
|
def test_line_name_not_found(self) -> None:
|
|
with self.assertRaises(FileNotFoundError):
|
|
gpiod.request_lines(self.sim.dev_path, config={"foo": None})
|
|
|
|
def test_request_no_arguments(self) -> None:
|
|
with self.assertRaises(TypeError):
|
|
gpiod.request_lines() # type: ignore[call-arg]
|
|
|
|
|
|
class ChipLineRequestWorks(TestCase):
|
|
def setUp(self) -> None:
|
|
self.sim = gpiosim.Chip(num_lines=8, line_names={5: "foo", 7: "bar"})
|
|
self.chip = gpiod.Chip(self.sim.dev_path)
|
|
|
|
def tearDown(self) -> None:
|
|
self.chip.close()
|
|
del self.chip
|
|
del self.sim
|
|
|
|
def test_request_with_positional_arguments(self) -> None:
|
|
with self.chip.request_lines({(0, 5, 3, 1): None}, "foobar", 32) as req:
|
|
self.assertEqual(req.offsets, [0, 5, 3, 1])
|
|
self.assertEqual(self.chip.get_line_info(0).consumer, "foobar")
|
|
|
|
def test_request_with_keyword_arguments(self) -> None:
|
|
with self.chip.request_lines(
|
|
config={(0, 5, 6): None},
|
|
consumer="foobar",
|
|
event_buffer_size=16,
|
|
) as req:
|
|
self.assertEqual(req.offsets, [0, 5, 6])
|
|
self.assertEqual(self.chip.get_line_info(0).consumer, "foobar")
|
|
|
|
def test_request_single_offset_as_int(self) -> None:
|
|
with self.chip.request_lines(config={4: None}) as req:
|
|
self.assertEqual(req.offsets, [4])
|
|
|
|
def test_request_single_offset_as_tuple(self) -> None:
|
|
with self.chip.request_lines(config={(4): None}) as req:
|
|
self.assertEqual(req.offsets, [4])
|
|
|
|
def test_request_by_name(self) -> None:
|
|
with self.chip.request_lines(config={(1, 2, "foo", "bar"): None}) as req:
|
|
self.assertEqual(req.offsets, [1, 2, 5, 7])
|
|
|
|
def test_request_single_line_by_name(self) -> None:
|
|
with self.chip.request_lines(config={"foo": None}) as req:
|
|
self.assertEqual(req.offsets, [5])
|
|
|
|
|
|
class ModuleLineRequestWorks(TestCase):
|
|
def setUp(self) -> None:
|
|
self.sim = gpiosim.Chip(num_lines=8, line_names={5: "foo", 7: "bar"})
|
|
|
|
def tearDown(self) -> None:
|
|
del self.sim
|
|
|
|
def test_request_with_positional_arguments(self) -> None:
|
|
with gpiod.request_lines(
|
|
self.sim.dev_path, {(0, 5, 3, 1): None}, "foobar", 32
|
|
) as req:
|
|
self.assertEqual(req.offsets, [0, 5, 3, 1])
|
|
with gpiod.Chip(self.sim.dev_path) as chip:
|
|
self.assertEqual(chip.get_line_info(5).consumer, "foobar")
|
|
|
|
def test_request_with_keyword_arguments(self) -> None:
|
|
with gpiod.request_lines(
|
|
path=self.sim.dev_path,
|
|
config={(0, 5, 6): None},
|
|
consumer="foobar",
|
|
event_buffer_size=16,
|
|
) as req:
|
|
self.assertEqual(req.offsets, [0, 5, 6])
|
|
with gpiod.Chip(self.sim.dev_path) as chip:
|
|
self.assertEqual(chip.get_line_info(5).consumer, "foobar")
|
|
|
|
def test_request_single_offset_as_int(self) -> None:
|
|
with gpiod.request_lines(path=self.sim.dev_path, config={4: None}) as req:
|
|
self.assertEqual(req.offsets, [4])
|
|
|
|
def test_request_single_offset_as_tuple(self) -> None:
|
|
with gpiod.request_lines(path=self.sim.dev_path, config={(4): None}) as req:
|
|
self.assertEqual(req.offsets, [4])
|
|
|
|
def test_request_by_name(self) -> None:
|
|
with gpiod.request_lines(
|
|
self.sim.dev_path, {(1, 2, "foo", "bar"): None}
|
|
) as req:
|
|
self.assertEqual(req.offsets, [1, 2, 5, 7])
|
|
|
|
|
|
class LineRequestGettingValues(TestCase):
|
|
def setUp(self) -> None:
|
|
self.sim = gpiosim.Chip(num_lines=8)
|
|
self.req = gpiod.request_lines(
|
|
self.sim.dev_path,
|
|
{(0, 1, 2, 3): gpiod.LineSettings(direction=Direction.INPUT)},
|
|
)
|
|
|
|
def tearDown(self) -> None:
|
|
self.req.release()
|
|
del self.req
|
|
del self.sim
|
|
|
|
def test_get_single_value(self) -> None:
|
|
self.sim.set_pull(1, Pull.UP)
|
|
|
|
self.assertEqual(self.req.get_values([1]), [Value.ACTIVE])
|
|
|
|
def test_get_single_value_helper(self) -> None:
|
|
self.sim.set_pull(1, Pull.UP)
|
|
|
|
self.assertEqual(self.req.get_value(1), Value.ACTIVE)
|
|
|
|
def test_get_values_for_subset_of_lines(self) -> None:
|
|
self.sim.set_pull(0, Pull.UP)
|
|
self.sim.set_pull(1, Pull.DOWN)
|
|
self.sim.set_pull(3, Pull.UP)
|
|
|
|
self.assertEqual(
|
|
self.req.get_values([0, 1, 3]), [Value.ACTIVE, Value.INACTIVE, Value.ACTIVE]
|
|
)
|
|
|
|
def test_get_all_values(self) -> None:
|
|
self.sim.set_pull(0, Pull.DOWN)
|
|
self.sim.set_pull(1, Pull.UP)
|
|
self.sim.set_pull(2, Pull.UP)
|
|
self.sim.set_pull(3, Pull.UP)
|
|
|
|
self.assertEqual(
|
|
self.req.get_values(),
|
|
[Value.INACTIVE, Value.ACTIVE, Value.ACTIVE, Value.ACTIVE],
|
|
)
|
|
|
|
def test_get_values_invalid_offset(self) -> None:
|
|
with self.assertRaises(ValueError):
|
|
self.req.get_values([9])
|
|
|
|
def test_get_values_invalid_argument_type(self) -> None:
|
|
with self.assertRaises(TypeError):
|
|
self.req.get_values(True) # type: ignore[arg-type]
|
|
|
|
|
|
class LineRequestGettingValuesByName(TestCase):
|
|
def setUp(self) -> None:
|
|
self.sim = gpiosim.Chip(num_lines=4, line_names={2: "foo", 3: "bar", 1: "baz"})
|
|
self.req = gpiod.request_lines(
|
|
self.sim.dev_path,
|
|
{(0, "baz", "bar", "foo"): gpiod.LineSettings(direction=Direction.INPUT)},
|
|
)
|
|
|
|
def tearDown(self) -> None:
|
|
self.req.release()
|
|
del self.req
|
|
del self.sim
|
|
|
|
def test_get_values_by_name(self) -> None:
|
|
self.sim.set_pull(1, Pull.UP)
|
|
self.sim.set_pull(2, Pull.DOWN)
|
|
self.sim.set_pull(3, Pull.UP)
|
|
|
|
self.assertEqual(
|
|
self.req.get_values(["foo", "bar", 1]),
|
|
[Value.INACTIVE, Value.ACTIVE, Value.ACTIVE],
|
|
)
|
|
|
|
def test_get_values_by_bad_name(self) -> None:
|
|
with self.assertRaises(ValueError):
|
|
self.req.get_values(["xyz"])
|
|
|
|
|
|
class LineRequestSettingValues(TestCase):
|
|
def setUp(self) -> None:
|
|
self.sim = gpiosim.Chip(num_lines=8)
|
|
self.req = gpiod.request_lines(
|
|
self.sim.dev_path,
|
|
{(0, 1, 2, 3): gpiod.LineSettings(direction=Direction.OUTPUT)},
|
|
)
|
|
|
|
def tearDown(self) -> None:
|
|
self.req.release()
|
|
del self.req
|
|
del self.sim
|
|
|
|
def test_set_single_value(self) -> None:
|
|
self.req.set_values({1: Value.ACTIVE})
|
|
self.assertEqual(self.sim.get_value(1), SimVal.ACTIVE)
|
|
|
|
def test_set_single_value_helper(self) -> None:
|
|
self.req.set_value(1, Value.ACTIVE)
|
|
self.assertEqual(self.sim.get_value(1), SimVal.ACTIVE)
|
|
|
|
def test_set_values_for_subset_of_lines(self) -> None:
|
|
self.req.set_values({0: Value.ACTIVE, 1: Value.INACTIVE, 3: Value.ACTIVE})
|
|
|
|
self.assertEqual(self.sim.get_value(0), SimVal.ACTIVE)
|
|
self.assertEqual(self.sim.get_value(1), SimVal.INACTIVE)
|
|
self.assertEqual(self.sim.get_value(3), SimVal.ACTIVE)
|
|
|
|
def test_set_values_invalid_offset(self) -> None:
|
|
with self.assertRaises(ValueError):
|
|
self.req.set_values({9: Value.ACTIVE})
|
|
|
|
|
|
class LineRequestSettingValuesByName(TestCase):
|
|
def setUp(self) -> None:
|
|
self.sim = gpiosim.Chip(num_lines=4, line_names={2: "foo", 3: "bar", 1: "baz"})
|
|
self.req = gpiod.request_lines(
|
|
self.sim.dev_path,
|
|
{(0, "baz", "bar", "foo"): gpiod.LineSettings(direction=Direction.OUTPUT)},
|
|
)
|
|
|
|
def tearDown(self) -> None:
|
|
self.req.release()
|
|
del self.req
|
|
del self.sim
|
|
|
|
def test_set_values_by_name(self) -> None:
|
|
self.req.set_values(
|
|
{"foo": Value.INACTIVE, "bar": Value.ACTIVE, 1: Value.ACTIVE}
|
|
)
|
|
|
|
self.assertEqual(self.sim.get_value(2), SimVal.INACTIVE)
|
|
self.assertEqual(self.sim.get_value(1), SimVal.ACTIVE)
|
|
self.assertEqual(self.sim.get_value(3), SimVal.ACTIVE)
|
|
|
|
def test_set_values_by_bad_name(self) -> None:
|
|
with self.assertRaises(ValueError):
|
|
self.req.set_values({"xyz": Value.ACTIVE})
|
|
|
|
|
|
class LineRequestComplexConfig(TestCase):
|
|
def test_complex_config(self) -> None:
|
|
sim = gpiosim.Chip(num_lines=8)
|
|
|
|
with gpiod.Chip(sim.dev_path) as chip:
|
|
with chip.request_lines(
|
|
config={
|
|
(0, 2, 4): gpiod.LineSettings(
|
|
direction=Direction.OUTPUT, output_value=Value.ACTIVE
|
|
),
|
|
(1, 3, 5): gpiod.LineSettings(
|
|
direction=Direction.INPUT,
|
|
edge_detection=Edge.BOTH,
|
|
event_clock=Clock.REALTIME,
|
|
),
|
|
},
|
|
) as req:
|
|
self.assertEqual(chip.get_line_info(2).direction, Direction.OUTPUT)
|
|
self.assertEqual(chip.get_line_info(3).edge_detection, Edge.BOTH)
|
|
self.assertEqual(chip.get_line_info(5).event_clock, Clock.REALTIME)
|
|
|
|
|
|
class LineRequestMixedConfigByName(TestCase):
|
|
def setUp(self) -> None:
|
|
self.sim = gpiosim.Chip(
|
|
num_lines=4, line_names={2: "foo", 3: "bar", 1: "baz", 0: "xyz"}
|
|
)
|
|
self.req = gpiod.request_lines(
|
|
self.sim.dev_path,
|
|
{
|
|
("baz", "bar"): gpiod.LineSettings(direction=Direction.OUTPUT),
|
|
("foo", "xyz"): gpiod.LineSettings(direction=Direction.INPUT),
|
|
},
|
|
)
|
|
|
|
def tearDown(self) -> None:
|
|
self.req.release()
|
|
del self.req
|
|
del self.sim
|
|
|
|
def test_set_values_by_name(self) -> None:
|
|
self.req.set_values({"bar": Value.ACTIVE, "baz": Value.INACTIVE})
|
|
|
|
self.assertEqual(self.sim.get_value(1), SimVal.INACTIVE)
|
|
self.assertEqual(self.sim.get_value(3), SimVal.ACTIVE)
|
|
|
|
def test_get_values_by_name(self) -> None:
|
|
self.sim.set_pull(0, Pull.UP)
|
|
self.sim.set_pull(2, Pull.DOWN)
|
|
|
|
self.assertEqual(
|
|
self.req.get_values(["foo", "xyz", "baz"]),
|
|
[Value.INACTIVE, Value.ACTIVE, Value.INACTIVE],
|
|
)
|
|
|
|
|
|
class RepeatingLinesInRequestConfig(TestCase):
|
|
def setUp(self) -> None:
|
|
self.sim = gpiosim.Chip(num_lines=4, line_names={0: "foo", 2: "bar"})
|
|
self.chip = gpiod.Chip(self.sim.dev_path)
|
|
|
|
def tearDown(self) -> None:
|
|
self.chip.close()
|
|
del self.chip
|
|
del self.sim
|
|
|
|
def test_offsets_repeating_within_the_same_tuple(self) -> None:
|
|
with self.assertRaises(ValueError):
|
|
self.chip.request_lines({(0, 1, 2, 1): None})
|
|
|
|
def test_offsets_repeating_in_different_tuples(self) -> None:
|
|
with self.assertRaises(ValueError):
|
|
self.chip.request_lines({(0, 1, 2): None, (3, 4, 0): None})
|
|
|
|
def test_offset_and_name_conflict_in_the_same_tuple(self) -> None:
|
|
with self.assertRaises(ValueError):
|
|
self.chip.request_lines({(2, "bar"): None})
|
|
|
|
def test_offset_and_name_conflict_in_different_tuples(self) -> None:
|
|
with self.assertRaises(ValueError):
|
|
self.chip.request_lines({(0, 1, 2): None, (4, 5, "bar"): None})
|
|
|
|
|
|
class LineRequestPropertiesWork(TestCase):
|
|
def setUp(self) -> None:
|
|
self.sim = gpiosim.Chip(num_lines=16, line_names={0: "foo", 2: "bar", 5: "baz"})
|
|
|
|
def tearDown(self) -> None:
|
|
del self.sim
|
|
|
|
def test_property_fd(self) -> None:
|
|
with gpiod.request_lines(
|
|
self.sim.dev_path,
|
|
config={
|
|
0: gpiod.LineSettings(
|
|
direction=Direction.INPUT, edge_detection=Edge.BOTH
|
|
)
|
|
},
|
|
) as req:
|
|
self.assertGreaterEqual(req.fd, 0)
|
|
|
|
def test_property_num_lines(self) -> None:
|
|
with gpiod.request_lines(
|
|
self.sim.dev_path, config={(0, 2, 3, 5, 6, 8, 12): None}
|
|
) as req:
|
|
self.assertEqual(req.num_lines, 7)
|
|
|
|
def test_property_offsets(self) -> None:
|
|
with gpiod.request_lines(
|
|
self.sim.dev_path, config={(1, 6, 12, 4): None}
|
|
) as req:
|
|
self.assertEqual(req.offsets, [1, 6, 12, 4])
|
|
|
|
def test_property_lines(self) -> None:
|
|
with gpiod.request_lines(
|
|
self.sim.dev_path, config={("foo", 1, "bar", 4, "baz"): None}
|
|
) as req:
|
|
self.assertEqual(req.lines, ["foo", 1, "bar", 4, "baz"])
|
|
|
|
|
|
class LineRequestConsumerString(TestCase):
|
|
def setUp(self) -> None:
|
|
self.sim = gpiosim.Chip(num_lines=4)
|
|
self.chip = gpiod.Chip(self.sim.dev_path)
|
|
|
|
def tearDown(self) -> None:
|
|
self.chip.close()
|
|
del self.chip
|
|
del self.sim
|
|
|
|
def test_custom_consumer(self) -> None:
|
|
with self.chip.request_lines(
|
|
consumer="foobar", config={(2, 3): None}
|
|
) as request:
|
|
info = self.chip.get_line_info(2)
|
|
self.assertEqual(info.consumer, "foobar")
|
|
|
|
def test_empty_consumer(self) -> None:
|
|
with self.chip.request_lines(consumer="", config={(2, 3): None}) as request:
|
|
info = self.chip.get_line_info(2)
|
|
self.assertEqual(info.consumer, "?")
|
|
|
|
def test_default_consumer(self) -> None:
|
|
with self.chip.request_lines(config={(2, 3): None}) as request:
|
|
info = self.chip.get_line_info(2)
|
|
self.assertEqual(info.consumer, "?")
|
|
|
|
|
|
class LineRequestSetOutputValues(TestCase):
|
|
def setUp(self) -> None:
|
|
self.sim = gpiosim.Chip(
|
|
num_lines=4, line_names={0: "foo", 1: "bar", 2: "baz", 3: "xyz"}
|
|
)
|
|
|
|
def tearDown(self) -> None:
|
|
del self.sim
|
|
|
|
def test_request_with_globally_set_output_values(self) -> None:
|
|
with gpiod.request_lines(
|
|
self.sim.dev_path,
|
|
config={(0, 1, 2, 3): gpiod.LineSettings(direction=Direction.OUTPUT)},
|
|
output_values={
|
|
0: Value.ACTIVE,
|
|
1: Value.INACTIVE,
|
|
2: Value.ACTIVE,
|
|
3: Value.INACTIVE,
|
|
},
|
|
) as request:
|
|
self.assertEqual(self.sim.get_value(0), SimVal.ACTIVE)
|
|
self.assertEqual(self.sim.get_value(1), SimVal.INACTIVE)
|
|
self.assertEqual(self.sim.get_value(2), SimVal.ACTIVE)
|
|
self.assertEqual(self.sim.get_value(3), SimVal.INACTIVE)
|
|
|
|
def test_request_with_globally_set_output_values_with_mapping(self) -> None:
|
|
with gpiod.request_lines(
|
|
self.sim.dev_path,
|
|
config={(0, 1, 2, 3): gpiod.LineSettings(direction=Direction.OUTPUT)},
|
|
output_values={"baz": Value.ACTIVE, "foo": Value.ACTIVE},
|
|
) as request:
|
|
self.assertEqual(self.sim.get_value(0), SimVal.ACTIVE)
|
|
self.assertEqual(self.sim.get_value(1), SimVal.INACTIVE)
|
|
self.assertEqual(self.sim.get_value(2), SimVal.ACTIVE)
|
|
self.assertEqual(self.sim.get_value(3), SimVal.INACTIVE)
|
|
|
|
def test_request_with_globally_set_output_values_bad_mapping(self) -> None:
|
|
with self.assertRaises(FileNotFoundError):
|
|
with gpiod.request_lines(
|
|
self.sim.dev_path,
|
|
config={(0, 1, 2, 3): gpiod.LineSettings(direction=Direction.OUTPUT)},
|
|
output_values={"foobar": Value.ACTIVE},
|
|
) as request:
|
|
pass
|
|
|
|
def test_request_with_globally_set_output_values_bad_offset(self) -> None:
|
|
with self.assertRaises(ValueError):
|
|
with gpiod.request_lines(
|
|
self.sim.dev_path,
|
|
config={(0, 1, 2, 3): gpiod.LineSettings(direction=Direction.OUTPUT)},
|
|
output_values={5: Value.ACTIVE},
|
|
) as request:
|
|
pass
|
|
|
|
|
|
class ReconfigureRequestedLines(TestCase):
|
|
def setUp(self) -> None:
|
|
self.sim = gpiosim.Chip(num_lines=8, line_names={3: "foo", 4: "bar", 6: "baz"})
|
|
self.chip = gpiod.Chip(self.sim.dev_path)
|
|
self.req = self.chip.request_lines(
|
|
{
|
|
(0, 2, "foo", "baz"): gpiod.LineSettings(
|
|
direction=Direction.OUTPUT, active_low=True, drive=Drive.OPEN_DRAIN
|
|
)
|
|
}
|
|
)
|
|
|
|
def tearDown(self) -> None:
|
|
self.chip.close()
|
|
del self.chip
|
|
self.req.release()
|
|
del self.req
|
|
del self.sim
|
|
|
|
def test_reconfigure_by_offsets(self) -> None:
|
|
info = self.chip.get_line_info(2)
|
|
self.assertEqual(info.direction, Direction.OUTPUT)
|
|
self.req.reconfigure_lines(
|
|
{(0, 2, 3, 6): gpiod.LineSettings(direction=Direction.INPUT)}
|
|
)
|
|
info = self.chip.get_line_info(2)
|
|
self.assertEqual(info.direction, Direction.INPUT)
|
|
|
|
def test_reconfigure_by_names(self) -> None:
|
|
info = self.chip.get_line_info(2)
|
|
self.assertEqual(info.direction, Direction.OUTPUT)
|
|
self.req.reconfigure_lines(
|
|
{(0, 2, "foo", "baz"): gpiod.LineSettings(direction=Direction.INPUT)}
|
|
)
|
|
info = self.chip.get_line_info(2)
|
|
self.assertEqual(info.direction, Direction.INPUT)
|
|
|
|
def test_reconfigure_by_misordered_offsets(self) -> None:
|
|
info = self.chip.get_line_info(2)
|
|
self.assertEqual(info.direction, Direction.OUTPUT)
|
|
self.req.reconfigure_lines(
|
|
{(6, 0, 3, 2): gpiod.LineSettings(direction=Direction.INPUT)}
|
|
)
|
|
info = self.chip.get_line_info(2)
|
|
self.assertEqual(info.direction, Direction.INPUT)
|
|
|
|
def test_reconfigure_by_misordered_names(self) -> None:
|
|
info = self.chip.get_line_info(2)
|
|
self.assertEqual(info.direction, Direction.OUTPUT)
|
|
self.req.reconfigure_lines(
|
|
{(0, "baz", 2, "foo"): gpiod.LineSettings(direction=Direction.INPUT)}
|
|
)
|
|
info = self.chip.get_line_info(2)
|
|
self.assertEqual(info.direction, Direction.INPUT)
|
|
|
|
def test_reconfigure_with_default(self) -> None:
|
|
info = self.chip.get_line_info(2)
|
|
self.assertEqual(info.direction, Direction.OUTPUT)
|
|
self.assertTrue(info.active_low)
|
|
self.assertEqual(info.drive, Drive.OPEN_DRAIN)
|
|
self.req.reconfigure_lines(
|
|
{
|
|
0: gpiod.LineSettings(direction=Direction.INPUT),
|
|
2: None,
|
|
("baz", "foo"): gpiod.LineSettings(direction=Direction.INPUT),
|
|
}
|
|
)
|
|
info = self.chip.get_line_info(0)
|
|
self.assertEqual(info.direction, Direction.INPUT)
|
|
info = self.chip.get_line_info(2)
|
|
self.assertEqual(info.direction, Direction.OUTPUT)
|
|
self.assertTrue(info.active_low)
|
|
self.assertEqual(info.drive, Drive.OPEN_DRAIN)
|
|
|
|
def test_reconfigure_missing_offsets(self) -> None:
|
|
info = self.chip.get_line_info(2)
|
|
self.assertEqual(info.direction, Direction.OUTPUT)
|
|
self.assertTrue(info.active_low)
|
|
self.assertEqual(info.drive, Drive.OPEN_DRAIN)
|
|
self.req.reconfigure_lines(
|
|
{(6, 0): gpiod.LineSettings(direction=Direction.INPUT)}
|
|
)
|
|
info = self.chip.get_line_info(0)
|
|
self.assertEqual(info.direction, Direction.INPUT)
|
|
info = self.chip.get_line_info(2)
|
|
self.assertEqual(info.direction, Direction.OUTPUT)
|
|
self.assertTrue(info.active_low)
|
|
self.assertEqual(info.drive, Drive.OPEN_DRAIN)
|
|
|
|
def test_reconfigure_extra_offsets(self) -> None:
|
|
info = self.chip.get_line_info(2)
|
|
self.assertEqual(info.direction, Direction.OUTPUT)
|
|
self.req.reconfigure_lines(
|
|
{(0, 2, 3, 6, 5): gpiod.LineSettings(direction=Direction.INPUT)}
|
|
)
|
|
info = self.chip.get_line_info(2)
|
|
self.assertEqual(info.direction, Direction.INPUT)
|
|
|
|
|
|
class ReleasedLineRequestCannotBeUsed(TestCase):
|
|
def test_using_released_line_request(self) -> None:
|
|
sim = gpiosim.Chip()
|
|
|
|
with gpiod.Chip(sim.dev_path) as chip:
|
|
req = chip.request_lines(config={0: None})
|
|
req.release()
|
|
|
|
with self.assertRaises(gpiod.RequestReleasedError):
|
|
_ = req.fd
|
|
|
|
|
|
class LineRequestSurvivesParentChip(TestCase):
|
|
def test_line_request_survives_parent_chip(self) -> None:
|
|
sim = gpiosim.Chip()
|
|
|
|
chip = gpiod.Chip(sim.dev_path)
|
|
try:
|
|
req = chip.request_lines(
|
|
config={0: gpiod.LineSettings(direction=Direction.INPUT)}
|
|
)
|
|
except:
|
|
chip.close()
|
|
raise
|
|
|
|
chip.close()
|
|
self.assertEqual(req.get_values([0]), [Value.INACTIVE])
|
|
req.release()
|
|
|
|
|
|
class LineRequestStringRepresentation(TestCase):
|
|
def setUp(self) -> None:
|
|
self.sim = gpiosim.Chip(num_lines=8)
|
|
|
|
def tearDown(self) -> None:
|
|
del self.sim
|
|
|
|
def test_str(self) -> None:
|
|
with gpiod.Chip(self.sim.dev_path) as chip:
|
|
with chip.request_lines(config={(2, 6, 4, 1): None}) as req:
|
|
self.assertEqual(
|
|
str(req),
|
|
f'<LineRequest chip="{self.sim.name}" num_lines=4 offsets=[2, 6, 4, 1] fd={req.fd}>',
|
|
)
|
|
|
|
def test_str_released(self) -> None:
|
|
req = gpiod.request_lines(self.sim.dev_path, config={(2, 6, 4, 1): None})
|
|
req.release()
|
|
self.assertEqual(str(req), "<LineRequest RELEASED>")
|