diff --git a/.travis.yml b/.travis.yml index 11c9233c4..660cb0f07 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,12 +1,14 @@ -sudo: required -dist: trusty +os: linux +dist: bionic language: python python: - - 2.7 - - 3.4 - 3.5 - 3.6 - - pypy + - 3.7 + - 3.8 + - pypy3 +services: + - docker cache: apt: true @@ -17,37 +19,26 @@ cache: addons: apt_packages: - binutils - - default-jdk + - openjdk-8-jdk - gdal-bin - - libgdal1h - - libgeos-c1 + - libgdal20 + - libgeos-c1v5 - libproj-dev - - libxapian22 - python-xapian - wajig before_install: - - sudo apt-get install -qy default-jre - mkdir -p $HOME/download-cache - # See https://www.elastic.co/guide/en/elasticsearch/reference/current/deb.html#deb-repo - - wget -qO - https://packages.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add - - > - if [[ $VERSION_ES == '>=2.0.0,<3.0.0' ]]; + if [[ $VERSION_ES == '>=2,<3' ]]; then - echo "deb http://packages.elastic.co/elasticsearch/2.x/debian stable main" | sudo tee -a /etc/apt/sources.list.d/elasticsearch-2.x.list - sudo apt-get update - sudo apt-get -qy --allow-downgrades install elasticsearch=2.4.6 - elif [[ $VERSION_ES == '>=5.0.0,<6.0.0' ]]; + docker run -d -p 9200:9200 elasticsearch:2.4.6-alpine + elif [[ $VERSION_ES == '>=5,<6' ]]; then - echo "deb https://artifacts.elastic.co/packages/5.x/apt stable main" | sudo tee -a /etc/apt/sources.list.d/elasticsearch-5.x.list - sudo apt-get update -qy - sudo apt-get -y --allow-downgrades install elasticsearch=5.6.10 + docker run -d -p 9200:9200 elasticsearch:5.6.10-alpine else - echo "deb http://packages.elastic.co/elasticsearch/1.7/debian stable main" | sudo tee -a /etc/apt/sources.list.d/elasticsearch-1.7.list - sudo apt-get update -qy - sudo apt-get -qy --allow-downgrades install elasticsearch=1.7.6 + docker run -d -p 9200:9200 elasticsearch:1.7.6-alpine fi - - sudo service elasticsearch restart install: - pip install --upgrade setuptools @@ -66,50 +57,37 @@ after_success: - codecov env: - matrix: - - DJANGO_VERSION=">=1.11,<2.0" VERSION_ES=">=1.0.0,<2.0.0" - - DJANGO_VERSION=">=2.0,<2.1" VERSION_ES=">=1.0.0,<2.0.0" - - DJANGO_VERSION=">=2.1,<2.2" VERSION_ES=">=1.0.0,<2.0.0" - - DJANGO_VERSION=">=1.11,<2.0" VERSION_ES=">=2.0.0,<3.0.0" - - DJANGO_VERSION=">=2.0,<2.1" VERSION_ES=">=2.0.0,<3.0.0" - - DJANGO_VERSION=">=2.1,<2.2" VERSION_ES=">=2.0.0,<3.0.0" - - DJANGO_VERSION=">=1.11,<2.0" VERSION_ES=">=5.0.0,<6.0.0" - - DJANGO_VERSION=">=2.0,<2.1" VERSION_ES=">=5.0.0,<6.0.0" - - DJANGO_VERSION=">=2.1,<2.2" VERSION_ES=">=5.0.0,<6.0.0" -matrix: + global: + - JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64 + jobs: + - DJANGO_VERSION=">=2.2,<3.0" VERSION_ES=">=1,<2" + - DJANGO_VERSION=">=3.0,<3.1" VERSION_ES=">=1,<2" + - DJANGO_VERSION=">=2.2,<3.0" VERSION_ES=">=2,<3" + - DJANGO_VERSION=">=3.0,<3.1" VERSION_ES=">=2,<3" + - DJANGO_VERSION=">=2.2,<3.0" VERSION_ES=">=5,<6" + - DJANGO_VERSION=">=3.0,<3.1" VERSION_ES=">=5,<6" +jobs: allow_failures: - - python: 'pypy' + - python: 'pypy3' exclude: - - python: 2.7 - env: DJANGO_VERSION=">=2.0,<2.1" VERSION_ES=">=5.0.0,<6.0.0" - - python: 2.7 - env: DJANGO_VERSION=">=2.0,<2.1" VERSION_ES=">=2.0.0,<3.0.0" - - python: 2.7 - env: DJANGO_VERSION=">=2.0,<2.1" VERSION_ES=">=1.0.0,<2.0.0" - - python: 2.7 - env: DJANGO_VERSION=">=2.1,<2.2" VERSION_ES=">=5.0.0,<6.0.0" - - python: 2.7 - env: DJANGO_VERSION=">=2.1,<2.2" VERSION_ES=">=2.0.0,<3.0.0" - - python: 2.7 - env: DJANGO_VERSION=">=2.1,<2.2" VERSION_ES=">=1.0.0,<2.0.0" - - python: 3.4 - env: DJANGO_VERSION=">=2.1,<2.2" VERSION_ES=">=5.0.0,<6.0.0" - - python: 3.4 - env: DJANGO_VERSION=">=2.1,<2.2" VERSION_ES=">=2.0.0,<3.0.0" - - python: 3.4 - env: DJANGO_VERSION=">=2.1,<2.2" VERSION_ES=">=1.0.0,<2.0.0" - - python: pypy - env: DJANGO_VERSION=">=2.0,<2.1" VERSION_ES=">=5.0.0,<6.0.0" - - python: pypy - env: DJANGO_VERSION=">=2.0,<2.1" VERSION_ES=">=2.0.0,<3.0.0" - - python: pypy - env: DJANGO_VERSION=">=2.0,<2.1" VERSION_ES=">=1.0.0,<2.0.0" - - python: pypy - env: DJANGO_VERSION=">=2.1,<2.2" VERSION_ES=">=5.0.0,<6.0.0" - - python: pypy - env: DJANGO_VERSION=">=2.1,<2.2" VERSION_ES=">=2.0.0,<3.0.0" - - python: pypy - env: DJANGO_VERSION=">=2.1,<2.2" VERSION_ES=">=1.0.0,<2.0.0" + - python: pypy3 + env: DJANGO_VERSION=">=2.2,<3.0" VERSION_ES=">=5,<6" + - python: pypy3 + env: DJANGO_VERSION=">=2.2,<3.0" VERSION_ES=">=2,<3" + - python: pypy3 + env: DJANGO_VERSION=">=2.2,<3.0" VERSION_ES=">=1,<2" + - python: pypy3 + env: DJANGO_VERSION=">=3.0,<3.1" VERSION_ES=">=5,<6" + - python: pypy3 + env: DJANGO_VERSION=">=3.0,<3.1" VERSION_ES=">=2,<3" + - python: pypy3 + env: DJANGO_VERSION=">=3.0,<3.1" VERSION_ES=">=1,<2" + - python: 3.5 + env: DJANGO_VERSION=">=3.0,<3.1" VERSION_ES=">=1,<2" + - python: 3.5 + env: DJANGO_VERSION=">=3.0,<3.1" VERSION_ES=">=2,<3" + - python: 3.5 + env: DJANGO_VERSION=">=3.0,<3.1" VERSION_ES=">=5,<6" notifications: irc: 'irc.freenode.org#haystack' diff --git a/README.rst b/README.rst index 4a1af4033..1eb90f0a4 100644 --- a/README.rst +++ b/README.rst @@ -50,7 +50,7 @@ Requirements Haystack has a relatively easily-met set of requirements. -* Python 2.7+ or Python 3.3+ +* Python 3.5+ * A supported version of Django: https://www.djangoproject.com/download/#supported-versions Additionally, each backend has its own requirements. You should refer to diff --git a/docs/conf.py b/docs/conf.py index 022e40b2a..2ff433372 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -11,8 +11,6 @@ # All configuration values have a default; values that are commented out # serve to show the default. -from __future__ import absolute_import, division, print_function, unicode_literals - import os import sys diff --git a/docs/multiple_index.rst b/docs/multiple_index.rst index 48b28a828..529bbf2b1 100644 --- a/docs/multiple_index.rst +++ b/docs/multiple_index.rst @@ -9,7 +9,7 @@ support. This allows you to talk to several different engines at the same time. It enables things like master-slave setups, multiple language indexing, separate indexes for general search & autocomplete as well as other options. -.. _`multiple database support`: http://docs.djangoproject.com/en/1.3/topics/db/multi-db/ +.. _`multiple database support`: http://docs.djangoproject.com/en/dev/topics/db/multi-db/ Specifying Available Connections diff --git a/docs/searchindex_api.rst b/docs/searchindex_api.rst index 4dd234832..c8da131ed 100644 --- a/docs/searchindex_api.rst +++ b/docs/searchindex_api.rst @@ -332,7 +332,6 @@ object and write its ``prepare`` method to populate/alter the data any way you choose. For instance, a (naive) user-created ``GeoPointField`` might look something like:: - from django.utils import six from haystack import indexes class GeoPointField(indexes.CharField): @@ -341,7 +340,7 @@ something like:: super(GeoPointField, self).__init__(**kwargs) def prepare(self, obj): - return six.text_type("%s-%s" % (obj.latitude, obj.longitude)) + return "%s-%s" % (obj.latitude, obj.longitude) The ``prepare`` method simply returns the value to be used for that field. It's entirely possible to include data that's not directly referenced to the object @@ -615,4 +614,3 @@ For the impatient:: def index_queryset(self, using=None): "Used when the entire index for model is updated." return Note.objects.filter(pub_date__lte=datetime.datetime.now()) - diff --git a/docs/spatial.rst b/docs/spatial.rst index 4e2906d58..34227fa85 100644 --- a/docs/spatial.rst +++ b/docs/spatial.rst @@ -33,7 +33,7 @@ Support ======= You need the latest & greatest of either Solr or Elasticsearch. None of the -other backends (specifially the engines) support this kind of search. +other backends (specifically the engines) support this kind of search. For Solr_, you'll need at least **v3.5+**. In addition, if you have an existing install of Haystack & Solr, you'll need to upgrade the schema & reindex your diff --git a/docs/tutorial.rst b/docs/tutorial.rst index a8133d7d7..578c3d923 100644 --- a/docs/tutorial.rst +++ b/docs/tutorial.rst @@ -157,7 +157,16 @@ Example (ElasticSearch 2.x):: 'INDEX_NAME': 'haystack', }, } + +Example (ElasticSearch 5.x):: + HAYSTACK_CONNECTIONS = { + 'default': { + 'ENGINE': 'haystack.backends.elasticsearch5_backend.Elasticsearch5SearchEngine', + 'URL': 'http://127.0.0.1:9200/', + 'INDEX_NAME': 'haystack', + }, + } Whoosh ~~~~~~ diff --git a/example_project/bare_bones_app/models.py b/example_project/bare_bones_app/models.py index 47739369e..aac17e9c9 100644 --- a/example_project/bare_bones_app/models.py +++ b/example_project/bare_bones_app/models.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - import datetime from django.db import models @@ -14,7 +11,7 @@ class Cat(models.Model): created = models.DateTimeField(default=datetime.datetime.now) updated = models.DateTimeField(default=datetime.datetime.now) - def __unicode__(self): + def __str__(self): return self.name @models.permalink diff --git a/example_project/bare_bones_app/search_indexes.py b/example_project/bare_bones_app/search_indexes.py index ab93b8e29..09d8bf789 100644 --- a/example_project/bare_bones_app/search_indexes.py +++ b/example_project/bare_bones_app/search_indexes.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - from bare_bones_app.models import Cat from haystack import indexes diff --git a/example_project/regular_app/models.py b/example_project/regular_app/models.py index 66025f31a..bbbb80d7a 100644 --- a/example_project/regular_app/models.py +++ b/example_project/regular_app/models.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - import datetime from django.db import models @@ -25,7 +22,7 @@ class Dog(models.Model): created = models.DateTimeField(default=datetime.datetime.now) updated = models.DateTimeField(default=datetime.datetime.now) - def __unicode__(self): + def __str__(self): return self.full_name() @models.permalink @@ -43,5 +40,5 @@ class Toy(models.Model): dog = models.ForeignKey(Dog, related_name="toys") name = models.CharField(max_length=60) - def __unicode__(self): + def __str__(self): return "%s's %s" % (self.dog.name, self.name) diff --git a/example_project/regular_app/search_indexes.py b/example_project/regular_app/search_indexes.py index 60dbb2136..60dcb95ba 100644 --- a/example_project/regular_app/search_indexes.py +++ b/example_project/regular_app/search_indexes.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - from regular_app.models import Dog from haystack import indexes diff --git a/example_project/settings.py b/example_project/settings.py index bd1341c2d..beb96c418 100644 --- a/example_project/settings.py +++ b/example_project/settings.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - import os from django.conf import settings diff --git a/haystack/__init__.py b/haystack/__init__.py index d9f5f8025..d25dcfec3 100644 --- a/haystack/__init__.py +++ b/haystack/__init__.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - from django.conf import settings from django.core.exceptions import ImproperlyConfigured from pkg_resources import DistributionNotFound, get_distribution, parse_version @@ -13,7 +10,7 @@ __author__ = "Daniel Lindsley" try: - pkg_distribution = get_distribution(__name__) + pkg_distribution = get_distribution("django-haystack") __version__ = pkg_distribution.version version_info = pkg_distribution.parsed_version except DistributionNotFound: diff --git a/haystack/admin.py b/haystack/admin.py index cfbe13092..7ccbdaa60 100644 --- a/haystack/admin.py +++ b/haystack/admin.py @@ -1,23 +1,21 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - from django.contrib.admin.options import ModelAdmin, csrf_protect_m from django.contrib.admin.views.main import SEARCH_VAR, ChangeList from django.core.exceptions import PermissionDenied from django.core.paginator import InvalidPage, Paginator from django.shortcuts import render -from django.utils.encoding import force_text +from django.utils.encoding import force_str from django.utils.translation import ungettext from haystack import connections +from haystack.constants import DEFAULT_ALIAS from haystack.query import SearchQuerySet from haystack.utils import get_model_ct_tuple class SearchChangeList(ChangeList): def __init__(self, **kwargs): - self.haystack_connection = kwargs.pop("haystack_connection", "default") + self.haystack_connection = kwargs.pop("haystack_connection", DEFAULT_ALIAS) super(SearchChangeList, self).__init__(**kwargs) def get_results(self, request): @@ -61,7 +59,7 @@ def get_results(self, request): class SearchModelAdminMixin(object): # haystack connection to use for searching - haystack_connection = "default" + haystack_connection = DEFAULT_ALIAS @csrf_protect_m def changelist_view(self, request, extra_context=None): @@ -135,7 +133,7 @@ def changelist_view(self, request, extra_context=None): ) context = { - "module_name": force_text(self.model._meta.verbose_name_plural), + "module_name": force_str(self.model._meta.verbose_name_plural), "selection_note": selection_note % {"count": len(changelist.result_list)}, "selection_note_all": selection_note_all % {"total_count": changelist.result_count}, diff --git a/haystack/apps.py b/haystack/apps.py index 239e83b60..579518637 100644 --- a/haystack/apps.py +++ b/haystack/apps.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - import logging from django.apps import AppConfig diff --git a/haystack/backends/__init__.py b/haystack/backends/__init__.py index 87355b531..9cc0f8385 100644 --- a/haystack/backends/__init__.py +++ b/haystack/backends/__init__.py @@ -1,14 +1,13 @@ # -*- coding: utf-8 -*- -from __future__ import unicode_literals import copy from copy import deepcopy from time import time + from django.conf import settings from django.db.models import Q from django.db.models.base import ModelBase -from django.utils import six from django.utils import tree -from django.utils.encoding import force_text +from django.utils.encoding import force_str from haystack.constants import VALID_FILTERS, FILTER_SEPARATOR, DEFAULT_ALIAS from haystack.exceptions import MoreLikeThisError, FacetingError @@ -160,7 +159,7 @@ def prep_value(self, value): Hook to give the backend a chance to prep an attribute value before sending it to the search engine. By default, just force it to unicode. """ - return force_text(value) + return force_str(value) def more_like_this( self, model_instance, additional_query_string=None, result_class=None @@ -312,9 +311,6 @@ def __bool__(self): """ return bool(self.children) - def __nonzero__(self): # Python 2 compatibility - return type(self).__bool__(self) - def __contains__(self, other): """ Returns True is 'other' is a direct child of this instance. @@ -404,12 +400,7 @@ def __repr__(self): ) def _repr_query_fragment_callback(self, field, filter_type, value): - if six.PY3: - value = force_text(value) - else: - value = force_text(value).encode("utf8") - - return "%s%s%s=%s" % (field, FILTER_SEPARATOR, filter_type, value) + return "%s%s%s=%s" % (field, FILTER_SEPARATOR, filter_type, force_str(value)) def as_query_string(self, query_fragment_callback): """ @@ -782,7 +773,7 @@ def clean(self, query_fragment): A basic (override-able) implementation is provided. """ - if not isinstance(query_fragment, six.string_types): + if not isinstance(query_fragment, str): return query_fragment words = query_fragment.split() diff --git a/haystack/backends/elasticsearch2_backend.py b/haystack/backends/elasticsearch2_backend.py index 5d149565d..ed28e52f4 100644 --- a/haystack/backends/elasticsearch2_backend.py +++ b/haystack/backends/elasticsearch2_backend.py @@ -1,6 +1,4 @@ # -*- coding: utf-8 -*- -from __future__ import absolute_import, division, print_function, unicode_literals - import datetime from django.conf import settings diff --git a/haystack/backends/elasticsearch5_backend.py b/haystack/backends/elasticsearch5_backend.py index 6574c37d1..1b1c20c7d 100644 --- a/haystack/backends/elasticsearch5_backend.py +++ b/haystack/backends/elasticsearch5_backend.py @@ -1,6 +1,4 @@ # -*- coding: utf-8 -*- -from __future__ import absolute_import, division, print_function, unicode_literals - import datetime import warnings diff --git a/haystack/backends/elasticsearch_backend.py b/haystack/backends/elasticsearch_backend.py index 3b023b9d1..582fec6ae 100644 --- a/haystack/backends/elasticsearch_backend.py +++ b/haystack/backends/elasticsearch_backend.py @@ -1,14 +1,10 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - import re import warnings from datetime import datetime, timedelta from django.conf import settings from django.core.exceptions import ImproperlyConfigured -from django.utils import six import haystack from haystack.backends import BaseEngine, BaseSearchBackend, BaseSearchQuery, log_query @@ -813,9 +809,9 @@ def _from_python(self, value): iso = self._iso_datetime(value) if iso: return iso - elif isinstance(value, six.binary_type): + elif isinstance(value, bytes): # TODO: Be stricter. - return six.text_type(value, errors="replace") + return str(value, errors="replace") elif isinstance(value, set): return list(value) return value @@ -825,7 +821,7 @@ def _to_python(self, value): if isinstance(value, (int, float, complex, list, tuple, bool)): return value - if isinstance(value, six.string_types): + if isinstance(value, str): possible_datetime = DATETIME_REGEX.search(value) if possible_datetime: @@ -894,7 +890,7 @@ def build_query_fragment(self, field, filter_type, value): if hasattr(value, "values_list"): value = list(value) - if isinstance(value, six.string_types): + if isinstance(value, str): # It's not an ``InputType``. Assume ``Clean``. value = Clean(value) else: @@ -945,7 +941,7 @@ def build_query_fragment(self, field, filter_type, value): # Iterate over terms & incorportate the converted form of each into the query. terms = [] - if isinstance(prepared_value, six.string_types): + if isinstance(prepared_value, str): for possible_value in prepared_value.split(" "): terms.append( filter_types[filter_type] @@ -1002,7 +998,7 @@ def build_alt_parser_query(self, parser_name, query_string="", **kwargs): kwarg_bits = [] for key in sorted(kwargs.keys()): - if isinstance(kwargs[key], six.string_types) and " " in kwargs[key]: + if isinstance(kwargs[key], str) and " " in kwargs[key]: kwarg_bits.append("%s='%s'" % (key, kwargs[key])) else: kwarg_bits.append("%s=%s" % (key, kwargs[key])) diff --git a/haystack/backends/simple_backend.py b/haystack/backends/simple_backend.py index abbd8fb1a..2cadd1951 100644 --- a/haystack/backends/simple_backend.py +++ b/haystack/backends/simple_backend.py @@ -2,13 +2,10 @@ """ A very basic, ORM-based backend for simple search during tests. """ - -from __future__ import absolute_import, division, print_function, unicode_literals - +from functools import reduce from warnings import warn from django.db.models import Q -from django.utils import six from haystack import connections from haystack.backends import ( @@ -71,7 +68,7 @@ def search(self, query_string, **kwargs): if queries: qs = model.objects.filter( - six.moves.reduce(lambda x, y: x | y, queries) + reduce(lambda x, y: x | y, queries) ) else: qs = [] @@ -128,7 +125,7 @@ def _build_sub_query(self, search_node): term_list.append(value.prepare(self)) - return (" ").join(map(six.text_type, term_list)) + return (" ").join(map(str, term_list)) class SimpleEngine(BaseEngine): diff --git a/haystack/backends/solr_backend.py b/haystack/backends/solr_backend.py index d1f4cc664..ca12df11c 100644 --- a/haystack/backends/solr_backend.py +++ b/haystack/backends/solr_backend.py @@ -1,12 +1,8 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - import warnings from django.conf import settings from django.core.exceptions import ImproperlyConfigured -from django.utils import six import haystack from haystack.backends import ( @@ -518,7 +514,7 @@ def _process_results( if spelling_suggestions: # Maintain compatibility with older versions of Haystack which returned a single suggestion: spelling_suggestion = spelling_suggestions[-1] - assert isinstance(spelling_suggestion, six.string_types) + assert isinstance(spelling_suggestion, str) else: spelling_suggestion = None @@ -609,7 +605,7 @@ def extract_spelling_suggestions(self, raw_results): if isinstance(collations, dict): # Solr 6.5 collation_values = collations["collation"] - if isinstance(collation_values, six.string_types): + if isinstance(collation_values, str): collation_values = [collation_values] elif isinstance(collation_values, dict): # spellcheck.collateExtendedResults changes the format to a dictionary: @@ -634,7 +630,7 @@ def extract_spelling_suggestions(self, raw_results): spelling_suggestions.append(j["word"]) else: spelling_suggestions.append(j) - elif isinstance(suggestions[0], six.string_types) and isinstance( + elif isinstance(suggestions[0], str) and isinstance( suggestions[1], dict ): # Solr 6.4 uses a list of paired (word, dictionary) pairs: @@ -761,7 +757,7 @@ def build_query_fragment(self, field, filter_type, value): if hasattr(value, "values_list"): value = list(value) - if isinstance(value, six.string_types): + if isinstance(value, str): # It's not an ``InputType``. Assume ``Clean``. value = Clean(value) else: @@ -863,7 +859,7 @@ def build_alt_parser_query(self, parser_name, query_string="", **kwargs): kwarg_bits = [] for key in sorted(kwargs.keys()): - if isinstance(kwargs[key], six.string_types) and " " in kwargs[key]: + if isinstance(kwargs[key], str) and " " in kwargs[key]: kwarg_bits.append("%s='%s'" % (key, kwargs[key])) else: kwarg_bits.append("%s=%s" % (key, kwargs[key])) diff --git a/haystack/backends/whoosh_backend.py b/haystack/backends/whoosh_backend.py index 702251c52..cc4d288cf 100644 --- a/haystack/backends/whoosh_backend.py +++ b/haystack/backends/whoosh_backend.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - import json import os import re @@ -11,9 +8,8 @@ from django.conf import settings from django.core.exceptions import ImproperlyConfigured -from django.utils import six from django.utils.datetime_safe import datetime -from django.utils.encoding import force_text +from django.utils.encoding import force_str from haystack.backends import ( BaseEngine, @@ -266,7 +262,9 @@ def update(self, index, iterable, commit=True): self.setup() self.index = self.index.refresh() - writer = AsyncWriter(self.index) + max_retries = getattr(settings, 'HAYSTACK_WHOOSH_WRITER_ACQUIRE_MAX_RETRIES', 0) + delay = getattr(settings, 'HAYSTACK_WHOOSH_WRITER_ACQUIRE_DELAY', 0.25) + writer = AsyncWriter(self.index, delay=delay, max_retries=max_retries) for obj in iterable: try: @@ -428,7 +426,7 @@ def search( if len(query_string) == 0: return {"results": [], "hits": 0} - query_string = force_text(query_string) + query_string = force_str(query_string) # A one-character query (non-wildcard) gets nabbed by a stopwords # filter and should yield zero results. @@ -514,7 +512,7 @@ def search( for nq in narrow_queries: recent_narrowed_results = narrow_searcher.search( - self.parser.parse(force_text(nq)), limit=None + self.parser.parse(force_str(nq)), limit=None ) if len(recent_narrowed_results) <= 0: @@ -642,7 +640,7 @@ def more_like_this( for nq in narrow_queries: recent_narrowed_results = narrow_searcher.search( - self.parser.parse(force_text(nq)), limit=None + self.parser.parse(force_str(nq)), limit=None ) if len(recent_narrowed_results) <= 0: @@ -793,7 +791,7 @@ def create_spelling_suggestion(self, query_string): spelling_suggestion = None reader = self.index.reader() corrector = reader.corrector(self.content_field_name) - cleaned_query = force_text(query_string) + cleaned_query = force_str(query_string) if not query_string: return spelling_suggestion @@ -833,12 +831,12 @@ def _from_python(self, value): else: value = "false" elif isinstance(value, (list, tuple)): - value = ",".join([force_text(v) for v in value]) - elif isinstance(value, (six.integer_types, float)): + value = ",".join([force_str(v) for v in value]) + elif isinstance(value, (int, float)): # Leave it alone. pass else: - value = force_text(value) + value = force_str(value) return value def _to_python(self, value): @@ -852,7 +850,7 @@ def _to_python(self, value): elif value == "false": return False - if value and isinstance(value, six.string_types): + if value and isinstance(value, str): possible_datetime = DATETIME_REGEX.search(value) if possible_datetime: @@ -877,7 +875,7 @@ def _to_python(self, value): # Try to handle most built-in types. if isinstance( converted_value, - (list, tuple, set, dict, six.integer_types, float, complex), + (list, tuple, set, dict, int, float, complex), ): return converted_value except: @@ -891,9 +889,9 @@ def _to_python(self, value): class WhooshSearchQuery(BaseSearchQuery): def _convert_datetime(self, date): if hasattr(date, "hour"): - return force_text(date.strftime("%Y%m%d%H%M%S")) + return force_str(date.strftime("%Y%m%d%H%M%S")) else: - return force_text(date.strftime("%Y%m%d000000")) + return force_str(date.strftime("%Y%m%d000000")) def clean(self, query_fragment): """ @@ -934,7 +932,7 @@ def build_query_fragment(self, field, filter_type, value): if hasattr(value, "strftime"): is_datetime = True - if isinstance(value, six.string_types) and value != " ": + if isinstance(value, str) and value != " ": # It's not an ``InputType``. Assume ``Clean``. value = Clean(value) else: @@ -985,7 +983,7 @@ def build_query_fragment(self, field, filter_type, value): # Iterate over terms & incorportate the converted form of each into the query. terms = [] - if isinstance(prepared_value, six.string_types): + if isinstance(prepared_value, str): possible_values = prepared_value.split(" ") else: if is_datetime is True: @@ -1030,7 +1028,7 @@ def build_query_fragment(self, field, filter_type, value): if is_datetime is True: pv = self._convert_datetime(pv) - if isinstance(pv, six.string_types) and not is_datetime: + if isinstance(pv, str) and not is_datetime: in_options.append('"%s"' % pv) else: in_options.append("%s" % pv) diff --git a/haystack/constants.py b/haystack/constants.py index 24ad98d64..63491c63c 100644 --- a/haystack/constants.py +++ b/haystack/constants.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - from django.conf import settings DEFAULT_ALIAS = "default" diff --git a/haystack/exceptions.py b/haystack/exceptions.py index 251559ee4..a1c038c34 100644 --- a/haystack/exceptions.py +++ b/haystack/exceptions.py @@ -1,8 +1,5 @@ # encoding: utf-8 -from __future__ import absolute_import, division, print_function, unicode_literals - - class HaystackError(Exception): """A generic exception for all others to extend.""" diff --git a/haystack/fields.py b/haystack/fields.py index 023df08e3..a12eab0dc 100644 --- a/haystack/fields.py +++ b/haystack/fields.py @@ -1,11 +1,9 @@ # encoding: utf-8 -from __future__ import absolute_import, division, print_function, unicode_literals - import re from inspect import ismethod from django.template import loader -from django.utils import datetime_safe, six +from django.utils import datetime_safe from haystack.exceptions import SearchFieldError from haystack.utils import get_model_ct_tuple @@ -240,7 +238,7 @@ def convert(self, value): if value is None: return None - return six.text_type(value) + return str(value) class LocationField(SearchField): @@ -269,7 +267,7 @@ def convert(self, value): value = ensure_point(value) return value - if isinstance(value, six.string_types): + if isinstance(value, str): lat, lng = value.split(",") elif isinstance(value, (list, tuple)): # GeoJSON-alike @@ -352,7 +350,7 @@ def convert(self, value): if value is None: return None - return six.text_type(value) + return str(value) class BooleanField(SearchField): @@ -390,7 +388,7 @@ def convert(self, value): if value is None: return None - if isinstance(value, six.string_types): + if isinstance(value, str): match = DATE_REGEX.search(value) if match: @@ -423,7 +421,7 @@ def convert(self, value): if value is None: return None - if isinstance(value, six.string_types): + if isinstance(value, str): match = DATETIME_REGEX.search(value) if match: @@ -468,7 +466,7 @@ def convert(self, value): if value is None: return None - if hasattr(value, "__iter__") and not isinstance(value, six.text_type): + if hasattr(value, "__iter__") and not isinstance(value, str): return value return [value] diff --git a/haystack/forms.py b/haystack/forms.py index 099f94817..27a784045 100644 --- a/haystack/forms.py +++ b/haystack/forms.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - from django import forms from django.utils.encoding import smart_text from django.utils.text import capfirst diff --git a/haystack/generic_views.py b/haystack/generic_views.py index 74cdfc9c9..5319ccb9e 100644 --- a/haystack/generic_views.py +++ b/haystack/generic_views.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - from django.conf import settings from django.core.paginator import Paginator from django.views.generic import FormView diff --git a/haystack/indexes.py b/haystack/indexes.py index f77cbf183..1e3bdbd08 100644 --- a/haystack/indexes.py +++ b/haystack/indexes.py @@ -1,14 +1,10 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - import copy import threading import warnings from django.core.exceptions import ImproperlyConfigured -from django.utils.encoding import force_text -from django.utils.six import with_metaclass +from django.utils.encoding import force_str from haystack import connection_router, connections from haystack.constants import Indexable # NOQA — exposed as a public export @@ -95,7 +91,7 @@ def __new__(cls, name, bases, attrs): return super(DeclarativeMetaclass, cls).__new__(cls, name, bases, attrs) -class SearchIndex(with_metaclass(DeclarativeMetaclass, threading.local)): +class SearchIndex(threading.local, metaclass=DeclarativeMetaclass): """ Base class for building indexes. @@ -221,7 +217,7 @@ def prepare(self, obj): self.prepared_data = { ID: get_identifier(obj), DJANGO_CT: get_model_ct(self.get_model()), - DJANGO_ID: force_text(obj.pk), + DJANGO_ID: force_str(obj.pk), } for field_name, field in self.fields.items(): diff --git a/haystack/inputs.py b/haystack/inputs.py index e2d79a337..712bb8c60 100644 --- a/haystack/inputs.py +++ b/haystack/inputs.py @@ -1,14 +1,10 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - import re import warnings -from django.utils.encoding import force_text, python_2_unicode_compatible +from django.utils.encoding import force_str -@python_2_unicode_compatible class BaseInput(object): """ The base input type. Doesn't do much. You want ``Raw`` instead. @@ -25,7 +21,7 @@ def __repr__(self): return "<%s '%s'>" % (self.__class__.__name__, self) def __str__(self): - return force_text(self.query_string) + return force_str(self.query_string) def prepare(self, query_obj): return self.query_string diff --git a/haystack/management/commands/build_solr_schema.py b/haystack/management/commands/build_solr_schema.py index dc6e48a8a..ab92166b8 100644 --- a/haystack/management/commands/build_solr_schema.py +++ b/haystack/management/commands/build_solr_schema.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - import os import requests diff --git a/haystack/management/commands/clear_index.py b/haystack/management/commands/clear_index.py index f2639f330..cb8a18ff5 100644 --- a/haystack/management/commands/clear_index.py +++ b/haystack/management/commands/clear_index.py @@ -1,9 +1,5 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - from django.core.management.base import BaseCommand -from django.utils import six from haystack import connections @@ -53,7 +49,7 @@ def handle(self, **options): "Your choices after this are to restore from backups or rebuild via the `rebuild_index` command." ) - yes_or_no = six.moves.input("Are you sure you wish to continue? [y/N] ") + yes_or_no = input("Are you sure you wish to continue? [y/N] ") if not yes_or_no.lower().startswith("y"): self.stdout.write("No action taken.") diff --git a/haystack/management/commands/haystack_info.py b/haystack/management/commands/haystack_info.py index 7d827e48b..6b321d9f9 100644 --- a/haystack/management/commands/haystack_info.py +++ b/haystack/management/commands/haystack_info.py @@ -1,10 +1,8 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - from django.core.management.base import BaseCommand from haystack import connections +from haystack.constants import DEFAULT_ALIAS class Command(BaseCommand): @@ -13,7 +11,7 @@ class Command(BaseCommand): def handle(self, **options): """Provides feedback about the current Haystack setup.""" - unified_index = connections["default"].get_unified_index() + unified_index = connections[DEFAULT_ALIAS].get_unified_index() indexed = unified_index.get_indexed_models() index_count = len(indexed) self.stdout.write("Number of handled %s index(es)." % index_count) diff --git a/haystack/management/commands/rebuild_index.py b/haystack/management/commands/rebuild_index.py index aa8af8a7d..5d18f6afd 100644 --- a/haystack/management/commands/rebuild_index.py +++ b/haystack/management/commands/rebuild_index.py @@ -1,6 +1,4 @@ # encoding: utf-8 -from __future__ import absolute_import, division, print_function, unicode_literals - from django.core.management import call_command from django.core.management.base import BaseCommand diff --git a/haystack/management/commands/update_index.py b/haystack/management/commands/update_index.py index 3cb2f6d73..fdfbfc0c7 100755 --- a/haystack/management/commands/update_index.py +++ b/haystack/management/commands/update_index.py @@ -1,6 +1,4 @@ # encoding: utf-8 -from __future__ import absolute_import, division, print_function, unicode_literals - import logging import multiprocessing import os @@ -9,7 +7,7 @@ from django.core.management.base import BaseCommand from django.db import close_old_connections, reset_queries -from django.utils.encoding import force_text, smart_bytes +from django.utils.encoding import force_str, smart_bytes from django.utils.timezone import now from haystack import connections as haystack_connections @@ -305,7 +303,7 @@ def update_backend(self, label, using): if self.verbosity >= 1: self.stdout.write( "Indexing %d %s" - % (total, force_text(model._meta.verbose_name_plural)) + % (total, force_str(model._meta.verbose_name_plural)) ) batch_size = self.batchsize or backend.batch_size diff --git a/haystack/manager.py b/haystack/manager.py index fb262a464..711a2996c 100644 --- a/haystack/manager.py +++ b/haystack/manager.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - from haystack.query import EmptySearchQuerySet, SearchQuerySet diff --git a/haystack/models.py b/haystack/models.py index aa4f65895..c774e81c8 100644 --- a/haystack/models.py +++ b/haystack/models.py @@ -1,14 +1,11 @@ # encoding: utf-8 # "Hey, Django! Look at me, I'm an app! For Serious!" - -from __future__ import absolute_import, division, print_function, unicode_literals - from django.core.exceptions import ObjectDoesNotExist -from django.utils import six -from django.utils.encoding import force_text +from django.utils.encoding import force_str from django.utils.text import capfirst +from haystack.constants import DEFAULT_ALIAS from haystack.exceptions import NotHandled, SpatialError from haystack.utils import log as logging from haystack.utils.app_loading import haystack_get_model @@ -59,8 +56,8 @@ def __repr__(self): self.pk, ) - def __unicode__(self): - return force_text(self.__repr__()) + def __str__(self): + return force_str(self.__repr__()) def __getattr__(self, attr): if attr == "__getnewargs__": @@ -71,7 +68,7 @@ def __getattr__(self, attr): def _get_searchindex(self): from haystack import connections - return connections["default"].get_unified_index().get_index(self.model) + return connections[DEFAULT_ALIAS].get_unified_index().get_index(self.model) searchindex = property(_get_searchindex) @@ -169,7 +166,7 @@ def _get_verbose_name(self): self.log.error("Model could not be found for SearchResult '%s'.", self) return "" - return force_text(capfirst(self.model._meta.verbose_name)) + return force_str(capfirst(self.model._meta.verbose_name)) verbose_name = property(_get_verbose_name) @@ -178,7 +175,7 @@ def _get_verbose_name_plural(self): self.log.error("Model could not be found for SearchResult '%s'.", self) return "" - return force_text(capfirst(self.model._meta.verbose_name_plural)) + return force_str(capfirst(self.model._meta.verbose_name_plural)) verbose_name_plural = property(_get_verbose_name_plural) @@ -188,7 +185,7 @@ def content_type(self): self.log.error("Model could not be found for SearchResult '%s'.", self) return "" - return six.text_type(self.model._meta) + return str(self.model._meta) def get_additional_fields(self): """ @@ -216,7 +213,7 @@ def get_stored_fields(self): from haystack import connections try: - index = connections["default"].get_unified_index().get_index(self.model) + index = connections[DEFAULT_ALIAS].get_unified_index().get_index(self.model) except NotHandled: # Not found? Return nothing. return {} diff --git a/haystack/panels.py b/haystack/panels.py index 08fff1a33..b1d3a48f5 100644 --- a/haystack/panels.py +++ b/haystack/panels.py @@ -1,12 +1,8 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - import datetime from debug_toolbar.panels import DebugPanel from django.template.loader import render_to_string -from django.utils import six from django.utils.translation import ugettext_lazy as _ from haystack import connections @@ -70,7 +66,7 @@ def content(self): if query.get("additional_kwargs"): if query["additional_kwargs"].get("result_class"): - query["additional_kwargs"]["result_class"] = six.text_type( + query["additional_kwargs"]["result_class"] = str( query["additional_kwargs"]["result_class"] ) diff --git a/haystack/query.py b/haystack/query.py index 390b099d6..606691bb2 100644 --- a/haystack/query.py +++ b/haystack/query.py @@ -1,12 +1,8 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - +from functools import reduce import operator import warnings -from django.utils import six - from haystack import connection_router, connections from haystack.backends import SQ from haystack.constants import DEFAULT_OPERATOR, ITERATOR_LOAD_PER_QUERY @@ -283,7 +279,7 @@ def __getitem__(self, k): """ Retrieves an item or slice from the set of results. """ - if not isinstance(k, (slice, six.integer_types)): + if not isinstance(k, (slice, int)): raise TypeError assert (not isinstance(k, slice) and (k >= 0)) or ( isinstance(k, slice) @@ -513,7 +509,7 @@ def autocomplete(self, **kwargs): kwargs = {field_name: bit} query_bits.append(SQ(**kwargs)) - return clone.filter(six.moves.reduce(operator.__and__, query_bits)) + return clone.filter(reduce(operator.__and__, query_bits)) def using(self, connection_name): """ diff --git a/haystack/routers.py b/haystack/routers.py index 0a77e17f2..cdc180878 100644 --- a/haystack/routers.py +++ b/haystack/routers.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - from haystack.constants import DEFAULT_ALIAS diff --git a/haystack/signals.py b/haystack/signals.py index 97d383056..a0f6a61c4 100644 --- a/haystack/signals.py +++ b/haystack/signals.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - from django.db import models from haystack.exceptions import NotHandled diff --git a/haystack/templatetags/highlight.py b/haystack/templatetags/highlight.py index 2853b83ae..ae901a9d6 100644 --- a/haystack/templatetags/highlight.py +++ b/haystack/templatetags/highlight.py @@ -1,11 +1,7 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - from django import template from django.conf import settings from django.core.exceptions import ImproperlyConfigured -from django.utils import six from haystack.utils import importlib @@ -125,12 +121,12 @@ def highlight(parser, token): for bit in arg_bits: if bit == "css_class": - kwargs["css_class"] = six.next(arg_bits) + kwargs["css_class"] = next(arg_bits) if bit == "html_tag": - kwargs["html_tag"] = six.next(arg_bits) + kwargs["html_tag"] = next(arg_bits) if bit == "max_length": - kwargs["max_length"] = six.next(arg_bits) + kwargs["max_length"] = next(arg_bits) return HighlightNode(text_block, query, **kwargs) diff --git a/haystack/templatetags/more_like_this.py b/haystack/templatetags/more_like_this.py index 8f69cd3cb..2c4f37b77 100644 --- a/haystack/templatetags/more_like_this.py +++ b/haystack/templatetags/more_like_this.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - import logging from django import template diff --git a/haystack/urls.py b/haystack/urls.py index f982545f1..5841f186e 100644 --- a/haystack/urls.py +++ b/haystack/urls.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - from django.conf.urls import url from haystack.views import SearchView diff --git a/haystack/utils/__init__.py b/haystack/utils/__init__.py index 17b10123c..db47b7f0a 100644 --- a/haystack/utils/__init__.py +++ b/haystack/utils/__init__.py @@ -1,12 +1,8 @@ # encoding: utf-8 - -from __future__ import unicode_literals - import importlib import re from django.conf import settings -from django.utils import six from haystack.constants import ID, DJANGO_CT, DJANGO_ID from haystack.utils.highlighting import Highlighter @@ -22,7 +18,7 @@ def default_get_identifier(obj_or_string): If not overridden, uses ... """ - if isinstance(obj_or_string, six.string_types): + if isinstance(obj_or_string, str): if not IDENTIFIER_REGEX.match(obj_or_string): raise AttributeError( "Provided string '%s' is not a valid identifier." % obj_or_string diff --git a/haystack/utils/app_loading.py b/haystack/utils/app_loading.py index b553fd581..8e485cbbd 100755 --- a/haystack/utils/app_loading.py +++ b/haystack/utils/app_loading.py @@ -1,6 +1,4 @@ # encoding: utf-8 -from __future__ import absolute_import, division, print_function, unicode_literals - from django.apps import apps from django.core.exceptions import ImproperlyConfigured diff --git a/haystack/utils/geo.py b/haystack/utils/geo.py index a25c9dad9..6dcb22c06 100644 --- a/haystack/utils/geo.py +++ b/haystack/utils/geo.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - from haystack.constants import WGS_84_SRID from haystack.exceptions import SpatialError diff --git a/haystack/utils/highlighting.py b/haystack/utils/highlighting.py index d57658267..a159233f0 100644 --- a/haystack/utils/highlighting.py +++ b/haystack/utils/highlighting.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - from django.utils.html import strip_tags diff --git a/haystack/utils/loading.py b/haystack/utils/loading.py index 985dfecc6..bd05e4503 100644 --- a/haystack/utils/loading.py +++ b/haystack/utils/loading.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - import copy import inspect import threading @@ -10,7 +7,6 @@ from django.conf import settings from django.core.exceptions import ImproperlyConfigured -from django.utils import six from django.utils.module_loading import module_has_submodule from haystack import constants @@ -163,7 +159,7 @@ def _for_action(self, action, many, **hints): connection_to_use = action_callable(**hints) if connection_to_use is not None: - if isinstance(connection_to_use, six.string_types): + if isinstance(connection_to_use, str): conns.append(connection_to_use) else: conns.extend(connection_to_use) diff --git a/haystack/utils/log.py b/haystack/utils/log.py index ef9bec8f6..97c0ab49b 100644 --- a/haystack/utils/log.py +++ b/haystack/utils/log.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - import logging from django.conf import settings diff --git a/haystack/views.py b/haystack/views.py index cdde85746..9083fde4d 100644 --- a/haystack/views.py +++ b/haystack/views.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - from django.conf import settings from django.core.paginator import InvalidPage, Paginator from django.http import Http404 diff --git a/setup.cfg b/setup.cfg index 8cfac863d..5e3dd1772 100644 --- a/setup.cfg +++ b/setup.cfg @@ -11,3 +11,7 @@ ignore = E203, E501, W503 line_length=88 default_section=THIRDPARTY known_first_party=haystack + +[options] +setup_requires = + setuptools_scm diff --git a/setup.py b/setup.py index 887956047..c53884676 100755 --- a/setup.py +++ b/setup.py @@ -1,8 +1,7 @@ #!/usr/bin/env python # encoding: utf-8 -# n.b. we can't have unicode_literals here due to http://bugs.python.org/setuptools/issue152 -from __future__ import absolute_import, division, print_function +from setuptools import setup try: from setuptools import setup @@ -12,7 +11,7 @@ use_setuptools() from setuptools import setup -install_requires = ["Django>=1.11"] +install_requires = ["Django>=2.2"] tests_require = [ "pysolr>=3.7.0", @@ -20,14 +19,14 @@ "python-dateutil", "geopy==0.95.1", "nose", - "mock", "coverage", "requests", ] setup( name="django-haystack", - use_scm_version=True, + #use_scm_version=True, + version="3.0.dev1", description="Pluggable search for Django.", author="Daniel Lindsley", author_email="daniel@toastdriven.com", @@ -48,20 +47,21 @@ "Development Status :: 5 - Production/Stable", "Environment :: Web Environment", "Framework :: Django", - "Framework :: Django :: 1.11", - "Framework :: Django :: 2.0", - "Framework :: Django :: 2.1", + "Framework :: Django :: 2.2", + "Framework :: Django :: 3.0", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", "Programming Language :: Python", - "Programming Language :: Python :: 2", "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.5", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", "Topic :: Utilities", ], zip_safe=False, install_requires=install_requires, tests_require=tests_require, test_suite="test_haystack.run_tests.run_all", - setup_requires=["setuptools_scm"], ) diff --git a/test_haystack/__init__.py b/test_haystack/__init__.py index 79256373d..9cd46a2ba 100644 --- a/test_haystack/__init__.py +++ b/test_haystack/__init__.py @@ -1,6 +1,4 @@ # encoding: utf-8 -from __future__ import absolute_import - import os test_runner = None diff --git a/test_haystack/core/admin.py b/test_haystack/core/admin.py index eaaacceea..681c246f1 100644 --- a/test_haystack/core/admin.py +++ b/test_haystack/core/admin.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - from django.contrib import admin from haystack.admin import SearchModelAdmin diff --git a/test_haystack/core/custom_identifier.py b/test_haystack/core/custom_identifier.py index 8239d74d7..57e6a215b 100644 --- a/test_haystack/core/custom_identifier.py +++ b/test_haystack/core/custom_identifier.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - import hashlib diff --git a/test_haystack/core/models.py b/test_haystack/core/models.py index 8334a357e..9ef9c2cb0 100644 --- a/test_haystack/core/models.py +++ b/test_haystack/core/models.py @@ -1,8 +1,6 @@ # encoding: utf-8 # A couple models for Haystack to test with. -from __future__ import absolute_import, division, print_function, unicode_literals - import datetime import uuid @@ -12,7 +10,7 @@ class MockTag(models.Model): name = models.CharField(max_length=32) - def __unicode__(self): + def __str__(self): return self.name @@ -22,7 +20,7 @@ class MockModel(models.Model): pub_date = models.DateTimeField(default=datetime.datetime.now) tag = models.ForeignKey(MockTag, models.CASCADE) - def __unicode__(self): + def __str__(self): return self.author def hello(self): @@ -33,7 +31,7 @@ class UUIDMockModel(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) characteristics = models.TextField() - def __unicode__(self): + def __str__(self): return str(self.id) @@ -41,7 +39,7 @@ class AnotherMockModel(models.Model): author = models.CharField(max_length=255) pub_date = models.DateTimeField(default=datetime.datetime.now) - def __unicode__(self): + def __str__(self): return self.author @@ -59,7 +57,7 @@ class AFourthMockModel(models.Model): editor = models.CharField(max_length=255) pub_date = models.DateTimeField(default=datetime.datetime.now) - def __unicode__(self): + def __str__(self): return self.author @@ -77,7 +75,7 @@ class AFifthMockModel(models.Model): objects = SoftDeleteManager() - def __unicode__(self): + def __str__(self): return self.author @@ -86,14 +84,14 @@ class ASixthMockModel(models.Model): lat = models.FloatField() lon = models.FloatField() - def __unicode__(self): + def __str__(self): return self.name class ScoreMockModel(models.Model): score = models.CharField(max_length=10) - def __unicode__(self): + def __str__(self): return self.score @@ -104,7 +102,7 @@ class ManyToManyLeftSideModel(models.Model): class ManyToManyRightSideModel(models.Model): name = models.CharField(max_length=32, default="Default name") - def __unicode__(self): + def __str__(self): return self.name diff --git a/test_haystack/core/urls.py b/test_haystack/core/urls.py index d9e36c78e..aab24c4db 100644 --- a/test_haystack/core/urls.py +++ b/test_haystack/core/urls.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - from django.conf.urls import include, url from django.contrib import admin diff --git a/test_haystack/discovery/models.py b/test_haystack/discovery/models.py index ea7e2eef7..72220ae21 100644 --- a/test_haystack/discovery/models.py +++ b/test_haystack/discovery/models.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - from django.db import models @@ -9,7 +6,7 @@ class Foo(models.Model): title = models.CharField(max_length=255) body = models.TextField() - def __unicode__(self): + def __str__(self): return self.title @@ -17,5 +14,5 @@ class Bar(models.Model): author = models.CharField(max_length=255) content = models.TextField() - def __unicode__(self): + def __str__(self): return self.author diff --git a/test_haystack/discovery/search_indexes.py b/test_haystack/discovery/search_indexes.py index 7b9793c5d..f40bc73ea 100644 --- a/test_haystack/discovery/search_indexes.py +++ b/test_haystack/discovery/search_indexes.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - from test_haystack.discovery.models import Bar, Foo from haystack import indexes diff --git a/test_haystack/elasticsearch2_tests/test_backend.py b/test_haystack/elasticsearch2_tests/test_backend.py index 6c644fa79..ae421e657 100644 --- a/test_haystack/elasticsearch2_tests/test_backend.py +++ b/test_haystack/elasticsearch2_tests/test_backend.py @@ -1,6 +1,4 @@ # -*- coding: utf-8 -*- -from __future__ import absolute_import, division, print_function, unicode_literals - import datetime import logging as std_logging import operator diff --git a/test_haystack/elasticsearch2_tests/test_inputs.py b/test_haystack/elasticsearch2_tests/test_inputs.py index 09593e251..cd693f158 100644 --- a/test_haystack/elasticsearch2_tests/test_inputs.py +++ b/test_haystack/elasticsearch2_tests/test_inputs.py @@ -1,7 +1,4 @@ # -*- coding: utf-8 -*- - -from __future__ import absolute_import, division, print_function, unicode_literals - from django.test import TestCase from haystack import connections, inputs diff --git a/test_haystack/elasticsearch2_tests/test_query.py b/test_haystack/elasticsearch2_tests/test_query.py index d10b7917e..e02a772a9 100644 --- a/test_haystack/elasticsearch2_tests/test_query.py +++ b/test_haystack/elasticsearch2_tests/test_query.py @@ -1,6 +1,4 @@ # -*- coding: utf-8 -*- -from __future__ import absolute_import, division, print_function, unicode_literals - import datetime import elasticsearch diff --git a/test_haystack/elasticsearch5_tests/test_backend.py b/test_haystack/elasticsearch5_tests/test_backend.py index cc94c0b03..f4dfb33db 100644 --- a/test_haystack/elasticsearch5_tests/test_backend.py +++ b/test_haystack/elasticsearch5_tests/test_backend.py @@ -1,6 +1,4 @@ # -*- coding: utf-8 -*- -from __future__ import absolute_import, division, print_function, unicode_literals - import datetime import logging as std_logging import operator diff --git a/test_haystack/elasticsearch5_tests/test_inputs.py b/test_haystack/elasticsearch5_tests/test_inputs.py index 423694972..b25ff09e2 100644 --- a/test_haystack/elasticsearch5_tests/test_inputs.py +++ b/test_haystack/elasticsearch5_tests/test_inputs.py @@ -1,7 +1,4 @@ # -*- coding: utf-8 -*- - -from __future__ import absolute_import, division, print_function, unicode_literals - from django.test import TestCase from haystack import connections, inputs diff --git a/test_haystack/elasticsearch5_tests/test_query.py b/test_haystack/elasticsearch5_tests/test_query.py index 564a2fd15..c2038a472 100644 --- a/test_haystack/elasticsearch5_tests/test_query.py +++ b/test_haystack/elasticsearch5_tests/test_query.py @@ -1,6 +1,4 @@ # -*- coding: utf-8 -*- -from __future__ import absolute_import, division, print_function, unicode_literals - import datetime from django.contrib.gis.measure import D diff --git a/test_haystack/elasticsearch_tests/test_elasticsearch_backend.py b/test_haystack/elasticsearch_tests/test_elasticsearch_backend.py index 2f72d081e..a6664e059 100644 --- a/test_haystack/elasticsearch_tests/test_elasticsearch_backend.py +++ b/test_haystack/elasticsearch_tests/test_elasticsearch_backend.py @@ -1,6 +1,4 @@ # -*- coding: utf-8 -*- -from __future__ import absolute_import, division, print_function, unicode_literals - import datetime import logging as std_logging import operator diff --git a/test_haystack/elasticsearch_tests/test_elasticsearch_query.py b/test_haystack/elasticsearch_tests/test_elasticsearch_query.py index 56f32346d..cd994c310 100644 --- a/test_haystack/elasticsearch_tests/test_elasticsearch_query.py +++ b/test_haystack/elasticsearch_tests/test_elasticsearch_query.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - import datetime import elasticsearch diff --git a/test_haystack/elasticsearch_tests/test_inputs.py b/test_haystack/elasticsearch_tests/test_inputs.py index 0b3c4a373..da904d799 100644 --- a/test_haystack/elasticsearch_tests/test_inputs.py +++ b/test_haystack/elasticsearch_tests/test_inputs.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - from django.test import TestCase from haystack import connections, inputs diff --git a/test_haystack/mocks.py b/test_haystack/mocks.py index 70ebacc63..6e6b9c4e6 100644 --- a/test_haystack/mocks.py +++ b/test_haystack/mocks.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - from django.apps import apps from haystack.backends import BaseEngine, BaseSearchBackend, BaseSearchQuery, log_query diff --git a/test_haystack/multipleindex/__init__.py b/test_haystack/multipleindex/__init__.py index 7b73b57e4..eddcb428a 100644 --- a/test_haystack/multipleindex/__init__.py +++ b/test_haystack/multipleindex/__init__.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - import haystack from haystack.signals import RealtimeSignalProcessor diff --git a/test_haystack/multipleindex/models.py b/test_haystack/multipleindex/models.py index ea7e2eef7..72220ae21 100644 --- a/test_haystack/multipleindex/models.py +++ b/test_haystack/multipleindex/models.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - from django.db import models @@ -9,7 +6,7 @@ class Foo(models.Model): title = models.CharField(max_length=255) body = models.TextField() - def __unicode__(self): + def __str__(self): return self.title @@ -17,5 +14,5 @@ class Bar(models.Model): author = models.CharField(max_length=255) content = models.TextField() - def __unicode__(self): + def __str__(self): return self.author diff --git a/test_haystack/multipleindex/routers.py b/test_haystack/multipleindex/routers.py index 32730f688..8f5a555da 100644 --- a/test_haystack/multipleindex/routers.py +++ b/test_haystack/multipleindex/routers.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - from haystack.routers import BaseRouter diff --git a/test_haystack/multipleindex/search_indexes.py b/test_haystack/multipleindex/search_indexes.py index 4e68ba5ee..c20011585 100644 --- a/test_haystack/multipleindex/search_indexes.py +++ b/test_haystack/multipleindex/search_indexes.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - from haystack import indexes from haystack.indexes import Indexable, SearchIndex diff --git a/test_haystack/multipleindex/tests.py b/test_haystack/multipleindex/tests.py index 9f5b3527d..c63c19e02 100644 --- a/test_haystack/multipleindex/tests.py +++ b/test_haystack/multipleindex/tests.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - from django.db import models from haystack import connections diff --git a/test_haystack/results_per_page_urls.py b/test_haystack/results_per_page_urls.py index 60ec9f772..d44a84895 100644 --- a/test_haystack/results_per_page_urls.py +++ b/test_haystack/results_per_page_urls.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - from django.conf.urls import url from haystack.views import SearchView diff --git a/test_haystack/run_tests.py b/test_haystack/run_tests.py index 0b76a71aa..136b0dc77 100755 --- a/test_haystack/run_tests.py +++ b/test_haystack/run_tests.py @@ -1,8 +1,5 @@ #!/usr/bin/env python # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - import sys from os.path import abspath, dirname diff --git a/test_haystack/settings.py b/test_haystack/settings.py index dd426f1f2..095d948a8 100644 --- a/test_haystack/settings.py +++ b/test_haystack/settings.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - import os from tempfile import mkdtemp @@ -17,6 +14,7 @@ "django.contrib.auth", "django.contrib.contenttypes", "django.contrib.sessions", + "django.contrib.messages", "haystack", "test_haystack.discovery", "test_haystack.core", @@ -36,7 +34,10 @@ "BACKEND": "django.template.backends.django.DjangoTemplates", "APP_DIRS": True, "OPTIONS": { - "context_processors": ["django.contrib.auth.context_processors.auth"] + "context_processors": [ + "django.contrib.auth.context_processors.auth", + "django.contrib.messages.context_processors.messages", + ] }, } ] diff --git a/test_haystack/simple_tests/search_indexes.py b/test_haystack/simple_tests/search_indexes.py index 1113e9b0b..9732d5067 100644 --- a/test_haystack/simple_tests/search_indexes.py +++ b/test_haystack/simple_tests/search_indexes.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - from haystack import indexes from ..core.models import MockModel, ScoreMockModel diff --git a/test_haystack/simple_tests/test_simple_backend.py b/test_haystack/simple_tests/test_simple_backend.py index 20528dbea..1645ec31c 100644 --- a/test_haystack/simple_tests/test_simple_backend.py +++ b/test_haystack/simple_tests/test_simple_backend.py @@ -1,6 +1,4 @@ # coding: utf-8 -from __future__ import absolute_import, division, print_function, unicode_literals - from datetime import date from django.conf import settings diff --git a/test_haystack/simple_tests/test_simple_query.py b/test_haystack/simple_tests/test_simple_query.py index 708b50763..b093db1de 100644 --- a/test_haystack/simple_tests/test_simple_query.py +++ b/test_haystack/simple_tests/test_simple_query.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - from django.test import TestCase from haystack import connections diff --git a/test_haystack/solr_tests/server/get-solr-download-url.py b/test_haystack/solr_tests/server/get-solr-download-url.py index d2e4b207c..1e0b66f12 100755 --- a/test_haystack/solr_tests/server/get-solr-download-url.py +++ b/test_haystack/solr_tests/server/get-solr-download-url.py @@ -1,8 +1,5 @@ #!/usr/bin/env python # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - import sys from itertools import chain @@ -52,9 +49,12 @@ if not test_url.endswith(tarball): test_url = urljoin(test_url, dist_path) - if requests.head(test_url, allow_redirects=True).status_code == 200: - download_url = test_url - break + try: + if requests.head(test_url, allow_redirects=True).status_code == 200: + download_url = test_url + break + except requests.exceptions.ConnectionError: + continue else: print("None of the Apache mirrors have %s" % dist_path, file=sys.stderr) sys.exit(1) diff --git a/test_haystack/solr_tests/server/wait-for-solr b/test_haystack/solr_tests/server/wait-for-solr index 09958920c..179294c7b 100755 --- a/test_haystack/solr_tests/server/wait-for-solr +++ b/test_haystack/solr_tests/server/wait-for-solr @@ -1,8 +1,6 @@ #!/usr/bin/env python # encoding: utf-8 """Simple throttle to wait for Solr to start on busy test servers""" -from __future__ import absolute_import, print_function, unicode_literals - import sys import time diff --git a/test_haystack/solr_tests/test_admin.py b/test_haystack/solr_tests/test_admin.py index d1075630b..2a7d99398 100644 --- a/test_haystack/solr_tests/test_admin.py +++ b/test_haystack/solr_tests/test_admin.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - from django.conf import settings from django.contrib.auth.models import User from django.test import TestCase diff --git a/test_haystack/solr_tests/test_inputs.py b/test_haystack/solr_tests/test_inputs.py index cea553a8e..b6a3a988b 100644 --- a/test_haystack/solr_tests/test_inputs.py +++ b/test_haystack/solr_tests/test_inputs.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - from django.test import TestCase from haystack import connections, inputs diff --git a/test_haystack/solr_tests/test_solr_backend.py b/test_haystack/solr_tests/test_solr_backend.py index 6f2e1de02..4ac74f756 100644 --- a/test_haystack/solr_tests/test_solr_backend.py +++ b/test_haystack/solr_tests/test_solr_backend.py @@ -1,17 +1,15 @@ # -*- coding: utf-8 -*- -from __future__ import absolute_import, division, print_function, unicode_literals - import datetime import logging as std_logging import os import unittest from decimal import Decimal +from unittest.mock import patch import pysolr from django.conf import settings from django.test import TestCase from django.test.utils import override_settings -from mock import patch from pkg_resources import parse_version from haystack import connections, indexes, reset_search_queries diff --git a/test_haystack/solr_tests/test_solr_management_commands.py b/test_haystack/solr_tests/test_solr_management_commands.py index f368f8ddc..f0a7b66f1 100644 --- a/test_haystack/solr_tests/test_solr_management_commands.py +++ b/test_haystack/solr_tests/test_solr_management_commands.py @@ -1,10 +1,8 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - import datetime import os from tempfile import mkdtemp +from unittest.mock import patch import pysolr from django.conf import settings @@ -12,7 +10,6 @@ from django.core.management import call_command from django.core.management.base import CommandError from django.test import TestCase -from mock import patch from haystack import connections, constants, indexes from haystack.utils.loading import UnifiedIndex @@ -227,62 +224,63 @@ def test_build_schema(self): oldui = connections["solr"].get_unified_index() oldurl = settings.HAYSTACK_CONNECTIONS["solr"]["URL"] - needle = "Th3S3cr3tK3y" - constants.DOCUMENT_FIELD = ( - needle - ) # Force index to use new key for document_fields - settings.HAYSTACK_CONNECTIONS["solr"]["URL"] = ( - settings.HAYSTACK_CONNECTIONS["solr"]["URL"].rsplit("/", 1)[0] + "/mgmnt" - ) - - ui = UnifiedIndex() - ui.build(indexes=[SolrMockSecretKeySearchIndex()]) - connections["solr"]._index = ui - - rendered_file = StringIO() - - script_dir = os.path.realpath(os.path.dirname(__file__)) - conf_dir = os.path.join( - script_dir, "server", "solr", "server", "solr", "mgmnt", "conf" - ) - schema_file = os.path.join(conf_dir, "schema.xml") - solrconfig_file = os.path.join(conf_dir, "solrconfig.xml") - - self.assertTrue( - os.path.isdir(conf_dir), msg="Expected %s to be a directory" % conf_dir - ) - - call_command("build_solr_schema", using="solr", stdout=rendered_file) - contents = rendered_file.getvalue() - self.assertGreater(contents.find('name="%s' % needle), -1) - - call_command("build_solr_schema", using="solr", configure_directory=conf_dir) - with open(schema_file) as s: - self.assertGreater(s.read().find('name="%s' % needle), -1) - with open(solrconfig_file) as s: - self.assertGreater(s.read().find('name="df">%s' % needle), -1) - - self.assertTrue(os.path.isfile(os.path.join(conf_dir, "managed-schema.old"))) - - call_command("build_solr_schema", using="solr", reload_core=True) - - os.rename(schema_file, "%s.bak" % schema_file) - self.assertRaises( - CommandError, - call_command, - "build_solr_schema", - using="solr", - reload_core=True, - ) - - call_command("build_solr_schema", using="solr", filename=schema_file) - with open(schema_file) as s: - self.assertGreater(s.read().find('name="%s' % needle), -1) - - # reset - constants.DOCUMENT_FIELD = oldhdf - connections["solr"]._index = oldui - settings.HAYSTACK_CONNECTIONS["solr"]["URL"] = oldurl + try: + needle = "Th3S3cr3tK3y" + constants.DOCUMENT_FIELD = ( + needle + ) # Force index to use new key for document_fields + settings.HAYSTACK_CONNECTIONS["solr"]["URL"] = ( + settings.HAYSTACK_CONNECTIONS["solr"]["URL"].rsplit("/", 1)[0] + "/mgmnt" + ) + + ui = UnifiedIndex() + ui.build(indexes=[SolrMockSecretKeySearchIndex()]) + connections["solr"]._index = ui + + rendered_file = StringIO() + + script_dir = os.path.realpath(os.path.dirname(__file__)) + conf_dir = os.path.join( + script_dir, "server", "solr", "server", "solr", "mgmnt", "conf" + ) + schema_file = os.path.join(conf_dir, "schema.xml") + solrconfig_file = os.path.join(conf_dir, "solrconfig.xml") + + self.assertTrue( + os.path.isdir(conf_dir), msg="Expected %s to be a directory" % conf_dir + ) + + call_command("build_solr_schema", using="solr", stdout=rendered_file) + contents = rendered_file.getvalue() + self.assertGreater(contents.find('name="%s' % needle), -1) + + call_command("build_solr_schema", using="solr", configure_directory=conf_dir) + with open(schema_file) as s: + self.assertGreater(s.read().find('name="%s' % needle), -1) + with open(solrconfig_file) as s: + self.assertGreater(s.read().find('name="df">%s' % needle), -1) + + self.assertTrue(os.path.isfile(os.path.join(conf_dir, "managed-schema.old"))) + + call_command("build_solr_schema", using="solr", reload_core=True) + + os.rename(schema_file, "%s.bak" % schema_file) + self.assertRaises( + CommandError, + call_command, + "build_solr_schema", + using="solr", + reload_core=True, + ) + + call_command("build_solr_schema", using="solr", filename=schema_file) + with open(schema_file) as s: + self.assertGreater(s.read().find('name="%s' % needle), -1) + finally: + # reset + constants.DOCUMENT_FIELD = oldhdf + connections["solr"]._index = oldui + settings.HAYSTACK_CONNECTIONS["solr"]["URL"] = oldurl class AppModelManagementCommandTestCase(TestCase): diff --git a/test_haystack/solr_tests/test_solr_query.py b/test_haystack/solr_tests/test_solr_query.py index a3c3728ab..1a39e85d3 100644 --- a/test_haystack/solr_tests/test_solr_query.py +++ b/test_haystack/solr_tests/test_solr_query.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - import datetime from django.test import TestCase diff --git a/test_haystack/solr_tests/test_templatetags.py b/test_haystack/solr_tests/test_templatetags.py index f2eee0151..08ab0dde1 100644 --- a/test_haystack/solr_tests/test_templatetags.py +++ b/test_haystack/solr_tests/test_templatetags.py @@ -1,11 +1,9 @@ # encoding: utf-8 -from __future__ import absolute_import, division, print_function, unicode_literals - import unittest +from unittest.mock import call, patch from django.template import Context, Template from django.test import TestCase -from mock import call, patch from ..core.models import MockModel diff --git a/test_haystack/spatial/__init__.py b/test_haystack/spatial/__init__.py index 272fab3c3..9e15777a6 100644 --- a/test_haystack/spatial/__init__.py +++ b/test_haystack/spatial/__init__.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - from ..utils import check_solr diff --git a/test_haystack/spatial/models.py b/test_haystack/spatial/models.py index 756536e2e..0220cf218 100644 --- a/test_haystack/spatial/models.py +++ b/test_haystack/spatial/models.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - import datetime from django.db import models diff --git a/test_haystack/spatial/search_indexes.py b/test_haystack/spatial/search_indexes.py index c850272b5..e412b0e7e 100644 --- a/test_haystack/spatial/search_indexes.py +++ b/test_haystack/spatial/search_indexes.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - from haystack import indexes from .models import Checkin diff --git a/test_haystack/spatial/test_spatial.py b/test_haystack/spatial/test_spatial.py index 750e7e1c5..7bcfd1318 100644 --- a/test_haystack/spatial/test_spatial.py +++ b/test_haystack/spatial/test_spatial.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - from django.contrib.gis.measure import D from django.test import TestCase diff --git a/test_haystack/test_altered_internal_names.py b/test_haystack/test_altered_internal_names.py index 1cedfdb45..ed3b6ec66 100644 --- a/test_haystack/test_altered_internal_names.py +++ b/test_haystack/test_altered_internal_names.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - from django.conf import settings from django.test import TestCase from test_haystack.core.models import AnotherMockModel, MockModel diff --git a/test_haystack/test_app_loading.py b/test_haystack/test_app_loading.py index ff200c5cb..df3942366 100644 --- a/test_haystack/test_app_loading.py +++ b/test_haystack/test_app_loading.py @@ -1,6 +1,4 @@ # encoding: utf-8 -from __future__ import absolute_import, division, print_function, unicode_literals - from types import GeneratorType, ModuleType from django.test import TestCase diff --git a/test_haystack/test_app_using_appconfig/__init__.py b/test_haystack/test_app_using_appconfig/__init__.py index dcc8a4f04..fc48781a6 100644 --- a/test_haystack/test_app_using_appconfig/__init__.py +++ b/test_haystack/test_app_using_appconfig/__init__.py @@ -1,5 +1,2 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - default_app_config = "test_app_using_appconfig.apps.SimpleTestAppConfig" diff --git a/test_haystack/test_app_using_appconfig/apps.py b/test_haystack/test_app_using_appconfig/apps.py index c1e07cabe..12e444de6 100644 --- a/test_haystack/test_app_using_appconfig/apps.py +++ b/test_haystack/test_app_using_appconfig/apps.py @@ -1,5 +1,3 @@ -from __future__ import absolute_import, division, print_function, unicode_literals - from django.apps import AppConfig diff --git a/test_haystack/test_app_using_appconfig/migrations/0001_initial.py b/test_haystack/test_app_using_appconfig/migrations/0001_initial.py index b7630a500..57206f386 100644 --- a/test_haystack/test_app_using_appconfig/migrations/0001_initial.py +++ b/test_haystack/test_app_using_appconfig/migrations/0001_initial.py @@ -1,6 +1,4 @@ # -*- coding: utf-8 -*- -from __future__ import absolute_import, division, print_function, unicode_literals - from django.db import migrations, models diff --git a/test_haystack/test_app_using_appconfig/models.py b/test_haystack/test_app_using_appconfig/models.py index 6e37c8f56..5ca8079c7 100644 --- a/test_haystack/test_app_using_appconfig/models.py +++ b/test_haystack/test_app_using_appconfig/models.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - from django.db.models import CharField, Model diff --git a/test_haystack/test_app_using_appconfig/search_indexes.py b/test_haystack/test_app_using_appconfig/search_indexes.py index ad0366bf8..3611784d1 100644 --- a/test_haystack/test_app_using_appconfig/search_indexes.py +++ b/test_haystack/test_app_using_appconfig/search_indexes.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - from haystack import indexes from .models import MicroBlogPost diff --git a/test_haystack/test_app_using_appconfig/tests.py b/test_haystack/test_app_using_appconfig/tests.py index 0863ef664..5da9e0c9b 100644 --- a/test_haystack/test_app_using_appconfig/tests.py +++ b/test_haystack/test_app_using_appconfig/tests.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - from django.test import TestCase from .models import MicroBlogPost diff --git a/test_haystack/test_app_with_hierarchy/contrib/django/hierarchal_app_django/models.py b/test_haystack/test_app_with_hierarchy/contrib/django/hierarchal_app_django/models.py index 59fac439f..0fd6d2ef3 100644 --- a/test_haystack/test_app_with_hierarchy/contrib/django/hierarchal_app_django/models.py +++ b/test_haystack/test_app_with_hierarchy/contrib/django/hierarchal_app_django/models.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - from django.db.models import BooleanField, CharField, Model diff --git a/test_haystack/test_app_without_models/urls.py b/test_haystack/test_app_without_models/urls.py index 7bd1cbc75..4ce6ed04f 100644 --- a/test_haystack/test_app_without_models/urls.py +++ b/test_haystack/test_app_without_models/urls.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - from django.conf.urls import url from .views import simple_view diff --git a/test_haystack/test_app_without_models/views.py b/test_haystack/test_app_without_models/views.py index 07dd1e962..fe612179f 100644 --- a/test_haystack/test_app_without_models/views.py +++ b/test_haystack/test_app_without_models/views.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - from django.http import HttpResponse diff --git a/test_haystack/test_backends.py b/test_haystack/test_backends.py index 8edbea24a..3bd894d81 100644 --- a/test_haystack/test_backends.py +++ b/test_haystack/test_backends.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - import warnings from django.core.exceptions import ImproperlyConfigured diff --git a/test_haystack/test_discovery.py b/test_haystack/test_discovery.py index 60c47ea66..b75ad77ec 100644 --- a/test_haystack/test_discovery.py +++ b/test_haystack/test_discovery.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - from django.test import TestCase from test_haystack.discovery.search_indexes import FooIndex diff --git a/test_haystack/test_fields.py b/test_haystack/test_fields.py index c0291a4ef..50e709492 100644 --- a/test_haystack/test_fields.py +++ b/test_haystack/test_fields.py @@ -1,13 +1,10 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - import datetime from decimal import Decimal +from unittest.mock import Mock from django.template import TemplateDoesNotExist from django.test import TestCase -from mock import Mock from test_haystack.core.models import ( ManyToManyLeftSideModel, ManyToManyRightSideModel, diff --git a/test_haystack/test_forms.py b/test_haystack/test_forms.py index 814ddb7a9..1e5620066 100644 --- a/test_haystack/test_forms.py +++ b/test_haystack/test_forms.py @@ -1,6 +1,4 @@ # -*- coding: utf-8 -*- -from __future__ import absolute_import, division, print_function, unicode_literals - from django.test import TestCase from test_haystack.core.models import AnotherMockModel, MockModel from test_haystack.test_views import ( diff --git a/test_haystack/test_generic_views.py b/test_haystack/test_generic_views.py index 82a9bc307..439615410 100644 --- a/test_haystack/test_generic_views.py +++ b/test_haystack/test_generic_views.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - from django.test.client import RequestFactory from django.test.testcases import TestCase diff --git a/test_haystack/test_indexes.py b/test_haystack/test_indexes.py index 40f558e37..94542f94a 100644 --- a/test_haystack/test_indexes.py +++ b/test_haystack/test_indexes.py @@ -1,13 +1,10 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - import datetime +import queue import time from threading import Thread from django.test import TestCase -from django.utils.six.moves import queue from test_haystack.core.models import ( AFifthMockModel, AnotherMockModel, @@ -17,7 +14,7 @@ MockModel, ) -from haystack import connection_router, connections, indexes +from haystack import connections, indexes from haystack.exceptions import SearchFieldError from haystack.utils.loading import UnifiedIndex diff --git a/test_haystack/test_inputs.py b/test_haystack/test_inputs.py index 5fe9f4191..110b7d1ed 100644 --- a/test_haystack/test_inputs.py +++ b/test_haystack/test_inputs.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - from django.test import TestCase from haystack import connections, inputs diff --git a/test_haystack/test_loading.py b/test_haystack/test_loading.py index bfa46234d..928e769d7 100644 --- a/test_haystack/test_loading.py +++ b/test_haystack/test_loading.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - import unittest from django.conf import settings diff --git a/test_haystack/test_management_commands.py b/test_haystack/test_management_commands.py index fa7f6dc17..33bf15041 100644 --- a/test_haystack/test_management_commands.py +++ b/test_haystack/test_management_commands.py @@ -1,11 +1,9 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals +from unittest.mock import call, patch from django.conf import settings from django.core.management import call_command from django.test import TestCase -from mock import call, patch __all__ = ["CoreManagementCommandsTestCase"] diff --git a/test_haystack/test_managers.py b/test_haystack/test_managers.py index 257de66d3..5c8b260c7 100644 --- a/test_haystack/test_managers.py +++ b/test_haystack/test_managers.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - import datetime from django.contrib.gis.measure import D diff --git a/test_haystack/test_models.py b/test_haystack/test_models.py index c081086c8..06577c43a 100644 --- a/test_haystack/test_models.py +++ b/test_haystack/test_models.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - import logging as std_logging import pickle @@ -95,14 +92,14 @@ def test_get_additional_fields(self): def test_unicode(self): self.assertEqual( - self.no_data_sr.__unicode__(), "" + self.no_data_sr.__str__(), "" ) self.assertEqual( - self.extra_data_sr.__unicode__(), + self.extra_data_sr.__str__(), "", ) self.assertEqual( - self.no_overwrite_data_sr.__unicode__(), + self.no_overwrite_data_sr.__str__(), "", ) diff --git a/test_haystack/test_query.py b/test_haystack/test_query.py index b4078d7c7..435ae2273 100644 --- a/test_haystack/test_query.py +++ b/test_haystack/test_query.py @@ -1,6 +1,4 @@ # -*- coding: utf-8 -*- -from __future__ import absolute_import, division, print_function, unicode_literals - import datetime import unittest diff --git a/test_haystack/test_templatetags.py b/test_haystack/test_templatetags.py index d392d5f50..2bf345787 100644 --- a/test_haystack/test_templatetags.py +++ b/test_haystack/test_templatetags.py @@ -1,6 +1,4 @@ # -*- coding: utf-8 -*- -from __future__ import absolute_import, division, print_function, unicode_literals - from django.conf import settings from django.core.exceptions import ImproperlyConfigured from django.template import Context, Template diff --git a/test_haystack/test_utils.py b/test_haystack/test_utils.py index 9a0fe8e8b..e0f22a56c 100644 --- a/test_haystack/test_utils.py +++ b/test_haystack/test_utils.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - from django.test import TestCase from django.test.utils import override_settings from test_haystack.core.models import MockModel diff --git a/test_haystack/test_views.py b/test_haystack/test_views.py index 256c3d4eb..6dbb7a5c4 100644 --- a/test_haystack/test_views.py +++ b/test_haystack/test_views.py @@ -1,7 +1,5 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - +import queue import time from threading import Thread @@ -9,7 +7,6 @@ from django.http import HttpRequest, QueryDict from django.test import TestCase, override_settings from django.urls import reverse -from django.utils.six.moves import queue from test_haystack.core.models import AnotherMockModel, MockModel from haystack import connections, indexes diff --git a/test_haystack/utils.py b/test_haystack/utils.py index 89101e0b4..d6b2799dc 100644 --- a/test_haystack/utils.py +++ b/test_haystack/utils.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - import unittest from django.conf import settings diff --git a/test_haystack/whoosh_tests/test_forms.py b/test_haystack/whoosh_tests/test_forms.py index 564ab92d5..d69271486 100644 --- a/test_haystack/whoosh_tests/test_forms.py +++ b/test_haystack/whoosh_tests/test_forms.py @@ -1,7 +1,5 @@ # encoding: utf-8 """Tests for Whoosh spelling suggestions""" -from __future__ import absolute_import, division, print_function, unicode_literals - from django.conf import settings from django.http import HttpRequest diff --git a/test_haystack/whoosh_tests/test_inputs.py b/test_haystack/whoosh_tests/test_inputs.py index 00a4b4e0e..8cd505e9e 100644 --- a/test_haystack/whoosh_tests/test_inputs.py +++ b/test_haystack/whoosh_tests/test_inputs.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - from django.test import TestCase from haystack import connections, inputs diff --git a/test_haystack/whoosh_tests/test_whoosh_backend.py b/test_haystack/whoosh_tests/test_whoosh_backend.py index 6af5da043..0511e7f0e 100644 --- a/test_haystack/whoosh_tests/test_whoosh_backend.py +++ b/test_haystack/whoosh_tests/test_whoosh_backend.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - import os import unittest from datetime import timedelta diff --git a/test_haystack/whoosh_tests/test_whoosh_query.py b/test_haystack/whoosh_tests/test_whoosh_query.py index 9813ac458..0fb54e3d2 100644 --- a/test_haystack/whoosh_tests/test_whoosh_query.py +++ b/test_haystack/whoosh_tests/test_whoosh_query.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - import datetime from haystack import connections diff --git a/test_haystack/whoosh_tests/testcases.py b/test_haystack/whoosh_tests/testcases.py index 28acf72e8..a2d1e6fe3 100644 --- a/test_haystack/whoosh_tests/testcases.py +++ b/test_haystack/whoosh_tests/testcases.py @@ -1,7 +1,4 @@ # encoding: utf-8 - -from __future__ import absolute_import, division, print_function, unicode_literals - import os import shutil diff --git a/tox.ini b/tox.ini index 7539c6cc2..6548f1023 100644 --- a/tox.ini +++ b/tox.ini @@ -1,229 +1,26 @@ [tox] -envlist = docs, - py27-django1.11-es1.x, - py34-django1.11-es1.x, - py34-django2.0-es1.x, - py35-django1.11-es1.x, - py35-django2.0-es1.x, - py35-django2.1-es1.x, - pypy-django1.11-es1.x, - py27-django1.11-es2.x, - py34-django1.11-es2.x, - py34-django2.0-es2.x, - py35-django1.11-es2.x, - py35-django2.0-es2.x, - py35-django2.1-es2.x, - py36-django1.11-es2.x, - py36-django2.0-es2.x, - py36-django2.1-es2.x, - pypy-django1.11-es2.x, - py27-django1.11-es5.x, - py36-django1.11-es5.x, - py36-django2.0-es5.x, - py36-django2.1-es5.x, - pypy-django1.11-es5.x, +envlist = + docs + py35-django2.2-es{1.x,2.x,5.x} + py{36,37,38,py}-django{2.2,3.0}-es{1.x,2.x,5.x} -[base] -deps = requests - -[django2.1] -deps = Django>=2.1,<2.2 - -[django2.0] -deps = - Django>=2.0,<2.1 - -[django1.11] -deps = - Django>=1.11,<2.0 - -[es5.x] -deps = - elasticsearch>=5.0.0,<6.0.0 - -[es2.x] -deps = - elasticsearch>=2.0.0,<3.0.0 - -[es1.x] -deps = - elasticsearch>=1.0.0,<2.0.0 [testenv] commands = python test_haystack/solr_tests/server/wait-for-solr python {toxinidir}/setup.py test - -[testenv:pypy-django1.11-es1.x] -setenv = VERSION_ES=>=1.0.0,<2.0.0 -deps = - {[es1.x]deps} - {[django1.11]deps} - {[base]deps} - -[testenv:py27-django1.11-es1.x] -basepython = python2.7 -setenv = VERSION_ES=>=1.0.0,<2.0.0 deps = - {[es1.x]deps} - {[django1.11]deps} - {[base]deps} + requests + django2.2: Django>=2.2,<3.0 + django3.0: Django>=3.0,<3.1 + es1.x: elasticsearch>=1,<2 + es2.x: elasticsearch>=2,<3 + es5.x: elasticsearch>=5,<6 +setenv = + es1.x: VERSION_ES=>=1,<2 + es2.x: VERSION_ES=>=2,<3 + es5.x: VERSION_ES=>=5,<6 -[testenv:py34-django1.11-es1.x] -basepython = python3.4 -setenv = VERSION_ES=>=1.0.0,<2.0.0 -deps = - {[django1.11]deps} - {[base]deps} - -[testenv:py34-django2.0-es1.x] -basepython = python3.4 -setenv = VERSION_ES=>=1.0.0,<2.0.0 -deps = - {[django2.0]deps} - {[base]deps} - -[testenv:py35-django1.11-es1.x] -basepython = python3.5 -setenv = VERSION_ES=>=1.0.0,<2.0.0 -deps = - {[es1.x]deps} - {[django1.11]deps} - {[base]deps} - -[testenv:py35-django2.0-es1.x] -basepython = python3.5 -setenv = VERSION_ES=>=1.0.0,<2.0.0 -deps = - {[es1.x]deps} - {[django2.0]deps} - {[base]deps} - -[testenv:py35-django2.1-es1.x] -basepython = python3.5 -setenv = VERSION_ES=>=1.0.0,<2.0.0 -deps = - {[es1.x]deps} - {[django2.1]deps} - {[base]deps} - -[testenv:pypy-django1.11-es2.x] -setenv = VERSION_ES=>=2.0.0,<3.0.0 -deps = - {[es2.x]deps} - {[django1.11]deps} - {[base]deps} - -[testenv:py27-django1.11-es2.x] -basepython = python2.7 -setenv = VERSION_ES=>=2.0.0,<3.0.0 -deps = - {[es2.x]deps} - {[django1.11]deps} - {[base]deps} - -[testenv:py34-django1.11-es2.x] -basepython = python3.4 -setenv = VERSION_ES=>=2.0.0,<3.0.0 -deps = - {[es2.x]deps} - {[django1.11]deps} - {[base]deps} - -[testenv:py34-django2.0-es2.x] -basepython = python3.4 -setenv = VERSION_ES=>=2.0.0,<3.0.0 -deps = - {[es2.x]deps} - {[django2.0]deps} - {[base]deps} - -[testenv:py35-django1.11-es2.x] -basepython = python3.5 -setenv = VERSION_ES=>=2.0.0,<3.0.0 -deps = - {[es2.x]deps} - {[django1.11]deps} - {[base]deps} - -[testenv:py35-django2.0-es2.x] -basepython = python3.5 -setenv = VERSION_ES=>=2.0.0,<3.0.0 -deps = - {[es2.x]deps} - {[django2.0]deps} - {[base]deps} - -[testenv:py35-django2.1-es2.x] -basepython = python3.5 -setenv = VERSION_ES=>=2.0.0,<3.0.0 -deps = - {[es2.x]deps} - {[django2.1]deps} - {[base]deps} - -[testenv:py36-django1.11-es2.x] -basepython = python3.6 -setenv = VERSION_ES=>=2.0.0,<3.0.0 -deps = - {[es2.x]deps} - {[django1.11]deps} - {[base]deps} - -[testenv:py36-django2.0-es2.x] -basepython = python3.6 -setenv = VERSION_ES=>=2.0.0,<3.0.0 -deps = - {[es2.x]deps} - {[django2.0]deps} - {[base]deps} - -[testenv:py36-django2.1-es2.x] -basepython = python3.6 -setenv = VERSION_ES=>=2.0.0,<3.0.0 -deps = - {[es2.x]deps} - {[django2.1]deps} - {[base]deps} - -[testenv:pypy-django1.11-es5.x] -setenv = VERSION_ES=>=5.0.0,<6.0.0 -deps = - {[es5.x]deps} - {[django1.11]deps} - {[base]deps} - -[testenv:py27-django1.11-es5.x] -basepython = python2.7 -setenv = VERSION_ES=>=5.0.0,<6.0.0 -deps = - {[es5.x]deps} - {[django1.11]deps} - {[base]deps} - -[testenv:py36-django1.11-es5.x] -basepython = python3.6 -setenv = VERSION_ES=>=5.0.0,<6.0.0 -deps = - {[es5.x]deps} - {[django1.11]deps} - {[base]deps} - -[testenv:py36-django2.0-es5.x] -basepython = python3.6 -setenv = VERSION_ES=>=5.0.0,<6.0.0 -deps = - {[es5.x]deps} - {[django2.0]deps} - {[base]deps} - -[testenv:py36-django2.1-es5.x] -basepython = python3.6 -setenv = VERSION_ES=>=5.0.0,<6.0.0 -deps = - {[es5.x]deps} - {[django2.1]deps} - {[base]deps} [testenv:docs] changedir = docs