From 61b987def427d3a0b4a10810cb974f83b741e38c Mon Sep 17 00:00:00 2001 From: Simon Kohlmeyer Date: Sun, 11 Mar 2018 18:38:47 +0100 Subject: [PATCH 1/2] Remove py dependency py is in maintenance mode and there are modern alternatives --- pytest_django/plugin.py | 47 +++++++++++++++++++++-------------------- setup.py | 6 +++++- tests/conftest.py | 11 +++++----- 3 files changed, 35 insertions(+), 29 deletions(-) diff --git a/pytest_django/plugin.py b/pytest_django/plugin.py index 1585c6983..73935827c 100644 --- a/pytest_django/plugin.py +++ b/pytest_django/plugin.py @@ -11,7 +11,7 @@ import sys import types -import py +import pathlib import pytest from .django_compat import is_django_unittest # noqa @@ -88,13 +88,6 @@ def pytest_addoption(parser): type='bool', default=False) -def _exists(path, ignore=EnvironmentError): - try: - return path.check() - except ignore: - return False - - PROJECT_FOUND = ('pytest-django found a Django project in %s ' '(it contains manage.py) and added it to the Python path.\n' 'If this is wrong, add "django_find_project = false" to ' @@ -121,22 +114,30 @@ def _handle_import_error(extra_message): def _add_django_project_to_path(args): - args = [x for x in args if not str(x).startswith("-")] - - if not args: - args = [py.path.local()] - - for arg in args: - arg = py.path.local(arg) - - for base in arg.parts(reverse=True): - manage_py_try = base.join('manage.py') - - if _exists(manage_py_try): - sys.path.insert(0, str(base)) - return PROJECT_FOUND % base + def is_django_project(path): + return path.is_dir() and (path / 'manage.py').exists() + + def find_django_path(args): + args = [pathlib.Path(x) for x in args if not str(x).startswith("-")] + args = [p for p in args if p.is_dir()] + + if not args: + args = [pathlib.Path.cwd()] + + for arg in args: + if is_django_project(arg): + return arg + for parent in arg.parents: + if is_django_project(parent): + return parent + return None - return PROJECT_NOT_FOUND + project_dir = find_django_path(args) + if project_dir: + sys.path.insert(0, str(project_dir)) + return PROJECT_FOUND % project_dir + else: + return PROJECT_NOT_FOUND def _setup_django(): diff --git a/setup.py b/setup.py index e25d5e4ef..0d9884dc7 100755 --- a/setup.py +++ b/setup.py @@ -30,7 +30,11 @@ def read(fname): long_description=read('README.rst'), python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*', setup_requires=['setuptools_scm>=1.11.1'], - install_requires=['pytest>=2.9'], + install_requires=[ + 'pytest>=2.9', + 'pathlib;python_version<"3.4"', + 'six', + ], classifiers=['Development Status :: 5 - Production/Stable', 'Framework :: Django', 'Framework :: Django :: 1.8', diff --git a/tests/conftest.py b/tests/conftest.py index 5ad2ca6ea..40095f664 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -2,15 +2,16 @@ import shutil from textwrap import dedent -import py +import pathlib import pytest +import six from django.conf import settings from pytest_django_test.db_helpers import DB_NAME, TEST_DB_NAME pytest_plugins = 'pytester' -REPOSITORY_ROOT = py.path.local(__file__).join('..') +REPOSITORY_ROOT = pathlib.Path(__file__).parent def pytest_configure(config): @@ -99,12 +100,12 @@ def django_testdir(request, testdir, monkeypatch): tpkg_path.ensure('__init__.py') - app_source = REPOSITORY_ROOT.dirpath('pytest_django_test/app') + app_source = REPOSITORY_ROOT / '../pytest_django_test/app' test_app_path = tpkg_path.join('app') # Copy the test app to make it available in the new test run - shutil.copytree(py.builtin._totext(app_source), - py.builtin._totext(test_app_path)) + shutil.copytree(six.text_type(app_source), + six.text_type(test_app_path)) tpkg_path.join("the_settings.py").write(test_settings) monkeypatch.setenv('DJANGO_SETTINGS_MODULE', 'tpkg.the_settings') From 1cdb6224173d53c691badb0683e5e175790d8db3 Mon Sep 17 00:00:00 2001 From: Simon Kohlmeyer Date: Sun, 11 Mar 2018 18:39:20 +0100 Subject: [PATCH 2/2] Also look in child dirs when discovering django project path --- docs/changelog.rst | 5 +++++ docs/managing_python_path.rst | 8 ++++---- pytest_django/plugin.py | 3 +++ 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index b9dcf20de..1db4fed4d 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -1,6 +1,11 @@ Changelog ========= +Features +^^^^^^^^ +* pytest-django now searches the immediate subdirectories of the current + working directory when trying to find the Django project. + 3.1.2 ----- diff --git a/docs/managing_python_path.rst b/docs/managing_python_path.rst index 32faaa638..29138b671 100644 --- a/docs/managing_python_path.rst +++ b/docs/managing_python_path.rst @@ -18,10 +18,10 @@ By default, pytest-django tries to find Django projects by automatically looking for the project's ``manage.py`` file and adding its directory to the Python path. -Looking for the ``manage.py`` file uses the same algorithm as pytest uses to -find ``pytest.ini``, ``tox.ini`` and ``setup.cfg``: Each test root directories -parents will be searched for ``manage.py`` files, and it will stop when the -first file is found. +Looking for the ``manage.py`` file uses the following algorithm: +Beginning at each directory given on the command line (or the current working +directory if none is given), the directory itself, its immediate children and +its parents are searched, and it will stop when the first file is found. If you have a custom project setup, have none or multiple ``manage.py`` files in your project, the automatic detection may not be correct. See diff --git a/pytest_django/plugin.py b/pytest_django/plugin.py index 73935827c..b0d64b391 100644 --- a/pytest_django/plugin.py +++ b/pytest_django/plugin.py @@ -127,6 +127,9 @@ def find_django_path(args): for arg in args: if is_django_project(arg): return arg + for child in arg.iterdir(): + if is_django_project(child): + return child for parent in arg.parents: if is_django_project(parent): return parent