Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Supporting with-statements #128

Open
erikbgithub opened this issue Sep 14, 2022 · 1 comment
Open

Supporting with-statements #128

erikbgithub opened this issue Sep 14, 2022 · 1 comment

Comments

@erikbgithub
Copy link

As the library already has a class, an open() method and a close() method, it would make sense to add the small steps needed to make it callable in a with statement. However, as it's a c-Extension I currently don't feel confident that I could write the code alone.

In Python I would add this:

class SpiDev(...):
    def __init__(self, param1, ...):
        ...
        self.param1 = param1
    ...
    def __enter__(self):
        self.open(self.param1)

    def __exit__(self):
        self.close()

    def __del__(self):
        self.close()

When the with statement is entered, the connection is opened. When it is left, the connection gets closed. Even in case of an exception. And just in case, the connection gets closed on object deletion as well.

More explanation regarding the value of supporting with.

Is there someone who has experience in transferring that idea to the C codebase here?

PS: Locally, I might simply add a wrapper class that gets the new methods added.

@yochem
Copy link

yochem commented Nov 18, 2024

It seems like this is currently implemented:

py-spidev/spidev_module.c

Lines 1409 to 1432 in ac2671e

PyObject *SpiDev_enter(PyObject *self, PyObject *args)
{
if (!PyArg_ParseTuple(args, ""))
return NULL;
Py_INCREF(self);
return self;
}
static
PyObject *SpiDev_exit(SpiDevObject *self, PyObject *args)
{
PyObject *exc_type = 0;
PyObject *exc_value = 0;
PyObject *traceback = 0;
if (!PyArg_UnpackTuple(args, "__exit__", 3, 3, &exc_type, &exc_value,
&traceback)) {
return 0;
}
SpiDev_close(self);
Py_RETURN_FALSE;
}

This should support something like:

with spidev.SpiDev() as spi:
   ...

However, with my level of understanding Python C modules, it seems like you would still need to call the open() method in the with-statement, and only the close() method is called for you:

How I think it would currently work:

with spidev.SpiDev() as spi:
   spi.open(0, 0)
   spi.max_speed_hz = 4_000_000
   spi.writebyte([0x00])

I am currently also not able to test this.

How I wish it would work:

with spidev.SpiDev(bus=0, device=0, max_speed_hz=4_000_000) as spi:
   spi.writebyte([0x00])

Or maybe even better, keeping the SPI object initialized but not opened:

spi_device = spidev.SpiDev(bus=0, device=0, max_speed_hz=4_000_000)

with spi_device.open() as conn:
   conn.writebyte([0x00])

# do some other stuff here...

with spi_device.open() as conn:
   conn.writebyte([0xFF])

@doceme In general, would it be an idea to document the interface for this package? Maybe autogenerate API documentation? I also feel the current readme is not sufficient, as it for example lacks documentation about this feature. If you would be interested, I could investigate the possibilities.

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

No branches or pull requests

2 participants