what causes AttributeError?


AttributeError happens when a name that is NOT in an object (everything in Python is an object) is used.


what is an attribute?

An attribute is a name (variable?) for something that belongs to an object (a class), for example, a human being has attributes like height, weight, sex and color, they are also known as properties.


preview

I have these tests by the end of the chapter

attribute_error/tests/test_attribute_error.py
 1import src.attribute_error
 2
 3
 4def test_attribute_error_w_variables():
 5    src.attribute_error.variable_00
 6    src.attribute_error.variable_01
 7    src.attribute_error.variable_02
 8    src.attribute_error.variable_03
 9    src.attribute_error.variable_04
10    src.attribute_error.variable_05
11    src.attribute_error.variable_06
12    src.attribute_error.variable_07
13    src.attribute_error.variable_08
14    src.attribute_error.variable_09
attribute_error/tests/test_attribute_error.py
17def test_attribute_error_w_functions():
18    src.attribute_error.function_00()
19    src.attribute_error.function_01()
20    src.attribute_error.function_02()
21    src.attribute_error.function_03()
22    src.attribute_error.function_04()
23    src.attribute_error.function_05()
24    src.attribute_error.function_06()
25    src.attribute_error.function_07()
26    src.attribute_error.function_08()
27    src.attribute_error.function_09()
28
29
30# Exceptions seen
31# AssertionError
32# AttributeError
33# NameError
34# TypeError

questions about AttributeError


start the project

  • I name this project attribute_error

  • I open a terminal

  • I change directory to the attribute_error folder in the pumping_python folder

    cd attribute_error
    

    the terminal shows

    cd: no such file or directory: attribute_error
    

    there is no folder with the name attribute_error in this folder.

  • I use uv to make a directory for the project and initialize it

    uv init attribute_error
    

    the terminal shows

    Initialized project `attribute-error`
    at `.../pumping_python/attribute_error`
    

    then goes back to the command line.

  • I change directory to the project

    cd attribute_error
    

    the terminal shows I am in the attribute_error folder

    .../pumping_python/attribute_error
    
  • I make a directory for the tests

    mkdir tests
    

    the terminal goes back to the command line.

  • I make the tests directory a Python package

    Danger

    use 2 underscores (__) before and after init for __init__.py not _init_.py

    touch tests/__init__.py
    
    New-Item tests/__init__.py
    

    the terminal goes back to the command line.

  • I make an empty file for the tests in the tests folder

    touch tests/test_attribute_error.py
    
    New-Item tests/test_attribute_error.py
    

    the terminal goes back to the command line.

  • I open test_attribute_error.py from the tests folder

  • I add the first failing test to tests/test_attribute_error.py

    1def test_failure():
    2    assert False is True
    
  • I go back to the terminal

  • I use echo to add pytest to requirements.txt

    echo "pytest" > requirements.txt
    
  • I add pytest-watcher to the requirements file

    echo "pytest-watcher" >> requirements.txt
    

    the terminal goes back to the command line.

  • I use Out-File to add pytest to requirements.txt

    "pytest" | Out-File requirements.txt -Encoding UTF8
    
  • I add pytest-watcher to the requirements file

    "pytest-watcher" >> requirements.txt
    
  • I use uv to install pytest-watcher with the requirements file

    uv add --requirement requirements.txt
    

    the terminal shows that it installed pytest-watcher and its dependencies.

  • I add the new files and folder to git for tracking

    git add .
    

    the terminal goes back to the command line.

  • I add a git commit message

    git commit -am 'setup project'
    

    the terminal shows a summary of the changes then goes back to the command line.

  • I use pytest-watcher to run the tests automatically

    uv run pytest-watcher . --now
    

    the terminal is my friend, and shows AssertionError

    ======================== FAILURES ========================
    ______________________ test_failure ______________________
    
        def test_failure():
    >       assert False is True
    E       assert False is True
    
    test_attribute_error.py:2: AssertionError
    ================ short test summary info =================
    FAILED test_attribute_error.py::test_failure - assert False is True
    =================== 1 failed in X.YZs ====================
    

    because False is NOT True.

    if the terminal does not show the same error, then check if

    • your tests/__init__.py has two underscores (__) before and after init for __init__.py not _init_.py

    • you ran echo "pytest-watcher" >> requirements.txt, to add pytest-watcher to the requirements file

    and try uv run pytest-watcher . --now again

  • I add AssertionError to the list of Exceptions seen, in tests/test_attribute_error.py

    1def test_failure():
    2    assert False is True
    3
    4
    5# Exceptions seen
    6# AssertionError
    
  • I change True to False in the assertion

    1def test_failure():
    2    # assert False is True
    3    assert False is False
    4
    5
    6# Exceptions seen
    7# AssertionError
    

    the test passes.

  • I add an import statement at the top of tests/test_attribute_error.py

    1import src.attribute_error
    

test_attribute_error_w_variables

AttributeError happens when I use a variable that does not exist in an object.


RED: make it fail


  • I change test_failure to test_attribute_error_w_variables

    1import src.attribute_error
    2
    3
    4def test_attribute_error_w_variables():
    5    src.attribute_error.variable_00
    6
    7
    8# Exceptions seen
    

    the terminal is my friend, and shows AttributeError

    AttributeError: module 'src.attribute_error'
                    has no attribute 'variable_00'
    

    because Python follows this path when src.attribute_error.variable_00 runs

    src.attribute_error.variable_00
    └── src/
        └── attribute_error/
            └── __init__.py
                └── variable_00 # does not exist
    

    which raises AttributeError since there is nothing named variable_00 in the attribute_error module in the src folder.

  • I add AttributeError to the list of Exceptions seen, in tests/test_attribute_error.py

     8# Exceptions seen
     9# AssertionError
    10# AttributeError
    

GREEN: make it pass


  • I open __init__.py from the attribute_error folder in the src folder

  • I delete the text in the file then add variable_00 to src/attribute_error/__init__.py

    1variable_00
    

    the terminal is my friend, and shows NameError

    NameError: name 'variable_00' is not defined
    

    because I used a name that is not defined in this file.

  • I add NameError to the list of Exceptions seen, in tests/test_attribute_error.py

     8# Exceptions seen
     9# AssertionError
    10# AttributeError
    11# NameError
    
  • I point variable_00 to None to define it, in src/attribute_error/__init__.py

    1# variable_00
    2variable_00 = None
    

    the test passes because

    • Python brings in an object for the src/attribute_error/__init__.py file from the src folder so I can use it in tests/test_attribute_error.py as src.attribute_error when import src.attribute_error runs.

    • Python looks at what the variable_00 variable from the object it imported for the src/attribute_error/__init__.py file from the src folder (src.attribute_error) points to when src.attribute_error.variable_00 runs.

    I think of src.attribute_error.variable_00 like an address

    src.attribute_error.variable_00
    └── src/
        └── attribute_error/
            └── __init__.py
                └── variable_00 = None
    
    • variable_00 is something in attribute_error, in this case it is a variable in attribute_error

    • attribute_error is something in src, in this case it is src/attribute_error/__init__.py (a module) in the src folder

    • src is something Python can import (a module, Python package or folder)

    • variable_00 is now an attribute/property of src/attribute_error/__init__.py in the src folder. I can use it from outside the file with src.attribute_error.variable_00


REFACTOR: make it better


  • I add a statement for variable_01 to tests/test_attribute_error.py

    4def test_attribute_error_w_variables():
    5    src.attribute_error.variable_00
    6    src.attribute_error.variable_01
    7
    8
    9# Exceptions seen
    

    the terminal is my friend, and shows AttributeError

    AttributeError: module 'src.attribute_error'
                    has no attribute 'variable_01'.
                    Did you mean: 'variable_00'?
    
  • I add variable_01 to src/attribute_error/__init__.py

    1# variable_00
    2variable_00 = None
    3variable_01
    

    the terminal is my friend, and shows NameError

    NameError: name 'variable_01' is not defined
    
  • I point it to None to define it

    1# variable_00
    2variable_00 = None
    3# variable_01
    4variable_01 = variable_00
    

    the test passes because variable_01 is now an attribute of src/attribute_error/__init__.py in the src folder, and I can use it from outside the file with src.attribute_error.variable_01

    src.attribute_error.variable_01
    └── src/
        └── attribute_error/
            └── __init__.py
                └── variable_01 = variable_00
    
  • I add a statement for variable_02 to tests/test_attribute_error.py

     4def test_attribute_error_w_variables():
     5    src.attribute_error.variable_00
     6    src.attribute_error.variable_01
     7    src.attribute_error.variable_02
     8
     9
    10# Exceptions seen
    

    the terminal is my friend, and shows AttributeError

    AttributeError: module 'src.attribute_error'
                    has no attribute 'variable_02'.
                    Did you mean: 'variable_00'?
    
  • I add variable_02 and point it to None in src/attribute_error/__init__.py

    1# variable_00
    2variable_00 = None
    3# variable_01
    4variable_01 = variable_00
    5variable_02 = variable_01
    

    the test passes because variable_02 is now an attribute of src/attribute_error/__init__.py in the src folder, and I can use it from outside the file with src.attribute_error.variable_02

    src.attribute_error.variable_02
    └── src/
        └── attribute_error/
            └── __init__.py
                └── variable_02 = variable_01
    
  • I add a line for variable_03 to tests/test_attribute_error.py

     4def test_attribute_error_w_variables():
     5    src.attribute_error.variable_00
     6    src.attribute_error.variable_01
     7    src.attribute_error.variable_02
     8    src.attribute_error.variable_03
     9
    10
    11# Exceptions seen
    

    the terminal is my friend, and shows AttributeError

    AttributeError: module 'src.attribute_error'
                    has no attribute 'variable_03'.
                    Did you mean: 'variable_00'?
    
  • I add variable_03 to src/attribute_error/__init__.py

    1# variable_00
    2variable_00 = None
    3# variable_01
    4variable_01 = variable_00
    5variable_02 = variable_01
    6variable_03 = variable_02
    

    the test passes because variable_03 is now an attribute of src/attribute_error/__init__.py in the src folder, and I can use it from outside the file with src.attribute_error.variable_03

    src.attribute_error.variable_03
    └── src/
        └── attribute_error/
            └── __init__.py
                └── variable_03 = variable_02
    
  • I add a line for variable_04 to tests/test_attribute_error.py

     4def test_attribute_error_w_variables():
     5    src.attribute_error.variable_00
     6    src.attribute_error.variable_01
     7    src.attribute_error.variable_02
     8    src.attribute_error.variable_03
     9    src.attribute_error.variable_04
    10
    11
    12# Exceptions seen
    

    the terminal is my friend, and shows AttributeError

    AttributeError: module 'src.attribute_error'
                    has no attribute 'variable_04'.
                    Did you mean: 'variable_00'?
    
  • I add variable_04 to src/attribute_error/__init__.py

    1# variable_00
    2variable_00 = None
    3# variable_01
    4variable_01 = variable_00
    5variable_02 = variable_01
    6variable_03 = variable_02
    7variable_04 = variable_03
    

    the test passes because variable_04 is now an attribute of src/attribute_error/__init__.py in the src folder, and I can use it from outside the file with src.attribute_error.variable_04

    src.attribute_error.variable_04
    └── src/
        └── attribute_error/
            └── __init__.py
                └── variable_04 = variable_03
    
  • I add a line for variable_05 to tests/test_attribute_error.py

     4def test_attribute_error_w_variables():
     5    src.attribute_error.variable_00
     6    src.attribute_error.variable_01
     7    src.attribute_error.variable_02
     8    src.attribute_error.variable_03
     9    src.attribute_error.variable_04
    10    src.attribute_error.variable_05
    11
    12
    13# Exceptions seen
    

    the terminal is my friend, and shows AttributeError

    AttributeError: module 'src.attribute_error'
                    has no attribute 'variable_05'.
                    Did you mean: 'variable_00'?
    
  • I add variable_05 to src/attribute_error/__init__.py

    1# variable_00
    2variable_00 = None
    3# variable_01
    4variable_01 = variable_00
    5variable_02 = variable_01
    6variable_03 = variable_02
    7variable_04 = variable_03
    8variable_05 = variable_04
    

    the test passes because variable_05 is now an attribute of src/attribute_error/__init__.py in the src folder, and I can use it from outside the file with src.attribute_error.variable_05

    src.attribute_error.variable_05
    └── src/
        └── attribute_error/
            └── __init__.py
                └── variable_05 = variable_04
    
  • I add a line for variable_06 to tests/test_attribute_error.py

     4def test_attribute_error_w_variables():
     5    src.attribute_error.variable_00
     6    src.attribute_error.variable_01
     7    src.attribute_error.variable_02
     8    src.attribute_error.variable_03
     9    src.attribute_error.variable_04
    10    src.attribute_error.variable_05
    11    src.attribute_error.variable_06
    12
    13
    14# Exceptions seen
    

    the terminal is my friend, and shows AttributeError

    AttributeError: module 'src.attribute_error'
                    has no attribute 'variable_06'.
                    Did you mean: 'variable_00'?
    
  • I add variable_06 to src/attribute_error/__init__.py

    1# variable_00
    2variable_00 = None
    3# variable_01
    4variable_01 = variable_00
    5variable_02 = variable_01
    6variable_03 = variable_02
    7variable_04 = variable_03
    8variable_05 = variable_04
    9variable_06 = variable_05
    

    the test passes because variable_06 is now an attribute of src/attribute_error/__init__.py in the src folder, and I can use it from outside the file with src.attribute_error.variable_06

    src.attribute_error.variable_06
    └── src/
        └── attribute_error/
            └── __init__.py
                └── variable_06 = variable_05
    
  • I add a line for variable_07 to tests/test_attribute_error.py

     4def test_attribute_error_w_variables():
     5    src.attribute_error.variable_00
     6    src.attribute_error.variable_01
     7    src.attribute_error.variable_02
     8    src.attribute_error.variable_03
     9    src.attribute_error.variable_04
    10    src.attribute_error.variable_05
    11    src.attribute_error.variable_06
    12    src.attribute_error.variable_07
    13
    14
    15# Exceptions seen
    

    the terminal is my friend, and shows AttributeError

    AttributeError: module 'src.attribute_error'
                    has no attribute 'variable_07'.
                    Did you mean: 'variable_00'?
    
  • I add variable_07 to src/attribute_error/__init__.py

     1# variable_00
     2variable_00 = None
     3# variable_01
     4variable_01 = variable_00
     5variable_02 = variable_01
     6variable_03 = variable_02
     7variable_04 = variable_03
     8variable_05 = variable_04
     9variable_06 = variable_05
    10variable_07 = variable_06
    

    the test passes because variable_07 is now an attribute of src/attribute_error/__init__.py in the src folder, and I can use it from outside the file with src.attribute_error.variable_07

    src.attribute_error.variable_07
    └── src/
        └── attribute_error/
            └── __init__.py
                └── variable_07 = variable_06
    
  • I add a line for variable_08 to tests/test_attribute_error.py

     4def test_attribute_error_w_variables():
     5    src.attribute_error.variable_00
     6    src.attribute_error.variable_01
     7    src.attribute_error.variable_02
     8    src.attribute_error.variable_03
     9    src.attribute_error.variable_04
    10    src.attribute_error.variable_05
    11    src.attribute_error.variable_06
    12    src.attribute_error.variable_07
    13    src.attribute_error.variable_08
    14
    15
    16# Exceptions seen
    

    the terminal is my friend, and shows AttributeError

    AttributeError: module 'src.attribute_error'
                    has no attribute 'variable_08'.
                    Did you mean: 'variable_00'?
    
  • I add variable_08 to src/attribute_error/__init__.py

     1# variable_00
     2variable_00 = None
     3# variable_01
     4variable_01 = variable_00
     5variable_02 = variable_01
     6variable_03 = variable_02
     7variable_04 = variable_03
     8variable_05 = variable_04
     9variable_06 = variable_05
    10variable_07 = variable_06
    11variable_08 = variable_07
    

    the test passes because variable_08 is now an attribute of src/attribute_error/__init__.py in the src folder, and I can use it from outside the file with src.attribute_error.variable_08

    src.attribute_error.variable_08
    └── src/
        └── attribute_error/
            └── __init__.py
                └── variable_08 = variable_07
    
  • I add a line for variable_09 to tests/test_attribute_error.py

     4def test_attribute_error_w_variables():
     5    src.attribute_error.variable_00
     6    src.attribute_error.variable_01
     7    src.attribute_error.variable_02
     8    src.attribute_error.variable_03
     9    src.attribute_error.variable_04
    10    src.attribute_error.variable_05
    11    src.attribute_error.variable_06
    12    src.attribute_error.variable_07
    13    src.attribute_error.variable_08
    14    src.attribute_error.variable_09
    15
    16
    17# Exceptions seen
    

    the terminal is my friend, and shows AttributeError

    AttributeError: module 'src.attribute_error'
                    has no attribute 'variable_09'.
                    Did you mean: 'variable_00'?
    
  • I add variable_09 to src/attribute_error/__init__.py

     1# variable_00
     2variable_00 = None
     3# variable_01
     4variable_01 = variable_00
     5variable_02 = variable_01
     6variable_03 = variable_02
     7variable_04 = variable_03
     8variable_05 = variable_04
     9variable_06 = variable_05
    10variable_07 = variable_06
    11variable_08 = variable_07
    12variable_09 = variable_08
    

    the test passes because variable_09 is now an attribute of src/attribute_error/__init__.py in the src folder, and I can use it from outside the file with src.attribute_error.variable_09

    src.attribute_error.variable_09
    └── src/
        └── attribute_error/
            └── __init__.py
                └── variable_09 = variable_08
    
  • I remove the commented lines

     1variable_00 = None
     2variable_01 = variable_00
     3variable_02 = variable_01
     4variable_03 = variable_02
     5variable_04 = variable_03
     6variable_05 = variable_04
     7variable_06 = variable_05
     8variable_07 = variable_06
     9variable_08 = variable_07
    10variable_09 = variable_08
    
  • I add a git commit message in the other terminal

    git commit -am \
    'add test_attribute_error_w_variables'
    

A variable in a module is an attribute of the module.


test_attribute_error_w_functions

RED: make it fail


  • I go back to the terminal where the tests are running

  • I add a test with a function call, to tests/test_attribute_error.py

    14    src.attribute_error.variable_09
    15
    16
    17def test_attribute_error_w_functions():
    18    src.attribute_error.function_00()
    19
    20
    21# Exceptions seen
    

    the terminal is my friend, and shows AttributeError

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

    because there is nothing named function_00 in src/attribute_error/__init__.py in the src folder.


GREEN: make it pass


  • I add the name and point it to None in src/attribute_error/__init__.py

    10variable_09 = variable_08
    11
    12
    13function_00 = variable_09
    

    the terminal is my friend, and shows TypeError

    TypeError: 'NoneType' object is not callable
    

    because I cannot call None like a function.

  • I add TypeError to the list of Exceptions seen, in tests/test_attribute_error.py

    21# Exceptions seen
    22# AssertionError
    23# AttributeError
    24# NameError
    25# TypeError
    
  • I change the variable to a function in src/attribute_error/__init__.py

    10variable_09 = variable_08
    11
    12
    13# function_00 = variable_09
    14def function_00(): return variable_09
    

    the test passes because function_00 is now an attribute of src/attribute_error/__init__.py in the src folder, and I can call it from outside the file with src.attribute_error.function_00()

    src.attribute_error.function_00() -> None
    └── src/
        └── attribute_error/
            └── __init__.py
                └── def function_00(): return variable_09
    

REFACTOR: make it better


  • I remove the commented line

    1variable_09 = variable_08
    2
    3
    4def function_00(): return variable_09
    

    time to make it a drill.

  • I add a call to function_01 from test_attribute_error_w_functions in tests/test_attribute_error.py

    17def test_attribute_error_w_functions():
    18    src.attribute_error.function_00()
    19    src.attribute_error.function_01()
    20
    21
    22# Exceptions seen
    

    the terminal is my friend, and shows AttributeError

    AttributeError: module 'src.attribute_error'
                    has no attribute 'function_01'.
                    Did you mean: 'function_00'?
    
  • I add a definition for function_01 to src/attribute_error/__init__.py

    13def function_00(): return variable_09
    14def function_01(): return function_00()
    

    the test passes because function_01 is now an attribute of src/attribute_error/__init__.py in the src folder, and I can call it from outside the file with src.attribute_error.function_01()

    src.attribute_error.function_01() -> None
    └── src/
        └── attribute_error/
            └── __init__.py
                └── def function_01(): return function_00()
    
  • I add a call to function_02 from test_attribute_error_w_functions in tests/test_attribute_error.py

    17def test_attribute_error_w_functions():
    18    src.attribute_error.function_00()
    19    src.attribute_error.function_01()
    20    src.attribute_error.function_02()
    21
    22
    23# Exceptions seen
    

    the terminal is my friend, and shows AttributeError

    AttributeError: module 'src.attribute_error'
                    has no attribute 'function_02'.
                    Did you mean: 'function_00'?
    
  • I add a definition for function_02 to src/attribute_error/__init__.py

    13def function_00(): return variable_09
    14def function_01(): return function_00()
    15def function_02(): return function_01()
    

    the test passes because function_02 is now an attribute of src/attribute_error/__init__.py in the src folder, and I can call it from outside the file with src.attribute_error.function_02()

    src.attribute_error.function_02() -> None
    └── src/
        └── attribute_error/
            └── __init__.py
                └── def function_02(): return function_01()
    
  • I add a call to function_03 from test_attribute_error_w_functions in tests/test_attribute_error.py

    17def test_attribute_error_w_functions():
    18    src.attribute_error.function_00()
    19    src.attribute_error.function_01()
    20    src.attribute_error.function_02()
    21    src.attribute_error.function_03()
    22
    23
    24# Exceptions seen
    

    the terminal is my friend, and shows AttributeError

    AttributeError: module 'src.attribute_error'
                    has no attribute 'function_03'.
                    Did you mean: 'function_00'?
    
  • I add a definition for function_03 to src/attribute_error/__init__.py

    13def function_00(): return variable_09
    14def function_01(): return function_00()
    15def function_02(): return function_01()
    16def function_03(): return function_02()
    

    the test passes because function_03 is now an attribute of src/attribute_error/__init__.py in the src folder, and I can call it from outside the file with src.attribute_error.function_03()

    src.attribute_error.function_03() -> None
    └── src/
        └── attribute_error/
            └── __init__.py
                └── def function_03(): return function_02()
    
  • I add a call to function_04 from test_attribute_error_w_functions in tests/test_attribute_error.py

    17def test_attribute_error_w_functions():
    18    src.attribute_error.function_00()
    19    src.attribute_error.function_01()
    20    src.attribute_error.function_02()
    21    src.attribute_error.function_03()
    22    src.attribute_error.function_04()
    23
    24
    25# Exceptions seen
    

    the terminal is my friend, and shows AttributeError

    AttributeError: module 'src.attribute_error'
                    has no attribute 'function_04'.
                    Did you mean: 'function_00'?
    
  • I add a definition for function_04 to src/attribute_error/__init__.py

    13def function_00(): return variable_09
    14def function_01(): return function_00()
    15def function_02(): return function_01()
    16def function_03(): return function_02()
    17def function_04(): return function_03()
    

    the test passes because function_04 is now an attribute of src/attribute_error/__init__.py in the src folder, and I can call it from outside the file with src.attribute_error.function_04()

    src.attribute_error.function_04() -> None
    └── src/
        └── attribute_error/
            └── __init__.py
                └── def function_04(): return function_03()
    
  • I add a call to function_05 from test_attribute_error_w_functions in tests/test_attribute_error.py

    17def test_attribute_error_w_functions():
    18    src.attribute_error.function_00()
    19    src.attribute_error.function_01()
    20    src.attribute_error.function_02()
    21    src.attribute_error.function_03()
    22    src.attribute_error.function_04()
    23    src.attribute_error.function_05()
    24
    25
    26# Exceptions seen
    

    the terminal is my friend, and shows AttributeError

    AttributeError: module 'src.attribute_error'
                    has no attribute 'function_05'.
                    Did you mean: 'function_00'?
    
  • I add a definition for function_05 to src/attribute_error/__init__.py

    13def function_00(): return variable_09
    14def function_01(): return function_00()
    15def function_02(): return function_01()
    16def function_03(): return function_02()
    17def function_04(): return function_03()
    18def function_05(): return function_04()
    

    the test passes because function_05 is now an attribute of src/attribute_error/__init__.py in the src folder, and I can call it from outside the file with src.attribute_error.function_05()

    src.attribute_error.function_05() -> None
    └── src/
        └── attribute_error/
            └── __init__.py
                └── def function_05(): return function_04()
    
  • I add a call to function_06 from test_attribute_error_w_functions in tests/test_attribute_error.py

    17def test_attribute_error_w_functions():
    18    src.attribute_error.function_00()
    19    src.attribute_error.function_01()
    20    src.attribute_error.function_02()
    21    src.attribute_error.function_03()
    22    src.attribute_error.function_04()
    23    src.attribute_error.function_05()
    24    src.attribute_error.function_06()
    25
    26
    27# Exceptions seen
    

    the terminal is my friend, and shows AttributeError

    AttributeError: module 'src.attribute_error'
                    has no attribute 'function_06'.
                    Did you mean: 'function_00'?
    
  • I add a definition for function_06 to src/attribute_error/__init__.py

    13def function_00(): return variable_09
    14def function_01(): return function_00()
    15def function_02(): return function_01()
    16def function_03(): return function_02()
    17def function_04(): return function_03()
    18def function_05(): return function_04()
    19def function_06(): return function_05()
    

    the test passes because function_06 is now an attribute of src/attribute_error/__init__.py in the src folder, and I can call it from outside the file with src.attribute_error.function_06()

    src.attribute_error.function_06() -> None
    └── src/
        └── attribute_error/
            └── __init__.py
                └── def function_06(): return function_05()
    
  • I add a call to function_07 from test_attribute_error_w_functions in tests/test_attribute_error.py

    17def test_attribute_error_w_functions():
    18    src.attribute_error.function_00()
    19    src.attribute_error.function_01()
    20    src.attribute_error.function_02()
    21    src.attribute_error.function_03()
    22    src.attribute_error.function_04()
    23    src.attribute_error.function_05()
    24    src.attribute_error.function_06()
    25    src.attribute_error.function_07()
    26
    27
    28# Exceptions seen
    

    the terminal is my friend, and shows AttributeError

    AttributeError: module 'src.attribute_error'
                    has no attribute 'function_07'.
                    Did you mean: 'function_00'?
    
  • I add a definition for function_07 to src/attribute_error/__init__.py

    13def function_00(): return variable_09
    14def function_01(): return function_00()
    15def function_02(): return function_01()
    16def function_03(): return function_02()
    17def function_04(): return function_03()
    18def function_05(): return function_04()
    19def function_06(): return function_05()
    20def function_07(): return function_06()
    

    the test passes because function_07 is now an attribute of src/attribute_error/__init__.py in the src folder, and I can call it from outside the file with src.attribute_error.function_07()

    src.attribute_error.function_07() -> None
    └── src/
        └── attribute_error/
            └── __init__.py
                └── def function_07(): return function_06()
    
  • I add a call to function_08 from test_attribute_error_w_functions in tests/test_attribute_error.py

    17def test_attribute_error_w_functions():
    18    src.attribute_error.function_00()
    19    src.attribute_error.function_01()
    20    src.attribute_error.function_02()
    21    src.attribute_error.function_03()
    22    src.attribute_error.function_04()
    23    src.attribute_error.function_05()
    24    src.attribute_error.function_06()
    25    src.attribute_error.function_07()
    26    src.attribute_error.function_08()
    27
    28
    29# Exceptions seen
    

    the terminal is my friend, and shows AttributeError

    AttributeError: module 'src.attribute_error'
                    has no attribute 'function_08'.
                    Did you mean: 'function_00'?
    
  • I add a definition for function_08 to src/attribute_error/__init__.py

    13def function_00(): return variable_09
    14def function_01(): return function_00()
    15def function_02(): return function_01()
    16def function_03(): return function_02()
    17def function_04(): return function_03()
    18def function_05(): return function_04()
    19def function_06(): return function_05()
    20def function_07(): return function_06()
    21def function_08(): return function_07()
    

    the test passes because function_08 is now an attribute of src/attribute_error/__init__.py in the src folder, and I can call it from outside the file with src.attribute_error.function_08()

    src.attribute_error.function_08() -> None
    └── src/
        └── attribute_error/
            └── __init__.py
                └── def function_08(): return function_07()
    
  • I add a call to function_09 from test_attribute_error_w_functions in tests/test_attribute_error.py

    17def test_attribute_error_w_functions():
    18    src.attribute_error.function_00()
    19    src.attribute_error.function_01()
    20    src.attribute_error.function_02()
    21    src.attribute_error.function_03()
    22    src.attribute_error.function_04()
    23    src.attribute_error.function_05()
    24    src.attribute_error.function_06()
    25    src.attribute_error.function_07()
    26    src.attribute_error.function_08()
    27    src.attribute_error.function_09()
    28
    29
    30# Exceptions seen
    

    the terminal is my friend, and shows AttributeError

    AttributeError: module 'src.attribute_error'
                    has no attribute 'function_09'.
                    Did you mean: 'function_00'?
    
  • I add a definition for function_09 to src/attribute_error/__init__.py

    13def function_00(): return variable_09
    14def function_01(): return function_00()
    15def function_02(): return function_01()
    16def function_03(): return function_02()
    17def function_04(): return function_03()
    18def function_05(): return function_04()
    19def function_06(): return function_05()
    20def function_07(): return function_06()
    21def function_08(): return function_07()
    22def function_09(): return function_08()
    

    the test passes because function_09 is now an attribute of src/attribute_error/__init__.py in the src folder, and I can call it from outside the file with src.attribute_error.function_09()

    src.attribute_error.function_09() -> None
    └── src/
        └── attribute_error/
            └── __init__.py
                └── def function_09(): return function_08()
    
  • I add a git commit message in the other terminal

    git commit -am \
    'add test_attribute_error_w_functions'
    

A function in a module is an attribute of the module


close the project

  • I close src/attribute_error/__init__.py and tests/test_attribute_error.py

  • I click in the terminal where the tests are running

  • I use q on the keyboard to leave the tests. The terminal goes back to the command line.

  • I change directory to the parent of attribute_error

    cd ..
    

    the terminal shows

    .../pumping_python
    

    I am back in the pumping_python directory.


review

I ran tests for AttributeError that showed

My problem with the tests is that they all show the correct way to use attributes I made in src/attribute_error/__init__.py. If someone reads the file or runs it, there is no way for them to know how the code relates to AttributeError unless they go through the process with me, there has to be a better way.


code from the chapter

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


what is next?

Would you like to test making a person with f-strings?


rate pumping python

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