1. 09 Jan, 2022 10 commits
  2. 15 Dec, 2021 4 commits
  3. 13 Dec, 2021 3 commits
  4. 27 Nov, 2021 1 commit
  5. 22 Nov, 2021 1 commit
  6. 19 Nov, 2021 1 commit
    • Julien Prigent's avatar
      [HaClient] Allow init from executor · 6a6b13e6
      Julien Prigent authored
      With py3.10, high level asyncio API can't specify the event_loop
      argument anymore.
      
      Consequently When using thread dedicated to run the event_.loop, we now need to
      instantiate object like asyncio.Lock within the thread. However, the
      event loop can't be running before creating these objects as
      `loop.run_for_ever()` must be the background running thread process.
      Therefore we can't have "get_running_loop()" calls in object
      constructors (like HaClient)
      when used with executors.
      
      Before
      ```
      In [15]: def get_t():
          ...:     loop = asyncio.new_event_loop()
          ...:     t = T()
          ...:     loop.run_for_ever()
      
      In [16]: class T:
          ...:     def __init__(self, loop):
          ...:         asyncio.set_event_loop(loop)
          ...:         asyncio.get_running_loop()
          ...:         self.l = asyncio.Lock()
          ...:         print("Lock created")
          ...:
      
      In [17]: t = Thread(target=get_t);t.start()
      
      Exception in thread Thread-9:
      Traceback (most recent call last):
        File "/usr/local/lib/python3.8/threading.py", line 932, in _bootstrap_inner
      In [41]:     self.run()
        File "/usr/local//lib/python3.8/threading.py", line 870, in run
      In [41]:     self._target(*self._args, **self._kwargs)
        File "<ipython-input-32-c4a1ea4cfdac>", line 3, in get_t
        File "<ipython-input-39-ebeae10dd173>", line 4, in __init__
      RuntimeError: no running event loop
      ```
      After
      
      ```
      In [15]: def get_t():
          ...:     loop = asyncio.new_event_loop()
          ...:     t = T()
          ...:     loop.run_for_ever()
      
      In [16]: class T:
          ...:     def __init__(self, loop):
          ...:         asyncio.set_event_loop(loop)
          ...:         self.l = asyncio.Lock()
          ...:         print("Lock created")
          ...:
      
      In [17]: t = Thread(target=get_t);t.start()
      
      Lock created
      
      ```
      6a6b13e6
  7. 15 Nov, 2021 2 commits
  8. 12 Nov, 2021 4 commits
    • janfelixklein's avatar
      Changes to xmlimporter to load customn data types when needed (#719) · 77796a37
      janfelixklein authored
      * Update xmlimporter.py
      
      This allows to load information about newly created data types in the same import process
      
      * Update xmlparser.py
      
      with this we can set the value to newly created datatypes
      
      * Update ua_utils.py
      
      This is conform to the I40AAS nodeset enumerations, e.g. given enumeration as "AccessPermissionRule_0" specifying the type and the integer
      
      * Update xmlimporter.py
      
      small changes due to necessary async and await
      
      * Update xmlparser.py
      
      switched from try/catch to check
      77796a37
    • oroulet's avatar
      new release v0.9.92 · 9b717c81
      oroulet authored
      9b717c81
    • oroulet's avatar
      86e9cc15
    • Julien Prigent's avatar
      [Safe Client disconnect] · 560eb91e
      Julien Prigent authored
      Follow-up of #711
      Make sure calling disconnect is safe when connection isn't established
      or half-established (i.e: protocol/transport exist but session is not
      ready).
      
      Test1
      Call to disconnect is safe when there's no existing connection
      ```
      > python -m IPython
      Python 3.10.0 (default, Oct 13 2021, 06:45:00) [Clang 13.0.0 (clang-1300.0.29.3)]
      
      In [1]: import sys; sys.path.insert(0, "~/Documents/github/opcua-asyncio"); import asyncua; c = asyncua.Client(url="opc.tcp://localhost:4840",timeout=10
         ...: );
      
      In [2]: await c.disconnect()
      close_session but connection wasn't established
      close_secure_channel was called but connection is closed
      
      In [3]:
      ```
      Test2
      
      Calling to disconnect is safe when there's no session established.
      To simulate this, I add delay to the server internal_session on session
      creation. I check that the client connects and disconnect from the
      server logs. Finally, the client doesn't raise any error.
      Ad delay to the internal server
      ```
      > python -m IPython
      Python 3.10.0 (default, Oct 13 2021, 06:45:00) [Clang 13.0.0 (clang-1300.0.29.3)]
      In [1]: import sys; sys.path.insert(0, "~/Documents/github/opcua-asyncio"); import asyncua; c = asyncua.Client(url="opc.tcp://localhost:4840",timeout=10
         ...: ); import threading; import asyncio;
      
      In [2]:
      
      In [2]: async def connect(c):
         ...:     await c.connect()
         ...:
      
      In [3]: async def disco(c):
         ...:     await c.disconnect()
         ...:
      
      In [4]: L = await asyncio.gather(connect(c), disco(c))
      close_session but connection wasn't established
      close_secure_channel was called but connection is closed
      
      In [5]: quit;
      ```
      560eb91e
  9. 11 Nov, 2021 3 commits
    • Julien Prigent's avatar
      [HaClient] Fix test race condition · b5edbdeb
      Julien Prigent authored
      According to the logs of the recent test failure, there's a small window when we test the connection is established where we have a socket connected but don't have the session created yet, and this is throwing exception when trying to disconnect because the renew loop is not yet created.
      
      This is caused by the HaManager (in charge of connecting/reconnecting the clients) running in its own task, thus we're not in the usual await connect(); await disconnect() scenario.
      This can also arguably be fixed at the client level by checking if
      the renew loop exist on disconnect.
      b5edbdeb
    • oroulet's avatar
      68b50bbf
    • oroulet's avatar
      revert and fix Variant array · 1449ba53
      oroulet authored
      1449ba53
  10. 10 Nov, 2021 1 commit
    • Julien Prigent's avatar
      [PyPi] Missing files · 100a711b
      Julien Prigent authored
      The HaClient is missing from the PyPi package:
      
      ```
      [/tmp]> curl https://codeload.github.com/FreeOpcUa/opcua-asyncio/tar.gz/refs/tags/v0.9.91 -s -o v0.9.91.tar.gz
      [/tmp]> tar xvf v0.9.91.tar.gz > /dev/null 2>&1
      [/tmp]> cd opcua-asyncio-0.9.91/
      [/tmp/opcua-asyncio-0.9.91]> python setup.py install > /dev/null 2>&1
      [/tmp/opcua-asyncio-0.9.91]> find build/ -type f |grep -i ha
      build//lib/tests/test_ha_client.py
      build//lib/asyncua/ua/uaprotocol_hand.py
      ```
      
      The build rules only look for the packages via
      (`find_packages`) in setup.py, making the ha client sub-directory a
      package fixes it:
      ```
      [/tmp/opcua-asyncio-0.9.91]> rm -rf build/
      [/tmp/opcua-asyncio-0.9.91]> cat asyncua/client/ha/__init__.py
      """
      Pure Python OPC-UA library
      """
      
      from .ha_client import HaClient, HaMode, HaSecurityConfig, ConnectionStatesing
      [/tmp/opcua-asyncio-0.9.91]> python setup.py build > /dev/null 2>&1
      [/tmp/opcua-asyncio-0.9.91]> find build/ -type f |grep -i ha
      build//lib/tests/test_ha_client.py
      build//lib/asyncua/ua/uaprotocol_hand.py
      build//lib/asyncua/client/ha/__init__.py
      build//lib/asyncua/client/ha/common.py
      build//lib/asyncua/client/ha/ha_client.py
      build//lib/asyncua/client/ha/reconciliator.py
      build//lib/asyncua/client/ha/virtual_subscription.py
      ```
      
      Changing the HaClient test import path to ensure no regression.
      100a711b
  11. 05 Nov, 2021 10 commits