TypeError


preview

Here are the tests I have by the end of the chapter

 1import src.type_error
 2import unittest
 3
 4
 5class TestTypeError(unittest.TestCase):
 6
 7    def test_type_error_w_the_uncallables(self):
 8        src.type_error.none()
 9        src.type_error.false()
10        src.type_error.true()
11        src.type_error.an_integer()
12        src.type_error.a_float()
13        src.type_error.a_string()
14        src.type_error.a_tuple()
15        src.type_error.a_list()
16        src.type_error.a_set()
17        src.type_error.a_dictionary()
18
19    def test_type_error_w_function_signatures(self):
20        src.type_error.function_00('a')
21        src.type_error.function_01('a', 'b')
22        src.type_error.function_02('a', 'b', 'c')
23        src.type_error.function_03('a', 'b', 'c', 'd')
24
25    def test_type_error_w_objects_that_do_not_mix(self):
26        with self.assertRaises(TypeError):
27            None + False
28        with self.assertRaises(TypeError):
29            True - 'text'
30        with self.assertRaises(TypeError):
31            (0, 1, 2, 'n') * [0, 1, 2, 'n']
32        with self.assertRaises(TypeError):
33            {0, 1, 2, 'n'} / {'key': 'value'}
34
35
36# Exceptions seen
37# AssertionError
38# AttributeError
39# TypeError

questions about TypeError

Here are questions you can answer after going through this chapter


start the project

  • I open a terminal

  • I type pwd to make sure I am in the pumping_python folder

    pwd
    

    the terminal goes back to the command line

    .../pumping_python
    

    Note

    if you are not in the pumping_python folder, try cd ~/pumping_python

  • I name this project type_error

  • I open makePythonTdd.sh or makePythonTdd.ps1 in the editor

    Tip

    Here is a quick way to open makePythonTdd.sh or makePythonTdd.ps1 if you are using Visual Studio Code

    code makePythonTdd.sh
    

    on Windows without Windows Subsystem for Linux use

    code makePythonTdd.ps1
    
  • I change everywhere I have exceptions to the name of this project

     1#!/bin/bash
     2mkdir type_error
     3cd type_error
     4mkdir src
     5touch src/type_error.py
     6mkdir tests
     7touch tests/__init__.py
     8
     9echo "import unittest
    10
    11
    12class TestTypeError(unittest.TestCase):
    13
    14    def test_failure(self):
    15        self.assertFalse(True)
    16
    17
    18# Exceptions seen
    19# AssertionError
    20" > tests/test_type_error.py
    

    Attention

    on Windows without Windows Subsystem for Linux use makePythonTdd.ps1 NOT makePythonTdd.sh

     1mkdir type_error
     2cd type_error
     3mkdir src
     4New-Item src/type_error.py
     5mkdir tests
     6New-Item tests/__init__.py
     7
     8"import unittest
     9
    10
    11class TestTypeError(unittest.TestCase):
    12
    13    def test_failure(self):
    14        self.assertFalse(True)
    15
    16# Exceptions seen
    17# AssertionError
    18" | Out-File tests/test_type_error.py
    
  • I run the program in the terminal

    ./makePythonTdd.sh
    

    Attention

    on Windows without Windows Subsystem for Linux use makePythonTdd.ps1 NOT makePythonTdd.sh

    ./makePythonTdd.ps1
    

    the terminal shows AssertionError

    ======================================= FAILURES =======================================
    ______________________________ TestTypeError.test_failure ______________________________
    
    self = <tests.test_exceptions.TestTypeError testMethod=test_failure>
    
        def test_failure(self):
    >       self.assertFalse(True)
    E       AssertionError: True is not false
    
    tests/test_type_error.py:7: AssertionError
    =============================== short test summary info ================================
    FAILED tests/test_type_error.py::TestTypeError::test_failure - AssertionError: True is not false
    ================================== 1 failed in X.YZs ===================================
    
  • I hold ctrl (Windows/Linux) or option or command (MacOS) on the keyboard and use the mouse to click on tests/test_type_error.py:7 to open it in the editor

  • then I change True to False

    7        self.assertFalse(False)
    

    the test passes


test_type_error_w_the_uncallables

There are objects that can NOT be called

RED: make it fail

  • I add an import statement at the top of test_type_error.py

    1import src.type_error
    2import unittest
    
  • I change test_failure to test_type_error_w_the_uncallables with a failing line

    5class TestTypeError(unittest.TestCase):
    6
    7    def test_type_error_w_the_uncallables(self):
    8        src.type_error.none()
    

    the terminal shows AttributeError

    AttributeError: module 'src.type_error' has no attribute 'none'
    

    there is nothing in type_error.py in the src folder yet

  • I add AttributeError to the list of Exceptions seen

    11# Exceptions seen
    12# AssertionError
    13# AttributeError
    

GREEN: make it pass

I can call a function, I cannot call None

REFACTOR: make it better

  • I add another failing line to test_type_error.py

    7    def test_type_error_w_the_uncallables(self):
    8        src.type_error.none()
    9        src.type_error.false()
    

    the terminal shows AttributeError

    AttributeError: module 'src.type_error' has no attribute 'false'
    

    nothing is named false in type_error.py

  • I add the name to type_error.py and point it to False

    1def none():
    2    return None
    3
    4
    5false = False
    

    the terminal shows TypeError

    TypeError: 'bool' object is not callable
    

    I cannot call a boolean the way I can call a function

  • I change the variable to a function

    1def none():
    2    return None
    3
    4def false():
    5    return False
    

    the terminal shows green again

  • I add a line to test the other boolean in test_type_error.py

     7    def test_type_error_w_the_uncallables(self):
     8        src.type_error.none()
     9        src.type_error.false()
    10        src.type_error.true()
    

    the terminal shows AttributeError

    AttributeError: module 'src.type_error' has no attribute 'true'
    

    there is nothing named true in type_error.py

  • I add the name and point it to True in type_error.py

    5def false():
    6    return False
    7
    8
    9true = True
    

    the terminal shows TypeError

    TypeError: 'bool' object is not callable
    
  • I make it a function

     5def false():
     6    return False
     7
     8
     9def true():
    10    return True
    

    the test passes. I can call a function, I cannot call a boolean or None

  • I add a failing line to test_type_error.py

     8        src.type_error.none()
     9        src.type_error.false()
    10        src.type_error.true()
    11        src.type_error.an_integer()
    

    the terminal shows AttributeError

    AttributeError: module 'src.type_error' has no attribute 'an_integer'
    
  • I add the name and point it to an integer in type_error.py

     9def true():
    10    return True
    11
    12
    13an_integer = 1234
    

    the terminal shows TypeError

  • I change the variable to a funcion

     9def true():
    10    return True
    11
    12
    13def an_integer():
    14    return 1234
    

    the test passes. I can call a function, I cannot call an integer, a boolean or None

  • I add a line for a float in test_type_error.py

     9        src.type_error.false()
    10        src.type_error.true()
    11        src.type_error.an_integer()
    12        src.type_error.a_float()
    

    the terminal shows AttributeError

    AttributeError: module 'src.type_error' has no attribute 'a_float'
    
  • I add the name and point it to a float in type_error.py

    13def an_integer():
    14    return 1234
    15
    16
    17a_float = 1.234
    

    the terminal shows TypeError

    TypeError: 'float' object is not callable
    
  • I make a_float a function

    13def an_integer():
    14    return 1234
    15
    16
    17def a_float():
    18    return 1.234
    

    the test passes. I can call a function, I cannot call a float, integer, boolean or None

  • I add a line for a string (anything in quotes) in test_type_error.py

    10        src.type_error.true()
    11        src.type_error.an_integer()
    12        src.type_error.a_float()
    13        src.type_error.a_string()
    

    the terminal shows AttributeError

    AttributeError: module 'src.type_error' has no attribute 'a_string'
    
  • I add the name and point it to a string in type_error.py

    17def a_float():
    18    return 1.234
    19
    20
    21a_string = 'a string'
    

    the terminal shows TypeError

    TypeError: 'str' object is not callable
    
  • I change a_string to a function

    17def a_float():
    18    return 1.234
    19
    20
    21def a_string():
    22    return 'a string'
    

    the test passes. I can call a function. I cannot call a string, a float, integer, boolean or None

  • I add a failing line for a tuple (anything in parentheses (), separated by a comma) in test_type_error.py

    11        src.type_error.an_integer()
    12        src.type_error.a_float()
    13        src.type_error.a_string()
    14        src.type_error.a_tuple()
    

    the terminal shows AttributeError

    AttributeError: module 'src.type_error' has no attribute 'a_tuple'
    
  • I add the name and point it to a tuple in type_error.py

    21def a_string():
    22    return 'a string'
    23
    24
    25a_tuple = (1, 2, 3, 'n')
    

    the terminal shows TypeError

    TypeError: 'tuple' object is not callable
    
  • I change it to a function

    21def a_string():
    22    return 'a string'
    23
    24
    25def a_tuple():
    26    return (1, 2, 3, 'n')
    

    the test passes. I can call a function. I cannot call a tuple, string, float, integer boolean or None

  • I add another line to test_type_error.py

    12        src.type_error.a_float()
    13        src.type_error.a_string()
    14        src.type_error.a_tuple()
    15        src.type_error.a_list()
    

    the terminal shows AttributeError

    AttributeError: module 'src.type_error' has no attribute 'a_list'
    
  • I add the name and point it to a list (anything in square brackets ([]) in type_error.py

    25def a_tuple():
    26    return (1, 2, 3, 'n')
    27
    28
    29a_list = [1, 2, 3, 'n']
    

    the terminal shows TypeError

    TypeError: 'list' object is not callable
    
  • I change a_list to a function

    25def a_tuple():
    26    return (1, 2, 3, 'n')
    27
    28
    29def a_list():
    30    return [1, 2, 3, 'n']
    

    the test passes. I can call a function, I cannot call a list, tuple, string, float, integer, boolean or None

  • I add another failing line to test_type_error.py

    13        src.type_error.a_string()
    14        src.type_error.a_tuple()
    15        src.type_error.a_list()
    16        src.type_error.a_set()
    

    the terminal shows AttributeError

    AttributeError: module 'src.type_error' has no attribute 'a_set'
    
  • I add the name and point it to a set in type_error.py

    29def a_list():
    30    return [1, 2, 3, 'n']
    31
    32
    33a_set = {1, 2, 3, 'n'}
    

    the terminal shows TypeError

    TypeError: 'set' object is not callable
    
  • I make it a function

    29def a_list():
    30    return [1, 2, 3, 'n']
    31
    32
    33def a_set():
    34    return {1, 2, 3, 'n'}
    

    the test passes. I can call a function, I cannot call a set, list, tuple, string, float, integer, boolean or None

  • I add the last failing line for this test to test_type_error.py

     7    def test_type_error_w_the_uncallables(self):
     8        src.type_error.none()
     9        src.type_error.false()
    10        src.type_error.true()
    11        src.type_error.an_integer()
    12        src.type_error.a_float()
    13        src.type_error.a_string()
    14        src.type_error.a_tuple()
    15        src.type_error.a_list()
    16        src.type_error.a_set()
    17        src.type_error.a_dictionary()
    18
    19
    20# Exceptions seen
    

    the terminal shows AttributeError

    AttributeError: module 'src.type_error' has no attribute 'a_dictionary'
    
  • I add the name and point it to a dictionary in type_error.py

    33def a_set():
    34    return {1, 2, 3, 'n'}
    35
    36
    37a_dictionary = {'key': 'value'}
    

    the terminal shows TypeError

    TypeError: 'dict' object is not callable
    
  • I change it to a function

    33def a_set():
    34    return {1, 2, 3, 'n'}
    35
    36
    37def a_dictionary():
    38    return {'key': 'value'}
    

    the terminal shows green again. I can call a function, I cannot call a dictionary, set, list, tuple, string, float, integer, boolean or None

It is safe to say that I cannot call data structures because they are NOT callable. I can call functions, they are callable


test_type_error_w_function_signatures

When I call a function I have to match its definition also known as its signature or I get TypeError

RED: make it fail

  • I add a new test to test_type_error.py

    17        src.type_error.a_dictionary()
    18
    19    def test_type_error_w_function_signatures(self):
    20        src.type_error.function_00('a')
    21
    22
    23# Exceptions seen
    

    the terminal shows AttributeError

    AttributeError: module 'src.type_error' has no attribute 'function_00'
    

GREEN: make it pass

  • I add the function to type_error.py

    37def a_dictionary():
    38    return {'key': 'value'}
    39
    40
    41def function_00():
    42    return None
    

    the terminal shows TypeError

    TypeError: function_00() takes 0 positional arguments but 1 was given
    

    because function_00 is called with 'a' as input and the definition does not allow any inputs

  • I add a name in parentheses to the function definition

    41def function_00(the_input):
    42    return None
    

    the test passes

I have to call a function in a way that matches its definition or I get TypeError

REFACTOR: make it better

  • I add a new failing line to test_type_error.py

    19def test_type_error_w_function_signatures(self):
    20    src.type_error.function_00('a')
    21    src.type_error.function_01('a', 'b')
    

    the terminal shows AttributeError

    AttributeError: module 'src.type_error' has no attribute 'function_01'. Did you mean: 'function_00'?
    
  • I add the function to type_error.py

    41def function_00(the_input):
    42    return None
    43
    44
    45def function_01(the_input):
    46    return None
    

    the terminal shows TypeError

    TypeError: function_01() takes 1 positional argument but 2 were given
    

    the definition only allows one input, and the test sent two

  • I change the first name, then add another name in parentheses so that the call to the function and its definition match

    45def function_01(first, second):
    46    return None
    

    the test passes

  • I add another failing line to test_type_error.py

    19    def test_type_error_w_function_signatures(self):
    20        src.type_error.function_00('a')
    21        src.type_error.function_01('a', 'b')
    22        src.type_error.function_02('a', 'b', 'c')
    

    the terminal shows AttributeError

    AttributeError: module 'src.type_error' has no attribute 'function_02'. Did you mean: 'function_00'?
    
  • I add the function to type_error.py

    45def function_01(first, second):
    46    return None
    47
    48
    49def function_02(first, second):
    50    return None
    

    the terminal shows TypeError

    TypeError: function_02() takes 2 positional arguments but 3 were given
    
  • I change the name of the first input, then add another name in parentheses to make the number of inputs match

    49def function_02(first, second, third):
    50    return None
    

    the test passes

  • I add one more failing line to test_type_error.py

    19    def test_type_error_w_function_signatures(self):
    20        src.type_error.function_00('a')
    21        src.type_error.function_01('a', 'b')
    22        src.type_error.function_02('a', 'b', 'c')
    23        src.type_error.function_03('a', 'b', 'c', 'd')
    

    the terminal shows AttributeError

    AttributeError: module 'src.type_error' has no attribute 'function_03'. Did you mean: 'function_00'?
    
  • I add the function to type_error.py

    49def function_02(first, second, third):
    50    return None
    51
    52
    53def function_03(first, second, third):
    54    return None
    

    the terminal shows TypeError

    TypeError: function_03() takes 3 positional arguments but 4 were given
    
  • I add a 4th name in parentheses to the definition

    53def function_03(first, second, third, fourth):
    54    return None
    

    the test passes

I have to call a function with the same number of inputs its definition expects


test_type_error_w_objects_that_do_not_mix

Some operations do not work if the objects are NOT the same type

RED: make it fail

I add a new test with a failing line in test_type_error.py

23        src.type_error.function_03('a', 'b', 'c', 'd')
24
25    def test_type_error_w_objects_that_do_not_mix(self):
26        None + False
27
28
29# Exceptions seen

the terminal shows TypeError

TypeError: unsupported operand type(s) for +: 'NoneType' and 'bool'

I cannot do arithmetic with None

GREEN: make it pass

I add the assertRaises method

25    def test_type_error_w_objects_that_do_not_mix(self):
26        with self.assertRaises(TypeError):
27            None + False

the test passes

REFACTOR: make it better

  • I add another failing line to the test

    25    def test_type_error_w_objects_that_do_not_mix(self):
    26        with self.assertRaises(TypeError):
    27            None + False
    28        True - 'text'
    

    the terminal shows TypeError

    TypeError: unsupported operand type(s) for -: 'bool' and 'str'
    
  • I use assertRaises to handle the Exception

    25    def test_type_error_w_objects_that_do_not_mix(self):
    26        with self.assertRaises(TypeError):
    27            None + False
    28        with self.assertRaises(TypeError):
    29            True - 'text'
    

    the test passes

  • I add another failing line

    25    def test_type_error_w_objects_that_do_not_mix(self):
    26        with self.assertRaises(TypeError):
    27            None + False
    28        with self.assertRaises(TypeError):
    29            True - 'text'
    30        (0, 1, 2, 'n') * [0, 1, 2, 'n']
    

    the terminal shows TypeError

    TypeError: can't multiply sequence by non-int of type 'list'
    
  • I add assertRaises

    25    def test_type_error_w_objects_that_do_not_mix(self):
    26        with self.assertRaises(TypeError):
    27            None + False
    28        with self.assertRaises(TypeError):
    29            True - 'text'
    30        with self.assertRaises(TypeError):
    31            (0, 1, 2, 'n') * [0, 1, 2, 'n']
    32
    33# Exceptions seen
    

    the test passes

  • I add another failing line

    25    def test_type_error_w_objects_that_do_not_mix(self):
    26        with self.assertRaises(TypeError):
    27            None + False
    28        with self.assertRaises(TypeError):
    29            True - 'text'
    30        with self.assertRaises(TypeError):
    31            (0, 1, 2, 'n') * [0, 1, 2, 'n']
    32        {0, 1, 2, 'n'} / {'key': 'value'}
    

    the terminal shows TypeError

    TypeError: unsupported operand type(s) for /: 'set' and 'dict'
    
  • I add assertRaises

    25def test_type_error_w_objects_that_do_not_mix(self):
    26    with self.assertRaises(TypeError):
    27        None + False
    28    with self.assertRaises(TypeError):
    29        True - 'text'
    30    with self.assertRaises(TypeError):
    31        (0, 1, 2, 'n') * [0, 1, 2, 'n']
    32    with self.assertRaises(TypeError):
    33        {0, 1, 2, 'n'} / {'key': 'value'}
    

    the terminal shows all tests are passing


close the project

  • I close test_type_error.py and type_error.py in the editor

  • then I click in the terminal and exit the tests with ctrl+c on the keyboard, the terminal shows

    .../pumping_python
    

    I am back in the pumping_python directory

Note

on Windows without Windows Subsystem for Linux

  • the terminal shows

    (.venv) ...\pumping_python\type_error
    
  • I deactivate the virtual environment

    deactivate
    

    the terminal goes back to the command line, (.venv) is no longer on the left side

    ...\pumping_python\type_error
    
  • I change directory to the parent of type_error

    cd ..
    

    the terminal shows

    ...\pumping_python
    

    I am back in the pumping_python directory


review

The calculator program can take 2 inputs and check if they are both numbers, then add, subtract, multiply or divide them

Even though the program says it only works with numbers, I did not add tests for tuples, lists, sets, and dictionaries, though they are touched in test_type_error_w_objects_that_do_not_mix, Do you want to add them or do we already have enough tests to know what would happen?

I ran tests for TypeError with


How many questions can you answer after going through this chapter?


code from the chapter

Do you want to see all the CODE I typed in this chapter?


what is next?

you know

Would you like to use what you know so far with the Calculator?


rate pumping python

If this has been a 7 star experience for you, please leave a 5 star review. It helps other people get into the book too