Statistics
| Branch: | Tag: | Revision:

root / kamaki / cli / history.py @ a313f923

History | View | Annotate | Download (4.6 kB)

1 73e0914d Stavros Sachtouris
#!/usr/bin/env python
2 73e0914d Stavros Sachtouris
3 5e383dd4 Stavros Sachtouris
# Copyright 2012-2014 GRNET S.A. All rights reserved.
4 73e0914d Stavros Sachtouris
#
5 73e0914d Stavros Sachtouris
# Redistribution and use in source and binary forms, with or
6 73e0914d Stavros Sachtouris
# without modification, are permitted provided that the following
7 73e0914d Stavros Sachtouris
# conditions are met:
8 73e0914d Stavros Sachtouris
#
9 73e0914d Stavros Sachtouris
#   1. Redistributions of source code must retain the above
10 73e0914d Stavros Sachtouris
#      copyright notice, this list of conditions and the following
11 73e0914d Stavros Sachtouris
#      disclaimer.
12 73e0914d Stavros Sachtouris
#
13 73e0914d Stavros Sachtouris
#   2. Redistributions in binary form must reproduce the above
14 73e0914d Stavros Sachtouris
#      copyright notice, this list of conditions and the following
15 73e0914d Stavros Sachtouris
#      disclaimer in the documentation and/or other materials
16 73e0914d Stavros Sachtouris
#      provided with the distribution.
17 73e0914d Stavros Sachtouris
#
18 73e0914d Stavros Sachtouris
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
19 73e0914d Stavros Sachtouris
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 73e0914d Stavros Sachtouris
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 73e0914d Stavros Sachtouris
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
22 73e0914d Stavros Sachtouris
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 73e0914d Stavros Sachtouris
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 73e0914d Stavros Sachtouris
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
25 73e0914d Stavros Sachtouris
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 73e0914d Stavros Sachtouris
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 73e0914d Stavros Sachtouris
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28 73e0914d Stavros Sachtouris
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 73e0914d Stavros Sachtouris
# POSSIBILITY OF SUCH DAMAGE.
30 73e0914d Stavros Sachtouris
#
31 73e0914d Stavros Sachtouris
# The views and conclusions contained in the software and
32 73e0914d Stavros Sachtouris
# documentation are those of the authors and should not be
33 73e0914d Stavros Sachtouris
# interpreted as representing official policies, either expressed
34 73e0914d Stavros Sachtouris
# or implied, of GRNET S.A.
35 73e0914d Stavros Sachtouris
36 c49188b7 Stavros Sachtouris
import codecs
37 50a32c37 Stavros Sachtouris
from logging import getLogger
38 50a32c37 Stavros Sachtouris
39 50a32c37 Stavros Sachtouris
40 50a32c37 Stavros Sachtouris
log = getLogger(__name__)
41 c49188b7 Stavros Sachtouris
42 fd5db045 Stavros Sachtouris
43 73e0914d Stavros Sachtouris
class History(object):
44 a313f923 Stavros Sachtouris
    ignore_commands = ['config set', ]
45 a313f923 Stavros Sachtouris
46 ddc97a10 Stavros Sachtouris
    def __init__(self, filepath, token=None):
47 fd5db045 Stavros Sachtouris
        self.filepath = filepath
48 2d1f5058 Stavros Sachtouris
        self.token = token
49 5e383dd4 Stavros Sachtouris
        self._limit = 0
50 5e383dd4 Stavros Sachtouris
        self.counter = 0
51 edaf3ba6 Stavros Sachtouris
52 a44a9d97 Stavros Sachtouris
    def __getitem__(self, cmd_ids):
53 a44a9d97 Stavros Sachtouris
        with codecs.open(self.filepath, mode='r', encoding='utf-8') as f:
54 edaf3ba6 Stavros Sachtouris
            try:
55 50a32c37 Stavros Sachtouris
                lines = f.readlines()
56 50a32c37 Stavros Sachtouris
                self.counter, cmd_list = int(lines[0]), lines[1:]
57 a44a9d97 Stavros Sachtouris
                return cmd_list[cmd_ids]
58 edaf3ba6 Stavros Sachtouris
            except IndexError:
59 edaf3ba6 Stavros Sachtouris
                return None
60 73e0914d Stavros Sachtouris
61 5e383dd4 Stavros Sachtouris
    @property
62 5e383dd4 Stavros Sachtouris
    def limit(self):
63 5e383dd4 Stavros Sachtouris
        return self._limit
64 5e383dd4 Stavros Sachtouris
65 5e383dd4 Stavros Sachtouris
    @limit.setter
66 5e383dd4 Stavros Sachtouris
    def limit(self, new_limit):
67 5e383dd4 Stavros Sachtouris
        new_limit = int(new_limit)
68 5e383dd4 Stavros Sachtouris
        if new_limit < 0:
69 5e383dd4 Stavros Sachtouris
            raise ValueError('Invalid history limit (%s)' % new_limit)
70 5e383dd4 Stavros Sachtouris
        old_limit, self._limit = self._limit, new_limit
71 50a32c37 Stavros Sachtouris
        if self._limit and ((not old_limit) or (self._limit <= old_limit)):
72 5e383dd4 Stavros Sachtouris
            with codecs.open(self.filepath, mode='r', encoding='utf-8') as f:
73 5e383dd4 Stavros Sachtouris
                lines = f.readlines()
74 50a32c37 Stavros Sachtouris
                self.counter = int(lines[0])
75 5e383dd4 Stavros Sachtouris
                old_len = len(lines[1:])
76 50a32c37 Stavros Sachtouris
            if old_len > new_limit:
77 50a32c37 Stavros Sachtouris
                self.counter += old_len - new_limit
78 50a32c37 Stavros Sachtouris
                with codecs.open(
79 50a32c37 Stavros Sachtouris
                        self.filepath, mode='w', encoding='utf-8') as f:
80 5e383dd4 Stavros Sachtouris
                    f.write('%s\n' % self.counter)
81 50a32c37 Stavros Sachtouris
                    f.write(''.join(lines[old_len - new_limit + 1:]))
82 5e383dd4 Stavros Sachtouris
                    f.flush()
83 5e383dd4 Stavros Sachtouris
84 fd5db045 Stavros Sachtouris
    @classmethod
85 fd5db045 Stavros Sachtouris
    def _match(self, line, match_terms):
86 a44a9d97 Stavros Sachtouris
        if match_terms:
87 a44a9d97 Stavros Sachtouris
            return all(term in line for term in match_terms.split())
88 fd5db045 Stavros Sachtouris
        return True
89 73e0914d Stavros Sachtouris
90 fd5db045 Stavros Sachtouris
    def get(self, match_terms=None, limit=0):
91 ddc97a10 Stavros Sachtouris
        """DEPRECATED since 0.14"""
92 24903c7d Stavros Sachtouris
        limit = int(limit or 0)
93 a44a9d97 Stavros Sachtouris
        r = ['%s.\t%s' % (i + 1, line) for i, line in enumerate(self[:]) if (
94 a44a9d97 Stavros Sachtouris
                self._match(line, match_terms))]
95 a44a9d97 Stavros Sachtouris
        return r[- limit:]
96 73e0914d Stavros Sachtouris
97 fd5db045 Stavros Sachtouris
    def add(self, line):
98 50a32c37 Stavros Sachtouris
        line = '%s' % line or ''
99 a313f923 Stavros Sachtouris
        bline = [w.lower() for w in line.split() if not w.startswith('-')]
100 a313f923 Stavros Sachtouris
        for cmd in self.ignore_commands:
101 a313f923 Stavros Sachtouris
            cmds = [w.lower() for w in cmd.split()]
102 a313f923 Stavros Sachtouris
            if cmds == bline[1:len(cmds) + 1]:
103 a313f923 Stavros Sachtouris
                log.debug('History ignored a command of type "%s"' % cmd)
104 a313f923 Stavros Sachtouris
                return
105 2d1f5058 Stavros Sachtouris
        line = line.replace(self.token, '...') if self.token else line
106 50a32c37 Stavros Sachtouris
        try:
107 50a32c37 Stavros Sachtouris
            with codecs.open(self.filepath, mode='a+', encoding='utf-8') as f:
108 50a32c37 Stavros Sachtouris
                f.write(line + '\n')
109 50a32c37 Stavros Sachtouris
                f.flush()
110 50a32c37 Stavros Sachtouris
            self.limit = self.limit
111 50a32c37 Stavros Sachtouris
        except Exception as e:
112 50a32c37 Stavros Sachtouris
            log.debug('Add history failed for "%s" (%s)' % (line, e))
113 73e0914d Stavros Sachtouris
114 edaf3ba6 Stavros Sachtouris
    def empty(self):
115 a44a9d97 Stavros Sachtouris
        with open(self.filepath, 'w') as f:
116 5e383dd4 Stavros Sachtouris
            f.write('0\n')
117 a44a9d97 Stavros Sachtouris
            f.flush()
118 5e383dd4 Stavros Sachtouris
        self.counter = 0
119 75a0ea7d Stavros Sachtouris
120 edaf3ba6 Stavros Sachtouris
    def clean(self):
121 a44a9d97 Stavros Sachtouris
        """DEPRECATED since version 0.14"""
122 edaf3ba6 Stavros Sachtouris
        return self.empty()
123 75a0ea7d Stavros Sachtouris
124 edaf3ba6 Stavros Sachtouris
    def retrieve(self, cmd_id):
125 a44a9d97 Stavros Sachtouris
        if not cmd_id:
126 a44a9d97 Stavros Sachtouris
            return None
127 a44a9d97 Stavros Sachtouris
        cmd_id = int(cmd_id)
128 a44a9d97 Stavros Sachtouris
        return self[cmd_id - (1 if cmd_id > 0 else 0)]