commit:     244ace4fee1054945eb97aad31919dba71374b0b
Author:     Brian Dolbec <dolsen <AT> gentoo <DOT> org>
AuthorDate: Fri Dec 26 21:15:22 2014 +0000
Commit:     Brian Dolbec <dolsen <AT> gentoo <DOT> org>
CommitDate: Tue Dec 30 21:42:25 2014 +0000
URL:        
http://sources.gentoo.org/gitweb/?p=proj/gentoo-keys.git;a=commit;h=244ace4f

gkeys: Add key-search action

Add _list_search() sub function.
Add category output and grouping.
Fix arg as a list searching as well as seed values as a list.
Use recursion to get to single value searches.
Make nick search to be partial unless --exact specified.
Move main key_search code to SeedHandler class, it is much better suited to 
this class.
Add 1name subparser option for single name entries only
Add seen tracking in key_search to eliminate duplicates
Add --all option to key-search
If --all is specified, it filters out search results to match a seed for all 
criteria specified.

---
 gkeys/gkeys/actions.py     | 34 ++++++++++++++++++++++++++++++++--
 gkeys/gkeys/base.py        | 17 +++++++++++++++++
 gkeys/gkeys/seed.py        | 43 ++++++++++++++++++++++++++++++++++++++++++-
 gkeys/gkeys/seedhandler.py | 25 +++++++++++++++++++++++++
 4 files changed, 116 insertions(+), 3 deletions(-)

diff --git a/gkeys/gkeys/actions.py b/gkeys/gkeys/actions.py
index ded3df7..be1823f 100644
--- a/gkeys/gkeys/actions.py
+++ b/gkeys/gkeys/actions.py
@@ -35,7 +35,7 @@ Seed_Actions = ['----seeds----', 'add-seed', 'fetch-seed', 
'list-cats',
     'list-seed', 'list-seedfiles', 'move-seed', 'remove-seed']
 
 Key_Actions = ['----keys-----', 'check-key', 'import-key', 'installed',
-    'install-key', 'list-key', 'move-key', 'refresh-key', 'remove-key',
+    'install-key', 'key-search', 'list-key', 'move-key', 'refresh-key', 
'remove-key',
     'spec-check']
 
 General_Actions = ['---general---', 'sign','verify']
@@ -56,6 +56,7 @@ Action_Options = {
     'move-key': ['nick', 'name', 'keydir', 'fingerprint', 'category', 
'keyring', 'dest'],
     'installed': ['nick', 'name', 'keydir', 'fingerprint', 'category', 
'keyring'],
     'import-key': ['nick', 'name', 'keydir', 'fingerprint', 'category', 
'keyring'],
+    'key-search': ['nick', '1name', 'keydir', 'fingerprint', 'keyid', 
'category', 'exact', 'all'],
     'verify': ['dest', 'nick', 'name', 'keydir', 'fingerprint', 'category', 
'1file', 'signature', 'timestamp'],
     'check-key': ['nick', 'name', 'keydir', 'fingerprint', 'category', 
'keyring', 'keyid'],
     'sign': ['nick', 'name', 'keydir', 'fingerprint', 'file', 'keyring'],
@@ -80,6 +81,7 @@ Action_Map = {
     'move-key': 'movekey',
     'installed': 'installed',
     'import-key': 'importkey',
+    'key-search': 'key_search',
     'verify': 'verify',
     'check-key': 'checkkey',
     'sign': 'sign',
@@ -845,5 +847,33 @@ class Actions(object):
         return (True, ['Completed'])
 
 
-
+    def key_search(self, args):
+        '''Search for a key's seed field in the installed keys db'''
+        handler = SeedHandler(self.logger, self.config)
+        results = {}
+        search_args = [x for x in
+            ['nick', 'name', 'keydir', 'fingerprint', 'keyid']
+            if getattr(args, x)]
+        if args.category:
+            handler.load_category(args.category)
+            results[args.category] = handler.key_search(args, search_args)
+        else:
+            for cat in list(self.config.get_key('seeds')):
+                handler.load_category(cat)
+                found = handler.key_search(args, search_args)
+                if found:
+                    if cat in results:
+                        results[cat].extend(found)
+                    else:
+                        results[cat] = found
+        msgs = []
+        for cat in results:
+            msgs.append("Category: %s" % cat)
+            seen = []
+            for result in results[cat]:
+                if result and result.nick not in seen:
+                    if isinstance(result, GKEY):
+                        seen.append(result)
+            msgs.append(seen)
+        return (True, msgs)
 

diff --git a/gkeys/gkeys/base.py b/gkeys/gkeys/base.py
index 499c291..541a12c 100644
--- a/gkeys/gkeys/base.py
+++ b/gkeys/gkeys/base.py
@@ -46,11 +46,23 @@ class CliBase(object):
 
 
     @staticmethod
+    def _option_all(parser=None):
+        parser.add_argument('-a', '--all', dest='all',
+            action='store_true', default=False,
+            help='Match all inputs arguments in searches')
+
+    @staticmethod
     def _option_dest(parser=None):
         parser.add_argument('-d', '--dest', dest='destination', default=None,
             help='The destination seed file or keydir for move, copy 
operations')
 
     @staticmethod
+    def _option_exact(parser=None):
+        parser.add_argument('-e', '--exact', dest='exact',
+            action='store_true', default=False,
+            help='Use CASE matching in searches')
+
+    @staticmethod
     def _option_fingerprint(parser=None):
         parser.add_argument('-f', '--fingerprint', dest='fingerprint',
             default=None, nargs='+',
@@ -83,6 +95,11 @@ class CliBase(object):
             default=None, help='The name of the the key')
 
     @staticmethod
+    def _option_1name(parser=None):
+        parser.add_argument('-N', '--name', dest='name',
+            default=None, help='The name of the the key')
+
+    @staticmethod
     def _option_category(parser=None):
         parser.add_argument('-C', '--category',
             dest='category', default=None,

diff --git a/gkeys/gkeys/seed.py b/gkeys/gkeys/seed.py
index f0cb019..2406c1a 100644
--- a/gkeys/gkeys/seed.py
+++ b/gkeys/gkeys/seed.py
@@ -160,7 +160,48 @@ class Seeds(object):
         try:
             return self.seeds[nick]
         except KeyError:
-            return None
+            return []
+
+
+    def field_search(self, field, value, exact=False):
+        '''Searches the seeds for a matching nick
+
+        @param keyid: string
+        @returns GKEY instance or None
+        '''
+        results = []
+        if field == 'nick' and exact:
+            return self.nick_search(value)
+        for nick in self.seeds:
+            seed = self.seeds[nick]
+            val = getattr(seed, field)
+            if isinstance(val, list) or isinstance(value, list):
+                if  self._list_search(value, val, exact):
+                    results.append(seed)
+            elif exact:
+                if value in val:
+                    results.append(seed)
+            else:
+                if value.lower() in val.lower():
+                    results.append(seed)
+
+        return results
+
+
+    def _list_search(self, find, values, exact):
+        if isinstance(find, list):
+            found = []
+            for f in find:
+                found.append(self._list_search(f, values, exact))
+            return True in found
+        for val in values:
+            if exact:
+                if find in val:
+                    return True
+            else:
+                if find.lower() in val.lower():
+                    return True
+        return False
 
 
     def _error(self, err):

diff --git a/gkeys/gkeys/seedhandler.py b/gkeys/gkeys/seedhandler.py
index bb233f9..2222bd2 100644
--- a/gkeys/gkeys/seedhandler.py
+++ b/gkeys/gkeys/seedhandler.py
@@ -26,6 +26,7 @@ class SeedHandler(object):
         self.logger = logger
         self.fingerprint_re = re.compile('[0-9A-Fa-f]{40}')
         self.finerprint_re2 = re.compile('[0-9A-Fa-f]{4}( [0-9A-Fa-f]{4}){9}')
+        self.seeds = None
 
 
     def new(self, args, checkgkey=False):
@@ -77,6 +78,7 @@ class SeedHandler(object):
             "%s" % filepath)
         seeds = Seeds(config=self.config)
         seeds.load(filepath)
+        self.seeds = seeds
         return seeds
 
     def load_category(self, category, nicks=None):
@@ -113,6 +115,7 @@ class SeedHandler(object):
         except OSError as error:
             self.logger.debug("SeedHandler: load_category; OSError for %s" % 
catdir)
             self.logger.debug("Error was: %s" % str(error))
+        self.seeds = seeds
         return seeds
 
     def fetch_seeds(self, seeds, args, verified_dl=None):
@@ -188,3 +191,25 @@ class SeedHandler(object):
             self.logger.error('  GPGKey: Non hexadecimal digits in ' + 
'fingerprint for fingerprint: ' + fingerprint)
             is_good = False
         return is_good, fingerprint
+
+    def key_search(self, args, search_args):
+        '''Performs a search for all listed args in the seeds'''
+        results = []
+        self.logger.debug("_field_search search_args: %s" % str(search_args))
+        found = {}
+        search_args.sort()
+        for arg in search_args:
+            seeds = self.seeds.field_search(arg, getattr(args, arg), 
args.exact)
+            for seed in seeds:
+                if seed.nick in found:
+                    found[seed.nick]['args'].append(arg)
+                else:
+                    found[seed.nick] = {'args': [arg], 'seed': seed}
+        if args.all:
+            for possible in sorted(found):
+                if search_args == found[possible]['args']:
+                    results.append(found[possible]['seed'])
+        else:
+            for nick in sorted(found):
+                results.append(found[nick]['seed'])
+        return results

Reply via email to