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>
In the example releasesearch script, show all matching releases.

The first test search I ran (releasesearch.py "Rush" "2112") returned
some expected results and some unexpected results:
  - expected: several different releases of the 1976 album "2112"
    by the Canadian rock trio "Rush"
  - unexpected, but entirely reasonable: a bootleg called "2112 Days
    in Seattle" by the same Rush
  - definitely unexpected: several releases by the same Rush that
    do not mention "2112" at all, e.g. their 1996 album "Test for Echo"
  - definitely unexpected: several releases by a Japanese artist
    named RusH, such as 理由在反抗 and 頂絶レパード

In short, this demonstrates that _do_mb_search() is behaving contrary
to my expectations: I expected it to AND my search terms together, not
OR them.

Signed-off-by: Greg Ward <greg@gerg.ca>
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>
Validate input to the rate limiting code. Fixes #42

Don't accept 0 as a parameter to either option in rate limiting.
Add a parameter to globally enable or disable rate limiting

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>
Correctly check includes and status on get_ methods. Fixes #58

Reported by palli81.
Allow includes to be a string as well as a list
Add some simple tests for get methods and basic includes.

Signed-off-by: Alastair Porter <alastair@porter.net.nz>
Merge branch 'entityget'

Signed-off-by: Alastair Porter <alastair@porter.net.nz>
Add missing util import

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

There was a merge conflict due to
97c535d41113eb18ea086cca0b2b091538e664f1

That commit is now reintegrated, fixing that merge.

Signed-off-by: Johannes Dewender <github@JonnyJD.net>
fixup: add util import again

Signed-off-by: Johannes Dewender <github@JonnyJD.net>
limit results to 5 releases in the example

Otherwise we can't see the first result in the terminal.

Signed-off-by: Johannes Dewender <github@JonnyJD.net>
Don't allow negative time values

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

* Try sphinx-build as well as sphinx-build2
* Fix latin et
* Add updated date to documentation pages

Signed-off-by: Alastair Porter <alastair@porter.net.nz>
examples: handle multiple artists in the credits

There can be multiple artists in the artist-credits that are separated
by a " + ". This is a string, not an artist object in itself.

The library provides "artist-credit-phrase", which is used in the
example.

Signed-off-by: Johannes Dewender <github@JonnyJD.net>
Merge branch 'ratelimit'

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

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

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