How to avoid circular import within django's tests dir? - python

I'm trying to fix a circular import issue I'm having with Django tests.
My dir structure is:
app/tests:
test_user_level01.py
test_user_level02.py
Within each file I have classes to test get 200s and get 403s (among other classes). Users in level 2 should have all the get 200s that level 1 users have and users in level 1 should have all the get 403s that the level 2 users have. Thus I have a circular import.
Normally I would solve this with an absolute import but I can't figure out what that would be.
I've tried:
"""test_user_level01.py"""
from . import test_user_level02
"""test_user_level02.py"""
from . import test_user_level01
But this seems to give a circular import error (missing classes).
Thank you ahead of time for your help.
PS. The following doesn't work:
import app.tests.test_user_level01 as level01
OR:
import tests.test_user_level01 as level01
OR:
import .test_user_level01 as level01

Move common code, i.e. code which is used in both test_user_level01.py and test_user_level02.py, to a separate file, e.g. app/tests/common.py, and then import from there. Don't forget to make app/tests a package (i.e. create __init__.py file in the dir).
"""test_user_level01.py"""
from app.tests.common import some_common_class_name
"""test_user_level02.py"""
from app.tests.common import some_common_class_name

Related

ImportError attempted relative import with no known parent

Based on some answers I try to be more specific.
I want to import the print and the models AND code in my main.py
I know the question gets asked a lot, but still I could not figure out whats wrong with my code!
I have a project directory like this
-project
--__init__py
--main.py
--print.py
--requests
--__init__.py
--models.py
--code.py
i want to import from print.py and * from requests
Therefore I tried to add these lines in main.py
from . import print
#or
import print
#for requests I tried
import os.path
import sys
sys.path.append('./requests')
from requests import *
all of those lines cause the same ImportError attempted relative import with no known parent ,
using Python 39
anyone an idea where the problem is?
I am very confused that this seems not to work, was it possible in older versions?
You should definitely not be doing anything with sys.path. If you are using a correct Python package structure, the import system should handle everything like this.
From the directory structure you described, project would be the name of your package. So when using your package in some external code you would do
import package
or to use a submodule/subpackage
import project.print
import project.requests
and so on.
For modules inside the package you can use relative imports. When you write
i want to import from print.py and * from requests Therefore I tried
it's not clear from where you want to import them, because this is important for relative imports.
For example, in project/main.py to import the print module you could use:
from . import print
But if it's from project/requests/code.py you would use
from .. import print
As an aside, "print" is probably not a good name for a module, since if you import the print module it will shadow the print() built-in function.
Your main file should be outside the 'project'-directory to use that as a package.
Then, from your main file, you can import using from project.print import ....
Within the project-package, relative imports are possible.

Attempted relative import beyond top-level package with Python

I have seen several questions related to this error but I think they are different cases. My Django project has 2 applications and a directory structure like this and I'm facing an issue with relative imports I don't understand the logic.
Python allows me to import market from file my_app2/signals.py but it returns ValueError: attempted relative import beyond top-level package if I import portfolio from file my_app1/signals.py. What is the reason and how can I found a wordaround?
/my_project
/my_project
__init__.py
/my_app1
market.py
signals.py # Here I can't import portfolio.py
/my_app2
portfolio.py
signals.py # Here I can import market.py
my_app1/signals.py
from ..my_app2 import portfolio # doesn't work
ValueError: attempted relative import beyond top-level package
from my_project.my_app2 import portfolio # doesn't work
ModuleNotFoundError: No module named 'my_project.my_app2'
my_app2/signals.py
from ..my_app1 import market # works
I finally solved the issue without the use of from, it's not clear for me what was causing the error.
import my_app2.portfolio as portfolio

Is there any advantage to importing a module by relative path vs actual package name?

Let's say I have a folder structure as below.
project/
-> app/
--> __init__.py (has db = SQLAlchemy(app))
--> model.py
I need to import db in model.py. I can either import it using
from app import db
or
from . import db
Is there a difference between the two? Does one method have any advantages over the other method?
Absolute imports are preferred because they are quite clear and straightforward. It is easy to tell exactly where the imported resource is, just by looking at the statement. In fact, pep8 explicitly recommends absolute imports.
Sometimes, however, absolute imports can get quite verbose, depending on the complexity of the directory structure. Imagine having a statement like this:
from package1.subpackage2.subpackage3.subpackage4.module5 import function6
This looks ridiculous! Right?
So, Relative imports comes into picture. A relative import specifies the resource to be imported relative to the current location—that is, the location where the import statement is.
Above complex import statement becomes:
from ..subpackage4.module5 import function6
Hope this helps!

Python: Import a file from from day_one.py to main.py then in day_one I import a function from main.py. Error cannot import

I'm not sure why it won't work, it may be an issue that you can't work around, but I would just like to know why it won't work. I am sorry if I waste your time, or didn't ask the question properly, I'm 16 and new to Python kind of.
in main.py
from day_one import day_one_def
in day_one.py
from main import main_home_window
error message
ImportError: cannot import name 'day_one'
It looks like you have a circular import: main imports from day_one and day_one imports from main. This isn't really how python is supposed to work. You should create linear dependencies, where the top module only relies on the ones below it, which only rely on the ones below them, etc.

is there any point in using relative paths in Python import statement?

I have a Python package called Util. It includes a bunch of files. Here is the include statements on top of one of the files in there:
from config_util import ConfigUtil #ConfigUtil is a class inside the config_util module
import error_helper as eh
This works fine when I run my unit tests.
When I install Util in a virtual environment in another package everything breaks. I will need to change the import statements to
from Util.config_util import ConfigUtil
from Util import error_helper as eh
and then everything works as before. So is there any point in using the first form or is it safe to say that it is better practice to always use the second form?
If there is no point in using the first form, then why is it allowed?
Just wrong:
from config_util import ConfigUtil
import error_helper as eh
It will only work if you happen to be in the directory Util, so that the imports resolve in the current working directory. Or you have messed with sys.path using some bad hack.
Right (using absolute imports):
from Util.config_util import ConfigUtil
import Util.error_helper as eh
Also right (using relative imports):
from .config_util import ConfigUtil
import .error_helper as eh
There is no particular advantage to using relative imports, only a couple of minor things I can think of:
Saves a few bytes in the source file (so what / who cares?)
Enables you to rename the top level without editing import statements in source code (...but how often do you do that?)
For your practical problems, maybe this answer can help you.
Regarding your direct question: there's not a lot to it, but they let you move files and rename containing directories more easily. You may also prefer relative imports for stylistic reasons; I sure do.
The semantics are the same if the paths are correct. If your module is foo.bar, then from foo.bar.baz import Baz and from .baz import Baz are the same. If they don't do the same, then you're likely calling your Python file as a script (python foo/bar.py), in which case it will be module __main__ instead of foo.bar.

Categories

Resources