How to properly import my module file into my test file? - python

I have the following file structure:
C:.
├───jobs_struct
│ │
│ └───app
│ └───job_struct
│ │ delta.py
│
└───test
├───integration
└───unitaire
│ test_delta.py
test_delta.py is a pytest file and import delta.py to test its functions.
In test_delta.py, I do not understand how I am supposed to import delta.py. I have tried the following:
Attempt 1
sys.path.append("../../")
from jobs_struct.app.job_struct.delta import ApplyDelta
Throws:
E ModuleNotFoundError: No module named 'jobs_struct'
Attempt 2
from jobs_struct.app.job_struct.delta import ApplyDelta
E ModuleNotFoundError: No module named 'jobs_struct'
Attempt 3
sys.path.append("/jobs_struct/app/job_struct")
from delta import ApplyDelta
from delta import ApplyDelta
E ModuleNotFoundError: No module named 'delta'
Additionnal details
Some answers recommend to include init.py files at specific locations (or everywhere). I would like to avoid changing/adding anything to the app itself.
Moreover, the pytest command is ran from the root of the project (if that has any impact).
Question
How to correctly import my module, knowing that using absolute path is not an option, in order to be able to run my test file.

Have you tried sys.path.append('your_complete_path_to/job_struct')
and then: from delta import ApplyDelta ?

Related

Impossible to import a package I made. "ModuleNotFoundError"

I have a project organized like so :
application
├── app
│ └── package
└── __init__.py
│ └── functions.py
└── app2
└── some_folder
└── file_2.py
My "functions.py" contains a basic function:
#functions.py
def add(x,y):
return x+y
The file "_init_.py" is empty
I want to use the "add" function in my "file_2.py" file, so I write:
#file_2.py
from application.app.package.functions import add
print(add(2,3))
But it returns an error message:
ModuleNotFoundError: No module named 'application'
it is the same if i try any of these:
from app.package.functions import add
from package.functions import add
from functions import add
Does anyone know where the problem comes from? I'm doing exactly like in this tutorial so I don't understand what's wrong
tutorial's link
Thank you for your help
One way to import functions.add is to import sys and use sys.path.insert()
after that you can import add from functions:
import sys
sys.path.insert(1, 'the/local/path/to/package')
from functions import add
print(add(1,2))

pdoc3 or Sphinx for directory with nested module

My code directory looks like below. I need to generate documentation for all the modules like for sub1,sub2,submoduleA1,submoduleB1 and so on.
Also as shown for submoduleB2.py: all the modules imports from other modules/submodules
<workspace>
└── toolbox (main folder)
├── __init__.py
│
├── sub
│ ├── __init__.py
│ ├── sub1.py
│ └── sub2.py
│
├── subpackageA
│ ├── __init__.py
│ ├── submoduleA1.py
│ └── submoduleA2.py
│
└── subpackageB
├── __init__.py
├── submoduleB1.py
└── submoduleB2.py code[from sub import sub1
from subpackageA import submoduleA2 and so on]
code structure for submoduleB2.py
from __future__ import absolute_import, division
import copy
import logging
import numpy as np
import pandas as pd
from dc.dc import DataCleaning
from sub.sub1 import ToolboxLogger
from subpackageA import pan
LOGGER = ToolboxLogger(
"MATH_FUNCTIONS", enableconsolelog=True, enablefilelog=False, loglevel=logging.DEBUG
).logger
"""
Calculations also take into account units of the tags that are passed in
"""
def spread(tag_list):
"""
Returns the spread of a set of actual tag values
:param tag_list: List of tag objects
:type tag_list: list
:return: Pandas Series of spreads
:rtype: Pandas Series
:example:
>>> tag_list = [tp.RH1_ogt_1,
tp.RH1_ogt_2,
tp.RH1_ogt_3,
tp.RH1_ogt_4,
tp.RH1_ogt_5,
tp.RH1_ogt_6]
>>> spread = pan.spread(tag_list)
"""
# use the same units for everything
units_to_use = tag_list[0].units
idxs = tag_list[0].actuals.index
spread_df = pd.DataFrame(index=idxs)
spread_series = spread_df.max(axis=1).copy()
return Q_(spread_series, units_to_use)
I tried to run the pdoc command using anaconda prompt by navigating it to the toolbox folder and executed the below command
pdoc --html --external-links --all-submodules preprocess/toolbox/subpackageA
after executing this command a "subpackageA" folder was created under toolbox with index.html file but it was all blank
Then i tried to generate documentation by providing specific module name
pdoc --html --external-links --all-submodules preprocess/toolbox/submoduleB2.py
but received this below error:
File "C:\Users\preprocess/toolbox/submoduleB2.py", line 16, in
from sub import sub1
ImportError: No module named sub.sub1
Can you please tell me how to generate the documentation using pdoc for complete directory?
Or is there any other package which will auto generate the documentation?
I even tried Sphnix, but faced issues in adding the module/submodule paths in config file
It appears that pdoc3 is throwing that kind of error for a module if it cannot find an import into that module in the python path. One solution is to put
import os, sys
syspath = os.path.dirname(os.path.abspath(__file__))
sys.path.append(path)
into the __init__.py files in each of the subdirectories.

import module in different contexts

I have a file structure like this:
work/
├─ analysis.ipynb
├─ app/
│ ├─ __init__.py
│ ├─ class_a.py
│ ├─ script.py
│ ├─ utils.py
File class_a.py contains a class MyClass and also an import from utils like this:
from utils import useful_function
class MyClass():
...
Then I try to import MyClass in analysis.ipynb like this:
from app.class_a import MyClass
and get an error:
ModuleNotFoundError Traceback (most recent call last)
<ipython-input-4-8eeb8559d767> in <module>
2 import os
3 from datetime import datetime
----> 4 from app.class_a import MyClass
5 from app.utils import useful_function
6 ...
~/Documents/work/app/class_a.py in <module>
1 import pandas as pd
----> 2 from utils import useful_function
3
4 class MyClass():
5 '''indeed very necessary class for me
ModuleNotFoundError: No module named 'utils'
I have figured out that if I change all imports in app folder to something like this:
from app.utils import useful_function
Then I can import all I need from analysis.ipynb
However app should work as something I run with python script.py and that does not work unless imports are written in the original way.
I do not understand modules and packaging and so can not even ask a question precisely, but how do I align import "styles" in order to both be able to run python scripts.py from the app directory and import MyClass from analys.ipynb?
import statements search through the list of paths in sys.path, so I've added these lines to my analysis.ipynb:
import sys
sys.path.append('/path/to/work/app/')
In case someone would have the same question and struggle as me.

Pytest and submodules

I am trying to run pytest tests on my python modules but am running into an error. It looks like it the main script ircFriend.py can't find the modules I import inside of it. This is the error I get. I get this error on every test.
______________________________________________ ERROR collecting test/configuration_test.py ____________________________________
ImportError while importing test module 'C:\Users\munded\Desktop\irc-friend\test\configuration_test.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
..\..\appdata\local\programs\python\python38\lib\importlib\__init__.py:127: in import_module
return _bootstrap._gcd_import(name[level:], package, level)
test\configuration_test.py:2: in <module>
from src import ircFriend
E ModuleNotFoundError: No module named 'configuration'
This is the file structure I am using for my tests. The __init__.py files are empty.
├───src
│ │ configuration.py
│ │ ircFriend.py
│ │ ircSync.py
│ │ logbook.py
│ │ networkdrive.py
│ │ server.py
│ │ tree.py
│ │ workspace.py
│ │ __init__.py
└───test
│ configuration_test.py
│ fileIO_test.py
│ sandbox_test.py
│ server_test.py
│ sync_test.py
│ __init__.py
If we look at the imports in ircFriend.py they look like this.
import sys
import getopt
import logging
from configuration import Configuration
from logbook import LogBook
from networkdrive import NetworkDrive
from ircSync import IRCSync
from workspace import Workspace
from server import Server
Finaly thees are what my tests look like.
from src import ircFriend
from unittest import mock
from src import configuration
from src import server
#mock.patch('builtins.input', side_effect=['X'])
def testPropertiesFileExists(mockInput):
conf = Configuration()
assert conf.propertiesFileExists() is True
#mock.patch('builtins.input', side_effect=['X'])
def testIrcConfigExists(mockInput):
conf = Configuration()
assert conf.ircConfigExists() is True
#mock.patch('builtins.input', side_effect=['devsite.dev', 'user'])
#mock.patch('src.ircFriend.getpass.getpass', return_value="IDK")
def testServerCreation(mock_input, mock_getpass):
dev = Server()
if isinstance(dev, ircFriend.Server):
assert True
else:
assert False
Any guidence on this subject would do me a world of good.
Best Regards,
E
You should not make both src/__init__.py and test/__init__.py files because these src and test are not packages. These are just root directories for source and test codes.
In test codes, You should remove from src because src is not a package.
Finally, run pytest adding src to PYTHONPATH otherwise pytest can't find modules under the src directory.
$ PYTHONPATH=src pytest test
Or, You can make src/conftest.py, this is a special file for pytest.
I checked these codes.
# test/conftest.py
import sys
sys.path.append("./src")
# src/a.py
from b import say
def func():
return say()
# src/b.py
def say():
return "Hello"
# test/test_a.py
import a
def test_a():
assert a.func() == "Hello"
$ pytest test

How to load module with same name as other module in Python?

Let me explain problem - we have such project:
model/__init__.py
model/abstract.py
task/__init__.py
task/model.py
How to load into task/model.py model.abstract what is the syntax for it?
# task/model.py
import model # it loads task/model.py not model
from model.abstract import test # there is no test exception
# model/abstract.py
test = 1
How to do such import?
Requested more details.
Google App Engine application:
- main is main.py
Directory structure:
└───src
│ app.yaml
│ index.yaml
│ main.html
│ main.py
│ task_master_api.py
│
├───circle
│ model.py
│ __init__.py
│
├───model
│ abstract.py
│ xxx.py
│ __init__.py
│
├───task
│ model.py
│ __init__.py
│
├───user
│ model.py
│ __init__.py
Exception (see task.model not model in root):
from .. import model
logging.critical((type(model), model.__name__))
from model.abstract import AbstractNamed, AbstractForgetable
-
CRITICAL 2014-02-17 21:23:36,828 model.py:8] (<type 'module'>, 'task.model')
from model.abstract import AbstractNamed, AbstractForgetable
ImportError: No module named abstract
Much more related to answer.
from .. import model
Gives exception.
ValueError: Attempted relative import beyond toplevel package
While the relative imports in ndpu's answer should work, the answer to this question that is burning in my mind is simply this: change the name of your files to avoid this error.
If you have model.py inside the circle directory, how about changing the name to circle_model.py?
Then, you should be able to import modules without any of the relative import .. business.
Edit - knowing now that you don't want to rename
Make sure you have an __init__.py file in your src directory, then try the relative import from .model.abstract import test
Relative import given in the other answer should just work fine. But it is not working because you have a name conflict. You have both a package and module named model. try to use another name either for your package or module.
I found two tricks to force load modele name into module name:
First forcing only absolute loading:
from __future__ import absolute_import
import name
Second is like previous but more code and more local impact:
save_path = sys.path[:]
sys.path.remove('')
import name
sys.path = save_path

Categories