--- a/goa/__init__.py Mon Mar 23 13:07:26 2009 +0100
+++ b/goa/__init__.py Mon Mar 23 17:38:30 2009 +0100
@@ -1,69 +1,12 @@
"""cubicweb on google appengine
:organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
__docformat__ = "restructuredtext en"
-from datetime import datetime, time, date
-from mx.DateTime import DateTime, Date, Time
-
-def mx2datetime(mxobj, yamstype):
- """converts a mx date object (DateTime, Date or Time) into a
- regular python datetime object
- """
- #if yamstype == 'Datetime':
- # don't use date, db model doesn't actually support it, only datetime
- return datetime(mxobj.year, mxobj.month, mxobj.day,
- mxobj.hour, mxobj.minute, int(mxobj.second))
-# elif yamstype == 'Date':
-# return date(mxobj.year, mxobj.month, mxobj.day)
-# # XXX don't support time either, what should we do here ?
-# return time(mxobj.hour, mxobj.minute, int(mxobj.second))
-
-def datetime2mx(datetimeobj, yamstype=None):
- """converts a mx date object (DateTime, Date or Time) into a
- regular python datetime object
- """
- if yamstype is None:
- yamstype = guess_yamstype_for_date(datetimeobj)
- assert yamstype is not None
- if yamstype == 'Datetime':
- # don't use date, db model doesn't actually support it, only datetime
- return DateTime(datetimeobj.year, datetimeobj.month, datetimeobj.day,
- datetimeobj.hour, datetimeobj.minute, int(datetimeobj.second))
- elif yamstype == 'Date':
- return Date(datetimeobj.year, datetimeobj.month, datetimeobj.day)
- # XXX don't support time either, what should we do here ?
- return Time(datetimeobj.hour, datetimeobj.minute, int(datetimeobj.second))
-
-
-def guess_yamstype_for_date(datetimeobj):
- """guesses yams correct type according to `datetimeobj`'s type"""
- if isinstance(datetimeobj, datetime):
- return 'Datetime'
- elif isinstance(datetimeobj, date):
- return 'Date'
- elif isinstance(datetimeobj, time):
- return 'Time'
- return None
-
-
-def use_mx_for_dates(func):
- """decorator to convert func's return value into mx objects
- instead of datetime objects
- """
- def wrapper(*args, **kwargs):
- value = func(*args, **kwargs)
- yamstype = guess_yamstype_for_date(value)
- if yamstype is None:
- return value
- return datetime2mx(value, yamstype)
- return wrapper
-
-
try:
# WARNING: do not import the google's db module here since it will take
# precedence over our own db submodule
--- a/goa/appobjects/components.py Mon Mar 23 13:07:26 2009 +0100
+++ b/goa/appobjects/components.py Mon Mar 23 17:38:30 2009 +0100
@@ -6,8 +6,6 @@
"""
__docformat__ = "restructuredtext en"
-from os.path import join
-
from logilab.mtconverter import html_escape
from logilab.common.decorators import cached
@@ -17,11 +15,8 @@
from cubicweb.common.view import StartupView, EntityView
from cubicweb.web import Redirect
from cubicweb.web.views import vid_from_rset
-from cubicweb.goa.db import rset_from_objs
-from google.appengine.api import datastore, mail
-
-from main import APPLROOT
+from google.appengine.api import mail
class SearchForAssociationView(EntityView):
--- a/goa/appobjects/sessions.py Mon Mar 23 13:07:26 2009 +0100
+++ b/goa/appobjects/sessions.py Mon Mar 23 17:38:30 2009 +0100
@@ -15,7 +15,7 @@
from logilab.common.decorators import cached, clear_cache
-from cubicweb import UnknownEid, BadConnectionId
+from cubicweb import BadConnectionId
from cubicweb.dbapi import Connection, ConnectionProperties, repo_connect
from cubicweb.selectors import none_rset, match_user_groups
from cubicweb.server.session import Session
--- a/goa/db.py Mon Mar 23 13:07:26 2009 +0100
+++ b/goa/db.py Mon Mar 23 17:38:30 2009 +0100
@@ -30,7 +30,6 @@
"""
__docformat__ = "restructuredtext en"
-from datetime import datetime
from copy import deepcopy
from logilab.common.decorators import cached, iclassmethod
@@ -39,7 +38,7 @@
from cubicweb.rset import ResultSet
from cubicweb.entity import metaentity
from cubicweb.server.utils import crypt_password
-from cubicweb.goa import use_mx_for_dates, mx2datetime, MODE
+from cubicweb.goa import MODE
from cubicweb.goa.dbinit import init_relations
from google.appengine.api.datastore import Get, Put, Key, Entity, Query
@@ -174,15 +173,11 @@
return '<ModelEntity %s %s %s at %s>' % (
self.e_schema, self.eid, self.keys(), id(self))
- __getattribute__ = use_mx_for_dates(entities.AnyEntity.__getattribute__)
-
def _cubicweb_to_datastore(self, attr, value):
attr = attr[2:] # remove 's_' / 'o_' prefix
if attr in self._attributes:
tschema = self.e_schema.destination(attr)
- if tschema in ('Datetime', 'Date', 'Time'):
- value = mx2datetime(value, tschema)
- elif tschema == 'String':
+ if tschema == 'String':
if len(value) > 500:
value = Text(value)
elif tschema == 'Password':
@@ -288,7 +283,6 @@
return 'eid', False
return mainattr, needcheck
- @use_mx_for_dates
def get_value(self, name):
try:
value = self[name]
--- a/goa/rqlinterpreter.py Mon Mar 23 13:07:26 2009 +0100
+++ b/goa/rqlinterpreter.py Mon Mar 23 17:38:30 2009 +0100
@@ -14,7 +14,6 @@
from cubicweb import Binary
from cubicweb.rset import ResultSet
-from cubicweb.goa import mx2datetime, datetime2mx
from cubicweb.server import SQL_CONNECT_HOOKS
from google.appengine.api.datastore import Key, Get, Query, Entity
@@ -250,9 +249,6 @@
def __init__(self, rel, kwargs):
RelationRestriction.__init__(self, rel, None)
value = self.rhs.eval(kwargs)
- if isinstance(value, (DateTimeType, DateTimeDeltaType)):
- #yamstype = self.schema.rschema(self.rtype).objects()[0]
- value = mx2datetime(value, 'Datetime')
self.value = value
if self.operator == 'ILIKE':
if value.startswith('%'):
@@ -294,11 +290,7 @@
RelationRestriction.__init__(self, rel, None)
values = []
for c in self.rel.children[1].iget_nodes(nodes.Constant):
- value = c.eval(kwargs)
- if isinstance(value, (DateTimeType, DateTimeDeltaType)):
- #yamstype = self.schema.rschema(self.rtype).objects()[0]
- value = mx2datetime(value, 'Datetime')
- values.append(value)
+ values.append(c.eval(kwargs))
self.value = values
@property
@@ -322,9 +314,7 @@
def append_result(res, descr, i, j, value, etype):
if value is not None:
- if etype in ('Date', 'Datetime', 'Time'):
- value = datetime2mx(value, etype)
- elif isinstance(value, Text):
+ if isinstance(value, Text):
value = unicode(value)
elif isinstance(value, Blob):
value = Binary(str(value))
--- a/goa/tools/i18n.py Mon Mar 23 13:07:26 2009 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,282 +0,0 @@
-#!/usr/bin/env python
-"""This script is just a thin wrapper around ``msgcat`` and ``msgfmt``
-to generate ``.mo`` files
-"""
-
-import sys
-import os
-import os.path as osp
-import shutil
-from tempfile import mktemp
-from glob import glob
-from mx.DateTime import now
-
-from logilab.common.fileutils import ensure_fs_mode
-from logilab.common.shellutils import find, rm
-
-from yams import BASE_TYPES
-
-from cubicweb import CW_SOFTWARE_ROOT
-# from cubicweb.__pkginfo__ import version as cubicwebversion
-cubicwebversion = '2.48.2'
-
-DEFAULT_POT_HEAD = r'''# LAX application po file
-
-msgid ""
-msgstr ""
-"Project-Id-Version: cubicweb %s\n"
-"PO-Revision-Date: 2008-03-28 18:14+0100\n"
-"Last-Translator: Logilab Team <contact@logilab.fr>\n"
-"Language-Team: fr <contact@logilab.fr>\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: cubicweb-devtools\n"
-"Plural-Forms: nplurals=2; plural=(n > 1);\n"
-
-''' % cubicwebversion
-
-
-STDLIB_ERTYPES = BASE_TYPES | set( ('EUser', 'EProperty', 'Card', 'identity', 'for_user') )
-
-def create_dir(directory):
- """create a directory if it doesn't exist yet"""
- try:
- os.makedirs(directory)
- print 'created directory', directory
- except OSError, ex:
- import errno
- if ex.errno != errno.EEXIST:
- raise
- print 'directory %s already exists' % directory
-
-def execute(cmd):
- """display the command, execute it and raise an Exception if returned
- status != 0
- """
- print cmd.replace(os.getcwd() + os.sep, '')
- status = os.system(cmd)
- if status != 0:
- raise Exception()
-
-def add_msg(w, msgid):
- """write an empty pot msgid definition"""
- if isinstance(msgid, unicode):
- msgid = msgid.encode('utf-8')
- msgid = msgid.replace('"', r'\"').splitlines()
- if len(msgid) > 1:
- w('msgid ""\n')
- for line in msgid:
- w('"%s"' % line.replace('"', r'\"'))
- else:
- w('msgid "%s"\n' % msgid[0])
- w('msgstr ""\n\n')
-
-
-def generate_schema_pot(w, vreg, tmpldir):
- """generate a pot file with schema specific i18n messages
-
- notice that relation definitions description and static vocabulary
- should be marked using '_' and extracted using xgettext
- """
- cube = tmpldir and osp.split(tmpldir)[-1]
- config = vreg.config
- vreg.register_objects(config.vregistry_path())
- w(DEFAULT_POT_HEAD)
- _generate_schema_pot(w, vreg, vreg.schema, libschema=None, # no libschema for now
- cube=cube)
-
-
-def _generate_schema_pot(w, vreg, schema, libschema=None, cube=None):
- w('# schema pot file, generated on %s\n' % now().strftime('%Y-%m-%d %H:%M:%S'))
- w('# \n')
- w('# singular and plural forms for each entity type\n')
- w('\n')
- # XXX hard-coded list of stdlib's entity schemas
- libschema = libschema or STDLIB_ERTYPES
- entities = [e for e in schema.entities() if not e in libschema]
- done = set()
- for eschema in sorted(entities):
- etype = eschema.type
- add_msg(w, etype)
- add_msg(w, '%s_plural' % etype)
- if not eschema.is_final():
- add_msg(w, 'This %s' % etype)
- add_msg(w, 'New %s' % etype)
- add_msg(w, 'add a %s' % etype)
- add_msg(w, 'remove this %s' % etype)
- if eschema.description and not eschema.description in done:
- done.add(eschema.description)
- add_msg(w, eschema.description)
- w('# subject and object forms for each relation type\n')
- w('# (no object form for final relation types)\n')
- w('\n')
- if libschema is not None:
- relations = [r for r in schema.relations() if not r in libschema]
- else:
- relations = schema.relations()
- for rschema in sorted(set(relations)):
- rtype = rschema.type
- add_msg(w, rtype)
- if not (schema.rschema(rtype).is_final() or rschema.symetric):
- add_msg(w, '%s_object' % rtype)
- if rschema.description and rschema.description not in done:
- done.add(rschema.description)
- add_msg(w, rschema.description)
- w('# add related box generated message\n')
- w('\n')
- for eschema in schema.entities():
- if eschema.is_final():
- continue
- entity = vreg.etype_class(eschema)(None, None)
- for x, rschemas in (('subject', eschema.subject_relations()),
- ('object', eschema.object_relations())):
- for rschema in rschemas:
- if rschema.is_final():
- continue
- for teschema in rschema.targets(eschema, x):
- if defined_in_library(libschema, eschema, rschema, teschema, x):
- continue
- if entity.relation_mode(rschema.type, teschema.type, x) == 'create':
- if x == 'subject':
- label = 'add %s %s %s %s' % (eschema, rschema, teschema, x)
- label2 = "creating %s (%s %%(linkto)s %s %s)" % (teschema, eschema, rschema, teschema)
- else:
- label = 'add %s %s %s %s' % (teschema, rschema, eschema, x)
- label2 = "creating %s (%s %s %s %%(linkto)s)" % (teschema, teschema, rschema, eschema)
- add_msg(w, label)
- add_msg(w, label2)
- cube = (cube or 'cubicweb') + '.'
- done = set()
- for reg, objdict in vreg.items():
- for objects in objdict.values():
- for obj in objects:
- objid = '%s_%s' % (reg, obj.id)
- if objid in done:
- continue
- if obj.__module__.startswith(cube) and obj.property_defs:
- add_msg(w, '%s_description' % objid)
- add_msg(w, objid)
- done.add(objid)
-
-def defined_in_library(libschema, etype, rtype, tetype, x):
- """return true if the given relation definition exists in cubicweb's library"""
- if libschema is None:
- return False
- if x == 'subject':
- subjtype, objtype = etype, tetype
- else:
- subjtype, objtype = tetype, etype
- try:
- return libschema.rschema(rtype).has_rdef(subjtype, objtype)
- except (KeyError, AttributeError):
- # if libschema is a simple list of entity types (lax specific)
- # or if the relation could not be found
- return False
-
-
-
-# XXX check if this is a pure duplication of the original
-# `cubicweb.common.i18n` function
-def compile_i18n_catalogs(sourcedirs, destdir, langs):
- """generate .mo files for a set of languages into the `destdir` i18n directory
- """
- print 'compiling %s catalogs...' % destdir
- errors = []
- for lang in langs:
- langdir = osp.join(destdir, lang, 'LC_MESSAGES')
- if not osp.exists(langdir):
- create_dir(langdir)
- pofiles = [osp.join(path, '%s.po' % lang) for path in sourcedirs]
- pofiles = [pof for pof in pofiles if osp.exists(pof)]
- mergedpo = osp.join(destdir, '%s_merged.po' % lang)
- try:
- # merge application messages' catalog with the stdlib's one
- execute('msgcat --use-first --sort-output --strict %s > %s'
- % (' '.join(pofiles), mergedpo))
- # make sure the .mo file is writeable and compile with *msgfmt*
- applmo = osp.join(destdir, lang, 'LC_MESSAGES', 'cubicweb.mo')
- try:
- ensure_fs_mode(applmo)
- except OSError:
- pass # suppose not osp.exists
- execute('msgfmt %s -o %s' % (mergedpo, applmo))
- except Exception, ex:
- errors.append('while handling language %s: %s' % (lang, ex))
- try:
- # clean everything
- os.unlink(mergedpo)
- except Exception:
- continue
- return errors
-
-
-def update_cubes_catalog(vreg, appdirectory, langs):
- toedit = []
- tmpl = osp.basename(osp.normpath(appdirectory))
- tempdir = mktemp()
- os.mkdir(tempdir)
- print '*' * 72
- print 'updating %s cube...' % tmpl
- os.chdir(appdirectory)
- potfiles = []
- if osp.exists(osp.join('i18n', 'entities.pot')):
- potfiles = potfiles.append( osp.join('i18n', 'entities.pot') )
- print '******** extract schema messages'
- schemapot = osp.join(tempdir, 'schema.pot')
- potfiles.append(schemapot)
- # XXX
- generate_schema_pot(open(schemapot, 'w').write, vreg, appdirectory)
- print '******** extract Javascript messages'
- jsfiles = find('.', '.js')
- if jsfiles:
- tmppotfile = osp.join(tempdir, 'js.pot')
- execute('xgettext --no-location --omit-header -k_ -L java --from-code=utf-8 -o %s %s'
- % (tmppotfile, ' '.join(jsfiles)))
- # no pot file created if there are no string to translate
- if osp.exists(tmppotfile):
- potfiles.append(tmppotfile)
- print '******** create cube specific catalog'
- tmppotfile = osp.join(tempdir, 'generated.pot')
- execute('xgettext --no-location --omit-header -k_ -o %s %s'
- % (tmppotfile, ' '.join(glob('*.py'))))
- if osp.exists(tmppotfile): # doesn't exists of no translation string found
- potfiles.append(tmppotfile)
- potfile = osp.join(tempdir, 'cube.pot')
- print '******** merging .pot files'
- execute('msgcat %s > %s' % (' '.join(potfiles), potfile))
- print '******** merging main pot file with existing translations'
- os.chdir('i18n')
- for lang in langs:
- print '****', lang
- tmplpo = '%s.po' % lang
- if not osp.exists(tmplpo):
- shutil.copy(potfile, tmplpo)
- else:
- execute('msgmerge -N -s %s %s > %snew' % (tmplpo, potfile, tmplpo))
- ensure_fs_mode(tmplpo)
- shutil.move('%snew' % tmplpo, tmplpo)
- toedit.append(osp.abspath(tmplpo))
- # cleanup
- rm(tempdir)
- # instructions pour la suite
- print '*' * 72
- print 'you can now edit the following files:'
- print '* ' + '\n* '.join(toedit)
-
-
-def getlangs(i18ndir):
- return [fname[:-3] for fname in os.listdir(i18ndir)
- if fname.endswith('.po')]
-
-
-def get_i18n_directory(appdirectory):
- if not osp.isdir(appdirectory):
- print '%s is not an application directory' % appdirectory
- sys.exit(2)
- i18ndir = osp.join(appdirectory, 'i18n')
- if not osp.isdir(i18ndir):
- print '%s is not an application directory ' \
- '(i18n subdirectory missing)' % appdirectory
- sys.exit(2)
- return i18ndir
--- a/goa/tools/laxctl.py Mon Mar 23 13:07:26 2009 +0100
+++ b/goa/tools/laxctl.py Mon Mar 23 17:38:30 2009 +0100
@@ -1,7 +1,7 @@
"""provides all lax instances management commands into a single utility script
:organization: Logilab
-:copyright: 2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
__docformat__ = "restructuredtext en"
@@ -17,14 +17,9 @@
from logilab.common.clcommands import Command, register_commands, main_run
-from cubicweb import CW_SOFTWARE_ROOT
from cubicweb.common.uilib import remove_html_tags
-
APPLROOT = osp.abspath(osp.join(osp.dirname(osp.abspath(__file__)), '..'))
-# XXX import custom?
-
-from tools import i18n
def initialize_vregistry(applroot):
# apply monkey patches first
@@ -51,33 +46,6 @@
def run(self, args):
self.vreg = initialize_vregistry(APPLROOT)
self._run(args)
-
-
-class I18nUpdateCommand(LaxCommand):
- """updates i18n catalogs"""
- name = 'i18nupdate'
-
- def _run(self, args):
- assert not args, 'no argument expected'
- i18ndir = i18n.get_i18n_directory(APPLROOT)
- i18n.update_cubes_catalog(self.vreg, APPLROOT,
- langs=i18n.getlangs(i18ndir))
-
-
-class I18nCompileCommand(LaxCommand):
- """compiles i18n catalogs"""
- name = 'i18ncompile'
- min_args = max_args = 0
-
- def _run(self, args):
- assert not args, 'no argument expected'
- i18ndir = i18n.get_i18n_directory(APPLROOT)
- langs = i18n.getlangs(i18ndir)
- print 'generating .mo files for langs', ', '.join(langs)
- cubicweb_i18ndir = osp.join(APPLROOT, 'cubes', 'shared')
- paths = self.vreg.config.cubes_path() + [cubicweb_i18ndir]
- sourcedirs = [i18ndir] + [osp.join(path, 'i18n') for path in paths]
- i18n.compile_i18n_catalogs(sourcedirs, i18ndir, langs=langs)
class GenerateSchemaCommand(LaxCommand):
@@ -274,9 +242,7 @@
self.extract_message(data)
-register_commands([I18nUpdateCommand,
- I18nCompileCommand,
- GenerateSchemaCommand,
+register_commands([GenerateSchemaCommand,
PopulateDataDirCommand,
DSInitCommand,
CleanSessionsCommand,