pylint icon indicating copy to clipboard operation
pylint copied to clipboard

Pyreverse: ValueError: need more than 1 value to unpack

Open pylint-bot opened this issue 12 years ago • 14 comments

Originally reported by: Jorge Araya Navarro (BitBucket: shackra, GitHub: @shackra?)


I'm not sure what's happening...

#!bash

jorge [~/coders/desarrollo/thomas-aquinas] ~> pyreverse -c cocos2d -a 1 -s 1 -f ALL -o png summa/
parsing summa/__init__.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/utils.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/__init__.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/framegrabber.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/summanode.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/collision_model.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/text.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/menu.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/particle.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/batch.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/director.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/shader.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/wired.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/rect.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/skeleton.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/gl_framebuffer_object.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/camera.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/draw.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/tiles.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/custom_clocks.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/path.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/sprite.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/grid.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/particle_systems.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/scene.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/euclid.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/scenes/__init__.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/scenes/transitions.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/scenes/pause.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/actions/__init__.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/actions/instant_actions.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/actions/base_actions.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/actions/grid3d_actions.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/actions/camera_actions.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/actions/tiledgrid_actions.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/actions/move_actions.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/actions/basegrid_actions.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/actions/interval_actions.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/actions/quadmoveby_actions.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/audio/__init__.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/audio/music.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/audio/vector.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/audio/system.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/audio/objectbase.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/audio/sftime.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/audio/libs.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/audio/soundstatus.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/audio/actions.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/audio/sfmusic.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/audio/effect.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/audio/listener.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/audio/exceptions.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/layer/__init__.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/layer/base_layers.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/layer/util_layers.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/layer/python_interpreter.py...
parsing /home/jorge/coders/desarrollo/thomas-aquinas/summa/layer/scrolling.py...
Traceback (most recent call last):
  File "/usr/bin/pyreverse", line 9, in <module>
    load_entry_point('pylint==0.28.0', 'console_scripts', 'pyreverse')()
  File "/usr/lib/python2.7/site-packages/pylint-0.28.0-py2.7.egg/pylint/__init__.py", line 39, in run_pyreverse
    Run(sys.argv[1:])
  File "/usr/lib/python2.7/site-packages/pylint-0.28.0-py2.7.egg/pylint/pyreverse/main.py", line 98, in __init__
    sys.exit(self.run(args))
  File "/usr/lib/python2.7/site-packages/pylint-0.28.0-py2.7.egg/pylint/pyreverse/main.py", line 112, in run
    diadefs = handler.get_diadefs(project, linker)
  File "/usr/lib/python2.7/site-packages/pylint-0.28.0-py2.7.egg/pylint/pyreverse/diadefslib.py", line 226, in get_diadefs
    diagrams.append(generator.class_diagram(project, klass))
  File "/usr/lib/python2.7/site-packages/pylint-0.28.0-py2.7.egg/pylint/pyreverse/diadefslib.py", line 194, in class_diagram
    module, klass = klass.rsplit('.', 1)
ValueError: need more than 1 value to unpack
jorge [~/coders/desarrollo/thomas-aquinas] ~>

Then I tried to parse that file directly to see what happen, and I got this:

#!bash

jorge [~/coders/desarrollo/thomas-aquinas] ~> pyreverse -c cocos2d -a 1 -s 1 -f ALL -o png summa/layer/scrolling.py
parsing summa/layer/scrolling.py...
Traceback (most recent call last):
  File "/usr/bin/pyreverse", line 9, in <module>
    load_entry_point('pylint==0.28.0', 'console_scripts', 'pyreverse')()
  File "/usr/lib/python2.7/site-packages/pylint-0.28.0-py2.7.egg/pylint/__init__.py", line 39, in run_pyreverse
    Run(sys.argv[1:])
  File "/usr/lib/python2.7/site-packages/pylint-0.28.0-py2.7.egg/pylint/pyreverse/main.py", line 98, in __init__
    sys.exit(self.run(args))
  File "/usr/lib/python2.7/site-packages/pylint-0.28.0-py2.7.egg/pylint/pyreverse/main.py", line 112, in run
    diadefs = handler.get_diadefs(project, linker)
  File "/usr/lib/python2.7/site-packages/pylint-0.28.0-py2.7.egg/pylint/pyreverse/diadefslib.py", line 226, in get_diadefs
    diagrams.append(generator.class_diagram(project, klass))
  File "/usr/lib/python2.7/site-packages/pylint-0.28.0-py2.7.egg/pylint/pyreverse/diadefslib.py", line 199, in class_diagram
    klass = module.ilookup(klass).next()
  File "/usr/lib/python2.7/site-packages/logilab_astng-0.24.3-py2.7.egg/logilab/astng/bases.py", line 124, in _infer_stmts
    raise InferenceError(str(stmt))
logilab.astng.exceptions.InferenceError: None
jorge [~/coders/desarrollo/thomas-aquinas] ~> 

The file is right here shackra/thomas-aquinas/src/summa/layer/scrolling.py...


  • Bitbucket: https://bitbucket.org/logilab/pylint/issue/22

pylint-bot avatar Jun 03 '13 05:06 pylint-bot

Original comment by Emile Anclin (BitBucket: anclin, GitHub: @anclin?):


It seems, it is a command line parsing errror of the "-c" option and comes in many variations:


#!python
  pyreverse  dynamics/* -c -p stroumpf

Traceback (most recent call last):
  File "/home/e1000/bin/pyreverse", line 3, in <module>
    run_pyreverse()
  ...
  File "/home/e1000/src/logilab/common/modutils.py", line 577, in _search_zip
    raise ImportError('No module named %s' % '.'.join(modpath))
ImportError: No module named stroumpf

After the '-c', we can also use a non existing '-E' option, and I get:

#!python

pyreverse dynamics/controler.py -c -E
...
    raise InferenceError(str(stmt))
astroid.exceptions.InferenceError: None

Parsing the whole directory with the non sens option '-E' yields yet another error:


#!python

pyreverse dynamics/* -o png -c -E
  File "/home/e1000/src/pylint/pyreverse/diadefslib.py", line 196, in class_diagram
    module, klass = klass.rsplit('.', 1)
ValueError: need more than 1 value to unpack

The problems with the '-E' are triggered the same way with the valid '-p' option...

pylint-bot avatar Mar 20 '14 11:03 pylint-bot

Original comment by Emile Anclin (BitBucket: anclin, GitHub: @anclin?):


I tried to understand the problem: let's take the example

#!python


pyreverse dynamics/ -A 1 -c -p name

At logilab.common.configuration line 685, in the load_command_line_configuration of OptionsManagerMixIn we have:

#!python


            (options, args) = self.cmdline_parser.parse_args(args=args)

before line 685 we have:

#!python

   args = ['dynamics/', '-A', '1', '-c', '-p', 'name']

after line 685:

#!python

    options = {'show_associated': None, 'module_names': None, 'output_format': None, 'only_classnames': None, 'project': None, 'show_ancestors': None, 'classes': ['-p'], 'mode': None, 'show_builtin': None, 'black_list': None}

    args = ['dynamics/', '1', 'name']

Instead we should have a option error message. The called parse_args method is from optparse import OptionParser; Pyreverse depends on the OptionsManagerMixIn through the ConfigurationMixIn(OptionsManagerMixIn, OptionsProviderMixIn) and pylint.pyreverse.main.Run(ConfigurationMixIn) . However ihmo, this complicated inheritage does not seem to be needed; the other OptionsProviderMixIn used for Pyreverse is AstroidManager(OptionsProviderMixIn), providing only the --filter and --projects options, and they are only needed for Pyreverse.

So, I think, we can remove these dependencies and just rewrite the pyreverse options with a simple Optparse usage. Is this ok for you?

pylint-bot avatar Apr 09 '14 18:04 pylint-bot

Original comment by Sylvain Thénault (BitBucket: sthenault, GitHub: @sthenault?):


Hi Emile,

I'm not sure your analysis is related to the original poster's problem. You're right there seem to have a problem with unknown option which are not reported as error though.

I don't think going back to optparse is the solution. Pylint use logilab.common.configuration and doesn't suffer from this problem. Also, we should benefit from it to rewrite the very dumb (broken?) pyreverse.rc support.

pylint-bot avatar Apr 10 '14 07:04 pylint-bot

Original comment by Emile Anclin (BitBucket: anclin, GitHub: @anclin?):


Yes, I was wrong, the original problem does not has a malformed command line in the first place, except that there is no class "cocos2d" in the file proposed in the link of the original problem ... I'll open another ticket adressing the command line problem.

pylint-bot avatar Apr 10 '14 12:04 pylint-bot

Original comment by Emile Anclin (BitBucket: anclin, GitHub: @anclin?):


Ok, I think the problem is the definition of the "-c" option: right now, it expects (de facto):

  • to be used with only one module, not even a package (here is first crash of the original problem )
  • after '-c', there should be the name of one class defined in the module (second crash of the original problem; it will also crash if the class is just imported in that module)

Bad enough, but the value of the '-c' option is put in a list ... (I know I coded that option, so I'm supposed know what it should do :-/ )... I suggest the following solution:

  1. An explaining message if the above conditions are not true and stop the program
  2. make '-c' accept a CSV list of classes to generate several diagrams
  3. Possibly add a '-C' option to generate class diagrams for all classes in the project

pylint-bot avatar Apr 10 '14 14:04 pylint-bot

Original comment by Sylvain Thénault (BitBucket: sthenault, GitHub: @sthenault?):


I would go for 2.

  1. sounds like the default behaviour, eg without option

pylint-bot avatar Apr 10 '14 14:04 pylint-bot

Original comment by Emile Anclin (BitBucket: anclin, GitHub: @anclin?):


Sorry, maybe I was not clear enough:

  • the -c option will generate a diagram of one Class called 'Class.dot'
  • whereas 'ASmy (without -c) will generate a diagram of all classes of the project's modules called 'classes<project_Name>.dot_' .

With -ASmy (without -c), the diagram might become too big, like :

#!python


pyreverse astroid.node_classes -ASmy

so my intention of the -c was having an option representing only one class..

The original post points out two bugs which are independent of his code:

A. pyreverse always crashes when used with -c option and more than one module, like :

#!python

 pyreverse -c Instance  astroid.builder astroid.bases  # two modules
 pyreverse -c Instance  astroid  # a package with several modules modules

B. pyreverse always crashes when used with -c option, one module which does not define the mentionned class, like :

#!python

pyreverse -c SomeClass  astroid.builder

B1. pyreverse always crashes when used with -c and two comma separated classes, like:

#!python

pyreverse -c Instance,Statement astroid.bases
  1. was meant to fix those bugs A. and B.
  2. should fix B1. (it is more or less a bug and/or an obvious improvement)
  3. would just be a possible other improvement

pylint-bot avatar Apr 14 '14 10:04 pylint-bot

Original comment by Sylvain Thénault (BitBucket: sthenault, GitHub: @sthenault?):


ok, then at least A and B should be fixed, probably by outputing proper error messages

pylint-bot avatar Apr 15 '14 06:04 pylint-bot

I had exactly this same problem. It was because I was saying -c classname instead of -c top_level_module.module1.module2.module3.classname

simsong avatar Jan 15 '19 19:01 simsong

yup, I reported this originally

shackra avatar Jan 16 '19 23:01 shackra

I have the same issue. Has there been any progress on this ?

lovasoa avatar Jan 17 '20 10:01 lovasoa

@lovasoa apparentely no one worked on it yet, I'd be glad to review a merge request that fix this.

Pierre-Sassoulas avatar Jun 14 '21 11:06 Pierre-Sassoulas

Is anyone able to provide accessible code (link in original issue isn't) to reproduce this?

clavedeluna avatar Dec 09 '22 17:12 clavedeluna

@clavedeluna theoretically this should work as a minimal example with our own codebase:

pyreverse -c FileItem pylint

As simsong rightly pointed out, the error here is that one needs to provide the fully qualified classname instead, so this should work:

pyreverse -c pylint.typing.FileItem pylint

However another bug is currently hiding it if you try to run this example on our current main branch:

parsing D:\Programming\git-forks\pylint\pylint\utils\utils.py...
    sys.exit(load_entry_point('pylint', 'console_scripts', 'pyreverse')())
  File "d:\programming\git-forks\pylint\pylint\__init__.py", line 74, in run_pyreverse
    PyreverseRun(argv or sys.argv[1:])
  File "d:\programming\git-forks\pylint\pylint\pyreverse\main.py", line 228, in __init__
    sys.exit(self.run(args))
  File "d:\programming\git-forks\pylint\pylint\pyreverse\main.py", line 243, in run
    diadefs = handler.get_diadefs(project, linker)
  File "d:\programming\git-forks\pylint\pylint\pyreverse\diadefslib.py", line 225, in get_diadefs
    diagrams.append(generator.class_diagram(project, klass))
  File "d:\programming\git-forks\pylint\pylint\pyreverse\diadefslib.py", line 196, in class_diagram
    self.extract_classes(klass, anc_level, association_level)
  File "d:\programming\git-forks\pylint\pylint\pyreverse\diadefslib.py", line 113, in extract_classes
    self.add_class(klass_node)
  File "d:\programming\git-forks\pylint\pylint\pyreverse\diadefslib.py", line 77, in add_class
    self.linker.visit(node)
  File "d:\programming\git-forks\pylint\pylint\pyreverse\utils.py", line 162, in visit
    methods[0](node)
  File "d:\programming\git-forks\pylint\pylint\pyreverse\inspector.py", line 195, in visit_classdef
    self.associations_handler.handle(assignattr, node)
  File "d:\programming\git-forks\pylint\pylint\pyreverse\inspector.py", line 371, in handle
    if isinstance(node.parent.value, astroid.node_classes.Name):
AttributeError: 'ClassDef' object has no attribute 'value'. Did you mean: 'values'?

It still works on 2.15.9 however. I opened https://github.com/PyCQA/pylint/issues/8031 for the new bug.

DudeNr33 avatar Jan 08 '23 08:01 DudeNr33