__init__.py 3.61 KB
Newer Older
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
1
2
from future import standard_library
standard_library.install_aliases()
3

J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
4
5
import inspect
import os.path
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
6
import os
7
import pickle
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
8
import logging
9
import tempfile
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
10
import copy
11
from .. import models
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
12
13
14

logger = logging.getLogger(__name__)

15

J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
16
class SenpyPlugin(models.Plugin):
17
    def __init__(self, info=None):
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
18
19
20
21
        """
        Provides a canonical name for plugins and serves as base for other
        kinds of plugins.
        """
22
        if not info:
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
23
24
            raise models.Error(message=("You need to provide configuration"
                                        "information for the plugin."))
25
        logger.debug("Initialising {}".format(info))
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
26
27
        id = 'plugins/{}_{}'.format(info['name'], info['version'])
        super(SenpyPlugin, self).__init__(id=id, **info)
28
        self.is_activated = False
29

J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
30
31
32
    def get_folder(self):
        return os.path.dirname(inspect.getfile(self.__class__))

33
34
35
36
37
38
39
40
41
    def activate(self):
        pass

    def deactivate(self):
        pass


class AnalysisPlugin(SenpyPlugin):

42
    def analyse(self, *args, **kwargs):
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
        raise NotImplemented(
            'Your method should implement either analyse or analyse_entry')

    def analyse_entry(self, entry, parameters):
        """ An implemented plugin should override this method.
        This base method is here to adapt old style plugins which only
        implement the *analyse* function.
        Note that this method may yield an annotated entry or a list of
        entries (e.g. in a tokenizer)
        """
        text = entry['text']
        params = copy.copy(parameters)
        params['input'] = text
        results = self.analyse(**params)
        for i in results.entries:
            yield i
59

J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
60
61
62
63
64
65
    def analyse_entries(self, entries, parameters):
        for entry in entries:
            logger.debug('Analysing entry with plugin {}: {}'.format(self, entry))
            for result in self.analyse_entry(entry, parameters):
                yield result

66

67
68
class ConversionPlugin(SenpyPlugin):
    pass
69

70

71
class SentimentPlugin(models.SentimentPlugin, AnalysisPlugin):
72
73
74
75
    def __init__(self, info, *args, **kwargs):
        super(SentimentPlugin, self).__init__(info, *args, **kwargs)
        self.minPolarityValue = float(info.get("minPolarityValue", 0))
        self.maxPolarityValue = float(info.get("maxPolarityValue", 1))
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
76

77

78
class EmotionPlugin(models.EmotionPlugin, AnalysisPlugin):
79
    def __init__(self, info, *args, **kwargs):
80
        super(EmotionPlugin, self).__init__(info, *args, **kwargs)
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
81
82
83
84
        self.minEmotionValue = float(info.get("minEmotionValue", -1))
        self.maxEmotionValue = float(info.get("maxEmotionValue", 1))


85
86
class EmotionConversionPlugin(models.EmotionConversionPlugin, ConversionPlugin):
    pass
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
87
88
89
90
91


class ShelfMixin(object):
    @property
    def sh(self):
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
92
        if not hasattr(self, '_sh') or self._sh is None:
93
94
95
            self.__dict__['_sh'] = {}
            if os.path.isfile(self.shelf_file):
                self.__dict__['_sh'] = pickle.load(open(self.shelf_file, 'rb'))
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
96
97
98
99
        return self._sh

    @sh.deleter
    def sh(self):
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
100
101
        if os.path.isfile(self.shelf_file):
            os.remove(self.shelf_file)
102
103
            del self.__dict__['_sh']
        self.save()
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
104

J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
105
106
    @property
    def shelf_file(self):
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
107
        if 'shelf_file' not in self or not self['shelf_file']:
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
108
109
            sd = os.environ.get('SENPY_DATA', tempfile.gettempdir())
            self.shelf_file = os.path.join(sd, self.name + '.p')
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
110
        return self['shelf_file']
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
111

112
    def save(self):
J. Fernando Sánchez's avatar
J. Fernando Sánchez committed
113
        logger.debug('saving pickle')
114
115
116
        if hasattr(self, '_sh') and self._sh is not None:
            with open(self.shelf_file, 'wb') as f:
                pickle.dump(self._sh, f)