Changeset 200

Show
Ignore:
Timestamp:
08/24/08 10:05:11 (3 months ago)
Author:
rgrp
Message:

[shakespeare/misc][m]: fix up config registration, make associated changes to cli.py and move all tests to shakespeare/tests.

  • config setup:
    • conf() in init was confusing, out of date, and was magically defaulting to 'development.ini'
    • added new register_config and refactor conf to just look the config up
  • cli.py: refactored to take account of this adding new --config option to shakespeare-admin
  • tests: move all tests into shakespeare/tests so that config is properly set up for them
Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/shakespeare.egg-info/paste_deploy_config.ini_tmpl

    Revision 169 Revision 200
    1# 1# 
    2# shakespeare - Pylons configuration 2# shakespeare - Pylons configuration 
    3# 3# 
    4# The %(here)s variable will be replaced with the parent directory of this file 4# The %(here)s variable will be replaced with the parent directory of this file 
    5# 5# 
    6[DEFAULT] 6[DEFAULT] 
    7debug = true 7debug = true 
    8email_to = you@yourdomain.com 8email_to = you@yourdomain.com 
    9smtp_server = localhost 9smtp_server = localhost 
    10error_email_from = paste@localhost 10error_email_from = paste@localhost 
    11 11 
    12 12 
    13# Cache directory where cached copies of downloaded materials can be stored 13# Cache directory where cached copies of downloaded materials can be stored 
    14#  14#  
    15# This directory needs to be semi-permanent so do *not* put under a location 15# This directory needs to be semi-permanent so do *not* put under a location 
    16# such as /tmp.  16# such as /tmp.  
    17#  17#  
    18# At present should be different from the app's cache_dir 18# At present should be different from the app's cache_dir 
    19cachedir = cache 19cachedir = cache 
    20 20 
    21# Directory for Xapian search index 21# Directory for Xapian search index 
    22search_index_dir = searchindex 22search_index_dir = searchindex 
    23 23 
    24 24 
    25[server:main] 25[server:main] 
    26use = egg:Paste#http 26use = egg:Paste#http 
    27host = 0.0.0.0 27host = 0.0.0.0 
    28port = 5000 28port = 5000 
    29 29 
    30[app:main] 30[app:main] 
    31use = egg:shakespeare 31use = egg:shakespeare 
    32full_stack = true 32full_stack = true 
    33cache_dir = %(here)s/data 33cache_dir = %(here)s/data 
    34beaker.session.key = shakespeare 34beaker.session.key = shakespeare 
    35beaker.session.secret = ${app_instance_secret} 35beaker.session.secret = ${app_instance_secret} 
    36app_instance_uuid = ${app_instance_uuid} 36app_instance_uuid = ${app_instance_uuid} 
    37 37 
    38# If you'd like to fine-tune the individual locations of the cache data dirs 38# If you'd like to fine-tune the individual locations of the cache data dirs 
    39# for the Cache data, or the Session saves, un-comment the desired settings 39# for the Cache data, or the Session saves, un-comment the desired settings 
    40# here: 40# here: 
    41#beaker.cache.data_dir = %(here)s/data/cache 41#beaker.cache.data_dir = %(here)s/data/cache 
    42#beaker.session.data_dir = %(here)s/data/sessions 42#beaker.session.data_dir = %(here)s/data/sessions 
    43 43 
    44# WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* 44# WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* 
    45# Debug mode will enable the interactive debugging tool, allowing ANYONE to 45# Debug mode will enable the interactive debugging tool, allowing ANYONE to 
    46# execute malicious code after an exception is raised. 46# execute malicious code after an exception is raised. 
    47set debug = false 47set debug = false 
    48 48 
    49# using sqlite in memory leads to thread issues when using db ...  49 # We use sqlalchemy to connect and work with databases. 
    50# sqlobject.dburi = sqlite:///:memory:  50 # This default config using sqlite. 
    51sqlobject.dburi = postgres://<username>:<password>@localhost/<your-dbname>  51 sqlalchemy.url = sqlite:///%(here)s/shkspr.db 
       52 # This is for postgres (obviously change the values to those for your system) 
       53 # sqlalchemy.url = postgres://<username>:<password>@localhost/<your-dbname> 
    52 54 
    53# Logging configuration 55# Logging configuration 
    54[loggers] 56[loggers] 
    55keys = root 57keys = root 
    56 58 
    57[handlers] 59[handlers] 
    58keys = console 60keys = console 
    59 61 
    60[formatters] 62[formatters] 
    61keys = generic 63keys = generic 
    62 64 
    63[logger_root] 65[logger_root] 
    64level = INFO 66level = INFO 
    65handlers = console 67handlers = console 
    66 68 
    67[handler_console] 69[handler_console] 
    68class = StreamHandler 70class = StreamHandler 
    69args = (sys.stderr,) 71args = (sys.stderr,) 
    70level = NOTSET 72level = NOTSET 
    71formatter = generic 73formatter = generic 
    72 74 
    73[formatter_generic] 75[formatter_generic] 
    74format = %(asctime)s %(levelname)-5.5s [%(name)s] %(message)s 76format = %(asctime)s %(levelname)-5.5s [%(name)s] %(message)s 
    75 77 
    76   
    77[misc]   
    78# directory where we can store all local copies of texts   
    79cachedir = ./cache   
    80   
    81[db]   
    82# sqlobject database uri. see sqlobject documentation for details   
    83# uri = postgres://user:pass@host/dbname   
    84uri = sqlite:/:memory:   
    85   
    86[web]   
    87# directory where the templates used by web front end are kept   
    88template_dir = ./src/shakespeare/template   
    89   
    90[annotater]   
    91# url at which marginalia files (css/js etc) should be mounted   
    92marginalia_prefix = /marginalia   
  • trunk/shakespeare/__init__.py

    Revision 185 Revision 200
    1''' 1''' 
    2Introduction 2Introduction 
    3************ 3************ 
    4 4 
    5The Open Shakespeare package provides a full open set of shakespeare's works 5The Open Shakespeare package provides a full open set of shakespeare's works 
    6(often in multiple versions) along with ancillary material, a variety of tools 6(often in multiple versions) along with ancillary material, a variety of tools 
    7and a python API. 7and a python API. 
    8 8 
    9Specifically in addition to the works themselves (often in multiple versions) 9Specifically in addition to the works themselves (often in multiple versions) 
    10there is an introduction, a chronology, explanatory notes, a concordance and 10there is an introduction, a chronology, explanatory notes, a concordance and 
    11search facilities. 11search facilities. 
    12 12 
    13All material is open source/open knowledge so that anyone can use, redistribute 13All material is open source/open knowledge so that anyone can use, redistribute 
    14and reuse these materials freely. For exact details of the license under which 14and reuse these materials freely. For exact details of the license under which 
    15this package is made available please see COPYING.txt. 15this package is made available please see COPYING.txt. 
    16 16 
    17Open Shakespeare has been developed under the aegis of the Open Knowledge 17Open Shakespeare has been developed under the aegis of the Open Knowledge 
    18Foundation (http://www.okfn.org/). 18Foundation (http://www.okfn.org/). 
    19 19 
    20Contact the Project 20Contact the Project 
    21******************* 21******************* 
    22 22 
    23Please mail info@okfn.org or join the okfn-discuss mailing list: 23Please mail info@okfn.org or join the okfn-discuss mailing list: 
    24 24 
    25  http://lists.okfn.org/listinfo/okfn-discuss 25  http://lists.okfn.org/listinfo/okfn-discuss 
    26 26 
    27 27 
    28Installation and Setup 28Installation and Setup 
    29********************** 29********************** 
    30 30 
    311. Install the code 311. Install the code 
    32=================== 32=================== 
    33 33 
    341.1: (EITHER) Install using setup.py (preferred) 341.1: (EITHER) Install using setup.py (preferred) 
    35------------------------------------------------ 35------------------------------------------------ 
    36 36 
    37Install ``shakespeare`` using easy_install:: 37Install ``shakespeare`` using easy_install:: 
    38 38 
    39    easy_install shakespeare 39    easy_install shakespeare 
    40 40 
    41NB: If you don't have easy_install you can get from here: 41NB: If you don't have easy_install you can get from here: 
    42 42 
    43<http://peak.telecommunity.com/DevCenter/EasyInstall#installation-instructions> 43<http://peak.telecommunity.com/DevCenter/EasyInstall#installation-instructions> 
    44 44 
    45 45 
    461.2 (OR) Get the code straight from subversion 461.2 (OR) Get the code straight from subversion 
    47------------------------------------------------ 47------------------------------------------------ 
    48 48 
    491. Check out the subversion trunk:: 491. Check out the subversion trunk:: 
    50 50 
    51    svn co https://knowledgeforge.net/shakespeare/svn/trunk 51    svn co https://knowledgeforge.net/shakespeare/svn/trunk 
    52 52 
    532. Do:: 532. Do:: 
    54 54 
    55    sudo python setup.py develop 55    sudo python setup.py develop 
    56 56 
    57 57 
    58Getting Started 58Getting Started 
    59*************** 59*************** 
    60 60 
    61As a user: 61As a user: 
    62========== 62========== 
    63 63 
    641. Basic setup 641. Basic setup 
    65-------------- 65-------------- 
    66 66 
    67To access most of the main features of Open Shakespeare you need a database. 67To access most of the main features of Open Shakespeare you need a database. 
    68For this an other bits and bobs of configuration you will need a configuration 68For this an other bits and bobs of configuration you will need a configuration 
    69file. 69file. 
    70 70 
    71You can make a config file as follows:: 71You can make a config file as follows:: 
    72 72 
    73    paster make-config shakespeare {your-config.ini} 73    paster make-config shakespeare {your-config.ini} 
    74 74 
    75Tweak the config file as appropriate and then setup the application:: 75Tweak the config file as appropriate and then setup the application:: 
    76 76 
    77    paster setup-app config.ini 77    paster setup-app config.ini 
    78  78  
    79[TODO: this should be part of setup-app] 79[TODO: this should be part of setup-app] 
    80 80 
    81Run:: 81Run:: 
    82 82 
    83    $ shakespeare-admin db create   
    84    $ shakespeare-admin db init 83    $ shakespeare-admin db init 
    85 84 
    862. Extras 852. Extras 
    87--------- 86--------- 
    88 87 
    891. Search index. [TODO] 881. Search index. [TODO] 
    90 89 
    912. You can start a web server to provide a easy-to-use web interface to the 902. You can start a web server to provide a easy-to-use web interface to the 
    92shakespeare material and facilities by doing:: 91shakespeare material and facilities by doing:: 
    93 92 
    94    $ paster serve {your-config.ini} 93    $ paster serve {your-config.ini} 
    95 94 
    96NB: {your-config.ini} should be replaced with the name of the config file you 95NB: {your-config.ini} should be replaced with the name of the config file you 
    97created earlier. 96created earlier. 
    98 97 
    99 98 
    100As a developer: 99As a developer: 
    101=============== 100=============== 
    102 101 
    1030. Setup 1020. Setup 
    104-------- 103-------- 
    105 104 
    106Follow the basic steps above put with an ini file named: development.ini 105Follow the basic steps above put with an ini file named: development.ini 
    107 106 
    108NB: you'll probably want to change log levels to debug. 107NB: you'll probably want to change log levels to debug. 
    109 108 
    1101. Check out the administrative commands 1091. Check out the administrative commands 
    111---------------------------------------- 110---------------------------------------- 
    112 111 
    113    $ bin/shakespeare-admin help. 112    $ bin/shakespeare-admin help. 
    114 113 
    1152. Run the tests using either py.test of nosetests:: 1142. Run the tests using either py.test of nosetests:: 
    116---------------------------------------------------- 115---------------------------------------------------- 
    117 116 
    118    $ nosetests shakespeare 117    $ nosetests shakespeare 
    119''' 118''' 
    120__version__ = '0.6a' 119__version__ = '0.6a' 
    121__application_name__ = 'shakespeare' 120__application_name__ = 'shakespeare' 
    122 121 
    123def conf(): 122def register_config(config_path): 
    124    import os 123    import os 
    125    defaultPath = os.path.abspath('./development.ini') 124    # TODO: remove? 2008-08-24 not mentioned in docs any more 
    126    envVarName = __application_name__.upper() + 'CONF' 125    # envVarName = __application_name__.upper() + 'CONF' 
    127    confPath = os.environ.get(envVarName, defaultPath) 126    # config_path = os.environ.get(envVarName, '') 
    128    if not os.path.exists(confPath): 127    config_path = os.path.abspath(config_path) 
    129        raise ValueError('No Configuration file exists at: %s' % confPath)   
    130   
    131    # register the config   
    132    import paste.deploy 128    import paste.deploy 
      129    pasteconf = paste.deploy.appconfig('config:' + config_path) 
    133    import shakespeare.config.environment 130    import shakespeare.config.environment 
    134    pasteconf = paste.deploy.appconfig('config:' + confPath)   
    135   
    136    shakespeare.config.environment.load_environment(pasteconf.global_conf, 131    shakespeare.config.environment.load_environment(pasteconf.global_conf, 
    137        pasteconf.local_conf) 132        pasteconf.local_conf) 
      133 
      134 
      135# TODO: rename to get_config() 
      136def conf(): 
    138    from pylons import config 137    from pylons import config 
    139    conf = config 138    conf = config 
    140   
    141    # import ConfigParser   
    142    # conf = ConfigParser.SafeConfigParser()   
    143    # conf.read(confPath)   
    144   
    145    return conf 139    return conf 
    146      140      
  • trunk/shakespeare/cli.py

    Revision 194 Revision 200
    1#!/usr/bin/env python 1#!/usr/bin/env python 
    2 2 
    3import cmd 3import cmd 
    4import os 4import os 
    5import StringIO 5import StringIO 
    6 6 
    7class ShakespeareAdmin(cmd.Cmd): 7class ShakespeareAdmin(cmd.Cmd): 
    8    """ 8    """ 
    9    TODO: self.verbose option and associated self._print 9    TODO: self.verbose option and associated self._print 
    10    """ 10    """ 
    11 11 
    12    def __init__(self, verbose=False): 12    def __init__(self, config=None, verbose=False): 
    13        # cmd.Cmd is not a new style class 13        # cmd.Cmd is not a new style class 
    14        cmd.Cmd.__init__(self) 14        cmd.Cmd.__init__(self) 
      15        self.config = config 
    15        self.verbose = verbose 16        self.verbose = verbose 
    16 17 
    17    def _print(self, msg, force=False): 18    def _print(self, msg, force=False): 
    18        if self.verbose or force: 19        if self.verbose or force: 
    19            print msg 20            print msg 
    20 21 
    21    prompt = 'The Bard > ' 22    def _register_config(self): 
    22 23        import sys 
    23    def run_interactive(self, line=None): 24        if not self.config: 
    24        """Run an interactive session. 25            msg = 'No configuration file has been specified. See -h help for details' 
    25        """ 26            print msg 
    26        print 'Welcome to shakespeare-admin interactive mode\n' 27            sys.exit(1) 
    27        self.do_about() 28        import shakespeare 
    28        print 'Type:  "?" or "help" for help on commands.\n' 29        shakespeare.register_config(self.config) 
    29        while 1:   
    30            try:   
    31                self.cmdloop()   
    32                break   
    33            except KeyboardInterrupt:   
    34                raise   
    35 30 
    36    def do_help(self, line=None): 31    def do_help(self, line=None): 
    37        cmd.Cmd.do_help(self, line) 32        cmd.Cmd.do_help(self, line) 
    38 33 
    39    def do_about(self, line=None): 34    def do_about(self, line=None): 
    40        import shakespeare 35        import shakespeare 
    41        version = shakespeare.__version__ 36        version = shakespeare.__version__ 
    42        about = \ 37        about = \ 
    43'''Open Shakespeare version %s. Copyright the Open Knowledge Foundation. 38'''Open Shakespeare version %s. Copyright the Open Knowledge Foundation. 
    44Open Shakespeare is open-knowledge and open-source. See COPYING for details. 39Open Shakespeare is open-knowledge and open-source. See COPYING for details. 
    45 40 
    46For more information about the package run `info`. 41For more information about the package run `info`. 
    47''' % version 42''' % version 
    48        print about 43        print about 
    49 44 
    50    def do_quit(self, line=None): 45    def do_quit(self, line=None): 
    51        sys.exit() 46        sys.exit() 
    52 47 
    53    def do_EOF(self, *args): 48    def do_EOF(self, *args): 
    54        print '' 49        print '' 
    55        sys.exit() 50        sys.exit() 
    56 51 
    57    # ================= 52    # ================= 
    58    # Commands 53    # Commands 
    59 54 
    60    def do_db(self, line=None): 55    def do_db(self, line=None): 
    61        actions = [ 'create', 'clean', 'rebuild', 'init' ] 56        actions = [ 'create', 'clean', 'init' ] 
    62        if line is None or line not in actions: 57        if line is None or line not in actions: 
    63            self.help_db() 58            self.help_db() 
    64            return 1 59            return 1 
      60        self._register_config() 
    65        import shakespeare.model 61        import shakespeare.model 
      62        import shakespeare 
    66        if line == 'init': 63        if line == 'init': 
    67            import pkg_resources 64            import pkg_resources 
    68            pkg = 'shksprdata' 65            pkg = 'shksprdata' 
    69            meta = pkg_resources.resource_stream(pkg, 'texts/metadata.txt') 66            meta = pkg_resources.resource_stream(pkg, 'texts/metadata.txt') 
    70            shakespeare.model.Material.load_from_metadata(meta) 67            shakespeare.model.Material.load_from_metadata(meta) 
    71        else:  68         elif line == 'clean': 
       69             config = shakespeare.conf() 
       70             shakespeare.model.metadata.drop_all(bind=config['pylons.g'].sa_engine) 
       71         elif line == 'create': 
    72            print 'To create db use paster: paster setup-app {config-file}' 72            print 'To create db use paster: paster setup-app {config-file}' 
      73        else: 
      74            print self.help_db() 
    73 75 
    74    def help_db(self, line=None): 76    def help_db(self, line=None): 
    75        usage = \ 77        usage = \ 
    76'''db { create | init } 78'''db { create | init } 
    77''' 79''' 
    78        print usage 80        print usage 
    79     81     
    80    def do_gutenberg(self, line=None): 82    def do_gutenberg(self, line=None): 
      83        self._register_config() 
    81        import shakespeare.gutenberg 84        import shakespeare.gutenberg 
    82        helper = shakespeare.gutenberg.Helper(verbose=True) 85        helper = shakespeare.gutenberg.Helper(verbose=True) 
    83        if not line: 86        if not line: 
    84            helper.execute() 87            helper.execute() 
    85        elif line == 'print_index': 88        elif line == 'print_index': 
    86            import pprint 89            import pprint 
    87            pprint.pprint(helper.get_index()) 90            pprint.pprint(helper.get_index()) 
    88        else: 91        else: 
    89            msg = 'Unknown argument %s' % line 92            msg = 'Unknown argument %s' % line 
    90            raise Exception(msg) 93            raise Exception(msg) 
    91 94 
    92    def help_gutenberg(self, line=None): 95    def help_gutenberg(self, line=None): 
    93        usage = \ 96        usage = \ 
    94""" 97""" 
    95Download and process all Project Gutenberg shakespeare texts""" 98Download and process all Project Gutenberg shakespeare texts""" 
    96        print usage  99        print usage  
    97 100 
    98    def do_moby(self, line=None): 101    def do_moby(self, line=None): 
    99        import shakespeare.moby 102        import shakespeare.moby 
    100        helper = shakespeare.moby.Helper(verbose=True) 103        helper = shakespeare.moby.Helper(verbose=True) 
    101        if not line: 104        if not line: 
    102            helper.execute() 105            helper.execute() 
    103        elif line == 'print_index': 106        elif line == 'print_index': 
    104            import pprint 107            import pprint 
    105            pprint.pprint(helper.get_index()) 108            pprint.pprint(helper.get_index()) 
    106        else: 109        else: 
    107            msg = 'Unknown argument %s' % line 110            msg = 'Unknown argument %s' % line 
    108            raise Exception(msg) 111            raise Exception(msg) 
    109 112 
    110    def help_moby(self, line=None): 113    def help_moby(self, line=None): 
      114        self._register_config() 
    111        usage = \ 115        usage = \ 
    112''' 116''' 
    113Download and process all Moby/Bosak shakespeare texts''' 117Download and process all Moby/Bosak shakespeare texts''' 
    114        print usage  118        print usage  
    115 119 
    116    def _init_index(self): 120    def _init_index(self): 
      121        self._register_config() 
    117        import shakespeare.index 122        import shakespeare.index 
    118        self._index = shakespeare.index.all 123        self._index = shakespeare.index.all 
    119 124 
    120    def _filter_index(self, line): 125    def _filter_index(self, line): 
    121        """Filter items in index return only those whose id (url) is in line 126        """Filter items in index return only those whose id (url) is in line 
    122        If line is empty or None return all items 127        If line is empty or None return all items 
    123        """ 128        """ 
    124        if line: 129        if line: 
    125            textsToAdd = [] 130            textsToAdd = [] 
    126            textNames = line.split() 131            textNames = line.split() 
    127            for item in self._index: 132            for item in self._index: 
    128                if item.name in textNames: 133                if item.name in textNames: 
    129                    textsToAdd.append(item) 134                    textsToAdd.append(item) 
    130            return textsToAdd 135            return textsToAdd 
    131        else: 136        else: 
    132            self._init_index() 137            self._init_index() 
    133            return self._index 138            return self._index 
    134     139     
    135    def do_index(self, line): 140    def do_index(self, line): 
    136        self._init_index() 141        self._init_index() 
    137        header = \ 142        header = \ 
    138'''          +-------------------+ 143'''          +-------------------+ 
    139          | Index of Material | 144          | Index of Material | 
    140          +-------------------+ 145          +-------------------+ 
    141 146 
    142''' 147''' 
    143        print header 148        print header 
    144        for row in self._index: 149        for row in self._index: 
    145            print row.name.ljust(35), row.title 150            print row.name.ljust(35), row.title 
    146 151 
    147    def help_index(self, line=None): 152    def help_index(self, line=None): 
    148        usage = \ 153        usage = \ 
    149'''Print index of Shakespeare texts to stdout''' 154'''Print index of Shakespeare texts to stdout''' 
    150        print usage 155        print usage 
    151 156 
    152    def do_runserver(self, line=None): 157    def do_runserver(self, line=None): 
    153        self.help_runserver() 158        self.help_runserver() 
    154 159 
    155    def help_runserver(self, line=None): 160    def help_runserver(self, line=None): 
    156        usage = \ 161        usage = \ 
    157'''This command has been DEPRECATED. 162'''This command has been DEPRECATED. 
    158 163 
    159Please use `paster serve` to run a server now, e.g.:: 164Please use `paster serve` to run a server now, e.g.:: 
    160 165 
    161    paster serve <my-config.ini> 166    paster serve <my-config.ini> 
    162''' 167''' 
    163        print usage 168        print usage 
    164     169     
    165    def do_info(self, line=None): 170    def do_info(self, line=None): 
    166        import shakespeare 171        import shakespeare 
    167        info = shakespeare.__doc__ 172        info = shakespeare.__doc__ 
    168        print 173        print 
    169        print '       ## Open Shakespeare ##' 174        print '       ## Open Shakespeare ##' 
    170        print info 175        print info 
    171     176     
    172    def help_info(self, line=None): 177    def help_info(self, line=None): 
    173        print 'Information about this package.' 178        print 'Information about this package.' 
    174 179 
    175    def _parse_line(self, line): 180    def _parse_line(self, line): 
    176        line = line.strip() 181        line = line.strip() 
    177        args = line.split() 182        args = line.split() 
    178        action = '' 183        action = '' 
    179        remainder = '' 184        remainder = '' 
    180        if len(args) > 0: 185        if len(args) > 0: 
    181            action = args[0] 186            action = args[0] 
    182        if len(args) > 1: 187        if len(args) > 1: 
    183            remainder = ' '.join(args[1:]) 188            remainder = ' '.join(args[1:]) 
    184        return (action, remainder) 189        return (action, remainder) 
    185 190 
    186    def do_search(self, line): 191    def do_search(self, line): 
      192        self._register_config() 
    187        import shakespeare.search 193        import shakespeare.search 
    188        index = shakespeare.search.SearchIndex.default_index() 194        index = shakespeare.search.SearchIndex.default_index() 
    189 195 
    190        action, extra = self._parse_line(line) 196        action, extra = self._parse_line(line) 
    191        if action == 'addpath': 197        if action == 'addpath': 
    192            index.add_from_path(extra) 198            index.add_from_path(extra) 
    193        elif action == 'query': 199        elif action == 'query': 
    194            results = index.search(extra) 200            results = index.search(extra) 
    195            print index.print_matches(results) 201            print index.print_matches(results) 
    196        elif action == 'addtext': 202        elif action == 'addtext': 
    197            import shakespeare.model as model 203            import shakespeare.model as model 
    198            text = model.Material.byName(extra) 204            text = model.Material.byName(extra) 
    199            fileobj = text.get_text() 205            fileobj = text.get_text() 
    200            index.add_item(fileobj) 206            index.add_item(fileobj) 
    201        elif action == 'init': 207        elif action == 'init': 
    202            self._init_index() 208            self._init_index() 
    203            for text in self._index: 209            for text in self._index: 
    204                # exclude folios as many odd spellings 210                # exclude folios as many odd spellings 
    205                if text.name.endswith('_f'): 211                if text.name.endswith('_f'): 
    206                    continue 212                    continue 
    207                self._print('Adding: %s' % text.name) 213                self._print('Adding: %s' % text.name) 
    208                fileobj = text.get_text() 214                fileobj = text.get_text() 
    209                index.add_item(fileobj) 215                index.add_item(fileobj) 
    210        else: 216        else: 
    211            print 'Unrecognized action: %s' % action 217            print 'Unrecognized action: %s' % action 
    212            self.help_search() 218            self.help_search() 
    213            return 1 219            return 1 
    214 220 
    215    def help_search(self, line=None): 221    def help_search(self, line=None): 
    216        info = \ 222        info = \ 
    217''' 223''' 
    218search addpath {path} 224search addpath {path} 
    219    - Add contents of {path} (file itself or all text files in directory if 225    - Add contents of {path} (file itself or all text files in directory if 
    220      directory) to the search index. 226      directory) to the search index. 
    221       227       
    222search addtext {name} 228search addtext {name} 
    223    - Add db text named {name} to search index. 229    - Add db text named {name} to search index. 
    224 230 
    225search query {query} 231search query {query} 
    226    - Query search index with {query}. 232    - Query search index with {query}. 
    227 233 
    228search init 234search init 
    229    - Add all texts in DB to index. 235    - Add all texts in DB to index. 
    230''' 236''' 
    231        print info 237        print info 
    232 238 
    233    def do_stats(self, line): 239    def do_stats(self, line): 
      240        self._register_config() 
    234        action, extra = self._parse_line(line) 241        action, extra = self._parse_line(line) 
    235 242 
    236        import shakespeare.stats 243        import shakespeare.stats 
    237        stats = shakespeare.stats.Stats() 244        stats = shakespeare.stats.Stats() 
    238        if action == 'init': 245        if action == 'init': 
    239            self._init_index() 246            self._init_index() 
    240            for text in self._index: 247            for text in self._index: 
    241                # exclude folios as many odd spellings 248                # exclude folios as many odd spellings 
    242                if text.name.endswith('_f'): 249                if text.name.endswith('_f'): 
    243                    continue 250                    continue 
    244                self._print('Adding: %s' % text.name) 251                self._print('Adding: %s' % text.name) 
    245                stats.statsify(text, text.get_text()) 252                stats.statsify(text, text.get_text()) 
    246        elif action == 'addtext': 253        elif action == 'addtext': 
    247            import shakespeare.model as model 254            import shakespeare.model as model 
    248            text = model.Material.byName(extra) 255            text = model.Material.byName(extra) 
    249            stats.statsify(text, text.get_text()) 256            stats.statsify(text, text.get_text()) 
    250        elif action == 'show': 257        elif action == 'show': 
    251            textstats = stats.text_stats(extra) 258            textstats = stats.text_stats(extra) 
    252            for s in textstats: 259            for s in textstats: 
    253                print s.word, s.freq 260                print s.word, s.freq 
    254        else: 261        else: 
    255            print 'Unrecognized action: %s' % action 262            print 'Unrecognized action: %s' % action 
    256            self.help_stats() 263            self.help_stats() 
    257            return 1 264            return 1 
    258 265 
    259    def help_stats(self, line=None): 266    def help_stats(self, line=None): 
    260        info = \ 267        info = \ 
    261''' 268''' 
    262stats addtext {name} 269stats addtext {name} 
    263    - Add db text named {name} to stats index. 270    - Add db text named {name} to stats index. 
    264 271 
    265stats show {name} 272stats show {name} 
    266    - Query stats index with {query}. 273    - Query stats index with {query}. 
    267 274 
    268stats init 275stats init 
    269    - Prepare statistics for all texts in DB. 276    - Prepare statistics for all texts in DB. 
    270''' 277''' 
    271        print info 278        print info 
    272 279 
    273 280 
    274def main(): 281def main(): 
    275    import optparse 282    import optparse 
    276    usage = \ 283    usage = \ 
    277'''%prog [options] <command> 284'''%prog [options] <command> 
    278 285 
    279Run about or help for details.'''  286 For list of the commands available run: 
       287  
       288     $ shakespeare-admin help 
       289  
       290 For more general information run the about or info commands.''' 
    280    parser = optparse.OptionParser(usage) 291    parser = optparse.OptionParser(usage) 
    281    parser.add_option('-v', '--verbose', dest='verbose', help='Be verbose', 292    parser.add_option('-v', '--verbose', dest='verbose', help='Be verbose', 
    282            action='store_true', default=False)  293            action='store_true', default=False)  
      294    parser.add_option('-c', '--config', dest='config', 
      295        help='Path to config file', default=None) 
    283    options, args = parser.parse_args() 296    options, args = parser.parse_args() 
    284     297     
    285    if len(args) == 0: 298    if len(args) == 0: 
    286        parser.print_help() 299        parser.print_help() 
    287        return 1 300        return 1 
    288    else: 301    else: 
    289        cmd = ShakespeareAdmin(verbose=options.verbose302        cmd = ShakespeareAdmin(verbose=options.verbose, config=options.config
    290        args = ' '.join(args) 303        args = ' '.join(args) 
    291        args = args.replace('-','_') 304        args = args.replace('-','_') 
    292        cmd.onecmd(args) 305        cmd.onecmd(args) 
    293 306