Completed
Push — master ( dd39f0...c2012d )
by Ronert
07:57
created

cf_predict.Model.__init__()   B

Complexity

Conditions 5

Size

Total Lines 16

Duplication

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