Skip to content

SerialDriver: BindingErrors hidden by AttributeError caused by not (yet) set target #1414

Description

@Bastian-Krause

When creating an env config with wrong SerialDriver bindings, a completely unrelated error happens:

$ labgrid-client con                                                                            
Selected role main from configuration file
Traceback (most recent call last):
  File "labgrid/labgrid/remote/client.py", line 1934, in main
    target = session._get_target(place)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "labgrid/labgrid/remote/client.py", line 671, in _get_target
    target = self.env.get_target(self.role)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "labgrid/labgrid/environment.py", line 49, in get_target
    target = target_factory.make_target(role, config, env=self)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "labgrid/labgrid/factory.py", line 159, in make_target
    self.make_driver(target, driver, name, args)
  File "labgrid/labgrid/factory.py", line 138, in make_driver
    d = cls(target, name, **args)
        ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<attrs generated init labgrid.driver.serialdriver.SerialDriver>", line 11, in __init__
    self.__attrs_post_init__()
  File "labgrid/labgrid/driver/serialdriver.py", line 26, in __attrs_post_init__
    super().__attrs_post_init__()
  File "labgrid/labgrid/driver/consoleexpectmixin.py", line 18, in __attrs_post_init__
    super().__attrs_post_init__()
  File "labgrid/labgrid/driver/common.py", line 25, in __attrs_post_init__
    super().__attrs_post_init__()
  File "labgrid/labgrid/binding.py", line 55, in __attrs_post_init__
    target.bind(self)
  File "labgrid/labgrid/target.py", line 430, in bind
    return self.bind_driver(bindable)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "labgrid/labgrid/target.py", line 406, in bind_driver
    f"{client} got unexpected bindings: {list(mapping.keys())}"
      ^^^^^^^^
  File "labgrid/labgrid/driver/serialdriver.py", line 116, in __str__
    return f"SerialDriver({self.target.name})"
                           ^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'name'

When dropping SerialDriver's __str___() the actual error cause is shown:

$ labgrid-client con
Selected role main from configuration file
Traceback (most recent call last):
  File "labgrid/labgrid/remote/client.py", line 1934, in main
    target = session._get_target(place)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "labgrid/labgrid/remote/client.py", line 671, in _get_target
    target = self.env.get_target(self.role)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "labgrid/labgrid/environment.py", line 49, in get_target
    target = target_factory.make_target(role, config, env=self)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "labgrid/labgrid/factory.py", line 159, in make_target
    self.make_driver(target, driver, name, args)
  File "labgrid/labgrid/factory.py", line 138, in make_driver
    d = cls(target, name, **args)
        ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<attrs generated init labgrid.driver.serialdriver.SerialDriver>", line 11, in __init__
    self.__attrs_post_init__()
  File "labgrid/labgrid/driver/serialdriver.py", line 26, in __attrs_post_init__
    super().__attrs_post_init__()
  File "labgrid/labgrid/driver/consoleexpectmixin.py", line 18, in __attrs_post_init__
    super().__attrs_post_init__()
  File "labgrid/labgrid/driver/common.py", line 25, in __attrs_post_init__
    super().__attrs_post_init__()
  File "labgrid/labgrid/binding.py", line 55, in __attrs_post_init__
    target.bind(self)
  File "labgrid/labgrid/target.py", line 430, in bind
    return self.bind_driver(bindable)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "labgrid/labgrid/target.py", line 405, in bind_driver
    raise BindingError(
labgrid.binding.BindingError: SerialDriver() got unexpected bindings: ['serial']

This happens because the target checks if the driver (called client here) consumed all bindings before setting itself to client.target:

labgrid/labgrid/target.py

Lines 403 to 418 in 9e0562e

# make sure drivers consume all given bindings
if mapping and not isinstance(client, Strategy):
raise BindingError(
f"{client} got unexpected bindings: {list(mapping.keys())}"
)
# update relationship in both directions
self.drivers.append(client)
# update lookup table
cls = client.__class__
self._lookup_table[cls.__name__] = cls
for c in cls.mro():
if abc.ABC in c.mro():
self._lookup_table[c.__name__] = c
client.target = self

If that check fails, the driver's __str__() is called. In the case of the SerialDriver, self.target.name is used in this method.

I am not really sure what's the correct fix. Setting client.target = self earlier? I am unsure about the implications.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions