IronLanguages / ironpython3

Implementation of Python 3.x for .NET Framework that is built on top of the Dynamic Language Runtime.
Apache License 2.0
2.5k stars 287 forks source link

pyserial throws exception when creating serial port #1439

Open maBarabas opened 2 years ago

maBarabas commented 2 years ago

Description

A strange exception is produced when trying to use pyserial on windows. The same version of pyserial works correctly on the official python implementation.

Is this because of pyserial using ctypes? I see that numpy is not supported because it is implemented in C.

(.venv) C:\Users\barabas\snip>ipy
IronPython 3.4.0b1 (3.4.0.0010)
[.NETFramework,Version=v4.6 on .NET Framework 4.8.4470.0 (64-bit)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import serial
>>> serial.Serial("COM4")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\barabas\snip\.venv\lib\site-packages\serial\serialwin32.py", line 33, in __init__
  File "C:\Users\barabas\snip\.venv\lib\site-packages\serial\serialutil.py", line 244, in __init__
TypeError: expected int or long, got bool

The lines are:

    def __init__(self, *args, **kwargs):
        self._port_handle = None
        self._overlapped_read = None
        self._overlapped_write = None
        super(Serial, self).__init__(*args, **kwargs) # here

and

        if port is not None:
            self.open() # here        

Steps to Reproduce

  1. Install pyserial==3.5, IronPython 3.4.0b1 on Windows
  2. Connect a USB to serial adapter
  3. Start ipy and run the commands from above

Expected behavior: Serial port is created

Actual behavior: Exception thrown

Versions

You can get this information from executing ipy -V.

IronPython 3.4.0b1

pip freeze:

pyserial==3.5
robotframework==4.1.3
typing==3.10.0.0
slozier commented 2 years ago

Thanks for the report. I think this occurs whenever a boolean is assigned to ctypes field with a bit count. Managed to hit the exception with code like this:

import ctypes

class Test(ctypes.Structure):
    _fields_ = [("x", ctypes.c_bool, 1)]

assert Test(True).x is True
BCSharp commented 2 years ago

This seems to be easy to fix. @slozier are you working on it or shall I pick it up?

slozier commented 2 years ago

@BCSharp go for it

BCSharp commented 2 years ago

1441 fixed the issue as reported by @slozier but I can't verify it solves the original issue as I don't have a serial port or a serial adapter. @maBarabas, can you confirm it is working now?

sensokame commented 2 years ago

am not sure if this is still relevant, but am getting a similar exception when trying to use serial

script used :

port = serial.Serial("COM3")
port.open()

port.close()

exception thrown: [2022-07-29 13:48:41]: serial_try Exception: could not open port 'COM3': OSError(22, 'The operation completed successfully') in "serial\serialwin32.py" function "open" at line: 72 in "serial\serialutil.py" function "init" at line: 244 in "serial\serialwin32.py" function "init" at line: 33 in "scripts\serial_try.py" at line: 7

I navigated to the code, and found that it calls CreateFile from win32 but as you can see from the exception, the operation was successful, but the handle being returned was invalid

if this another bug or invalid handling from my side?

ironpython version 3.4.0-alpha1

sensokame commented 2 years ago

I did some digging, and turns out that pyserial no longer detects ironpython newer versions;

so I created a pull request in pyserial to fix this issue

https://github.com/pyserial/pyserial/pull/661

slozier commented 2 years ago

@sensokame Thanks for the report. I managed to get the same error with alpha1 and with beta1 the same issue as the original poster. However, the issue appears to have been resolved with the latest bits:

>>> import serial
>>> serial.Serial("COM1")
Serial<id=0x2b, open=True>(port='COM1', baudrate=9600, bytesize=8, parity='N', stopbits=1, timeout=None, xonxoff=False, rtscts=False, dsrdtr=False)