tags:

views:

168

answers:

4

I have this function call here:

import test_hosts

test_hosts.LocalTestHost(mst, port, local_ip, remote_if_mac, remote_if_ip, service_port)

and when I run it, the interpreter fails, and says I'm passing 6 parameters to a function that receives 7 parameters.

LocalTestHost is a class which its constructor takes a self parameter and six others: resulting in a total of 7 parameters. This is it's declaration:

class LocalTestHost:

    def __init__(self, mst, port, local_ip, remote_if_mac, remote_if_ip, service_port):
        ...

I've stared at this code for hours, and I can't find the problem. When I run this as is, it fails because I pass 6 parameters, which is too few, if I call the constructor with an added parameter just to see that I can still count, it says I'm passing 8 parameters, which is too many.

+1  A: 

I've seen these issues before, but it was because of preceding code being crafted in such a way that it syntactically correct but was not as I had intended.

This snippet isn't enough to reproduce the problem for me, at least not on 2.5.1 on OS X.

EmmEff
+2  A: 

Another idea: you are inadvertently calling an older version of the code. Make sure you don't have a .pyc file lying around somewhere.

Ned Batchelder
FWIW, I've had this happen where I chdir out of my devel directory and instead of getting the devel version of a module, I get the older one I installed in site-packages.
EmmEff
No, I have checked that too. I've cleaned up the working directory. Moved everything to other locations several times. That's not the case. But I've encountered that one too in my life. It can really get you bewildering.
Avihu Turzion
+3  A: 

The snippets of code you pasted look fine. As others correctly said, to find the problem you should find the smallest amount of code that still has the bug.

My suggestion would be to

(1) check that module test_hosts is written for your version of Python and that it's indeed the file being imported

(2) copy the class LocalTestHost: def __init__(... function to your file and try calling it from there. It will raise something like NameError if you get the # of params right.

(3) if the above function works for you, check the test_hosts.LocalTestHost.__init__() signature using runtime introspection. somebody might be changing it by e.g. __init__ = staticmethod(__init__) somewhere (an old method of defining static functions).

And please tell us how it's going!

ilya n.
A: 

My god, I was an idiot. I need to start reading the error messages more thoroughly.

The code that actually caused the problem wasn't in here actually. It was several lines inside the constructor. Here it is:

class LocalTestHost:

    def __init__(self, mst, port, local_ip, remote_if_mac, remote_if_ip, service_port):
        .
        . <some initialization code>
        .

        # This is the faulty line
        self.__host_operations = HostOperationsFactory().create(
                        local_ip, port, mst, remote_if_ip)

And here is the error message, I kept not reading, and foolishly did not post with my question:

>>> test_hosts.LocalTestHost(1,2,3,4,5,6)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "test_hosts.py", line 709, in __init__
    self.__host_operations = HostOperationsFactory().create(
  File "test_hosts.py", line 339, in create
    remote_ip)
  File "test_hosts.py", line 110, in __init__
    packet_size, remote_ip)
TypeError: __init__() takes exactly 7 arguments (6 given)

I've refactored my code a bit, and added parameters to several methods and constructors, but I forgot to update their usage in several places. This create function actually returns another object it instantiates, and it's constructor (incidentally has the same parameters as the constructor I picked on) did not receive all the parameters it should have.

I did not read the message thoroughly, and my confusion came from the last line stating I have passed the constructor too few parameters. Now, I also tried adding too many parameters as a sanity check, and there it actually was the constructor I was picking on. I'm surprised I didn't see that in this case the error trace was significantly shorter.

I've learned a valuable lesson today. The problem is I think I've leaned it several times already for some years.

Avihu Turzion
I think it's always good to learn a lesson! Speaking about instantiation, maybe your semantics will be more closely matched by `= HostOperationsFactory.create(...)`. You'll just have to declare `create()` to be a class method. And while we're at it, why not make it a constructior: `= HostOperationsFactory(...)` ?
ilya n.
By doing: `= HostOperationsFactory(...)` you mean implementing it as a function. Sounds interesting. I wonder what's the proper practice for this? A function or a class method?
Avihu Turzion