evil-mad / axidraw

Software for the AxiDraw drawing machine
GNU General Public License v2.0
433 stars 131 forks source link

AttributeError: 'AxiDraw' object has no attribute 'x_bounds_max' #131

Closed dcposch closed 2 years ago

dcposch commented 2 years ago

To reproduce

    ad = axidraw.AxiDraw()
    ad.interactive()
    ad.connect()
    ad.moveto(0, 0)

Error

  File "/Users/dc/code/art/plotter-art/common.py", line 67, in safe_plot
    ad.moveto(0, 0)
  File "/usr/local/lib/python3.9/site-packages/pyaxidraw/axidraw.py", line 287, in moveto
    self._xy_plot_segment(False,x_target, y_target)
  File "/usr/local/lib/python3.9/site-packages/pyaxidraw/axidraw.py", line 194, in _xy_plot_segment
    if math.isclose(x_value, self.x_bounds_max, abs_tol=1e-9):
AttributeError: 'AxiDraw' object has no attribute 'x_bounds_max'

Possible culprit

The following 3.5.0 diff:

https://github.com/evil-mad/axidraw/commit/e753fdebc5aff05cb8d77cdeca904502509b463b#r83903872

dcposch commented 2 years ago

This is actually the failure mode if you run without the USB not fully plugged in.

I recommend throwing a descriptive error in that situation.

For example, connect() could throw rather than return False when it detects disconnection.

oskay commented 2 years ago

The AxiDraw Python API is designed to let you add your own logic around whether a connection was successful or not. A failure to connect does not warrant returning with an error.

The code in our examples and in the API documentation is typically something like:

connected = ad.connect()
if not connected:
    return

Additionally, a failure to connect automatically prints a "Failed to connect to AxiDraw" message. I would call that reasonably descriptive. The reasons for that failure can be a cable not plugged in, a port in use, or a permissions error, and determining which is which is sometimes a challenge.

We do not want to raise an error automatically upon a failure to connect. There are a number of use cases, particularly those working with multiple AxiDraw machines, that benefit from being able to try connecting.

dcposch commented 2 years ago

You could have a second try_connect() for the rare case where someone wants to connect to AxiDraw, then continue even if the connection fails.

Crashing with what looks like a type error later on, when the actual issue is that the cable was unplugged is definitely a surprising behavior.

I should say I'm a happy customer overall. The AxiV3 is an amazing machine, very fun watching it work.

dcposch commented 2 years ago

Got the pattern from here btw

Screen Shot 2022-09-14 at 11 13 27 AM
oskay commented 2 years ago

We will not make a breaking change to the behavior of the function. It is working as intended and there are significant costs in making breaking changes in the API.

We could potentially add a second function (maybe connect_quick()?) that throws an error on a failure to connect. However, this is not something that has come up as a regular feature request, nor something that we frequently see people run into as an issue.

We did add two new issues on our internal issue tracker yesterday:

I will add one more today:

oskay commented 2 years ago

Fixes (as described above) added in v 3.6.

The original example reported to reproduce this issue now fails "properly" with RuntimeError: Not connected to AxiDraw.