Commits

Anonymous committed c20f721

Added pluggable commands system to paster inspired by django management commands
- overrall project fixes
- added version prompt to interactive setup
- upgraded create_db script with some fancy options
- version bump
- fixed deprecation for paster templates

  • Participants
  • Parent commits 050a562

Comments (0)

Files changed (11)

 * Add a production.ini and test.ini.
 * Add a database demo such as a wiki.
 * Allow keyword args to supplement settings in ``add_engine()``.
-* Add an appendix explaining the different ways to initialize the database
-  and why we chose an "-m" script over a bin script, Paster plugin, or
-  websetup.
 * Add an article explaining the exact differences in the application 
   template compared to the standard Pyramid templates, and why it was
   made that way.
+1.1.0 (2011-09-21)
+------------------
+
+-Added pluggable commands system inspired by django management commands
+
+
 1.0.1 (2011-07-18)
 ------------------
 - Fix bug in ``URLGenerator.app``: it was returning the wrong value and was

akhet/paster_templates/__init__.py

 from paste.deploy.converters import asbool
 from paste.script.templates import var
 from paste.util.template import paste_script_template_renderer
-from pyramid.paster import PyramidTemplate
+from pyramid.scaffolds  import PyramidTemplate
 
 class AkhetProjectTemplate(PyramidTemplate):
     _template_dir = "akhet"
             default=False),
         var("crypto", "Include pycryptopp for encrypted sessions? (y/n)",
             default=False),
+        var("version","Specify application version",
+            default="0.0.1")
         ]
 
     def pre(self, command, output_dir, vars): # pragma: no cover
         vars["crypto"] = asbool(vars["crypto"])
         vars['random_1'] = uuid.uuid4().hex
         vars['random_2'] = uuid.uuid4().hex
+        vars['version']  = vars["version"]
+

akhet/paster_templates/akhet/+package+/commands/__init__.py_tmpl

+import os
+
+def ask_ok(prompt, retries=4, complaint='Yes or no, please!'):
+    while True:
+        ok = raw_input(prompt)
+        if ok in ('y', 'ye', 'yes'):
+            return True
+        if ok in ('n', 'no', 'nop', 'nope'):
+            return False
+        retries = retries - 1
+        if retries < 0:
+            raise IOError
+        print complaint
+
+
+def _scan_commands(package):
+    """
+    Given a path to a package directory, returns a list of all the command
+    names that are available.
+    
+    Returns an empty list if no commands are defined.
+    
+    code borrowed from django...
+    
+    """
+    module_dir = os.path.dirname(os.path.abspath(__file__))
+    try:
+        return [f[:-3] for f in os.listdir(module_dir)
+                if not f.startswith('_') and f.endswith('.py')]
+    except OSError:
+        return []
+
+
+def extend_entry_points(package):
+    head = """
+    [paste.paster_command]    
+    """
+    CMD_TMPL = "%(cmd_name)s = %(module_path)s:%(callable_cls)s"
+
+    for cmd in _scan_commands(package):
+        module_path = '.'.join([package, 'commands', cmd])
+        head += CMD_TMPL % dict(cmd_name=cmd, 
+                                module_path=module_path, 
+                                callable_cls='Command')
+
+    return head 

akhet/paster_templates/akhet/+package+/commands/create_db.py_tmpl

+import sys
+import logging.config
+
+import transaction
+import sqlalchemy
+import sqlahelper
+
+from paste.script.command import Command
+from pyramid.paster import PCommand
+
+import {{package}}.models as models
+from {{package}}.commands import ask_ok
+
+
+class Command(PCommand):
+    """
+    Create's the application tables based on Models.
+    
+    It's safe to run this multiple time during development since it always
+    checks if table exists and creates only new ones.
+    
+    To modify exists table use `*` to drop all  or list of tables you wish
+    to drop first and create from scratch 
+    
+    options
+        * - drops all tables before making new ones
+        table1 table2  - list of tables to drop before 
+    
+    Example::
+        paster create_db production.ini table1 table2
+    """
+    summary = "Create the application's database."
+    
+    min_args = 1 # defines mix arguments that function takes
+    stdout = sys.stdout
+    
+    usage = "CONFIG_FILE"
+    
+    group_name = "{{project}}"
+    takes_config_file = -1
+    parser = Command.standard_parser(verbose=True)
+
+    def command(self):
+        """
+        put you'r action here !
+        """
+        config_uri = self.args[0]
+        # setup logging if you want to
+        logging.config.fileConfig(config_uri)
+        # logger instance
+        log = logging.getLogger(__name__)
+        
+        #pyramid env
+        env = self.bootstrap[0](config_uri)
+        #registry
+        registry = env['registry']    
+        settings = registry.settings
+        
+        
+        # create all engines and connections, if you're 
+        # using more than one engine
+        # also define it here and add into sqlahelper
+        try:
+            engine = sqlalchemy.engine_from_config(settings,
+                                                   prefix="sqlalchemy.")
+            sqlahelper.add_engine(engine)
+            
+        except KeyError:
+            self.stdout.write('missing db uri in config\n')
+            sys.exit()
+        
+        all_tables = models.Base.metadata.sorted_tables
+        tables = list()
+        drop_all =drop_some= False
+        if len(self.args) > 1:
+            drop_all = self.args[1] == '*'
+            if not drop_all:
+                # just mark tables
+                all_tables = self.args[1:]
+                drop_some = True
+                        
+        if drop_all or drop_some:
+            upgrade = ask_ok('You are about to perform db creation, and '
+                             'have choosen to drop %s '
+                             'Continue ? [y/n]' % \
+                             ('all tables' if drop_all else 
+                              'some tables %s' % all_tables))
+            if not upgrade:
+                sys.exit('Nothing done')
+    
+            models.Base.metadata.drop_all(tables=all_tables)
+                
+        # Check for any existing tables, and add only tables that are not present
+        # in current database skipping those already created
+        for table in all_tables:
+            log.debug("checking if table '%s' exists", table.name)
+            if not table.exists():
+                tables.append(table)
+    
+        # Create the tables
+        models.Base.metadata.create_all(tables=tables)
+        sess = models.Session()
+    
+        # Record 1
+        #p = models.MyModel(id=1, name=u"Foo Bar")
+        #sess.add(p)
+    
+        transaction.commit()    

akhet/paster_templates/akhet/+package+/scripts/__init__.py

-
-def ask_ok(prompt, retries=4, complaint='Yes or no, please!'):
-    while True:
-        ok = raw_input(prompt)
-        if ok in ('y', 'ye', 'yes'):
-            return True
-        if ok in ('n', 'no', 'nop', 'nope'):
-            return False
-        retries = retries - 1
-        if retries < 0:
-            raise IOError
-        print complaint

akhet/paster_templates/akhet/+package+/scripts/create_db.py_tmpl

-"""Create the application's database.
-
-Run this once after installing the application::
-
-    python -m {{package}}.scripts.create_db development.ini
-    python -m {{package}}.scripts.create_db development.ini drop_all    
-"""
-import logging.config
-import sys
-
-from pyramid.paster import get_app
-import transaction
-
-import sqlalchemy
-import sqlahelper
-import {{package}}.models as models
-
-from crm.scripts import ask_ok
-
-def main():
-    if len(sys.argv) < 2:
-        sys.exit("Usage: python -m {{package}}.scripts.create_db INI_FILE [drop_all]")
-    ini_file = sys.argv[1]
-    dropfirst = False
-    if len(sys.argv) == 3:
-        dropfirst = sys.argv[2] == 'drop_all'    
-    logging.config.fileConfig(ini_file)
-    log = logging.getLogger(__name__)
-    app = get_app(ini_file, "myapp")
-    settings = app.registry.settings
-    
-    # create all engines and connections, if you're using more than one engine
-    # also define it here and add into sqlahelper
-    
-    engine = sqlalchemy.engine_from_config(settings,
-                                           prefix="sqlalchemy.url.")
-
-    sqlahelper.add_engine(engine)
-    
-    tables = list()
-    if dropfirst:
-        upgrade = ask_ok('You are about to perform db creation, and '
-                         'have choosen to drop all tables'
-                         'Continue ? [y/n]')
-        if not upgrade:
-            sys.exit('Nothing done')
-
-        models.BaseCrm.metadata.drop_all()
-            
-    # Check for any existing tables, and add only tables that are not present
-    # in current database skipping those already created
-    for table in models.Base.metadata.sorted_tables:
-        log.debug("checking if table '%s' exists", table.name)
-        if not table.exists():
-            tables.append(table)
-
-    # Create the tables
-    models.Base.metadata.create_all(tables=tables)
-    sess = models.Session()
-
-    # Record 1
-    #p = models.MyModel(id=1, name=u"Foo Bar")
-    #sess.add(p)
-
-    transaction.commit()
-
-    
-
-if __name__ == "__main__":  
-    main()

akhet/paster_templates/akhet/CHANGES.txt_tmpl

-0.0
+{{version}}
 ---
 
 -  Initial version

akhet/paster_templates/akhet/setup.py_tmpl

 
 from setuptools import setup, find_packages
 
+from {{package}}.commands import extend_entry_points
+
 here = os.path.abspath(os.path.dirname(__file__))
 README = open(os.path.join(here, "README.txt")).read()
 CHANGES = open(os.path.join(here, "CHANGES.txt")).read()
     main = paste.script.appinstall:Installer
 """
 
+entry_points += extend_entry_points('{{package}}')
+
 setup(name="{{project}}",
-      version="0.0",
+      version="{{version}}",
       description="{{project}}",
       long_description=README + "\n\n" +  CHANGES,
       classifiers=[
 Akhet
 =====
-:Version: 1.0.2, released 2011-07-20
+:Version: 1.1.0, released 2011-XX-XX
 :PyPI: http://pypi.python.org/pypi/Akhet
 :Docs: http://docs.pylonsproject.org/projects/akhet/dev/
 :Source: https://bitbucket.org/sluggo/akhet (Mercurial)
 Version 1.0.2 fixes a bug in ``URLGenerator.app`` (aka ``url.app`` in
 templates).
 
-**Existing Akhet applications:** Akhet 1.1 will be released soon, and will
-depend on Pyramid 1.1. If you don't want to upgrade, set your dependencies in your
+**Existing Akhet applications:** Akhet 1.2 will be released soon, and will
+depend on Pyramid 1.2. If you don't want to upgrade, set your dependencies in your
 application's *setup.py*: "Akhet>= 1.0, <= 1.0.99" and "pyramid>=1.0a10, <=
 1.0.99".
 
 """
 
 setup(name="Akhet",
-      version="1.0.2",
+      version="1.1.0",
       description="Pyramid application templates inspired by Pylons 1.",
-      long_description=README,
-      #long_description=README + "\n\n" +  CHANGES,
+      long_description=README + "\n\n" +  CHANGES,
       classifiers=[
         "Intended Audience :: Developers",
         "Framework :: Pylons",