Переглянути джерело

Only write the strings file if necessary

Now we check a hash of the voice commands before writing the strings
file to reduce how much we write to the hard disk.  In implementing
this, I realized that some code was being duplicated in an easily
fixable way, so I created a Hasher object that keeps track of the
hash.json file.

Resolves #6
Clara Hobbs 8 роки тому
джерело
коміт
bc07966df1
4 змінених файлів з 69 додано та 20 видалено
  1. 37
    0
      hasher.py
  2. 22
    4
      kaylee.py
  3. 8
    15
      languageupdater.py
  4. 2
    1
      recognizer.py

+ 37
- 0
hasher.py Переглянути файл

1
+# This is part of Kaylee
2
+# -- this code is licensed GPLv3
3
+# Copyright 2015-2016 Clayton G. Hobbs
4
+# Portions Copyright 2013 Jezra
5
+
6
+import json
7
+import hashlib
8
+
9
+class Hasher:
10
+    """Keep track of hashes for Kaylee"""
11
+
12
+    def __init__(self, config):
13
+        self.config = config
14
+        try:
15
+            with open(self.config.hash_file, 'r') as f:
16
+                self.hashes = json.load(f)
17
+        except IOError:
18
+            # No stored hash
19
+            self.hashes = {}
20
+
21
+    def __getitem__(self, hashname):
22
+        try:
23
+            return self.hashes[hashname]
24
+        except (KeyError, TypeError):
25
+            return None
26
+
27
+    def __setitem__(self, hashname, value):
28
+        self.hashes[hashname] = value
29
+
30
+    def get_hash_object(self):
31
+        """Returns an object to compute a new hash"""
32
+        return hashlib.sha256()
33
+
34
+    def store(self):
35
+        """Store the current hashes into a the hash file"""
36
+        with open(self.config.hash_file, 'w') as f:
37
+            json.dump(self.hashes, f)

+ 22
- 4
kaylee.py Переглянути файл

11
 import os.path
11
 import os.path
12
 import subprocess
12
 import subprocess
13
 from gi.repository import GObject, GLib
13
 from gi.repository import GObject, GLib
14
-import json
15
 
14
 
16
 from recognizer import Recognizer
15
 from recognizer import Recognizer
17
 from config import Config
16
 from config import Config
18
 from languageupdater import LanguageUpdater
17
 from languageupdater import LanguageUpdater
19
 from numberparser import NumberParser
18
 from numberparser import NumberParser
19
+from hasher import Hasher
20
 
20
 
21
 
21
 
22
 class Kaylee:
22
 class Kaylee:
27
         ui_continuous_listen = False
27
         ui_continuous_listen = False
28
         self.continuous_listen = False
28
         self.continuous_listen = False
29
 
29
 
30
-        self.commands = {}
31
-
32
         # Load configuration
30
         # Load configuration
33
         self.config = Config()
31
         self.config = Config()
34
         self.options = vars(self.config.options)
32
         self.options = vars(self.config.options)
37
         # Create number parser for later use
35
         # Create number parser for later use
38
         self.number_parser = NumberParser()
36
         self.number_parser = NumberParser()
39
 
37
 
38
+        # Create a hasher
39
+        self.hasher = Hasher(self.config)
40
+
40
         # Create the strings file
41
         # Create the strings file
41
-        self.create_strings_file()
42
+        self.update_strings_file_if_changed()
42
 
43
 
43
         if self.options['interface']:
44
         if self.options['interface']:
44
             if self.options['interface'] == "g":
45
             if self.options['interface'] == "g":
71
         self.recognizer = Recognizer(self.config)
72
         self.recognizer = Recognizer(self.config)
72
         self.recognizer.connect('finished', self.recognizer_finished)
73
         self.recognizer.connect('finished', self.recognizer_finished)
73
 
74
 
75
+    def update_voice_commands_if_changed(self):
76
+        """Use hashes to test if the voice commands have changed"""
77
+        stored_hash = self.hasher['voice_commands']
78
+
79
+        # Calculate the hash the voice commands have right now
80
+        hasher = self.hasher.get_hash_object()
81
+        for voice_cmd in self.commands.keys():
82
+            hasher.update(voice_cmd.encode('utf-8'))
83
+            # Add a separator to avoid odd behavior
84
+            hasher.update('\n'.encode('utf-8'))
85
+        new_hash = hasher.hexdigest()
86
+
87
+        if new_hash != stored_hash:
88
+            self.create_strings_file()
89
+            self.hasher['voice_commands'] = new_hash
90
+            self.hasher.store()
91
+
74
     def create_strings_file(self):
92
     def create_strings_file(self):
75
         # Open the strings file
93
         # Open the strings file
76
         with open(self.config.strings_file, 'w') as strings:
94
         with open(self.config.strings_file, 'w') as strings:

+ 8
- 15
languageupdater.py Переглянути файл

3
 # Copyright 2015-2016 Clayton G. Hobbs
3
 # Copyright 2015-2016 Clayton G. Hobbs
4
 # Portions Copyright 2013 Jezra
4
 # Portions Copyright 2013 Jezra
5
 
5
 
6
-import hashlib
7
-import json
8
 import re
6
 import re
9
 
7
 
10
 import requests
8
 import requests
11
 
9
 
10
+from hasher import Hasher
11
+
12
 class LanguageUpdater:
12
 class LanguageUpdater:
13
 
13
 
14
     def __init__(self, config):
14
     def __init__(self, config):
15
         self.config = config
15
         self.config = config
16
+        self.hasher = Hasher(config)
16
 
17
 
17
     def update_language_if_changed(self):
18
     def update_language_if_changed(self):
18
         """Test if the language has changed, and if it has, update it"""
19
         """Test if the language has changed, and if it has, update it"""
21
             self.save_language_hash()
22
             self.save_language_hash()
22
 
23
 
23
     def language_has_changed(self):
24
     def language_has_changed(self):
24
-        """Use SHA256 hashes to test if the language has changed"""
25
-        # Load the stored hash from the hash file
26
-        try:
27
-            with open(self.config.hash_file, 'r') as f:
28
-                hashes = json.load(f)
29
-            self.stored_hash = hashes['language']
30
-        except (IOError, KeyError, TypeError):
31
-            # No stored hash
32
-            self.stored_hash = ''
25
+        """Use hashes to test if the language has changed"""
26
+        self.stored_hash = self.hasher['language']
33
 
27
 
34
         # Calculate the hash the language file has right now
28
         # Calculate the hash the language file has right now
35
-        hasher = hashlib.sha256()
29
+        hasher = self.hasher.get_hash_object()
36
         with open(self.config.strings_file, 'rb') as sfile:
30
         with open(self.config.strings_file, 'rb') as sfile:
37
             buf = sfile.read()
31
             buf = sfile.read()
38
             hasher.update(buf)
32
             hasher.update(buf)
75
         self._download_file(dic_url, self.config.dic_file)
69
         self._download_file(dic_url, self.config.dic_file)
76
 
70
 
77
     def save_language_hash(self):
71
     def save_language_hash(self):
78
-        new_hashes = {'language': self.new_hash}
79
-        with open(self.config.hash_file, 'w') as f:
80
-            json.dump(new_hashes, f)
72
+        self.hasher['language'] = self.new_hash
73
+        self.hasher.store()
81
 
74
 
82
     def _download_file(self, url, path):
75
     def _download_file(self, url, path):
83
         r = requests.get(url, stream=True)
76
         r = requests.get(url, stream=True)

+ 2
- 1
recognizer.py Переглянути файл

15
 
15
 
16
 class Recognizer(GObject.GObject):
16
 class Recognizer(GObject.GObject):
17
     __gsignals__ = {
17
     __gsignals__ = {
18
-        'finished' : (GObject.SIGNAL_RUN_LAST, GObject.TYPE_NONE, (GObject.TYPE_STRING,))
18
+        'finished' : (GObject.SIGNAL_RUN_LAST, GObject.TYPE_NONE,
19
+                      (GObject.TYPE_STRING,))
19
     }
20
     }
20
 
21
 
21
     def __init__(self, config):
22
     def __init__(self, config):

Завантаження…
Відмінити
Зберегти