devtools/devctl.py
changeset 4737 64143d458495
parent 4722 9c13d5db03d9
child 5184 955ee1b24756
child 5344 ed4cd1ca96d6
equal deleted inserted replaced
4622:790181bfd19c 4737:64143d458495
     6 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
     6 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
     7 :license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
     7 :license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
     8 """
     8 """
     9 __docformat__ = "restructuredtext en"
     9 __docformat__ = "restructuredtext en"
    10 
    10 
       
    11 # *ctl module should limit the number of import to be imported as quickly as
       
    12 # possible (for cubicweb-ctl reactivity, necessary for instance for usable bash
       
    13 # completion). So import locally in command helpers.
    11 import sys
    14 import sys
    12 from datetime import datetime
    15 from datetime import datetime
    13 from os import mkdir, chdir, getcwd
    16 from os import mkdir, chdir
    14 from os.path import join, exists, abspath, basename, normpath, split, isdir
    17 from os.path import join, exists, abspath, basename, normpath, split, isdir
    15 from copy import deepcopy
       
    16 from warnings import warn
    18 from warnings import warn
    17 from tempfile import NamedTemporaryFile
       
    18 from subprocess import Popen
       
    19 
    19 
    20 from logilab.common import STD_BLACKLIST
    20 from logilab.common import STD_BLACKLIST
    21 from logilab.common.modutils import get_module_files
       
    22 from logilab.common.textutils import splitstrip
       
    23 from logilab.common.shellutils import ASK
       
    24 from logilab.common.clcommands import register_commands, pop_arg
    21 from logilab.common.clcommands import register_commands, pop_arg
    25 
       
    26 from yams import schema2dot
       
    27 
    22 
    28 from cubicweb.__pkginfo__ import version as cubicwebversion
    23 from cubicweb.__pkginfo__ import version as cubicwebversion
    29 from cubicweb import CW_SOFTWARE_ROOT as BASEDIR, BadCommandUsage
    24 from cubicweb import CW_SOFTWARE_ROOT as BASEDIR, BadCommandUsage
    30 from cubicweb.toolsutils import Command, copy_skeleton, underline_title
    25 from cubicweb.toolsutils import Command, copy_skeleton, underline_title
    31 from cubicweb.schema import CONSTRAINTS
       
    32 from cubicweb.web.webconfig import WebConfiguration
    26 from cubicweb.web.webconfig import WebConfiguration
    33 from cubicweb.server.serverconfig import ServerConfiguration
    27 from cubicweb.server.serverconfig import ServerConfiguration
    34 from yams import BASE_TYPES
       
    35 from cubicweb.schema import (META_RTYPES, SCHEMA_TYPES, SYSTEM_RTYPES,
       
    36                              WORKFLOW_TYPES, INTERNAL_TYPES)
       
    37 
    28 
    38 
    29 
    39 class DevConfiguration(ServerConfiguration, WebConfiguration):
    30 class DevConfiguration(ServerConfiguration, WebConfiguration):
    40     """dummy config to get full library schema and appobjects for
    31     """dummy config to get full library schema and appobjects for
    41     a cube or for cubicweb (without a home)
    32     a cube or for cubicweb (without a home)
   108     schema = config.load_schema(remove_unused_rtypes=False)
    99     schema = config.load_schema(remove_unused_rtypes=False)
   109     vreg = CubicWebVRegistry(config)
   100     vreg = CubicWebVRegistry(config)
   110     # set_schema triggers objects registrations
   101     # set_schema triggers objects registrations
   111     vreg.set_schema(schema)
   102     vreg.set_schema(schema)
   112     w(DEFAULT_POT_HEAD)
   103     w(DEFAULT_POT_HEAD)
   113     _generate_schema_pot(w, vreg, schema, libconfig=libconfig, cube=cube)
   104     _generate_schema_pot(w, vreg, schema, libconfig=libconfig)
   114 
   105 
   115 
   106 
   116 def _generate_schema_pot(w, vreg, schema, libconfig=None, cube=None):
   107 def _generate_schema_pot(w, vreg, schema, libconfig=None):
       
   108     from copy import deepcopy
   117     from cubicweb.i18n import add_msg
   109     from cubicweb.i18n import add_msg
   118     from cubicweb.web import uicfg
   110     from cubicweb.web import uicfg
   119     from cubicweb.schema import META_RTYPES, SYSTEM_RTYPES
   111     from cubicweb.schema import META_RTYPES, SYSTEM_RTYPES, CONSTRAINTS
   120     no_context_rtypes = META_RTYPES | SYSTEM_RTYPES
   112     no_context_rtypes = META_RTYPES | SYSTEM_RTYPES
   121     w('# schema pot file, generated on %s\n' % datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
   113     w('# schema pot file, generated on %s\n' % datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
   122     w('# \n')
   114     w('# \n')
   123     w('# singular and plural forms for each entity type\n')
   115     w('# singular and plural forms for each entity type\n')
   124     w('\n')
   116     w('\n')
   219     for objid in _iter_vreg_objids(vreg, vregdone):
   211     for objid in _iter_vreg_objids(vreg, vregdone):
   220         add_msg(w, '%s_description' % objid)
   212         add_msg(w, '%s_description' % objid)
   221         add_msg(w, objid)
   213         add_msg(w, objid)
   222 
   214 
   223 
   215 
   224 def _iter_vreg_objids(vreg, done, prefix=None):
   216 def _iter_vreg_objids(vreg, done):
   225     for reg, objdict in vreg.items():
   217     for reg, objdict in vreg.items():
   226         for objects in objdict.values():
   218         for objects in objdict.values():
   227             for obj in objects:
   219             for obj in objects:
   228                 objid = '%s_%s' % (reg, obj.__regid__)
   220                 objid = '%s_%s' % (reg, obj.__regid__)
   229                 if objid in done:
   221                 if objid in done:
   236                     yield objid
   228                     yield objid
   237                     done.add(objid)
   229                     done.add(objid)
   238                     break
   230                     break
   239 
   231 
   240 
   232 
   241 def defined_in_library(etype, rtype, tetype, role):
       
   242     """return true if the given relation definition exists in cubicweb's library
       
   243     """
       
   244     if libschema is None:
       
   245         return False
       
   246     if role == 'subject':
       
   247         subjtype, objtype = etype, tetype
       
   248     else:
       
   249         subjtype, objtype = tetype, etype
       
   250     try:
       
   251         return libschema.rschema(rtype).has_rdef(subjtype, objtype)
       
   252     except KeyError:
       
   253         return False
       
   254 
       
   255 
       
   256 LANGS = ('en', 'fr', 'es')
   233 LANGS = ('en', 'fr', 'es')
   257 I18NDIR = join(BASEDIR, 'i18n')
   234 I18NDIR = join(BASEDIR, 'i18n')
   258 DEFAULT_POT_HEAD = r'''msgid ""
   235 DEFAULT_POT_HEAD = r'''msgid ""
   259 msgstr ""
   236 msgstr ""
   260 "Project-Id-Version: cubicweb %s\n"
   237 "Project-Id-Version: cubicweb %s\n"
   285         import shutil
   262         import shutil
   286         import tempfile
   263         import tempfile
   287         import yams
   264         import yams
   288         from logilab.common.fileutils import ensure_fs_mode
   265         from logilab.common.fileutils import ensure_fs_mode
   289         from logilab.common.shellutils import globfind, find, rm
   266         from logilab.common.shellutils import globfind, find, rm
       
   267         from logilab.common.modutils import get_module_files
   290         from cubicweb.i18n import extract_from_tal, execute
   268         from cubicweb.i18n import extract_from_tal, execute
   291         tempdir = tempfile.mkdtemp()
   269         tempdir = tempfile.mkdtemp()
   292         potfiles = [join(I18NDIR, 'static-messages.pot')]
   270         potfiles = [join(I18NDIR, 'static-messages.pot')]
   293         print '-> extract schema messages.'
   271         print '-> extract schema messages.'
   294         schemapot = join(tempdir, 'schema.pot')
   272         schemapot = join(tempdir, 'schema.pot')
   499          ),
   477          ),
   500         )
   478         )
   501 
   479 
   502 
   480 
   503     def run(self, args):
   481     def run(self, args):
       
   482         from logilab.common.shellutils import ASK
   504         if len(args) != 1:
   483         if len(args) != 1:
   505             raise BadCommandUsage("exactly one argument (cube name) is expected")
   484             raise BadCommandUsage("exactly one argument (cube name) is expected")
   506         cubename, = args
   485         cubename, = args
   507         verbose = self.get('verbose')
   486         verbose = self.get('verbose')
   508         cubesdir = self.get('directory')
   487         cubesdir = self.get('directory')
   556                    'author-web-site': self['author-web-site'],
   535                    'author-web-site': self['author-web-site'],
   557                    }
   536                    }
   558         copy_skeleton(skeldir, cubedir, context)
   537         copy_skeleton(skeldir, cubedir, context)
   559 
   538 
   560     def _ask_for_dependancies(self):
   539     def _ask_for_dependancies(self):
       
   540         from logilab.common.shellutils import ASK
       
   541         from logilab.common.textutils import splitstrip
   561         includes = []
   542         includes = []
   562         for stdtype in ServerConfiguration.available_cubes():
   543         for stdtype in ServerConfiguration.available_cubes():
   563             answer = ASK.ask("Depends on cube %s? " % stdtype,
   544             answer = ASK.ask("Depends on cube %s? " % stdtype,
   564                              ('N','y','skip','type'), 'N')
   545                              ('N','y','skip','type'), 'N')
   565             if answer == 'y':
   546             if answer == 'y':
   573 
   554 
   574 
   555 
   575 class ExamineLogCommand(Command):
   556 class ExamineLogCommand(Command):
   576     """Examine a rql log file.
   557     """Examine a rql log file.
   577 
   558 
   578     usage: python exlog.py < rql.log
       
   579 
       
   580     will print out the following table
   559     will print out the following table
   581 
   560 
   582       total execution time || number of occurences || rql query
   561       total execution time || number of occurences || rql query
   583 
   562 
   584     sorted by descending total execution time
   563     sorted by descending total execution time
   585 
   564 
   586     chances are the lines at the top are the ones that will bring
   565     chances are the lines at the top are the ones that will bring the higher
   587     the higher benefit after optimisation. Start there.
   566     benefit after optimisation. Start there.
   588     """
   567     """
       
   568     arguments = '< rql.log'
   589     name = 'exlog'
   569     name = 'exlog'
   590     options = (
   570     options = (
   591         )
   571         )
   592 
   572 
   593     def run(self, args):
   573     def run(self, args):
   660                  'help':'coma separated list of entity types to include in view'}
   640                  'help':'coma separated list of entity types to include in view'}
   661                ),
   641                ),
   662               ]
   642               ]
   663 
   643 
   664     def run(self, args):
   644     def run(self, args):
       
   645         from subprocess import Popen
       
   646         from tempfile import NamedTemporaryFile
   665         from logilab.common.textutils import splitstrip
   647         from logilab.common.textutils import splitstrip
       
   648         from yams import schema2dot, BASE_TYPES
       
   649         from cubicweb.schema import (META_RTYPES, SCHEMA_TYPES, SYSTEM_RTYPES,
       
   650                                      WORKFLOW_TYPES, INTERNAL_TYPES)
   666         cubes = splitstrip(pop_arg(args, 1))
   651         cubes = splitstrip(pop_arg(args, 1))
   667         dev_conf = DevConfiguration(*cubes)
   652         dev_conf = DevConfiguration(*cubes)
   668         schema = dev_conf.load_schema()
   653         schema = dev_conf.load_schema()
   669         out, viewer = self['output-file'], self['viewer']
   654         out, viewer = self['output-file'], self['viewer']
   670         if out is None:
   655         if out is None: