[Perfect Numbers] failed two tests b/c tuple index out of range?

This is a head-scratcher error message given there are no tuples that I’m aware of. Has this come up before (have searched the forums, already)?

If we need to supply more, for context, let me know. Not sure what one needs to post, or not post. Open to any advice.

Please always post as much information as you have!

Can you share your code and the exact test details? Please use codeblocks and not screenshots.

1 Like

Noted, and thank you for piping in.

def classify(number):
    """ A perfect number equals the sum of its positive divisors.
    :param number: int a positive integer
    :return: str the classification of the input integer
    """
    def base_factors(x):
        base = [1]
        r = range(2, int(x / 2) + 1)
        base.extend(u for u in r if x % u == 0)
        return base
        
    if not isinstance (number, int) or number < 1:
        raise ValueError
    if number == 1:
        return 'deficient'
    s = base_factors(number)
    # number is prime?
    if len(s) == 1:
        return 'deficient'
    t = sum(s)
    return t < number and 'deficient' or t > number and 'abundant' or t == number and 'perfect'


My local shell results give ValueError for the first two calls, and expected returns on the rest. I beefed up my local version for the fun of it:

if len(s) == 1:
        return 'deficient and prime'
#print (classify(-1))
#print (classify(0))
print (classify(1))
print (classify(6))
print (classify(36))
print (classify(47))
deficient
perfect
abundant
deficient and prime

Also, my factorization approach yielded a primeness test that is yet unproven, but seems to give correct results…

def is_prime(x):
    if not isinstance (x, int) or x < 2:
        raise ValueError
    base = [1]
    r = range(2, int(x ** 0.5) + 1)
    base.extend(u for u in r if x % u == 0)
    return len(base) == 1

On an aside, one could discuss idiomatic Python, though I would be willing to leave that to another discussion. My mindset is probably pretty far off from writing Pythonic code, being more a tinkerer than a pro.

Best we focus on the issue at hand.

Could you share all those test details as text? Images are hard to copy/paste from, or even difficult for some people to read!

1 Like

For the failed tests, do you understand what the tests are doing and what they are expecting to be returned? I’d recommend reviewing the tests in question closely.

1 Like

The platform won’t let me select and copy, at least not yet.

Are you running pytest locally? That’s the only way to actually ensure you’re testing the right thing locally!

1 Like

Which platform? There should be no copy limitations on Exercism.org.

1 Like
    def test_negative_integer_is_rejected_as_it_is_not_a_positive_integer(self):
        with self.assertRaises(ValueError) as err:
            classify(-1)
        self.assertEqual(type(err.exception), ValueError)
        self.assertEqual(
>           err.exception.args[0],
            "Classification is only possible for positive integers.",
        )
E       IndexError: tuple index out of range

The tuple it is referring to is err.exception.args which is the arguments provided when you create the ValueError. Your exception object’s first argument (index 0) is out of range because it is lacks any argument.

1 Like

Seems my aging brain is just slightly outside of any understanding. I’m not really sure what they are testing for. I’ve disallowed non integers and values less than 1. Where is this tuple the error message refers to? At this stage I refuse to pardon my ignorance. I’ve reviewed the tests as best I can, to no avail, unfortunately.

Is there supposed to be an argument with 'raise ValueError`?

Yes. Specifically to the ValueError part. The exception is expected to have a message. Consider taking a look at Raising Exceptions on python.org.

1 Like

D’oh! You all have been champions at giving me a shake. Thanks, and don’t mind if I dish out a couple Likes. You both led me to the solution so I hope you don’t mind I’m not giving a check mark, as you should both get one. Dilemma. Edit: Goes to the earliest tree shaker.

raise ValueError('Classification is only possible for positive integers.')

It was staring me in the the face the whole time; Jiminy Cricket.

1 Like

No tests, just test running in my shell (an old version of Spyder), but I also have a more recent version of IDLE. Not much need for workflow when you’re seventy. It’s more a hike to the playground everyday, much like Sudoku.

You don’t need much of a workflow or tooling, but you should actually run the tests locally. All you need is Python and pytest which you can run directly in your shell, or via most IDEs via extensions.

Let me check if it is already in Spyder, as it does contain libraries that would otherwise need to be installed for IDLE. Is pytest the module name I should look for?

Yes. It’s also an executable you might be able to run directly in your shell if it is already installed.

Looks like I don’t have it and will need to do some fancy pip stuff, which I’m totally foreign to. We’re what you might call an ‘expert beginner’ from which level, in ten years we have not risen above. Mind, we’re not vacuous. You can give direction. How might one install that module? Better yet, is it included in the local installation of the exercise environment (as opposed to the built in editor we’re currently using)?

I have no idea what “exercise environment” is supposed to mean but you can install it independent of any “environments” and IDEs. It’s all documented. See Testing on the Python track | Exercism's Docs

Hi @mtf :wave:

Chiming in here to talk a little about Spyder/Anaconda/pytest/working locally with Exercism et. al.

Not sure what you mean by “old version of Spyder”, but I recommend you upgrade to the most recent version if you can. It has a better console, better error messaging, and better performance.

I am also not sure if “using an old version of Spyder” means that you are using a stand-alone Spyder install, or that you’ve also installed Anaconda, nor what version of Python you are running. If you are using the Anaconda distribution of Python, you will need to upgrade Spyder via the Anaconda Navigator GUI, or the conda terminal tool.

For Pytest, you will want to use pip to install it and some plugins globally via:

python3 -m pip install pytest pytest-cache pytest-subtests

Once that’s sorted, you can install a plug-in to Spyder called spyder-unittest. It will allow you to run pytest (or nose or unittest) via the Spyder interface. You can find directions here, although for Exercism, you will not be creating a project, but pointing to a downloaded exercise folder.

In order to get downloaded exercises and tests, you will want to install and configure the Exercism CLI on your machine. It may feel like a PITA, but it beats having to copy code and tests from the website or from GitHub.


On my version of Spyder, here is what things look like:

And then you can change which exercise folder to run tests against by using the “hamburger” menu at the top-right of the unittest window to change the folder:

Hope this helps a little. :slightly_smiling_face: , and let us know if you have any additional questions or issues.

1 Like