Skip to content

Conversation

@jepler
Copy link

@jepler jepler commented Nov 7, 2024

Now it's possible to construct outputs or enable pulls immediately:

>>> d = digitalio.DigitalInOut(board.A0, pull=digitalio.Pull.UP)
>>> d.pull
digitalio.Pull.UP
>>> d = digitalio.DigitalInOut(board.A0, value=True)
>>> d.direction
digitalio.Direction.OUTPUT
>>> d.value
True
>>> d = digitalio.DigitalInOut(board.A0, value=False, drive_mode=digitalio.DriveMode.OPEN_DRAIN)
>>> d.drive_mode
digitalio.DriveMode.OPEN_DRAIN

The finaliser means that if a pin object is allowed to go out of scope, then it will be deinitialized automatically when GC runs. this is a potential incompatibility: some hypothetical code that intentionally leaked a pin might function differently, i.e.

digitalio.DigitalInOut(board.A0).switch_to_output(True)

as a way to stick a pin in output mode indefinitely will no longer work (but may still appear to work "for awhile" because gc doesn't run right away).

I made this change in part because it simplifies error handling in the constructor: An incorrect argument would otherwise have left the pin stuck in allocated state until the interpreter was reset; with this change, it's available again though not until the GC runs so it would remain perplexing in interactive situations:

>>> d = digitalio.DigitalInOut(board.A0, pull=7)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: pull must be of type Pull or None, not int
>>> d = digitalio.DigitalInOut(board.A0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: A0 in use
>>> gc.collect()
>>> d = digitalio.DigitalInOut(board.A0)
>>> d
<DigitalInOut>

Now it's possible to construct outputs or enable pulls immediately:

```py
>>> d = digitalio.DigitalInOut(board.A0, pull=digitalio.Pull.UP)
>>> d.pull
digitalio.Pull.UP
```

```py
>>> d = digitalio.DigitalInOut(board.A0, value=True)
>>> d.direction
digitalio.Direction.OUTPUT
>>> d.value
True
```

```py
>>> d = digitalio.DigitalInOut(board.A0, value=False, drive_mode=digitalio.DriveMode.OPEN_DRAIN)
>>> d.drive_mode
digitalio.DriveMode.OPEN_DRAIN
```

The finaliser means that if a pin object is allowed to go out of scope,
then it will be deinitialized automatically when GC runs. **this is a
potential incompatibility**: some hypothetical code that intentionally
leaked a pin might function differently, i.e.
```py
digitalio.DigitalInOut(board.A0).switch_to_output(True)
```
as a way to stick a pin in output mode indefinitely will no longer work
(but may still appear to work "for awhile" because gc doesn't run right
away).

I made this change in part because it simplifies error handling in the
constructor: An incorrect argument would otherwise have left the pin
stuck in allocated state until the interpreter was reset; with this
change, it's available again though not until the GC runs so it would
remain perplexing in interactive situations:
```py
>>> d = digitalio.DigitalInOut(board.A0, pull=7)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: pull must be of type Pull or None, not int
>>> d = digitalio.DigitalInOut(board.A0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: A0 in use
>>> gc.collect()
>>> d = digitalio.DigitalInOut(board.A0)
>>> d
<DigitalInOut>
```
@jepler
Copy link
Author

jepler commented Nov 7, 2024

On reflection I think that the constructor error handling needs to ensure the object's immediately deallocated. but I'll let this run and get some important info: does this fit, or does it add enough code to overflow our most constrained builds...?

@dhalbert
Copy link
Collaborator

dhalbert commented Nov 7, 2024

I have been wanting this for years :) . I hope it fits.

@dhalbert
Copy link
Collaborator

dhalbert commented Nov 7, 2024

But @tannewt has not been in favor of some of this: see #5124 and #8534.

@jepler
Copy link
Author

jepler commented Nov 8, 2024

And it doesn't fit, either

@jepler jepler closed this Nov 8, 2024
@relic-se
Copy link

relic-se commented Nov 8, 2024

From @tannewt 's comments on #8534 :

Having direction in the constructor would require cross parameter validation (if pull is set but direction is output then fail.)

Is there a specific reason why cross parameter validation would be something to avoid within DigitalInOut or other classes?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants