Commit f53e95761d1dcfddafcc36788f48f17efcc2c5e6

Authored by Tássia Camões Araújo
1 parent 994c1225
Exists in master and in 1 other branch add_vagrant

Created Config class to handle configuration options. (close #6)

Showing 2 changed files with 182 additions and 28 deletions   Show diff stats
src/app_recommender.py
@@ -19,6 +19,8 @@ @@ -19,6 +19,8 @@
19 19
20 import os 20 import os
21 import sys 21 import sys
  22 +
  23 +from config import *
22 from data import * 24 from data import *
23 from evaluation import * 25 from evaluation import *
24 from similarity_measure import * 26 from similarity_measure import *
@@ -27,49 +29,70 @@ from strategy import * @@ -27,49 +29,70 @@ from strategy import *
27 from user import * 29 from user import *
28 30
29 # Setup configuration 31 # Setup configuration
30 -DB_PATH = "/var/lib/debtags/package-tags"  
31 -INDEX_PATH = os.path.expanduser("~/.app-recommender/debtags_index") 32 +#DB_PATH = "/var/lib/debtags/package-tags"
  33 +#INDEX_PATH = os.path.expanduser("~/.app-recommender/debtags_index")
  34 +#
  35 +#XAPIANDBPATH = os.environ.get("AXI_DB_PATH", "/var/lib/apt-xapian-index")
  36 +#XAPIANDB = XAPIANDBPATH + "/index"
  37 +#XAPIANDBVALUES = XAPIANDBPATH + "/values"
32 38
33 -XAPIANDBPATH = os.environ.get("AXI_DB_PATH", "/var/lib/apt-xapian-index")  
34 -XAPIANDB = XAPIANDBPATH + "/index"  
35 -XAPIANDBVALUES = XAPIANDBPATH + "/values" 39 +def set_up_logger(cfg):
  40 + log_format = '%(asctime)s AppRecommender %(levelname)s: %(message)s'
  41 + log_level = logging.INFO
  42 + if cfg.debug is 1:
  43 + log_level = logging.DEBUG
  44 + logging.basicConfig(level=log_level,format=log_format,filename=cfg.output)
  45 + console = logging.StreamHandler(sys.stdout)
  46 + console.setLevel(log_level)
  47 + formatter = logging.Formatter('%(levelname)s: %(message)s')
  48 + console.setFormatter(formatter)
  49 + logging.getLogger('').addHandler(console)
36 50
37 -if __name__ == '__main__': 51 +def set_up_recommender(cfg):
  52 +# reindex = 0
  53 +# axi = 0
  54 +# if len(sys.argv) == 2:
  55 +# if sys.argv[1] == "axi":
  56 +# axi = 1
  57 +# else:
  58 +# DB_PATH = sys.argv[1]
  59 +# reindex = 1
  60 +# elif len(sys.argv) > 2:
  61 +# print >> sys.stderr, ("Usage: %s [PATH_TO_DEBTAGS_DATABASE]" %
  62 +# sys.argv[0])
  63 +# sys.exit(1)
38 64
39 reindex = 0 65 reindex = 0
40 - axi = 0  
41 - if len(sys.argv) == 2:  
42 - if sys.argv[1] == "axi":  
43 - axi = 1  
44 - else:  
45 - DB_PATH = sys.argv[1]  
46 - reindex = 1  
47 - elif len(sys.argv) > 2:  
48 - print >> sys.stderr, ("Usage: %s [PATH_TO_DEBTAGS_DATABASE]" %  
49 - sys.argv[0])  
50 - sys.exit(1)  
51 66
52 - if axi:  
53 - axi_db = xapian.Database(XAPIANDB) 67 + if cfg.strategy == "cta":
  68 + axi_db = xapian.Database(cfg.axi)
54 app_rec = Recommender(axi_db) 69 app_rec = Recommender(axi_db)
55 app_rec.set_strategy(AxiContentBasedStrategy()) 70 app_rec.set_strategy(AxiContentBasedStrategy())
56 - else:  
57 - debtags_db = DebtagsDB(DB_PATH) 71 +
  72 + elif cfg.strategy == "ct":
  73 + debtags_db = DebtagsDB(cfg.tags_db)
58 if not debtags_db.load(): 74 if not debtags_db.load():
59 print >> sys.stderr,("Could not load DebtagsDB from %s." % DB_PATH) 75 print >> sys.stderr,("Could not load DebtagsDB from %s." % DB_PATH)
60 sys.exit(1) 76 sys.exit(1)
61 - debtags_index = DebtagsIndex(  
62 - os.path.expanduser("~/.app-recommender/debtags_index")) 77 + debtags_index = DebtagsIndex(os.path.expanduser(cfg.tags_index))
63 debtags_index.load(debtags_db,reindex) 78 debtags_index.load(debtags_db,reindex)
64 app_rec = Recommender(debtags_index) 79 app_rec = Recommender(debtags_index)
65 app_rec.set_strategy(ContentBasedStrategy()) 80 app_rec.set_strategy(ContentBasedStrategy())
  81 + return app_rec
66 82
67 - user = LocalSystem()  
68 - result = app_rec.get_recommendation(user)  
69 - result.print_result()  
70 - 83 +def cross_validation(recommender):
71 metrics = [] 84 metrics = []
72 metrics.append(Precision()) 85 metrics.append(Precision())
73 metrics.append(Recall()) 86 metrics.append(Recall())
74 - validation = CrossValidation(0.1,10,app_rec,metrics) 87 + validation = CrossValidation(0.1,10,recommender,metrics)
75 validation.run(user) 88 validation.run(user)
  89 +
  90 +if __name__ == '__main__':
  91 + cfg = Config()
  92 + cfg.load_options()
  93 + set_up_logger(cfg)
  94 + rec = set_up_recommender(cfg)
  95 + user = LocalSystem()
  96 + result = rec.get_recommendation(user)
  97 + result.print_result()
  98 + cross_validation(rec)
src/config.py 0 → 100644
@@ -0,0 +1,131 @@ @@ -0,0 +1,131 @@
  1 +#!/usr/bin/python
  2 +
  3 +# AppRecommender - A GNU/Linux application recommender
  4 +#
  5 +# Copyright (C) 2010 Tassia Camoes <tassia@gmail.com>
  6 +#
  7 +# This program is free software: you can redistribute it and/or modify
  8 +# it under the terms of the GNU General Public License as published by
  9 +# the Free Software Foundation, either version 3 of the License, or
  10 +# (at your option) any later version.
  11 +#
  12 +# This program is distributed in the hope that it will be useful,
  13 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 +# GNU General Public License for more details.
  16 +#
  17 +# You should have received a copy of the GNU General Public License
  18 +# along with this program. If not, see <http://www.gnu.org/licenses/>.
  19 +
  20 +import getopt
  21 +import sys
  22 +import os
  23 +import logging
  24 +
  25 +from ConfigParser import *
  26 +
  27 +class Config():
  28 + """
  29 + Class to handle configuration options.
  30 + """
  31 + def __init__(self):
  32 + """
  33 + Set default configuration options.
  34 + """
  35 + self.debug = 0
  36 + self.output = "/dev/null"
  37 + self.config = None
  38 + self.tags_db = "/var/lib/debtags/package-tags"
  39 + self.tags_index = "~/.app-recommender/debtags_index"
  40 + self.axi = "/var/lib/apt-xapian-index/index"
  41 + self.axi_values = "/var/lib/apt-xapian-index/values"
  42 + self.strategy = "ct" # defaults to the cheapest one
  43 +
  44 + def usage(self):
  45 + """
  46 + Print usage help.
  47 + """
  48 + print " [ general ]"
  49 + print " -h, --help Print this help"
  50 + print " -d, --debug Set debug to true. Default is false."
  51 + print " -o, --output=PATH Path to file to save output."
  52 + print " -c, --config=PATH Path to configuration file."
  53 + print ""
  54 + print " [ recommender ]"
  55 + print " -t, --tagsdb=PATH Path to debtags database."
  56 + print " -i, --tagsindex=PATH Path to debtags dedicated index."
  57 + print " -a, --axi=PATH Path to Apt-xapian-index."
  58 + print " -s, --strategy=OPTION Recommendation strategy."
  59 + print ""
  60 + print " [ strategy options ] "
  61 + print " ct = content-based using tags "
  62 + print " cta = content-based using tags via apt-xapian-index"
  63 + print " cp = content-based using package descriptions "
  64 + print " col = collaborative "
  65 + print " colct = collaborative through tags content "
  66 + print " colcp = collaborative through package descriptions content "
  67 +
  68 + def read_option(self, section, option):
  69 + """
  70 + Read option from configuration file if it is defined there or return
  71 + default value.
  72 + """
  73 + var = "self.%s" % option
  74 + if self.config.has_option(section, option):
  75 + return self.config.get(section, option)
  76 + else:
  77 + return eval(var)
  78 +
  79 + def load_options(self):
  80 + """
  81 + Load options from configuration file and command line arguments.
  82 + """
  83 + try:
  84 + self.config = ConfigParser()
  85 + self.config.read(['/etc/apprecommender/recommender.conf',
  86 + os.path.expanduser('~/apprecommender.rc')])
  87 + except (MissingSectionHeaderError), err:
  88 + logging.error("Error in config file syntax: %s", str(err))
  89 + os.abort()
  90 +
  91 + self.debug = self.read_option('general', 'debug')
  92 + self.output_filename = self.read_option('general', 'output')
  93 + self.config = self.read_option('general', 'config')
  94 +
  95 + self.tags_db = self.read_option('recommender', 'tags_db')
  96 + self.tags_index = self.read_option('recommender', 'tags_index')
  97 + self.axi = self.read_option('recommender', 'axi')
  98 +
  99 + short_options = "hdo:c:t:i:a:s:"
  100 + long_options = ["help", "debug", "output=", "config=",
  101 + "tagsdb=", "tagsindex=", "axi=", "strategy="]
  102 + try:
  103 + opts, args = getopt.getopt(sys.argv[1:], short_options,
  104 + long_options)
  105 + except getopt.GetoptError, err:
  106 + logging.error("Error parsing args: %s", str(err))
  107 + print "Syntax error"
  108 + self.usage()
  109 + sys.exit()
  110 +
  111 + for o, p in opts:
  112 + if o in ("-h", "--help"):
  113 + self.usage()
  114 + sys.exit()
  115 + elif o in ("-d", "--debug"):
  116 + self.debug = 1
  117 + elif o in ("-o", "--output"):
  118 + self.output = p
  119 + elif o in ("-c", "--config"):
  120 + self.config = p
  121 + elif o in ("-t", "--tagsdb"):
  122 + self.tagsdb = p
  123 + elif o in ("-i", "--tagsindex"):
  124 + self.tagsindex = p
  125 + elif o in ("-a", "--axi"):
  126 + self.axi = p + "/index"
  127 + self.axi_values = p + "/values"
  128 + elif o in ("-s", "--strategy"):
  129 + self.strategy = p
  130 + else:
  131 + assert False, "unhandled option"