Completed
Push — master ( c2012d...81359f )
by Ronert
06:22
created

cf_predict.Model.post()   A

Complexity

Conditions 4

Size

Total Lines 20

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 20
rs 9.2
cc 4
1
import pickle
2
import os
3
import numpy as np
0 ignored issues
show
Configuration introduced by
The import numpy could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
4
from flask_restful import Resource, request
0 ignored issues
show
Configuration introduced by
The import flask_restful could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
5
from flask import url_for, current_app
0 ignored issues
show
Configuration introduced by
The import flask could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
6
from .errors import NoPredictMethod
0 ignored issues
show
Bug introduced by
The name NoPredictMethod does not seem to exist in module errors.
Loading history...
7
import cf_predict
8
9
10
def get_db():
11
    """Fetch Redis client."""
12
    return current_app.extensions["redis"]
13
14
15
class Catalogue(Resource):
0 ignored issues
show
Coding Style introduced by
This class has no __init__ method.
Loading history...
16
    def get(self):
17
        """Show a catalogue of available endpoints."""
18
        return {
19
            "model_url": url_for("api.model", _external=True),
20
            "api_version": cf_predict.__version__
21
        }
22
23
24
class Model(Resource):
25
    def __init__(self):
26
        self.r = get_db()
27
        self.version = os.getenv("MODEL_VERSION") or "latest"
28
        if self.version == "latest":
29
            try:
30
                self.version = self.find_latest_version(self.version)
31
            except (TypeError, ValueError) as e:
32
                current_app.logger.error("No model {} found".format(self.version))
33
                raise e
34
            try:
35
                self.model = self.load_model(self.version)
36
            except (pickle.UnpicklingError, IOError, AttributeError, EOFError, ImportError, IndexError) as e:
37
                current_app.logger.error("Model {} could not be unpickled".format(self.version))
38
                raise e
39
            if not hasattr(self.model, 'predict'):
40
                raise NoPredictMethod
41
42
    def find_latest_version(self, version):
43
        """Find model with the highest version number in Redis."""
44
        keys = [key.decode("utf-8") for key in self.r.scan_iter()]
45
        latest_version = max(keys)
46
        return latest_version
47
48
    def load_model(self, version):
49
        """Deserialize and load model."""
50
        return pickle.loads(self.r.get(version))
51
52
    def get(self):
53
        """Get current model version."""
54
        return {"model_version": self.version}
55
56
    def post(self):
57
        """Get prediction from model.
58
59
        Input: Feature array
60
        """
61
        try:
62
            raw_features = request.get_json()["features"]
63
        except KeyError:
64
            return {"message": "Features not found in {}".format(request.get_json())}, 400
65
        try:
66
            features = np.array(raw_features)
67
            if len(features.shape) == 1:
68
                features.reshape(1, -1)
69
            prediction = self.model.predict(features)
70
            return {
71
                "model_version": self.version,
72
                "prediction": list(prediction)
73
            }
74
        except ValueError:
75
            return {"message": "Features {} do not match expected input for model version {}".format(raw_features, self.version)}, 400
76