switch to enable strict search, default: False

Add a "strict" switch to our search functions,
still defaulting to fuzzy searches.

Currently search fields are concatenated with spaces,
which default to the OR operator.
The values for the field are grouped with parentheses.
This Lucene syntax results in a fuzzy search,
where you also get results that just match part of the query,
but the close results are still the first results.

This is nice if you want to find additional information
and you are happy that you get results even if the query is not 100 %
accurate.

However, sometimes you don't want any results that don't
fit exactly what you asked for.
You want to know how many items match your query exactly
without filtering the results for scores and mismatches.

When "strict" is set to True then every field value
is enclosed in quotation marks, forming a lucene phrase.
That whole phrase has to match.
Additionally the fields are concatenated with AND.

Alternatives:
It would also be possible to prepend a + (plus) to every word
of the field values.
This would force every word to match, but any order is allowed.

Please note, that you can use the query parameter directly
for full Lucene support.

Signed-off-by: Johannes Dewender <github@JonnyJD.net>
prevent http 400 in search queries

If fields are not set, we don't change the query.
Full Lucene syntax is available in the query
and http status 400 messages can occur.
The user is fully responsible to prevent this.

If there are any fields set,
we escape any lucene special characters that might appear in the query.

In fuzzy mode (strict=False, default) we lowercase the field values,
and possibly the query (if fields are set).

In strict mode we enclose the field values,
and possibly the query (if fields are set) in quotation marks.

Both changes should prevent uppercase AND / OR from appearing in the query.
Otherwise, these operators could lead to http 400 messages
when placed incorrectly.

Alternatives:

Always escape lucene special chars in the query in strict mode,
even if no fields are set.
That would support doing a plain search including entities with AND
or special characters.
However, even the MB website just fails when you search for AND.
Advanced queries would only be possible in fuzzy mode,
but this is the default mode anyways.

Signed-off-by: Johannes Dewender <github@JonnyJD.net>
use absolute imports, even intra-package

Starting with Python 3, imports are always absolute by default.
This means a package is searched in the library path
and in the current directory of the active script.

Intra-package imports can bo done in two ways:
from packagename import module  (absolute)
from . import module		(relative)

With absolute imports you have to use the actual name of the package and
change the import when the name of the package changes.
The relative import is "name-agnostic".

However, there are also downsides with the relative approach:

Relative imports break outside of the package context.
```python -m pkg/module``` breaks with:
```ValueError: Attempted relative import in non-package```
in Python 2 and 3.
Making a quick syntax-check impossible and breaking
epydoc with:
```Bad dotted name```

Therefore we use absolute imports unless there is a specific
reason to use relative imports.

Please note that you can still use a library in the same folder (locally)
without installing it to a library path.

Signed-off-by: Johannes Dewender <github@JonnyJD.net>
Move common test functionality into _common.

Also set up paths correctly for running tests against the checked out
source, not one that may be already installed

Signed-off-by: Alastair Porter <alastair@porter.net.nz>
Merge remote-tracking branch 'jonnyjd/absolute_import'

Signed-off-by: Alastair Porter <alastair@porter.net.nz>
Merge remote-tracking branch 'jonnyjd/avoid_400'

Signed-off-by: Alastair Porter <alastair@porter.net.nz>