0

I get error while trying to execute pytest UTs for the project.

E       TypeError: 'module' object is not callable

I have the following repository structure:

├───src
│   └───company
│       ├───acc
│       └───dp
│           └───logic
│               ├───business
│               │   ├───__init__.py 
│               │   ├───alter_customer.py
│               │   ├───filter_customer.py
│               │   └───review_customers.py
│               └───general
│                   ├───some_function.py
│                   └───__init__.py
├───tests
│   └───company
│       └───dp
│           └───logic
│                └───business
│                    ├───test_alter_customer.py
│                    └───test_review_customers.py
├───conftest.py
└───pyproject.toml

Each file under business package contains one function with the same name as the file.

Let's imagine file filter_customer.py like that:

def filter_customer(i: int) -> int:
    return i

Let's imagine file review_customers.py like that:

from company.dp.logic.general import some_function
def review_customers() -> str:
    x = some_function("custom")
    return x

Let's imagine file alter_customer.py like that:

from company.dp.logic.business import filter_customer
def alter_customer() -> str:
    x = filter_customer(10) <- this line raise error while trying to run Unit Test
    return x

UT looks something like that:

from company.dp.logic.business import alter_customer
def test_alter_customer():
    x = alter_customer()
    assert x == 10

./business/__init__.py file for business package looks like that:

from company.dp.logic.business.alter_customer import alter_customer
from company.dp.logic.business.filter_customer import filter_customer
from company.dp.logic.business.review_customers import review_customers

./general/__init__.py file for business package looks like that:

from src.company.dp.logic.general.some_function import some_function 

pyproject.toml

[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"

[tool.setuptools.packages.find]
where = ["src"]

[tool.pytest.ini_options]
addopts = [
]
testpaths = ["tests/company/dp/logic/business"]
python_files = "test_*.py"
python_functions = "test_*"
pythonpath = "src"
norecursedirs = "*"

How to correctly organize the packages/modules in such scenario?

The goal was to have one function per file and packages like business and general to cover imports from modules.

I have tried multiple versions.

When I use direct import from module/file, it work. It also works when I call function from different package like general.

# This works:
from src.company.dp.logic.business.filter_customer import filter_customer

# With this I have error, even though IDE resolve it correctly:
from src.company.dp.logic.business import filter_customer


# This works:
from src.company.dp.logic.general import some_function

def review_customers()
    c = filter_customer(10)
    return something

I prepared repository which allows to recreate this problem: https://github.com/paweltajs/module-package/tree/main

Edit. Few other observations.

When I change the name of the function to differ from file name, I got different error:

E   ImportError: cannot import name 'f_filter_customer' from partially initialized module 'company.dp.logic.business' (most likely due to a circular import) (C:\Repositories\module-package\src\company\dp\logic\business\__init__.py)

When I put import within the function, it works. Like that:

def alter_customer() -> str:
    from company.dp.logic.business import filter_customer
    x = filter_customer(10)
    return x
2
  • src shouldn't be considered to define a package, just a directory that contains the top-level module/package company. Commented Oct 18, 2024 at 13:26
  • @chepner I added link to GitHub with example. Commented Oct 19, 2024 at 11:57

1 Answer 1

1

filter_customer is a module that also contains a function named filter_customer. You're calling filter_customer, not filter_customer.filter_customer.

(There is no reason to define a separate module for each function; don't do that.)

Sign up to request clarification or add additional context in comments.

8 Comments

There are reasons to have separate files for each function. Why this is then working when calling general ?
I don't see how general has anything to do with this. Is your last code block supposed to be three different files? The first import makes sense; the second one does not, because it only imports the module into the current namespace, not any functions in that module.
Importing functions from general works in business module. So I can do ‘ from src.company.dp.logic.general import some_function’ an it correctly imports the function, not module. Problem is only when I do this between modules under business.
Yes, because general.some_function actually is a function. business.filter_customer is not; it's a module that contains a function, which is why business.filter_customer.filter_customer works.
some_function is under the same rule, there is some_function.py file and it is in init file. The only difference is that it it under different folder/package.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.