Exemple #1
0
def background_load_to_neo4j(username,filename):
    ''' Imports gramps xml data to database '''
    upload_folder = get_upload_folder(username) 
    pathname = os.path.join(upload_folder,filename)
    metaname = pathname+".meta"
    logname =  pathname+".log"
    update_metafile(metaname, progress={})
    steps = []
    try:
        os.makedirs(upload_folder, exist_ok=True)
        set_meta(username,filename,status=STATUS_LOADING)
        this_thread = threading.current_thread()
        this_thread.progress = {}
        counts = gramps_loader.analyze_xml(username, filename)
        update_metafile(metaname,counts=counts,progress={})
        threading.Thread(target=lambda: i_am_alive(metaname,this_thread),name="i_am_alive for " + filename).start()
        steps,batch_id = gramps_loader.xml_to_neo4j(pathname,username)
        for step in steps:
            print(step)
        if not batch_id:
            raise RuntimeError("Run Failed, missing batch_id")

        if os.path.exists(metaname): 
            set_meta(username,filename,
                     batch_id=batch_id,
                     status=STATUS_DONE)
        msg = "{}:\nStored the file {} from user {} to neo4j".format(util.format_timestamp(),pathname,username)
        msg += "\nBatch id: {}".format(batch_id)
        msg += "\nLog file: {}".format(logname)
        msg += "\n"
        for step in steps:
            msg += "\n{}".format(step)
        msg += "\n"
        open(logname,"w", encoding='utf-8').write(msg)
        email.email_admin(
                    "Stk: Gramps XML file stored",
                    msg )
        syslog.log(type="storing to database complete",file=filename,user=username)
    except:
        traceback.print_exc()
        res = traceback.format_exc()
        set_meta(username,filename,status=STATUS_FAILED)
        msg = "{}:\nStoring the file {} from user {} to database FAILED".format(util.format_timestamp(),pathname,username)
        msg += "\nLog file: {}".format(logname)
        msg += "\n" + res
        for step in steps:
            msg += "\n{}".format(step)
        msg += "\n"
        open(logname,"w", encoding='utf-8').write(msg)
        email.email_admin(
                    "Stk: Gramps XML file storing FAILED",
                    msg )
        syslog.log(type="gramps store to database failed",file=filename,user=username)
Exemple #2
0
def process_gedcom(args, transform_module, task_name=''):

    LOG.info("------ Ajo '%s'   alkoi %s ------", task_name,
             util.format_timestamp())

    transform_module.initialize(args)

    if hasattr(transform_module, "process"):
        with Output(args) as f:
            transform_module.process(args, f)
    else:
        try:
            # 1st traverse
            if hasattr(transform_module, "phase1"):
                for gedline in read_gedcom(args):
                    transform_module.phase1(args, gedline)

            # Intermediate processing of collected data
            if hasattr(transform_module, "phase2"):
                transform_module.phase2(args)

            do_phase4 = hasattr(transform_module, "phase4")

            if hasattr(transform_module, "phase3"):
                # 2nd traverse "phase3"
                with Output(args) as f:
                    f.transform_name = transform_module.__name__
                    f.display_changes = args.display_changes
                    for gedline in read_gedcom(args):
                        if do_phase4 and gedline.tag == "TRLR":
                            f.original_line = ""
                            transform_module.phase4(args, f)
                        f.original_line = gedline.line.strip()
                        f.saved_line = ""
                        transform_module.phase3(args, gedline, f)

        except FileNotFoundError as err:
            LOG.error("Ohjelma päättyi virheeseen {}: {}".format(
                type(err).__name__, str(err)))

    LOG.info("------ Ajo '%s' päättyi %s ------", task_name,
             util.format_timestamp())
Exemple #3
0
def gedcom_save(gedcom):
    filename1 = gedcom_utils.gedcom_fullname(gedcom)
    filename2 = filename1 + "-temp"
    newname = util.generate_name(filename1)
    os.rename(filename1,newname)
    os.rename(filename2,filename1)
    gedcom_utils.history_append(filename1,"\n{}:".format(util.format_timestamp()))
    gedcom_utils.history_append(filename1,_("File {} saved as {}").format(filename1,newname))
    gedcom_utils.history_append(filename1,_("File {} saved as {}").format(filename2,filename1))
    logger.info(f'-> bp.gedcom.routes.gedcom_save f="{os.path.basename(newname)}"')
    rsp = dict(newname=os.path.basename(newname))
    return jsonify(rsp) 
Exemple #4
0
 def from_node(cls, node):
     ''' Convert a Neo4j node to Batch object.
     '''
     obj = cls()
     obj.uniq_id = node.id
     obj.user = node.get('user', "")
     obj.file = node.get('file', None)
     obj.id = node.get('id', None)
     obj.status = node.get('status', "")
     obj.timestamp = node.get('timestamp', 0)
     obj.upload = format_timestamp(obj.timestamp)
     obj.auditor = node.get('auditor', None)
     return obj
Exemple #5
0
def gedcom_revert(gedcom,version):
    filename1 = gedcom_utils.gedcom_fullname(gedcom)
    filename2 = gedcom_utils.gedcom_fullname(version)
    newname = util.generate_name(filename1)
    if os.path.exists(filename1) and os.path.exists(filename2):
        os.rename(filename1,newname)
        os.rename(filename2,filename1)
        gedcom_utils.history_append(filename1,"\n{}:".format(util.format_timestamp()))
        gedcom_utils.history_append(filename1,_("File {} saved as {}").format(filename1,newname))
        gedcom_utils.history_append(filename1,_("File {} saved as {}").format(filename2,filename1))
        rsp = dict(newname=os.path.basename(newname))
    else:
        rsp = dict(status="Error")
    return jsonify(rsp) 
Exemple #6
0
def log(type,**kwargs):
    """ Create a Syslog event node with given arguments and timestamp.
    """
    try:
        user=current_user.username
    except:
        user = kwargs.get("user","")
    timestamp = time.time()
    timestr=util.format_timestamp(timestamp)
    msg = json.dumps(kwargs)
    try:
        shareds.driver.session().run(syslog_cypher_write, type=type, user=user,
                                     msg=msg, time=timestamp, timestr=timestr)
    except Exception:
        traceback.print_exc()
Exemple #7
0
    def emit(self, line):
        ''' Process an input line '''
        #if self.display_changes and self.original_line and \
        if self.args.display_changes and self.original_line is not None:
            if self.original_line == "" and self.saved_line != "":
                print('{:>36} --> {}'.format(self.saved_line, self.saved_line))
                print('{:>36} --> {}'.format(self.original_line, line))
                self.saved_line = ""
            elif line.strip() != self.original_line:
                print('{:>36} --> {}'.format(self.original_line, line))
            else:
                self.saved_line = self.original_line
            self.original_line = ""
        if line.startswith("1 CHAR"):
            # this is probably unnecessary because the result should always be
            # the same as in the input file, i.e. the line is not modified
            if self.output_encoding == "UTF-8":
                line = "1 CHAR UTF-8"
            elif self.output_encoding == "ISO8859-1":
                line = "1 CHAR ANSI"
            else:
                line = "1 CHAR {}".format(self.output_encoding)
        self.f.write(line + "\n")

        if self.log:
            #TODO: Should follow a setting from gedder.py
            self.log = False
            args = sys.argv[1:]
            try:
                v = " v." + VERSION
            except NameError:
                v = ""
            self.emit("1 NOTE _TRANSFORM{} {}".format(v, self.transform_name))
            self.emit("2 CONT args:")
            for name, value in vars(self.args).items():
                self.emit("1 CONT - {}={}".format(name, value))
            self.emit("2 CONT _COMMAND {} {}".\
                      format(os.path.basename(sys.argv[0]), " ".join(args)))
            user = getpass.getuser()
            if not user:
                user = "******"
            datestring = util.format_timestamp()
            self.emit("2 CONT _USER {}".format(user))
            self.emit("2 CONT _DATE {}".format(datestring))
            if self.new_name:
                self.emit("2 CONT _SAVEDFILE " + self.new_name)
Exemple #8
0
    def from_node(cls, node):
        ''' Convert a Neo4j node to an Audit object.

        <Node id=439060 labels={'Audit'}
            properties={'auditor': 'juha', 'id': '2020-01-03.001', 
                        'user': '******', 'timestamp': 1578940247182}>
        '''
        obj = cls()
        obj.uniq_id = node.id
        obj.user = node.get('user', "")
        obj.auditor = node.get('auditor')
        obj.id = node.get('id', None)
        #obj.status = node.get('status', "")
        obj.timestamp = node.get('timestamp', 0)
        if obj.timestamp:
            obj.updated = format_timestamp(obj.timestamp/1000.)
        return obj
Exemple #9
0
def gedcom_upload():
    # code from: http://flask.pocoo.org/docs/1.0/patterns/fileuploads/
    def allowed_file(filename):
        return '.' in filename and \
               filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
    
    gedcom_folder = gedcom_utils.get_gedcom_folder()
    # check if the post request has the file part
    if 'file' not in request.files:
        flash(_('Choose a GEDCOM file to upload'), category='flash_warning')
        return redirect(url_for('.gedcom_list'))
    file = request.files['file']
    # if user does not select file, browser also
    # submit an empty part without filename
    if file.filename == '': # pragma: no cover
        flash(_('Choose a GEDCOM file to upload'), category='flash_warning')
        return redirect(url_for('.gedcom_list'))
    if file and allowed_file(file.filename):
        filename = secure_filename(file.filename)
        os.makedirs(gedcom_folder, exist_ok=True)
        fullname = os.path.join(gedcom_folder, filename)

        if os.path.exists(fullname):
            flash(_('This GEDCOM file already exists'), category='flash_error')
            return redirect(url_for('.gedcom_list'))
            
        file.save(fullname)

        desc = request.form['desc']
        encoding = util.guess_encoding(fullname)
        metadata = {
            'desc':desc,
            'encoding':encoding,
            'upload_time':util.format_timestamp(),
            'size':os.stat(fullname).st_size,
        }
        gedcom_utils.save_metadata(filename, metadata)
        gedcom_utils.history_init(fullname)
        syslog.log(type="uploaded a gedcom",gedcom=file.filename)
        logger.info(f'-> bp.gedcom.routes.gedcom_upload n={os.stat(fullname).st_size/1024.}kb')
        return redirect(url_for('.gedcom_info',gedcom=filename))
Exemple #10
0
def process_gedcom(arglist, transform_module):
    """ Implements a mechanism for Gedcom transforms.
    
    Returns a dictionary:
        - stdout        result texts for the user log page
        - stderr        errors texts for the user log page 
        - oldname       original name of gedcom file
        - logfile       log file name

    The transform_module is assumed to contain the following methods:
    - initialize
    - transform: implements the actual transformation for a single line block ("item")
    - fixlines: preprocesses the Gedcom contents (list of lines/strings)
    - add_args: adds the transform-specific arguments (ArgumentParser style)

    See sukujutut.py as an example
    """

    msg = _("Transform '{}' started at {}").format(transform_module.name,
                                                   util.format_timestamp())
    LOG.info(f"------ {msg} ------")

    parser = ArgumentParser()
    #    parser.add_argument('transform', help="Name of the transform (Python module)")
    parser.add_argument('input_gedcom',
                        help=_("Name of the input GEDCOM file"))
    parser.add_argument('--logfile',
                        help=_("Name of the log file"),
                        default="_LOGFILE")
    #    parser.add_argument('--output_gedcom', help="Name of the output GEDCOM file; this file will be created/overwritten" )
    parser.add_argument('--display-changes',
                        action='store_true',
                        help=_('Display changed rows'))
    parser.add_argument('--dryrun',
                        action='store_true',
                        help=_('Do not produce an output file'))
    parser.add_argument('--nolog',
                        action='store_true',
                        help=_('Do not produce a log in the output file'))
    parser.add_argument('--encoding',
                        type=str,
                        default="UTF-8",
                        choices=["UTF-8", "UTF-8-SIG", "ISO8859-1"],
                        help=_("Encoding of the input GEDCOM"))
    transform_module.add_args(parser)
    args = parser.parse_args(arglist)
    args.output_gedcom = None
    args.nolog = True  # replaced by history file
    gedcom_utils.history_append(args.input_gedcom, "\n" + msg)
    gedcom_utils.history_append_args(args)

    # You may deny stdout redirect by setting GEDCOM_REDIRECT_SYSOUT=False in config.py
    if not 'GEDCOM_REDIRECT_SYSOUT' in globals():
        GEDCOM_REDIRECT_SYSOUT = True
    try:
        gedcom_utils.init_log(args.logfile)
        with Output(args) as out:
            out.original_line = None
            out.transform_name = transform_module.__name__
            if GEDCOM_REDIRECT_SYSOUT:
                saved_stdout = sys.stdout
                saved_stderr = sys.stderr
                sys.stdout = io.StringIO()
                sys.stderr = io.StringIO()
            if args.dryrun:
                old_name = ""
            else:
                old_name = out.new_name

            print(f"<h3>------ {msg} ------</h3>")
            t = transformer.Transformer(
                transform_module=transform_module,
                display_callback=gedcom_utils.display_changes,
                options=args)
            """ Create a Gedcom transformer g from Transformer t and execute
                the transformations.
                
                The resulting Items are in the list g.items 
            """
            g = t.transform_file(args.input_gedcom)
            g.print_items(out)
            print("<div>")
            print("<b>------ " + ngettext(
                "Total {num} change", "Total {num} changes",
                num=t.num_changes).format(num=t.num_changes) + "</b>")
            #print(_("------ Number of changes: {}").format(t.num_changes))
    except:
        traceback.print_exc()
    finally:
        if old_name:
            gedcom_utils.history_append(
                args.input_gedcom,
                _('File saved as {}').format(args.input_gedcom))
            gedcom_utils.history_append(
                args.input_gedcom,
                _("Old file saved as {}").format(old_name))
        else:
            gedcom_utils.history_append(
                args.input_gedcom,
                _("File saved as {}").format(args.input_gedcom + "temp"))
            msg = _("Transform '{}' ended at {}").format(
                transform_module.name, util.format_timestamp())
        gedcom_utils.history_append(args.input_gedcom, msg)
        print(f"<h3>------ {msg} ------</h3>")
        print("</div>")
        output = None
        errors = None
        if GEDCOM_REDIRECT_SYSOUT:
            output = sys.stdout.getvalue()
            errors = sys.stderr.getvalue()
            sys.stdout = saved_stdout
            sys.stderr = saved_stderr
    if old_name:
        old_basename = os.path.basename(old_name)
    else:
        old_basename = ""
    if errors and old_basename:
        os.rename(old_name, args.input_gedcom)
        old_basename = ""
    rsp = dict(stdout=output,
               stderr=errors,
               oldname=old_basename,
               logfile=args.logfile)
    if hasattr(transform_module, "output_format") \
       and transform_module.output_format == "plain_text":
        rsp["plain_text"] = True
    return rsp
Exemple #11
0
    def get_nameobject(self):
        ''' Returns the latest object of type PersonName_v1 '''
        if self.current_index >= 0:
            return self.rows[self.current_index]


if __name__ == '__main__':
    ''' Test set '''
    from .ged_output import Output

    logging.basicConfig(filename='example.log',
                        level=logging.DEBUG,
                        format='%(levelname)s:%(message)s')
    LOG.info("------ Ajo '%s' alkoi %s", "Testi",
             util.format_timestamp() + " ------")

    # One person with two NAME lines
    my_record_1 = GedcomRecord(GedcomLine('0 @I1@ INDI'))
    my_name = PersonName_v1(
        GedcomLine(
            '1 NAME Amalia Saima* (Sanni) Erikint./Raitala os. von Krats/Ericsdr.'
        ))
    my_record_1.add_member(my_name)
    my_name.add_line(GedcomLine(('2', 'GIVN', 'Saimi')))
    my_name.add_line(GedcomLine('3 SOUR Äidiltä'))
    my_name.add_line(GedcomLine('2 SURN Raitala'))
    my_name.add_line(GedcomLine('2 NOTE Kummin kaima'))
    my_record_2 = GedcomRecord(GedcomLine('0 @I2@ INDI'))
    my_name = PersonName_v1(GedcomLine('1 NAME vauva//Ericsdr.'))
    my_record_2.add_member(my_name)
Exemple #12
0
def history_init(gedcom_fname):
    ''' Initialize history file. '''
    history_file_name = gedcom_fname + "-history"
    open(history_file_name,"w").write("{}: Uploaded {}\n".format(util.format_timestamp(),gedcom_fname))
Exemple #13
0
def list_uploads(username):
    ''' Gets a list of uploaded files and their process status.
    
        Also db Batches without upload file are included in the list.
    '''
    # 1. List Batches, their status and Person count
    batches = {}
    result = shareds.driver.session().run(Cypher_batch.get_user_batch_names, 
                                          user=username)
    for record in result:
        # <Record batch='2019-08-12.001' timestamp=None persons=1949>
        batch = record['batch']
        batches[batch] = (record['status'], record['persons'])

    # 2. List uploaded files
    upload_folder = get_upload_folder(username)
    try:
        names = sorted([name for name in os.listdir(upload_folder)]) 
    except:
        names = []
    uploads = []
    class Upload: pass
    for name in names:
        if name.endswith(".meta"):
            fname = os.path.join(upload_folder,name)
            xmlname = name.rsplit(".",maxsplit=1)[0]
            meta = get_meta(fname)
            status = meta["status"]
            batch_id = ""
            status_text = None

            if status == STATUS_UPLOADED:
                status_text = _("UPLOADED")
            elif status == STATUS_LOADING:
                status_text = _("STORING") 
            elif status == STATUS_DONE:
                status_text = _("STORED")
                if 'batch_id' in meta:
                    batch_id = meta['batch_id']
            elif status == STATUS_FAILED:
                status_text = _("FAILED")
            elif status == STATUS_ERROR:
                status_text = _("ERROR")
            elif status == STATUS_REMOVED:
                status_text = _("REMOVED")

            if not batch_id in batches:
                if status_text == _("STORED"):
                    status_text = _("REMOVED")
                batch_id = ""
                person_count = 0
            else:
                status, person_count = batches.pop(batch_id)

            if status_text:
                upload = Upload()
                upload.xmlname = xmlname
                upload.status = status_text
                upload.batch_id = batch_id
                upload.count = person_count
                upload.done = (status_text == _("STORED"))
                upload.uploaded = (status_text == _("UPLOADED"))
                upload.loading = (status_text == _("STORING"))
                upload.upload_time = meta["upload_time"]
                upload.upload_time_s = util.format_timestamp(upload.upload_time)
                upload.user = username
                uploads.append(upload)
    
    # 3. Add batches where there is no file
    for batch, item in batches.items():
        upload = Upload()
        upload.batch_id = batch
        status, count = item
        if status == "started":
            upload.status = "?"
        elif status == "completed":
            upload.status = _("STORED")
        upload.count = count
        upload.upload_time = 0.0
        uploads.append(upload)
        
    return sorted(uploads,key=lambda x: x.upload_time)