pytest-django could not find a Django project - python

Trying to configure pytest with django, the project already has a lot of test not written with pytest (written with unittest) but I am trying to get them run with pytest so I can write pytest tests and get it work with old tests.
I know pytest-django checks for the manage.py file in the root dir of a django project but this project the manage.py file is not in the root dir so I guess that's why the error below is thrown when I run pytest however running pytest and supplying a particular file works. How do I specify where manage.py is? As I can't find this in the documentation
pytest-django could not find a Django project (no manage.py file could be found).
You must explicitly add your Django project to the Python path to have it picked up.

you can define a python path to python commands that you want to run:
PYTHONPATH=/your/path/to/your/django/project/ pytest
or export your pythonpath before you run the pytest command:
export PYTHONPATH=/your/path/to/your/django/project/
pytest

As a standard practice, you should add a setup.cfg file to your root, with the following block -
[tool:pytest]
DJANGO_SETTINGS_MODULE=<package_name>.settings.py
You can later use the same file for linters by adding specific blocks for them.

In my case, I created a configure file named pytest.ini in the tests folder with the following content:
[pytest]
pythonpath = ../bitpin
DJANGO_SETTINGS_MODULE = bitpin.settings
python_files = tests.py test_*.py *_tests.py
Repository tree:
bitpin-repo
├── bitpin
│   ├── bitpin
│   │   ├── asgi.py
│   │   ├── __init__.py
│   │   ├── settings.py
│   │   ├── urls.py
│   │   └── wsgi.py
│   ├── __init__.py
│   └── manage.py
├── tests
│ ├── test_models.py
│ ├── pytest.ini
│ └── conftest.py
└── setup.py
[NOTE]
If the tests/ is next to the project, replace bitpin with .:
[pytest]
pythonpath = .

Related

How to run coverage for a Python project with src-layout?

My python project is structured in the so called src-layout.
hyperorg
├── README.md
├── setup.cfg
├── setup.py
├── src
│   └── hyperorg
│   ├── content.py
│   ├── exporter.py
│   ├── __init__.py
│   ├── __main__.py
│   └── reader.py
└── tests
├── helper.py
├── __init__.py
├── test_content.py
├── test_exporter.py
├── test_hyperorg.py
└── test_reader.py
I am not able to get coverage running for it. How can I do this?
What I tried so far
Run coverage in the projects root folder just gives me Nothing to run.
Or coverage run ./src/hyperorg gives me
Traceback (most recent call last):
File "/home/user/tab-cloud/hyperorg/src/hyperorg/__main__.py", line 6, in <module>
from .content import Content
ImportError: attempted relative import with no known parent package
One of the ways of doing that is entering the src folder by cd src and then running coverage from there as following:
coverage run -m unittest discover -s ../tests
You can also leverage rcfile (default .coveragerc) to specify configurations and change HTML report path to be created outside the src folder as well.

Python how to import local module?

I have the following directory structure in Ubuntu. I'm trying to import the module config from my local package my_app into my script my_app_script.py
$ tree
.
├── my_app/
│   ├── config.py
│   ├── __init__.py
│   └── test/
├── my_app-info # created by pip install -e .
│   ├── dependency_links.txt
│   ├── PKG-INFO
│   ├── requires.txt
│   ├── SOURCES.txt
│   └── top_level.txt
├── bin/
│   └── my_app_script.py
├── LICENSE
├── README.md
└── setup.py
# setup.py
setup(
name='my_app',
version='0.1.2',
description='',
url='',
packages=['my_app'],
scripts=['bin/my_app_script.py'],
install_requires=[],
python_requires='>=3.6',
)
# my_app_script.py
from my_app import config
When I run my_app_script.py it results in "ImportError: cannot import name 'config'
What am I doing wrong?
Edit:
I am trying to follow this guide on packaging a program.
You need an __init__.py file in the parent directory as well as in bin directory.
You can use either of below approaches.
The first approach seems best to me as the script will always set the path relative to it, and will also work if you clone your repos.
Add an __init__.py in parent directory(Next to setup.py).
And add below line in my_app_script.py
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir, "my_app")))
What this will do is add .../my_app to PYTHONPATH at runtime, when my_app_script.py is executed.
Add an env.sh in parent directory. Below should be the contents of env.sh.
export PYTHONPATH=$(pwd):$PYTHONPATH
Now cd int the directory where env.sh is kept and then source it
source env.sh
Now run your my_app_script.py
python bin/my_app_script.py
Set PYTHONPATH from commandline.
PYTHONPATH=$(pwd) python bin/my_app_script.py

How to run my python program with -m (full path)?

I have a structure similar to this:
/home/user/nginx_http/
├── nginx_http
│   ├── common
│   │   ├── autodiscovery.py
│   │   ├── __init__.py
│   ├── __init__.py
│   ├── __main__.py
│   ├── nginx_http.py
├── README.rst
└── setup.py
When I'm in the /home/user/nginx_http folder and I run this:
python -m nginx_http
it works fine. But soon as I try to run it with full path it gives me an error;
python -m /home/user/nginx_http/nginx_http
/bin/python: Import by filename is not supported.; '/home/user/nginx_http/nginx_http' is a package and cannot be directly executed
I want to run my python program as a cronjob which would require the full path. The two options I wanted clarification on:
Should I consider moving my python program into python's module folder?
/usr/lib/python2.7/site-packages
Or should I set PYTHONPATH env to the location of /home/user/nginx_http. Will that break anything as far as other modules are concerned?
Thanks.

Django runs differently between python version?

Today I have come across wired error running the Django application with virtual environments.
The application runs without errors both locally and Heroku under python-3.5.1 with Procfile
web: gunicorn --pythonpath='src/' proj.wsgi:application --log-file -
And my project structure is:
```
.
├── LICENSE.txt
├── Procfile
├── README.md
├── db.sqlite3
├── docs
├── env3
├── env
├── logs
├── manifest.yml
├── requirements
├── requirements.txt
├── run.sh
├── runtime.txt
├── site
└── src/proj
├── logger.py
├── settings
│ ├── __init__.py
│ ├── base.py
│ ├── development.py
│ └── production.py
├── urls.py
├── views.py
├── wsgi.py
```
But when I run it with python 2.7.11 I get the following error
ImportError: No module named proj.settings.development
I could easily guess the error is related pythonpath config. However I am curious why in first place I am getting an error?
Fixed now! The reason is that as the default django structure is rewritten every nested folder contains module need an __init__.py.
src/proj missing the __init__.py. Adding it fixed the error for python2. From python3.3 this is not an requirement
Reference PEP420 https://www.python.org/dev/peps/pep-0420/

Why is alembic not autogenerating?

I am learning flask . Using sqlalchemy for orm and alembic for migrations
Going through and following:
http://alembic.readthedocs.org/en/latest/autogenerate.html
whenever i pass the command " alembic revision --autogenerate -m 'name' " , this error pops up . whatever i do , i configured the config.py file but i think maybe i am configuring the env.py file the wrong way . Or something is wrong because i followed every step of the tutorial.
File "alembic/env.py", line 20, in <module>
from myapp.mymodel import Base
ImportError: No module named app.models
folder directory:
project/
app/
models.py
views.py
__init__.py
alembic/
versions
env.py
config.py
When you run the alembic command, your app package is not in Python's module path. So it can't be imported. The easiest way to solve this is to use an extension such as Flask-Migrate or Flask-Alembic to handle setting up the migration environment for you. Both these extensions require you to use Flask-SQLAlchemy as well.
If you don't want to use an extension, the quick and dirty way is to just force the directory containing your app package to be on the path. In env.py, before importing Base, add
import os, sys
sys.path.insert(0, os.path.realpath(os.path.join(os.path.dirname(__file__), '..')))
A better solution would be to properly set up your project with a setup.py file and install your package in editable mode: pip install -e .. Then your package would be on the path the "right" way, as if it were actually installed.
You should use export PYTHONPATH='.'
you need to add the absolute path to the root directory where your alembic folder lives.
Eg:
If your current folder structure is:
.
├── app
│   ├── alembic
│   │   ├── env.py
│   │   ├── __pycache__
│   │   ├── README
│   │   ├── script.py.mako
│   │   └── versions
│   ├── alembic.ini
│   ├── constants
│   ├── core
│   ├── enums
│   ├── models
│   ├── repository
│   ├── routes
│   ├── __init__.py
│   ├── main.py
and your app has absolute path of:
/home/username/dev/app
then run the following line to add the path in your ~/.bashrc or ~/.zshrc for local development and update the env variables.
echo "export $PYTHONPATH=$PYTHONPATH:/home/username/dev/app" >> ~/.bashrc
source ~/.bashrc
or
echo "export $PYTHONPATH=$PYTHONPATH:/home/username/dev/app" >> ~/.zshrc
source ~/.zshrc

Categories

Resources