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

AttributeError: 'NoneType' object has no attribute 'split' on importing dns.query #1088

Closed
drboone opened this issue Jun 4, 2024 · 7 comments

Comments

@drboone
Copy link

drboone commented Jun 4, 2024

import dns.query results in a traceback due to an attribute error arising during module import.

A script which uses dnspython crashes with this traceback:

Traceback (most recent call last):
  File "/opt/local/bin/rfc2136_acme_tool", line 13, in <module>
    import dns.query
  File "/opt/local/lib/python3.12/site-packages/dns/query.py", line 35, in <module>
    import dns.message
  File "/opt/local/lib/python3.12/site-packages/dns/message.py", line 25, in <module>
    import dns.edns
  File "/opt/local/lib/python3.12/site-packages/dns/edns.py", line 28, in <module>
    import dns.rdata
  File "/opt/local/lib/python3.12/site-packages/dns/rdata.py", line 33, in <module>
    import dns.name
  File "/opt/local/lib/python3.12/site-packages/dns/name.py", line 33, in <module>
    if dns._features.have("idna"):
       ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/local/lib/python3.12/site-packages/dns/_features.py", line 67, in have
    if not _version_check(requirement):
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/local/lib/python3.12/site-packages/dns/_features.py", line 37, in _version_check
    t_version = _tuple_from_text(version)
                ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/local/lib/python3.12/site-packages/dns/_features.py", line 10, in _tuple_from_text
    text_parts = version.split(".")
                 ^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'split'

pip show dnspython produces:

Name: dnspython
Version: 2.6.1
Summary: DNS toolkit
Home-page: 
Author: 
Author-email: Bob Halley <halley@dnspython.org>
License: 
Location: /opt/local/lib/python3.12/site-packages
Requires: 
Required-by: 

The non-comment lines of the script leading up to the import are:

from __future__ import print_function
import argparse
import dns.query

python is 3.12.3, installed from pkgsrc. OS is smartos. The dnspython module was installed with pip. This script has been working for some years.

Presumably I managed to do something silly here, but...

@rthalley
Copy link
Owner

rthalley commented Jun 5, 2024

The immediate problem is that importlib.metadata.version("idna") is unexpectedly returning None, which dnspython does not expect. I don't see the documentation saying this is a possible result either, and I haven't figured out the importlib code yet. Dnspython is expecting to get a string or for an exception to be raised.

I can't reproduce this with a normal install on my Mac, so I decided to investigate. I went into the lib/python3.12/site-packages directory associated with my venv. In there is a directory idna that has the source of the idna library, and also a directory idna-3.7.dist-info which has all of the metadata for the package installation, including the version metadata which is in file METADATA.

% ls idna-3.7.dist-info         
INSTALLER	METADATA	REQUESTED
LICENSE.md	RECORD		WHEEL

% egrep ^Version: idna-3.7.dist-info/METADATA
Version: 3.7

If I remove the whole METADATA file, or just the Version: 3.7 line, then I get the same failure you report. If I remove the whole dist-info directory, then the problem doesn't happen and dnspython thinks idna is unavailable.

So, I advise taking a look at your metadata to see what might be missing. How old is the idna you have, if you can tell without the metadata? If you go into your site-packages directory and rm -rf idna* and then pip install idna does that fix it?

@rthalley
Copy link
Owner

rthalley commented Jun 5, 2024

(And I should have said that dnspython is trying to look at the metadata of modules because it doesn't require you to install any modules, but will use features like idna or cryptography if they are present and new enough. It's the "is it new enough" check that is unexpectedly failing.)

@drboone
Copy link
Author

drboone commented Jun 5, 2024

This stuff is ordinarily installed via ansible. Armed with your notes above, I decided to try to force a reinstall of idna. This showed me some complaints about wonkiness with info directories in the site_packages tree. I ended up manually removing the named offenders and doing another force-reinstall. (Not sure the final reinstall was actually necessary, but belt+suspenders+paranoia.) This seems to have cured the problem.

I hypothesize that and automated upgrade somewhere along the way didn't complete cleanly. Looking at backups, I had a fragment of idna 3.6, and a more complete idna 3.7 in site-packages:

phantom 6 $ dir .zfs/snapshot/1717385161/evita.h-net.org/opt/local/lib/python3.12/site-packages/idna-3.6.dist-info/
total 18
drwxr-xr-x   2 root root   3 May 15 09:20 ./
drwxr-xr-x 101 root root 115 Jun  1 08:36 ../
-rw-r--r--   1 root root   4 Feb 17 08:35 INSTALLER
phantom 7 $ dir .zfs/snapshot/1717385161/evita.h-net.org/opt/local/lib/python3.12/site-packages/idna-3.7.dist-info/
total 51
drwxr-xr-x   2 root root    6 May 27 09:03 ./
drwxr-xr-x 101 root root  115 Jun  1 08:36 ../
-rw-r--r--   1 root root 1541 May 25 00:40 LICENSE.md
-rw-r--r--   1 root root 9888 May 25 00:40 METADATA
-rw-r--r--   1 root root  925 May 25 00:40 RECORD
-rw-r--r--   1 root root   81 May 25 00:40 WHEEL

Thanks for your quick and informative response!

@rthalley
Copy link
Owner

rthalley commented Jun 5, 2024

Thanks for the clear ticket! I will leave this one open a bit to remind me to add some bulletproofing since I now know that None can be returned.

bwelling added a commit that referenced this issue Jun 5, 2024
importlib.metadata.version() can return None in some cases, even though
it's not documented as doing so.  Treat that as an error.
@bwelling
Copy link
Collaborator

bwelling commented Jun 7, 2024

Closing this, as it should be fixed now.

@bwelling bwelling closed this as completed Jun 7, 2024
@ishans-crest
Copy link

@bwelling @rthalley
When this fix will be GAed?

@rthalley
Copy link
Owner

We don't have any specific next release date yet, but probably pretty soon as we've accumulated enough new stuff.

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

No branches or pull requests

4 participants