Skip over levels of a directory when importing python package - python

I've got a directory structure like:
Folder_in_PYTHONPATH/
├── Package1
│   ├── __init__.py
│   ├── src
│   │   ├── Class1.py
│   │   ├── Class2.py
│   │   └── __init__.py
│   └── test
│   └── testfile.py
├── Package2
│   ├── __init__.py
│   ├── src
│   │   ├── Class1.py
│   │   ├── Class2.py
│   │   └── __init__.py
│   └── test
│   ├── test1.py
│   └── test2.py
.
.
.
When I import things from this folder, I need to always type
import Package1.src.Class1
Is there any way to set up my __init__.py so that I can just type
import Package1.Class1
instead?

Add them into your packages' __init__.py files so they look like:
from src import Class1
from src import Class2
Have a look at the docs
I would recommend putting the *.py files in the top level folder of their package to get the import Package_1.Class1 behaviour you are after. The unit tests can stay in their own folder to keep them separate.

Related

Sphinx ignores py-file starting with a _ in filename

I am playing around with Sphinx 4.4.0 in a test project. I use sphinx.ext.autodoc and sphinx-apidoc.
But not all py files are recognized. It seams like that files with a starting _ in filename are ignored (e.g. _mypackage.py). But i am not sure if that character is the cause or something else.
Are you aware of an option to modify that behavior?
This is the project structure
sphinx_versuch
├── docs
│   ├── make.bat
│   ├── Makefile
│   └── source
│   ├── conf.py
│   ├── index.rst
│   ├── modules.rst
│   ├── mypackage.rst
│   ├── _static
│   └── _templates
├── LICENSE
├── README.md
├── src
│   ├── mypackage
│   │   ├── a.py
│   │   ├── b.py
│   │   ├── __init__.py
│   │   └── _mypackage.py
│   ├── setup.cfg
│   └── setup.py
└── tests
├── __init__.py
├── test_a.py
├── test_b.py
└── test_mypackage.py
The option --private or -P for sphinx-apidoc make sure that private files (which start with an underscore by convention) are included also.
See also
https://www.sphinx-doc.org/en/master/man/sphinx-apidoc.html#cmdoption-sphinx-apidoc-P

moduleNotFoundError: no module named (*)

 I'm trying to run my tests using python -m pytest but I get an error that
ModuleNotFoundError: No module named 'sample'
When using nosetests or anything else it works fine, but when trying to use pytest, it doesn't work.
My tree looks like below, do you have any advice why it doesn't work?
├── LICENSE.txt
├── README.md
├── data
│   └── data_file
├── exported_register.csv
├── pyproject.toml
├── requirements.txt
├── setup.cfg
├── setup.py
├── src
│   └── sample
│   ├── __init__.py
│   ├── __pycache__
│   │   ├── __init__.cpython-39.pyc
│   │   ├── dziennik.cpython-39.pyc
│   │   ├── przedmiot.cpython-39.pyc
│   │   ├── simple.cpython-39.pyc
│   │   └── uczen.cpython-39.pyc
│   ├── dziennik.py
│   ├── package_data.dat
│   ├── przedmiot.py
│   ├── simple.py
│   └── uczen.py
├── tests
│   ├── __init__.py
│   ├── __pycache__
│   │   ├── __init__.cpython-39.pyc
│   │   ├── test_ASSERTPY_uczen.cpython-39-pytest-6.2.1.pyc
│   │   ├── test_ASSERTPY_uczen.cpython-39-pytest-6.2.5.pyc
│   │   ├── test_ASSERTPY_uczen.cpython-39.pyc
│   │   ├── test_PYHAMCREST_uczen.cpython-39-pytest-6.2.1.pyc
│   │   ├── test_PYHAMCREST_uczen.cpython-39-pytest-6.2.5.pyc
│   │   ├── test_PYHAMCREST_uczen.cpython-39.pyc
│   │   ├── test_UNITTEST_register.cpython-39-pytest-6.2.1.pyc
│   │   ├── test_UNITTEST_register.cpython-39-pytest-6.2.5.pyc
│   │   ├── test_UNITTEST_register.cpython-39.pyc
│   │   ├── test_UNITTEST_uczen.cpython-39-pytest-6.2.1.pyc
│   │   ├── test_UNITTEST_uczen.cpython-39-pytest-6.2.5.pyc
│   │   ├── test_UNITTEST_uczen.cpython-39.pyc
│   │   ├── test_simple.cpython-39-pytest-6.2.1.pyc
│   │   ├── test_simple.cpython-39-pytest-6.2.5.pyc
│   │   └── test_simple.cpython-39.pyc
│   ├── test_ASSERTPY_uczen.py
│   ├── test_PYHAMCREST_uczen.py
│   ├── test_UNITTEST_register.py
│   ├── test_UNITTEST_uczen.py
│   └── test_simple.py
└── tox.ini
When you run pytest with python -m pytest it uses the current directory as it its working dir, which doesn't contain the sample module (located inside ./src). The way I deal with this is I have a conftest.py inside my tests directory where I add my source dir to python path something like this:
import sys
from pathlib import Path
source_path = Path(__file__).parents[1].joinpath("src").resolve()
sys.path.append(str(source_path))
I've recently started using pytorch and have had similar problems. Couple steps come to mind:
How are you writing the .py file that contains the tests? It may simply be that you need to change up how you import sample within the unit test file. I would expect that you need something like import src.sample.simple. In other words, could be just a pathing issue.
Try a (much) simpler folder structure and try again. If that doesn't work, try to just copy an example of a simple scheme that someone has posted. That is, just get python -m pytest to run somehow, then start slowly adding the complexities of your project.

Importing multiple files as a single module?

I have been chasing my tail for the last 4 hours here and can't find the solution.
I have the following module/package structure for my project.
.
├── app-cli.py
├── tools
│   ├── __init__.py
│   ├── adapters
│   │   ├── __init__.py
│   │   ├── cli.py
│   │   ├── web.py
│   ├── utils
│   │   ├── __init__.py
│   │   ├── core.py
│ │   │   ├── my_public_method()
│   │   ├── io.py
│ │   │   ├── some_other_public_method()
What I'm trying to do is bundle everything inside utils within the utils name space.
So when I do import tools at the main level, I can access the util functions as:
tools.utils.my_public_method()
tools.utils.some_other_public_method()
Instead of:
tools.utils.core.my_public_method()
tools.utils.io.some_other_public_method()
I have been editing the __init__.py messing around with the levels of imports, attempting to create a shortcut but with no success.
In your __init__.py inside the utils package you can add
from .core import my_public_method
from .io import some_other_public_method
and then you can do:
import tools.utils
tools.utils.my_public_method()
tools.utils.some_other_public_method()

Python Imports with packages

I have a my projects set up like so(the name package is used isn't the name of the directory only for this example it has been used):
.
├── Installer\ Script.iss
├── LICENSE
├── README.md
├── TODO.md
├── docs
├── requirements.txt
├── resources
│   ├── logo.hqx
│   ├── logo.icns
│   ├── logo.ico
│   └── qt.conf
├── setup.py
└── project
├── Main.py
├── Controller.py
├── Updator.py
├── Updator.pyc
├── __init__.py
├── tests
│   ├── TestController.py
│   ├── TestUpdator.py
│   ├── TestUpdator.pyc
│   └── __init__.py
└── ui.py
In my Main.py how should I import ui.py? Currently my code for importing looks like:
import project.ui as ui
Is this correct? As when I freeze the project with py2app it doesn't like my imports.
If the the package that you want to import in the same directory, you just write "import ui" in your main.py can work as you want it to.If you want to import ui in you setup.py(just for example), you can do it what you ask above.
Hope this can help you .

Importing a Python module in a package returns a different module from the same package

When I run an import in my development environment, I seem to get the wrong module.
How do I make sense of this?
$ python -c "import breathe.renderer.rst.doxygen.compound as com; print com"
<module 'breathe.parser.doxygen.compound' from 'breathe/parser/doxygen/compound.pyc'>
The layout of the breathe directory is:
breathe
├── directives.py
├── finder
│   ├── doxygen
│   │   ├── base.py
│   │   ├── compound.py
│   │   ├── index.py
│   │   └── __init__.py
│   └── __init__.py
├── __init__.py
├── nodes.py
├── parser
│   ├── doxygen
│   │   ├── compound.py
│   │   ├── compoundsuper.py
│   │   ├── index.py
│   │   ├── indexsuper.py
│   │   ├── __init__.py
│   ├── __init__.py
├── process.py
├── renderer
│   ├── __init__.py
│   └── rst
│   ├── doxygen
│   │   ├── base.py
│   │   ├── compound.py
│   │   ├── domain.py
│   │   ├── filter.py
│   │   ├── index.py
│   │   ├── __init__.py
│   │   └── target.py
│   ├── __init__.py
└── transforms.py
Check your breathe/renderer/rst/__init__.py file. I suspect that you have something like
from breathe.parser import doxygen
What happens is that when a module is imported, the module's __init__.py is executed. Then the next submodule is imported and it's __init__.py is run.
So, in the above situation, you'll get breathe.renderer.rst importing fine, but when running
breathe.renderer.rst.__init__, the breathe.parser.doxygen module is bound to the local name doxygen overriding the doxygen submodule. So you should see something like this:
>>> from breathe.renderer import rst
>>> print(rst.doxygen)
<module 'breathe.parser.doxygen' from 'breathe/parser/doxygen/__init__.pyc'>
Possible solutions:
Use absolute imports in __init__.py
Keep as much code as possible out of __init__.py
Use import inside the functions it's needed rather than globally. (This can also resolve circular import problems)
Note that there is nothing that prohibits code in __init__.py, and several modules in the stdlib do it too. However, because of exactly this sort of issue it is generally considered a good idea to avoid doing it too much.

Categories