labgrid-project / labgrid

Embedded systems control library for development, testing and installation
https://labgrid.readthedocs.io/
Other
315 stars 163 forks source link

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

Open Bastian-Krause opened 1 month ago

Bastian-Krause commented 1 month ago

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:

https://github.com/labgrid-project/labgrid/blob/9e0562e1c8d6842c850c239d64896b88c3bf3bd1/labgrid/target.py#L403-L418

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.

Emantor commented 1 month ago

IMO we should fix the __str__ call sites as there are only two.