Python requests library

Hi,

We try to use the requests library in Ignition (8.1.15).

We get this error:

Error running action 'component.onActionPerformed' on jasperlg@D/root/Button: Traceback (most recent call last): File "<function:runAction>", line 2, in runAction ImportError: Error loading module requests: Traceback (most recent call last): File "<module:requests>", line 86, in <module> File "<module:requests>", line 72, in getImage File "<module:requests>", line 48, in create_signed_jwt File "/usr/local/bin/ignition/user-lib/pylib/site-packages/jwt/api_jwt.py", line 64, in encode return super(PyJWT, self).encode( File "/usr/local/bin/ignition/user-lib/pylib/site-packages/jwt/api_jws.py", line 118, in encode raise NotImplementedError( NotImplementedError: Algorithm 'RS256' could not be found. Do you have cryptography installed?

We used pip for Jython, so we could import the library with all it’s dependencies, but it still asked for the cryptogrpahy library.
I tried installing cryptography, but pip on jython refused to install it and gives this error:

  ERROR: Command errored out with exit status 1:
   command: /usr/local/jython/bin/jython /usr/local/jython/Lib/site-packages/pip install --ignore-installed --no-user --prefix /tmp/pip-build-env-mmTpXJ/overlay --no-warn-script-location --no-binary :none: --only-binary :none: -i https://pypi.org/simple -- 'setuptools>=40.6.0' wheel 'cffi>=1.12; platform_python_implementation != '"'"'PyPy'"'"''
       cwd: None
  Complete output (34 lines):
  WARNING: An illegal reflective access operation has occurred
  WARNING: Illegal reflective access by org.python.core.io.StreamIO (file:/usr/local/jython/jython.jar) to field java.io.FilterInputStream.in
  WARNING: Please consider reporting this to the maintainers of org.python.core.io.StreamIO
  WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
  WARNING: All illegal access operations will be denied in a future release
  DEPRECATION: pip 21.0 will drop support for Python 2.7 in January 2021. More details about Python 2 support in pip can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support pip 21.0 will remove support for this functionality.
  WARNING: pip is configured with locations that require TLS/SSL, however the ssl module in Python is not available.
  Collecting setuptools>=40.6.0
    Using cached setuptools-44.1.1-py2.py3-none-any.whl (583 kB)
  Collecting wheel
    Using cached wheel-0.37.1-py2.py3-none-any.whl (35 kB)
  Collecting cffi>=1.12
    Using cached cffi-1.15.0.tar.gz (484 kB)
      ERROR: Command errored out with exit status 1:
       command: /usr/local/jython/bin/jython -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-jXS2Lc/cffi/setup.py'"'"'; __file__='"'"'/tmp/pip-install-jXS2Lc/cffi/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base /tmp/pip-pip-egg-info-8Qff1t
           cwd: /tmp/pip-install-jXS2Lc/cffi/
      Complete output (15 lines):
      Traceback (most recent call last):
        File "<string>", line 1, in <module>
        File "/tmp/pip-install-jXS2Lc/cffi/setup.py", line 148, in <module>
          ask_supports_thread()
        File "/tmp/pip-install-jXS2Lc/cffi/setup.py", line 76, in ask_supports_thread
          ok = (sys.platform != 'win32' and
        File "/usr/local/jython/Lib/distutils/command/config.py", line 232, in try_compile
          self._compile(body, headers, include_dirs, lang)
        File "/usr/local/jython/Lib/distutils/command/config.py", line 232, in try_compile
          self._compile(body, headers, include_dirs, lang)
        File "/usr/local/jython/Lib/distutils/command/config.py", line 136, in _compile
          (obj,) = self.compiler.object_filenames([src])
        File "/usr/local/jython/Lib/distutils/ccompiler.py", line 821, in object_filenames
          if ext not in self.src_extensions:
      TypeError: 'NoneType' object is not iterable
      ----------------------------------------
  ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.
  ----------------------------------------
ERROR: Command errored out with exit status 1: /usr/local/jython/bin/jython /usr/local/jython/Lib/site-packages/pip install --ignore-installed --no-user --prefix /tmp/pip-build-env-mmTpXJ/overlay --no-warn-script-location --no-binary :none: --only-binary :none: -i https://pypi.org/simple -- 'setuptools>=40.6.0' wheel 'cffi>=1.12; platform_python_implementation != '"'"'PyPy'"'"'' Check the logs for full command output.

Could it be that cryptography is CPython only? Or how come this can’t be installed? I had the same issue with the Pillow library.
I also tried downloading the libraries manually (for Py2.7), but that gave an error in Ignition.
I’m having a hard time debugging stuff like this.

Any help here would be great.

I would recommend using httpClient() instead of requests… system.net.httpClient - Ignition User Manual 8.1 - Ignition Documentation

More information about python libraries can be found here: https://support.inductiveautomation.com/hc/en-us/articles/360056397252-Python-In-Ignition

3 Likes

Could it be that cryptography is CPython only? - Yes, that’s what’s happening here. If you look through the dependencies that pip is trying to install, you’ll see that it’s getting stuck on cffi. The cffi package is a “C Foreign Function Interface for Python”.

As mentioned here, I’d definitely explore system.net.httpClient. It can do most of what requests does, and is normally really good at it. It might be a little less ‘pythonic’, but it’s very capable, and even gives you access to the underlying HttpClient / HttpRequest / HttpResponse objects if you need them.

2 Likes

Thank you Kevin! That helps.
Now I will have to find a way to encrypt my message RS256 with java libs probably.

urllib should work without having to install anything new.

Haven’t used it myself though, the 2.7 version looks a bit outdated, but it seems to work.

https://docs.python.org/2/library/urllib.html

image

Yes, urllib works directly. Any idea on how to encrypt to RS256?

If you post to https, encryption should work automattically, i think.
Otherwise no idea, you’ll have to find a lib or the correct algoritme xd

If you encounter international characters, urllib is likely to let you down in a jython environment. Use httpClient.

Yes, it worked with httpClient! Indeed, quite easy to implement.

The Google cloud integration was a bit harder.
If anyone needs to encrypt something with RS256 in Jython,

you can do this:

from java.security import KeyFactory
from java.security import Signature
from java.security.spec import PKCS8EncodedKeySpec
from java.util import Base64

def signSHA256RSA(input, pkey):
	#Remove markers and new line characters in private key
	realPK = pkey.replace("-----END PRIVATE KEY-----", "")
	realPK = realPK.replace("-----BEGIN PRIVATE KEY-----", "")
	realPK = realPK.replace("\n", "")
	b1 = Base64.getDecoder().decode(realPK)
	spec = PKCS8EncodedKeySpec(b1)
	kf = KeyFactory.getInstance("RSA")
	privateSignature = Signature.getInstance("SHA256withRSA")
	privateSignature.initSign(kf.generatePrivate(spec))
	privateSignature.update(str(input))
	s = privateSignature.sign()
	return Base64.getUrlEncoder().encodeToString(s)
5 Likes