예제 #1
0
파일: jbedits.py 프로젝트: cobysy/jmdictdb
def main(args, opts):
    jdb.reset_encoding(sys.stdout, 'utf-8')
    errs = []
    try:
        form, svc, dbg, cur, sid, sess, parms, cfg = jmcgi.parseform()
    except Exception as e:
        jmcgi.err_page([str(e)])

    # The filesystem path of the directory containing editdata files.
    filesdir = cfg['web']['EDITDATA_DIR']
    # The URL for the directory containing editdata files.
    httpdir = cfg['web']['EDITDATA_URL']

    fv = lambda x: (form.getfirst(x) or '').decode(Enc)
    is_editor = jmcgi.is_editor(sess)

    allfiles = sorted(os.listdir(filesdir))
    editfiles = [x for x in allfiles if re.search(r'[0-9]{5}\.dat$', x)]
    logfiles = [x for x in allfiles if re.search(r'((ok)|(bad))\.log$', x)]

    jmcgi.jinja_page('jbedits.jinja',
                     parms=parms,
                     filesdir=filesdir,
                     httpdir=httpdir,
                     editfiles=editfiles,
                     logfiles=logfiles,
                     svc=svc,
                     dbg=dbg,
                     sid=sid,
                     session=sess,
                     cfg=cfg,
                     this_page='jbedits.py')
예제 #2
0
def main (args, opts):
        jdb.reset_encoding (sys.stdout, 'utf-8')
        errs = []
        try: form, svc, dbg, cur, sid, sess, parms, cfg = jmcgi.parseform()
        except Exception as e: jmcgi.err_page ([str (e)])

          # The filesystem path of the directory containing editdata files.
        filesdir = cfg['web']['EDITDATA_DIR']
          # The URL for the directory containing editdata files.
        httpdir  = cfg['web']['EDITDATA_URL']

        fv = lambda x:(form.getfirst(x) or '').decode(Enc)
        is_editor = jmcgi.is_editor (sess)
        srcs = sorted (jdb.KW.recs('SRC'), key=lambda x: x.kw.lower())

          # Get the filename url parameter, and validate it.
        fn = fv ('fn')
        if not re.search (r'[0-9]{5}\.dat$', fn) or '/' in fn:
            err_page (["Bad 'fn' url parameter"])
        fullname = os.path.join (filesdir, fn)
          # Open the file, get the data.
        try: e, ref, comment, name, email = read_editdata (cur, fullname)
        except Exception as e:
            err_page (["Bad file data, unable to unserialize: %s" % str(e)])
        extra = {'ref':ref, 'comment':comment, 'name':name, 'email':email}
        e.NOCORPOPT = ''  # This seems to be required by template, see edform.py
        jmcgi.jinja_page ('edform.jinja', parms=parms,
                        entrs=[e], extra=extra, srcs=srcs, is_editor=is_editor,
                        svc=svc, dbg=dbg, sid=sid, session=sess, cfg=cfg,
                        this_page='jbedit.py')
예제 #3
0
def main(args, opts):
    global Svc, Sid
    jdb.reset_encoding(sys.stdout, 'utf-8')
    errs = []
    dbh = svc = None
    try:
        form, svc, dbg, dbh, sid, sess, parms, cfg = jmcgi.parseform()
    except ValueError as e:
        jmcgi.err_page([str(e)])
    # Svc and Sid are used in function url() and are global in
    # in order to avoid having to pass them through several layers
    # of function calls.
    Svc, Sid = svc, sid

    L('cgi.edsubmit').debug("started: userid=%s, sid=%s" %
                            (sess and sess.userid, sess and sess.id))
    fv = form.getfirst
    # disp values: '': User submission, 'a': Approve. 'r': Reject;
    disp = fv('disp') or ''
    if not sess and disp:
        errs.append("Only registered editors can approve or reject entries")
    if errs: jmcgi.err_page(errs)
    try:
        entrs = serialize.unserialize(fv("entr"))
    except Exception:
        jmcgi.err_page(["Bad 'entr' parameter, unable to unserialize."])

    added = []
    # Clear any possible transactions begun elsewhere (e.g. by the
    # keyword table read in jdb.dbOpen()).  Failure to do this will
    # cause the following START TRANSACTON command to fail with:
    #  InternalError: SET TRANSACTION ISOLATION LEVEL must be
    #  called before any query
    L('cgi.edsubmit.main').debug("starting transaction")
    dbh.connection.rollback()
    dbh.execute("START TRANSACTION ISOLATION LEVEL SERIALIZABLE")
    # FIXME: we unserialize the entr's xref's as they were resolved
    #  by the edconf.py page.  Should we check them again here?
    #  If target entry was deleted in meantime, attempt to add
    #  our entr to db will fail with obscure foreign key error.
    #  Alternatively an edited version of target may have been
    #  created which wont have our xref pointing to it as it should.
    for entr in entrs:
        # FIXME: submission() can raise a psycopg2
        # TransactionRollbackError if there is a serialization
        # error resulting from a concurrent update.  Detecting
        # such a condition is why run with serializable isolation
        # level.  We need to trap it and present some sensible
        # error message.
        e = submission(dbh, entr, disp, errs, jmcgi.is_editor(sess),
                       sess.userid if sess else None)
        # The value returned by submission() is a 3-tuple consisting
        # of (id, seq, src) for the added entry.
        if e: added.append(e)

    if errs:
        L('cgi.edsubmit.main').info("rolling back transaction due to errors")
        dbh.connection.rollback()
        jmcgi.err_page(errs)
    else:
        L('cgi.edsubmit.main').info("doing commit")
        dbh.connection.commit()
    jmcgi.jinja_page("submitted.jinja",
                     added=added,
                     parms=parms,
                     svc=svc,
                     dbg=dbg,
                     sid=sid,
                     session=sess,
                     cfg=cfg,
                     this_page='edsubmit.py')
    L('cgi.edsubmit.main').debug("thank you page sent, exiting normally")
예제 #4
0
def main(args, opts):
    jdb.reset_encoding(sys.stdout, 'utf-8')
    errs = []
    chklist = {}
    try:
        form, svc, dbg, cur, sid, sess, parms, cfg = jmcgi.parseform()
    except Exception as e:
        jmcgi.err_page([str(e)])

    fv = form.getfirst
    fl = form.getlist
    KW = jdb.KW

    # 'eid' will be an integer if we are editing an existing
    # entry, or undefined if this is a new entry.
    pentr = None
    eid = url_int('id', form, errs)
    if eid:
        # Get the parent entry of the edited entry.  This is what the
        # edited entry will be diff'd against for the history record.
        # It is also the entry that will be pointed to by the edited
        # entry's 'dfrm' field.
        pentr = jdb.entrList(cur, None, [eid])
        #FIXME: Need a better message with more explanation.
        if not pentr:
            errs.append("The entry you are editing has been deleted.")
        else:
            pentr = pentr[0]

    # Desired disposition: 'a':approve, 'r':reject, undef:submit.
    disp = url_str('disp', form)
    if disp != 'a' and disp != 'r' and disp != '' and disp is not None:
        errs.append("Invalid 'disp' parameter: '%s'" % disp)

    # New status is A for edit of existing or new entry, D for
    # deletion of existing entry.
    delete = fv('delete')
    makecopy = fv('makecopy')
    if delete and makecopy:
        errs.append(
            "The 'delete' and 'treat as new'"
            " checkboxes are mutually exclusive; please select only one.")
    if makecopy: eid = None
    # FIXME: we need to disallow new entries with corp.seq
    # that matches an existing A, A*, R*, D*, D? entry.
    # Do same check in submit.py.

    seq = url_int('seq', form, errs)
    src = url_int('src', form, errs)
    notes = url_str('notes', form)
    srcnote = url_str('srcnote', form)

    # These are the JEL (JMdict Edit Language) texts which
    # we will concatenate into a string that is fed to the
    # JEL parser which will create an Entr object.
    kanj = (stripws(url_str('kanj', form))).strip()
    rdng = (stripws(url_str('rdng', form))).strip()
    sens = (url_str('sens', form)).strip()
    intxt = "\f".join((kanj, rdng, sens))
    grpstxt = url_str('grp', form)

    # Get the meta-edit info which will go into the history
    # record for this change.
    comment = url_str('comment', form)
    refs = url_str('reference', form)
    name = url_str('name', form)
    email = url_str('email', form)

    if errs: jmcgi.err_page(errs)

    # Parse the entry data.  Problems will be reported
    # by messages in 'perrs'.  We do the parse even if
    # the request is to delete the entry (is this right
    # thing to do???) since on the edconf page we want
    # to display what the entry was.  The edsubmit page
    # will do the actual deletion.

    entr, errs = parse(intxt)
    # 'errs' is a list which if not empty has a single item
    # which is a 2-seq of str's: (error-type, error-message).
    if errs or not entr:
        if not entr and not errs:
            errs = ([], "Unable to create an entry from your input.")
        jmcgi.err_page([errs[0][1]], prolog=errs[0][0], cssclass="errormsg")

    entr.dfrm = eid
    entr.unap = not disp

    # To display the xrefs and reverse xrefs in html, they
    # need to be augmented with additional info about their
    # targets.  collect_refs() simply returns a list Xref
    # objects that are on the entr argument's .xref list
    # (forward xrefs) if rev not true, or the Xref objects
    # on the entr argument's ._xrer list (reverse xrefs) if
    # rev is true).  This does not remove them from the entry
    # and is done simply for convenience so we can have
    # augment_xrefs() process them all in one shot.
    # augment_xrefs add an attribute, .TARG, to each Xref
    # object whose value is an Entr object for the entry the
    # xref points to if rev is not true, or the entry the xref
    # is from, if rev is true.  These Entr objects can be used
    # to display info about the xref target or source such as
    # seq#, reading or kanji.  See jdb.augment_xrefs() for details.
    # Note that <xrefs> and <xrers> below contain references
    # to the xrefs on the entries; thus the augmentation done
    # by jdb.augment_xrefs() alters the xref objects on those
    # entries.
    if pentr:
        x = jdb.collect_xrefs([pentr])
        if x: jdb.augment_xrefs(cur, x)
        # Although we don't allow editing of an entry's reverse
        # xref, we still augment them (on the parent entry)
        # because we will display them.
        x = jdb.collect_xrefs([pentr], rev=True)
        if x: jdb.augment_xrefs(cur, x, rev=True)
    x = jdb.collect_xrefs([entr])
    if x: jdb.augment_xrefs(cur, x)

    if delete:
        # Ignore any content changes made by the submitter by
        # restoring original values to the new entry.
        entr.seq = pentr.seq
        entr.src = pentr.src
        entr.stat = KW.STAT['D'].id
        entr.notes = pentr.notes
        entr.srcnote = pentr.srcnote
        entr._kanj = getattr(pentr, '_kanj', [])
        entr._rdng = getattr(pentr, '_rdng', [])
        entr._sens = getattr(pentr, '_sens', [])
        entr._snd = getattr(pentr, '_snd', [])
        entr._grp = getattr(pentr, '_grp', [])
        entr._cinf = getattr(pentr, '_cinf', [])

    else:
        # Migrate the entr details to the new entr object
        # which to this point has only the kanj/rdng/sens
        # info provided by jbparser.
        entr.seq = seq
        entr.src = src
        entr.stat = KW.STAT['A'].id
        entr.notes = notes
        entr.srcnote = srcnote
        entr._grp = jelparse.parse_grp(grpstxt)

        # This form and the JEL parser provide no way to change
        # some entry attributes such _cinf, _snd, reverse xrefs
        # and for non-editors, _freq.  We need to copy these items
        # from the original entry to the new, edited entry to avoid
        # loosing them.  The copy can be shallow since we won't be
        # changing the copied content.
        if pentr:
            if not jmcgi.is_editor(sess):
                jdb.copy_freqs(pentr, entr)
            if hasattr(pentr, '_cinf'): entr._cinf = pentr._cinf
            copy_snd(pentr, entr)

            # Copy the reverse xrefs that are on pentr to entr,
            # removing any that are no longer valid because they
            # refer to senses , readings or kanji no longer present
            # on the edited entry.  Note that these have already
            # been augmented above.
            nuked_xrers = realign_xrers(entr, pentr)
            if nuked_xrers:
                chklist['xrers'] = format_for_warnings(nuked_xrers, pentr)

        # Add sound details so confirm page will look the same as the
        # original entry page.  Otherwise, the confirm page will display
        # only the sound clip id(s).
        #FIXME? Should the following snd augmentation stuff be outdented
        # one level so that it is done in both the delete and non-delete
        # paths?
        snds = []
        for s in getattr(entr, '_snd', []):
            snds.append(s)
        for r in getattr(entr, '_rdng', []):
            for s in getattr(r, '_snd', []):
                snds.append(s)
        if snds: jdb.augment_snds(cur, snds)

        # If any xrefs were given, resolve them to actual entries
        # here since that is the form used to store them in the
        # database.  If any are unresolvable, an approriate error
        # is saved and will reported later.

        rslv_errs = jelparse.resolv_xrefs(cur, entr)
        if rslv_errs: chklist['xrslv'] = rslv_errs

    if errs: jmcgi.err_page(errs)

    # Append a new hist record details this edit.
    if not hasattr(entr, '_hist'): entr._hist = []
    entr = jdb.add_hist(entr, pentr, sess.userid if sess else None, name,
                        email, comment, refs, entr.stat == KW.STAT['D'].id)
    if not delete:
        check_for_errors(entr, errs)
        if errs: jmcgi.err_page(errs)
        pseq = pentr.seq if pentr else None
        check_for_warnings(cur, entr, pseq, chklist)

    # The following all expect a list of entries.
    jmcgi.add_filtered_xrefs([entr], rem_unap=False)
    serialized = serialize.serialize([entr])
    jmcgi.htmlprep([entr])

    entrs = [[entr, None]]  # Package 'entr' as expected by entr.jinja.
    jmcgi.jinja_page("edconf.jinja",
                     entries=entrs,
                     serialized=serialized,
                     chklist=chklist,
                     disp=disp,
                     parms=parms,
                     svc=svc,
                     dbg=dbg,
                     sid=sid,
                     session=sess,
                     cfg=cfg,
                     this_page='edconf.py')
예제 #5
0
def main(args, opts):
    jdb.reset_encoding(sys.stdout, 'utf-8')
    errs = []
    entrs = []
    try:
        form, svc, dbg, cur, sid, sess, parms, cfg = jmcgi.parseform()
    except Exception as e:
        jmcgi.err_page([str(e)])

    fv = form.getfirst
    fl = form.getlist
    is_editor = jmcgi.is_editor(sess)
    dbg = fv('dbg')
    meth = fv('meth')
    def_corp = fv('c')  # Default corpus for new entries.
    defcorpid = None
    if def_corp:
        try:
            def_corp = int(def_corp)
        except ValueError:
            pass
        try:
            defcorpid = jdb.KW.SRC[def_corp].id
        except KeyError:
            errs.append("Bad url parameter: c=%s" % def_corp)
    force_corp = fv('f')  # Force default corpus for new entries.

    sentrs = fl("entr")
    for sentr in sentrs:
        try:
            entrs = serialize.unserialize(sentr)
        except Exception as e:
            errs.append("Bad 'entr' value, unable to unserialize: %s" % str(e))
        else:
            entrs.append(entr)

    jentrs = fl('j')
    for jentr in jentrs:
        try:
            entr = edparse.entr(jentr)
        except Exception as e:
            errs.append("Bad 'j' value, unable to parse: %s" % str(e))
        else:
            entr.src = None
            entrs.append(entr)

    elist, qlist, active = fl('e'), fl('q'), fv('a')
    if elist or qlist:
        entrs.extend(
            jmcgi.get_entrs(cur,
                            elist or [],
                            qlist or [],
                            errs,
                            active=active,
                            corpus=def_corp) or [])
    cur.close()

    if (elist or qlist or jentrs or sentrs) and not entrs:
        # The caller explictly specified and entry to edit but we
        # didn't find it (or them).  Rather than treating this as
        # though no entries were given and displaying a blank edit
        # form, show an error message.
        errs.append("No matching entries were found")
    if errs: jmcgi.err_page(errs)

    srcs = sorted(jdb.KW.recs('SRC'), key=lambda x: x.kw.lower())
    #srcs.insert (0, jdb.Obj (id=0, kw='', descr=''))
    if not entrs:
        # This is a blank new entry.
        # The following dummy entry will produce the default
        # text for new entries: no kanji, no reading, and sense
        # text "[1][n]".
        entr = jdb.Entr(
            _sens=[jdb.Sens(_pos=[jdb.Pos(kw=jdb.KW.POS['n'].id)])], src=None)
        entrs = [entr]
    for e in entrs:
        if not is_editor: remove_freqs(e)
        e.ISDELETE = (e.stat == jdb.KW.STAT['D'].id) or None
        # Provide a default corpus.
        if not e.src: e.src = defcorpid
        e.NOCORPOPT = force_corp

    if errs: jmcgi.err_page(errs)

    for e in entrs:
        e.ktxt = fmtjel.kanjs(e._kanj)
        e.rtxt = fmtjel.rdngs(e._rdng, e._kanj)
        e.stxt = fmtjel.senss(e._sens, e._kanj, e._rdng)

    if errs: jmcgi.err_page(errs)

    jmcgi.jinja_page('edform.jinja',
                     parms=parms,
                     extra={},
                     entrs=entrs,
                     srcs=srcs,
                     is_editor=is_editor,
                     svc=svc,
                     dbg=dbg,
                     sid=sid,
                     session=sess,
                     cfg=cfg,
                     this_page='edform.py')