Esempio n. 1
0
def move_iter (mod, iter, sibling=None, parent=None, direction="before"):
    """move_iter will move iter relative to sibling or
    parent. Direction (before or after) tells us whether to
    insert_before or insert_after (with a sib) or to prepend or append
    (with a parent)."""
    if direction != "after":
        direction = "before"
    path = mod.get_path(iter)
    if sibling:
        dpath = mod.get_path(sibling)
    elif parent:
        dpath = mod.get_path(parent)
    else:
        dpath = ()
    rowdata = get_row(mod, iter)
    children=harvest_children(mod, iter)
    if direction != "after":
        direction = "before"
    path = mod.get_path(iter)
    if sibling:
        dpath = mod.get_path(sibling)
    elif parent:
        dpath = mod.get_path(parent)
    else:
        dpath = ()
    rowdata = get_row(mod, iter)
    children=harvest_children(mod, iter)
    def insert_new (parent):
        """A little subroutine to insert our row. We'll call this at the appropriate
        time depending on the order of source and destination iters"""
        if not parent:
            parent=None
            if len(dpath) > 1:
                parent=mod.get_iter(dpath[0:-1])
        if parent==sibling or not sibling:
            """If our parent is our destination iter or if we have
            only a parent specified, we're moving inside, not before"""
            if direction=="before":
                return mod.append(parent, rowdata)
            else:
                return mod.prepend(parent, rowdata)
        elif direction=="before":
                return mod.insert_before(parent,sibling,rowdata)
        else:
            return mod.insert_after(parent,sibling,rowdata)
    # if the source is before the destination, we add then remove. otherwise, we remove then add.
    path_last = path_compare(path,dpath)
    if path_last==1:
        # Source after destination (remove, then add)
        remove_children(mod, iter)
        mod.remove(iter)
        new=insert_new(parent)
        insert_children(mod, new, children)
    elif path_last==0: debug("Moving into my self is nonsensical!",1)
    else:
        # Source before destination (add, then remove)
        new=insert_new(parent)
        insert_children(mod, new, children)
        remove_children(mod, iter)
        mod.remove(iter)
Esempio n. 2
0
 def append (self,obj):
     debug('Appending %s'%obj,0)
     list.append(self,obj)
     if obj.is_undo==False: # Is this necessary? Not sure...
         for h in self.action_hooks:
             h(self,obj,'perform')
     self.gui_update()
Esempio n. 3
0
 def compile_regexps (self):
     testtimer = TimeAction('mealmaster_importer.compile_regexps',10)
     debug("start compile_regexps",5)
     plaintext_importer.TextImporter.compile_regexps(self)
     self.start_matcher = re.compile(mm_start_pattern)
     self.end_matcher = re.compile("^[M-][M-][M-][M-][M-]\s*$")
     self.group_matcher = re.compile("^\s*([M-][M-][M-][M-][M-])-*\s*([^-]+)\s*-*",re.IGNORECASE)
     self.ing_cont_matcher = re.compile("^\s*[-;]")
     self.ing_opt_matcher = re.compile("(.+?)\s*\(?\s*optional\)?\s*$",re.IGNORECASE)
     self.ing_or_matcher = re.compile("^[- ]*[Oo][Rr][- ]*$",re.IGNORECASE)
     self.variation_matcher = re.compile("^\s*(VARIATION|HINT|NOTES?)(:.*)?",re.IGNORECASE)
     # a crude ingredient matcher -- we look for two numbers,
     # intermingled with spaces followed by a space or more,
     # followed by a two digit unit (or spaces)
     self.ing_num_matcher = re.compile(
         "^\s*%s+\s+[a-z ]{1,2}\s+.*\w+.*"%convert.NUMBER_REGEXP,
         re.IGNORECASE)
     self.amt_field_matcher = re.compile("^(\s*%s\s*)$"%convert.NUMBER_REGEXP)
     # we build a regexp to match anything that looks like
     # this: ^\s*ATTRIBUTE: Some entry of some kind...$
     self.mmf = mmf
     attrmatch="^\s*("
     for k in self.mmf.recattrs.keys():
         attrmatch += "%s|"%re.escape(k)
     attrmatch="%s):\s*(.*)\s*$"%attrmatch[0:-1]
     self.attr_matcher = re.compile(attrmatch)
     testtimer.end()
 def handle_ingline (self,line):
     if self.ing_or_matcher.match(line):
         self.in_or = True
         return
     amt = line.__getslice__(*self.amt_col).strip()
     unit = line.__getslice__(*self.unit_col).strip()
     itm = line[self.itm_col[0]:].strip()
     gm=self.ing_group_matcher.match(itm)
     if gm:
         if self.ing: self.commit_ing()
         self.group = gm.groups()[1]
         # undo grouping if it has no letters...
         if re.match('^[^A-Za-z]*$',self.group): self.group=None
         return
     if amt or unit:
         if self.in_or: self.ing['optional']=True
         if self.ing: self.commit_ing()
         self.start_ing()
         if self.in_or:
             self.ing['optional']=True
             self.in_or = False
         self.add_amt(amt)
         self.add_unit(unit)
         self.add_item(itm)
         return
     elif self.ing and self.ing.has_key('item'):
         # otherwise, we assume we are a continuation and
         # add onto the previous item
         self.ing['item']=self.ing['item']+' '+itm.strip()
     else:
         debug('"%s" in the midst of ingredients looks like instructions!'%itm.strip(),2)
         self.instr += "\n"+itm.strip()
Esempio n. 5
0
def parse_range(number_string):
    """Parse a range and return a tuple with a low and high number as floats.

    We will also parse regular numbers, in which case the tuple will
    only have one item.
    """
    if type(number_string) in [int, float]:
        return (float(number_string), None)
    nums = convert.RANGE_MATCHER.split(number_string.strip())
    if len(nums) > 2:
        debug("WARNING: String %s does not appear to be a normal range." % number_string, 0)
        retval = map(convert.frac_to_float, nums)
        # filter any non-numbers before we take 1 and 3
        retval = filter(lambda x: x, retval)
        if len(retval) > 2:
            debug("Parsing range as %s-%s" % (retval[0], retval[-1]), 0)
            retval = retval[0], retval[-1]
    else:
        retval = map(convert.frac_to_float, nums)
    if len(retval) == 2:
        return tuple(retval)
    elif len(retval) == 1:
        return tuple(retval + [None])
    else:
        return (None, None)
Esempio n. 6
0
 def __init__ (self, parent_thread=None,conv=None):
     debug('MastercookXMLHandler starting',0)
     xml_importer.RecHandler.__init__(self,parent_thread=parent_thread,conv=None)
     self.total = 0
     self.recs_done = 0
     self.elements = {
         'mx2':['source','date'],
         #'Summ':[],
         'Nam':[],
         'RcpE':['name'],
         'RTxt':[],
         'Serv':['qty'],
         'PropT':['elapsed'],
         'IngR':['name','unit','qty'],
         'IPrp':[],
         #'DirS':[],
         'DirT':[],
         'Desc':[],
         'Srce':[],
         'Note':[],
         'CatT':[],
         'Yield':['unit','qty'],
         }
     self.current_elements = []
     self.bufs = []
     xml.sax.ContentHandler.__init__(self)
     importer.Importer.__init__(self,conv=conv)
Esempio n. 7
0
def create_thumbnail (path, thumbpath, uri, type="large"):
    """Create a thumbnail at path and return path"""
    mtime = os.stat(path)[8]
    size = os.path.getsize(path)
    if int(size) > MAX_THUMBSIZE:
        debug('File too large!',0)
        return None
    try:
        im = Image.open(path)
    except:
        return None
    w,h = im.size
    if type=='large':
        geo = (256,256)
    else: geo = (128,128)
    im.thumbnail(geo)
    # set thumbnail attributes
    info={}
    info['Thumb::MTime']=str(mtime)
    info['Thumb::Image::Width']=str(w)
    info['Thumb::Image::Height'] =str(h)
    info['Software']='Gourmet Recipe Manager'
    info['URI']=str(uri)
    # now we must create our image guy
    import PngImagePlugin
    pnginfo = PngImagePlugin.PngInfo()

    for k,v in info.items():
        pnginfo.add_text(k,v)
    im.save(thumbpath, pnginfo=pnginfo)
    # we must make all thumbnails permissions 700
    os.chmod(thumbpath,0700)
    return thumbpath
Esempio n. 8
0
 def get_referenced_rec(self, ing):
     """Get recipe referenced by ingredient object."""
     if hasattr(ing, "refid") and ing.refid:
         rec = self.get_rec(ing.refid)
         if rec:
             return rec
     # otherwise, our reference is no use! Something's been
     # foobared. Unfortunately, this does happen, so rather than
     # screwing our user, let's try to look based on title/item
     # name (the name of the ingredient *should* be the title of
     # the recipe, though the user could change this)
     if hasattr(ing, "item"):
         recs = self.search(self.recipe_table, "title", ing.item, exact=True, use_regexp=False)
         if len(recs) == 0:
             self.modify_ing(ing, {"idref": recs[0].id})
             return recs[0]
         else:
             debug(
                 """Warning: there is more than one recipe titled"%(title)s"
             and our id reference to %(idref)s failed to match any
             recipes.  We are going to assume recipe ID %(id)s is
             the correct one."""
                 % {"title": ing.item, "idref": ing.refid, "id": recs[0].id},
                 0,
             )
             return recs[0]
Esempio n. 9
0
 def compile_regexps (self):
     """Compile our regular expressions for the rezkonv format.
     """
     testtimer = TimeAction('mealmaster_importer.compile_regexps',10)
     debug("start compile_regexps",5)
     plaintext_importer.TextImporter.compile_regexps(self)
     self.start_matcher = re.compile(rzc_start_pattern)
     self.end_matcher = re.compile("^[=M-][=M-][=M-][=M-][=M-]\s*$")
     self.group_matcher = re.compile("^\s*([=M-][=M-][=M-][=M-][=M-]+)-*\s*([^-]+)\s*-*",re.IGNORECASE)
     self.ing_cont_matcher = re.compile("^\s*[-;]")
     self.ing_opt_matcher = re.compile("(.+?)\s*\(?\s*optional\)?\s*$",re.IGNORECASE)
     # or or the German, oder
     self.ing_or_matcher = re.compile("^[-= ]*[Oo][dD]?[eE]?[Rr][-= ]*$",re.IGNORECASE)
     self.variation_matcher = re.compile("^\s*(VARIATION|HINT|NOTES?|VERÄNDERUNG|VARIANTEN|TIPANMERKUNGEN)(:.*)?",re.IGNORECASE)
     # a crude ingredient matcher -- we look for two numbers, intermingled with spaces
     # followed by a space or more, followed by a two digit unit (or spaces)
     self.ing_num_matcher = re.compile(
         "^\s*%(top)s%(num)s+\s+[A-Za-z ][A-Za-z ]? .*"%{'top':convert.DIVIDEND_REGEXP,
                                                          'num':convert.NUMBER_REGEXP},
         re.IGNORECASE)
     self.amt_field_matcher = convert.NUMBER_MATCHER
     # we build a regexp to match anything that looks like
     # this: ^\s*ATTRIBUTE: Some entry of some kind...$
     attrmatch="^\s*("
     self.mmf = rzc
     for k in self.mmf.recattrs.keys():
         attrmatch += "%s|"%re.escape(k)
     attrmatch="%s):\s*(.*)\s*$"%attrmatch[0:-1]
     self.attr_matcher = re.compile(attrmatch)
     testtimer.end()
Esempio n. 10
0
 def set_sensitive (self,w,val):
     debug('set_sensitive',0)
     if not w:
         #import traceback; traceback.print_stack()
         #print 'No widget to sensitize',w,val
         return
     w.set_sensitive(val)
Esempio n. 11
0
 def toss_regs (self, instr):
     m = self.toss_regexp.search(instr)
     if m:
         outstr = instr[0:m.start()] + instr[m.end():]
         debug('Converted "%s" to "%s"'%(instr,outstr),1)
         return outstr
     else:
         return instr
Esempio n. 12
0
 def encode (self, l):
     for e in self.encodings:
         try:
             return l.decode(e)
         except:
             debug('Could not decode as %s'%e,2)
             pass
     raise Exception("Could not encode %s" % l)
Esempio n. 13
0
 def load_properties (self):
     #if os.name=='nt': return
     for p,f in ['window_size', self.w.resize],['position',self.w.move]:
         if self.dictionary.has_key(p) and self.dictionary[p]:
             debug('applying %s %s'%(f,self.dictionary[p]),3)
             #if os.name=='nt' and p=='position' and self.dictionary['position'][1]<20:
             #    #print 'FIDDLING WITH WINDOW FOR WINDOWS'
             #    #self.dictionary[p] = self.dictionary[p][0],20
             apply(f,self.dictionary[p])
Esempio n. 14
0
 def delete_rec(self, rec):
     """Delete recipe object rec from our database."""
     if type(rec) != int:
         rec = rec.id
     debug("deleting recipe ID %s" % rec, 0)
     self.delete_by_criteria(self.recipe_table, {"id": rec})
     self.delete_by_criteria(self.categories_table, {"id": rec})
     self.delete_by_criteria(self.ingredients_table, {"id": rec})
     debug("deleted recipe ID %s" % rec, 0)
Esempio n. 15
0
 def startElement (self, name, attrs):
     self.in_mixed=0
     if not self.elements.has_key(name):
         debug('Unhandled element: %s'%name,0)
         return
     else:
         self.current_elements = [name] + self.current_elements
         handler = self._get_handler(name)
         handler(start=True,attrs=attrs)
Esempio n. 16
0
def field_width (tuple):
    testtimer = TimeAction('mealmaster_importer.field_width',10)
    debug("start field_width",10)
    if tuple[1]:
        testtimer.end()
        return tuple[1]-tuple[0]
    else:
        testtimer.end()
        return None
Esempio n. 17
0
 def pre_run (self):
     self.emit('progress',0.03, _("Tidying up XML"))
     cleaner = Mx2Cleaner()
     base,ext=os.path.splitext(self.fn)
     cleanfn = base + ".gourmetcleaned" + ext
     cleaner.cleanup(self.fn,cleanfn)
     debug('Cleaned up file saved to %s'%cleanfn,1)
     self.orig_fn = self.fn
     self.fn = cleanfn
Esempio n. 18
0
    def run (self):
        """Import our recipe to our database.

        This must be called after self.d is already populated by scraping
        our web page.
        """
        debug('Scraping url %s'%self.url,0)
        try:
            self.d = scrape_url(self.url, progress=self.prog)
        except:
            print 'Trouble using default recipe filter to download %s'%self.url
            traceback.print_exc()
            print 'We will use a generic importer instead.'
            self.d = {}
        debug('Scraping url returned %s'%self.d,0)
        do_generic = not self.d
        if not do_generic:
            try:
                if self.prog: self.prog(-1,'Parsing webpage based on template.')
                self.get_url_based_on_template()
            except:
                if not self.interactive: raise
                do_generic = True
                print """Automated HTML Import failed
                ***Falling back to generic import***

                We were attempting to scrape using the following rules:
                """
                print self.d
                print """The following exception was raised:"""
                traceback.print_exc()
                print """If you think automated import should have worked for the webpage you
                were importing, copy the output starting at "Automated HTML Import failed" into
                a bug report and submit it at the GitHub site
                
                https://github.com/thinkle/gourmet/issues

                Sorry automated import didn't work. I hope you like
                the new generic web importer!
                """
        if do_generic:
            if not self.interactive:
                raise Exception("Unable to find importer for %s" % self.url)
            # Interactive we go...
            self.prog(-1,_("Don't recognize this webpage. Using generic importer..."))
            gs = GenericScraper()
            text,images = gs.scrape_url(self.url, progress=self.prog)
            if not text and not images:
                raise Exception("Unable to obtain text or images from url %s" % self.url)
            import interactive_importer
            ii = interactive_importer.InteractiveImporter(self.rd)
            ii.set_text(text)
            ii.add_attribute('link',self.url)
            ii.set_images(images)
            ii.run()
            if self.prog: self.prog(1,_('Import complete.'))
            return
Esempio n. 19
0
def tarball_to_filelist (fi, progress=None, name="zipfile"):
    tb = tarfile.TarFile.open(fi,mode='r')
    fi_info = tb.next()
    filist = []
    while fi_info:
        fi = tb.extractfile(fi_info)
        if fi: filist.append(fi)
        fi_info = tb.next()
    debug('tarball_to_filelist returning %s'%filist,0)
    return filist
Esempio n. 20
0
 def do_run (self):
     debug('Running ing hooks',0)
     for i in self.added_ings:
         for h in self.rd_orig_ing_hooks:
             h(i)
     #debug('Running rec hooks',0)  
     #for r in self._added_recs:
     #    for h in self.rd_orig_hooks:
     #        h(r)
     self.rd.add_ing_hooks = self.rd_orig_ing_hooks
Esempio n. 21
0
 def density_itm_changed (self, *args):
     debug('density_itm_changed',5)
     self.changing_item=True
     itm=cb_get_active_text(self.itemComboBox)
     if itm != _('None'):
         self.densitySpinButton.set_value(self.conv.density_table[itm])
     else:
         self.densitySpinButton.set_value(0)
     self.changed()
     self.changing_item=False
Esempio n. 22
0
 def modify_ing (self, ing, ingdict):
     """modify ing based on dictionary of properties and new values."""
     #self.delete_ing(ing)
     #return self.add_ing(ingdict)
     for k,v in ingdict.items():
         if hasattr(ing,k):
             self.changed=True
             setattr(ing,k,v)
         else:
             debug("Warning: ing has no attribute %s (attempted to set value to %s" %(k,v),0)
     return ing
Esempio n. 23
0
 def replace_ings (self, ingdicts):
     """Add a new ingredients and remove old ingredient list."""
     ## we assume (hope!) all ingdicts are for the same ID
     id=ingdicts[0]['id']
     debug("Deleting ingredients for recipe with ID %s"%id,1)
     ings = self.get_ings(id)
     for i in ings:
         debug("Deleting ingredient: %s"%i.ingredient,5)
         self.delete_ing(i)
     for ingd in ingdicts:
         self.add_ing(ingd)
Esempio n. 24
0
 def toggle_widget (self, w, val):
     """Toggle the visibility of widget 'w'"""
     if val: method = 'hide'
     else: method = 'show'
     if type(w)==type(""): w = [w]
     for wn in w:
         widg = self.glade.get_widget(wn)
         if widg:
             getattr(widg,method)()
         else:
             debug('There is no widget %s'%wn,1)
Esempio n. 25
0
 def check_for_sleep(self):
     if self.terminated:
         raise Exception("Exporter Terminated!")
     while self.suspended:
         if self.terminated:
             debug("Thread Terminated!", 0)
             raise Exception("Exporter Terminated!")
         if use_threads:
             time.sleep(1)
         else:
             time.sleep(0.1)
Esempio n. 26
0
def get_fields (string, tuples):
    testtimer = TimeAction('mealmaster_importer.get_fields',10)
    debug("start get_fields",10)
    lst = []
    for t in tuples:
        if t:
            lst.append(string[t[0]:t[1]])
        else:
            lst.append("")
    testtimer.end()
    return lst
Esempio n. 27
0
 def send_email (self):
     self.url = "mailto:"
     if self.emailaddress: self.url += self.emailaddress
     if self.subject:
         self.url_append('subject',self.subject)
     if self.body:
         self.url_append('body',self.body)
     for a in self.attachments:
         self.url_append('attachment',a)              
     debug('launching URL %s'%self.url,0)
     gglobals.launch_url(self.url)
Esempio n. 28
0
 def handle_group (self, groupm):
     """Start a new ingredient group."""
     testtimer = TimeAction('mealmaster_importer.handle_group',10)
     debug("start handle_group",10)
     # the only group of the match will contain
     # the name of the group. We'll put it into
     # a more sane title case (MealMaster defaults
     # to all caps
     name = groupm.groups()[1].title()
     self.group=name
     if re.match('^[^A-Za-z]*$',self.group): self.group=None
     testtimer.end()
Esempio n. 29
0
def field_match (strings, tup, matcher):
    testtimer = TimeAction('mealmaster_importer.field_match',10)
    debug("start field_match",10)
    if type(matcher)==type(""):
        matcher=re.compile(matcher)
    for f in [s[tup[0]:tup[1]] for s in strings]:
        #f=s[tup[0]:tup[1]]
        if f and not matcher.match(f):
            testtimer.end()
            return False
    testtimer.end()
    return True
Esempio n. 30
0
 def __init__ (self, rd, recipe_table, out, conv=None):
     debug('rtf_exporter_multidoc starting!',5)
     self.doc = PyRTF.Document()
     exporter.ExporterMultirec.__init__(self,
                                        rd,
                                        recipe_table,
                                        out,
                                        one_file=True, ext='rtf',
                                        exporter=rtf_exporter,
                                        exporter_kwargs={'doc':self.doc,
                                                         'multidoc':True})        
     debug('rtf_exporter_multidoc done!',5)
Esempio n. 31
0
 def finish_ing (self):
     timeaction = TimeAction('importer.finish_ing 1',10)
     # Strip whitespace...
     for key in ['item','ingkey','unit']:
         if self.ing.has_key(key):
             self.ing[key]=re.sub('\s+',' ',self.ing[key]).strip()
     if not (
         (self.ing.has_key('refid') and
          self.ing['refid'])
         or
         (self.ing.has_key('ingkey') and
          self.ing['ingkey'])
         ):
         #self.ing['ingkey']=self.km.get_key(self.ing['item'],0.9)
         if self.ing.has_key('item'):
             self.ing['ingkey']=self.km.get_key_fast(self.ing['item'])
         else:
             debug('Ingredient has no item! %s'%self.ing,-1)
     timeaction.end()
     # if we have an amount (and it's not None), let's convert it
     # to a number
     if self.ing.has_key('amount') and self.ing['amount']\
            and not self.ing.has_key('rangeamount'):
         if convert.RANGE_MATCHER.search(str(self.ing['amount'])):
             self.ing['amount'],self.ing['rangeamount']=parse_range(self.ing['amount'])
     if self.ing.has_key('amount'):
         self.ing['amount']=convert.frac_to_float(
             self.ing['amount']
             )
     if self.ing.has_key('rangeamount'):
         self.ing['rangeamount']=convert.frac_to_float(
             self.ing['rangeamount']
             )
     timeaction = TimeAction('importer.commit_ing 2',10)
     if not (self.ing.has_key('position') and self.ing['position']):
         self.ing['position']=self.position
         self.position+=1
     timeaction.end()
     timeaction = TimeAction('importer.commit_ing 3',10)
     if self.group:
         self.ing['inggroup']=self.group
     timeaction.end()
     timeaction = TimeAction('importer.commit_ing 4',10)
     self.added_ings.append(self.ing); self.ing = {}
     timeaction.end()
Esempio n. 32
0
 def commit_rec(self):
     """Commit our recipe to our database."""
     testtimer = TimeAction('mealmaster_importer.commit_rec', 10)
     if self.committed: return
     debug("start _commit_rec", 5)
     self.instr = self.unwrap_lines(self.instr)
     self.mod = self.unwrap_lines(self.mod)
     self.rec['instructions'] = self.instr
     if self.mod:
         self.rec['modifications'] = self.mod
     self.parse_inglist()
     if self.source:
         self.rec['source'] = self.source
     importer.Importer.commit_rec(self)
     # blank rec
     self.committed = True
     self.in_variation = False
     testtimer.end()
Esempio n. 33
0
 def reassign_buttons (self, pausecb=None, stopcb=None):
     debug('reassign_buttons called with pausecb=%s, stopcb=%s'%(pausecb,stopcb),1)
     while self.custom_pause_handlers:
         h=self.custom_pause_handlers.pop()
         if self.pause.handler_is_connected(h):
             self.pause.disconnect(h)
     if pausecb:
         self.pause.connect('toggled',pausecb)
         self.pause.set_property('visible',True)
     else:
         self.pause.set_property('visible',False)
     while self.custom_stop_handlers:
         h=self.custom_stop_handlers.pop()
         if self.stop.handler_is_connected(h):
             self.stop.disconnect(h)
     if stopcb:
         self.stop.connect('clicked',stopcb)
         #self.stop.connect('clicked',self.cancelcb)
         self.stop.set_property('visible',True)
     else:
         self.stop.set_property('visible',False)
Esempio n. 34
0
 def add_ing(self, ingdict):
     """Add ingredient to ingredients_table based on ingdict and return
     ingredient object. Ingdict contains:
     id: recipe_id
     unit: unit
     item: description
     key: keyed descriptor
     alternative: not yet implemented (alternative)
     #optional: yes|no
     optional: True|False (boolean)
     position: INTEGER [position in list]
     refid: id of reference recipe. If ref is provided, everything
            else is irrelevant except for amount.
     """
     self.changed = True
     debug('adding to ingredients_table %s' % ingdict, 3)
     timer = TimeAction('rdatabase.add_ing 2', 5)
     if ingdict.has_key('amount') and not ingdict['amount']:
         del ingdict['amount']
     self.ingredients_table.append(ingdict)
     timer.end()
     debug('running ing hooks %s' % self.add_ing_hooks, 3)
     timer = TimeAction('rdatabase.add_ing 3', 5)
     if self.add_ing_hooks:
         self.run_hooks(self.add_ing_hooks, self.ingredients_table[-1])
     timer.end()
     debug('done with ing hooks', 3)
     return self.ingredients_table[-1]
Esempio n. 35
0
 def __init__(self, rows, titles=None):
     """Handed a list of data, we create a simple treeview.  The
     rules are simple. Each row can be a LIST in which case it is
     taken to be a list of columns (and each LIST is assumed to be
     the same length). Alternatively, each row can be an item, in
     which case there is only one column. All items must produce a
     string with str(item)."""
     debug('QuickTree got rows: %s' % rows, 0)
     Gtk.ScrolledWindow.__init__(self)
     self.tv = Gtk.TreeView()
     self.rows = rows
     self.titles = titles
     if self.rows:
         first = self.rows[0]
         if type(first) != type(()) and type(first) != type([]):
             debug('Mappifying!', 0)
             self.rows = [[x] for x in self.rows]
         self.setup_columns()
         self.setup_model()
     self.add(self.tv)
     self.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
     self.show_all()
Esempio n. 36
0
def find_columns(strings, char=" "):
    testtimer = TimeAction('mealmaster_importer.find_columns', 10)
    """Return a list of character indices that match char for each string in strings."""
    debug("start find_columns", 10)
    # we start with the columns in the first string
    if not strings:
        return None
    strings = strings[0:]
    strings.sort(lambda x, y: len(x) > len(y))
    columns = [
        match.start() for match in re.finditer(re.escape(char), strings[0])
    ]
    if len(strings) == 1:
        return columns
    # we eliminate all columns that aren't blank for every string
    for s in strings:
        for c in columns[0:]:  # we'll be modifying columns
            if c < len(s) and s[c] != char:
                columns.remove(c)
    columns.sort()
    testtimer.end()
    return columns
Esempio n. 37
0
    def do_run(self):
        with open(self.fn, 'rb') as fp:
            attrs = pl.load(fp)
        debug(f'Imported property list {attrs}')

        plist = NSKeyedArchiverPlist.to_dict(attrs)
        attrDict = plist['attributeDictionary']

        if 'title' in attrDict and attrDict['title'].strip():
            self.start_rec()

            self.rec['title'] = attrDict['title'].strip()
            if 'instructions' in attrDict:
                self.rec['instructions'] = attrDict['instructions'].strip()
            if 'sourceAsString' in attrDict:
                self.rec['source'] = attrDict['sourceAsString'].strip()
            # 2021-05-09 Not sure about mapping rating
            if 'rating' in attrDict:
                self.rec['rating'] = attrDict['rating']
            # 2121-06-09 RecipeBox data model seems to allow multiple categories, like tags
            # Pick the first category
            if 'categories' in plist and len(plist['categories']) > 0:
                it = iter(plist['categories'])
                self.rec['category'] = next(it)['RBCategoryObjectName'].strip()
            if 'ingredientsListing' in attrDict:
                for l in attrDict['ingredientsListing'].strip().splitlines():
                    l = l.strip()
                    if len(l) > 0:
                        quantity, unit, ingredient = '', '', ''
                        parsed = self.rd.parse_ingredient(l,
                                                          conv=self.conv,
                                                          get_key=False)
                        if parsed and parsed.get('amount', '') and parsed.get(
                                'item', ''):
                            quantity = str(parsed['amount'])
                            unit = parsed.get('unit', '')
                            ingredient = parsed['item']
                            debug(
                                f'Parsed from ingredient string "{l}": quantity={quantity}, unit={unit}, ingredient={ingredient}'
                            )
                        if quantity.strip() or unit.strip(
                        ) or ingredient.strip():
                            self.start_ing()
                            if quantity:
                                self.add_amt(quantity)
                            if unit:
                                self.add_unit(unit)
                            optm = _OPT_MATCHER.match(ingredient)
                            if optm:
                                item = optm.groups()[0]
                                self.ing['optional'] = True
                            else:
                                item = ingredient
                            self.add_item(item)
                            debug("Committing ingredient: %s" % self.ing, 6)
                            self.commit_ing()

            self.commit_rec()
            self._run_cleanup_()
Esempio n. 38
0
def parse_range (number_string):
    """Parse a range and return a tuple with a low and high number as floats.

    We will also parse regular numbers, in which case the tuple will
    only have one item.
    """
    if type(number_string) in [int,float]:
        return (float(number_string),None)
    nums=convert.RANGE_MATCHER.split(number_string.strip())
    if len(nums) > 2:
        debug('WARNING: String %s does not appear to be a normal range.'%number_string,0)
        retval = map(convert.frac_to_float,nums)
        # filter any non-numbers before we take 1 and 3
        retval = filter(lambda x: x, retval)        
        if len(retval) > 2:
            debug('Parsing range as %s-%s'%(retval[0],retval[-1]),0)
            retval = retval[0],retval[-1]
    else:
        retval = map(convert.frac_to_float,nums)
    if len(retval)==2: return tuple(retval)
    elif len(retval)==1: return tuple(retval+[None])
    else: return (None,None)
Esempio n. 39
0
 def ingredient_parser(self, s, conv=None, get_key=True):
     """Handed a string, we hand back a dictionary (sans recipe ID)"""
     debug('ingredient_parser handed: %s' % s, 0)
     s = unicode(s)  # convert to unicode so our ING MATCHER works properly
     s = s.strip("\n\t #*+-")
     debug('ingredient_parser handed: "%s"' % s, 1)
     m = convert.ING_MATCHER.match(s)
     if m:
         debug('ingredient parser successfully parsed %s' % s, 1)
         d = {}
         g = m.groups()
         a, u, i = (g[convert.ING_MATCHER_AMT_GROUP],
                    g[convert.ING_MATCHER_UNIT_GROUP],
                    g[convert.ING_MATCHER_ITEM_GROUP])
         if a:
             asplit = convert.RANGE_MATCHER.split(a)
             if len(asplit) == 2:
                 d['amount'] = convert.frac_to_float(asplit[0].strip())
                 d['rangeamount'] = convert.frac_to_float(asplit[1].strip())
             else:
                 d['amount'] = convert.frac_to_float(a.strip())
         if u:
             if conv and conv.unit_dict.has_key(u.strip()):
                 d['unit'] = conv.unit_dict[u.strip()]
             else:
                 d['unit'] = u.strip()
         if i:
             optmatch = re.search('\s+\(?[Oo]ptional\)?', i)
             if optmatch:
                 d['optional'] = True
                 i = i[0:optmatch.start()] + i[optmatch.end():]
             d['item'] = i.strip()
             if get_key: d['ingkey'] = self.km.get_key(i.strip())
         debug('ingredient_parser returning: %s' % d, 0)
         return d
     else:
         debug("Unable to parse %s" % s, 0)
         return None
 def handle_ingline(self, line):
     if self.ing_or_matcher.match(line):
         self.in_or = True
         return
     amt = line[slice(*self.amt_col)].strip()
     unit = line[slice(*self.unit_col)].strip()
     itm = line[self.itm_col[0]:].strip()
     gm = self.ing_group_matcher.match(itm)
     if gm:
         if self.ing:
             self.commit_ing()
         self.group = gm.groups()[1]
         # undo grouping if it has no letters...
         if re.match('^[^A-Za-z]*$', self.group):
             self.group = None
         return
     if amt or unit:
         if self.in_or:
             self.ing['optional'] = True
         if self.ing:
             self.commit_ing()
         self.start_ing()
         if self.in_or:
             self.ing['optional'] = True
             self.in_or = False
         self.add_amt(amt)
         self.add_unit(unit)
         self.add_item(itm)
         return
     elif self.ing and 'item' in self.ing:
         # otherwise, we assume we are a continuation and
         # add onto the previous item
         self.ing['item'] = self.ing['item'] + ' ' + itm.strip()
     else:
         debug(
             '"%s" in the midst of ingredients looks like instructions!' %
             itm.strip(), 2)
         self.instr += "\n" + itm.strip()
Esempio n. 41
0
def create_thumbnail(path, thumbpath, uri, type="large"):
    """Create a thumbnail at path and return path"""
    mtime = os.stat(path)[8]
    size = os.path.getsize(path)
    if int(size) > MAX_THUMBSIZE:
        debug('File too large!', 0)
        return None
    try:
        im = Image.open(path)
    except:
        return None
    w, h = im.size
    if type == 'large':
        geo = (256, 256)
    else:
        geo = (128, 128)
    im.thumbnail(geo)
    # set thumbnail attributes
    info = {}
    info['Thumb::MTime'] = str(mtime)
    info['Thumb::Image::Width'] = str(w)
    info['Thumb::Image::Height'] = str(h)
    info['Software'] = 'Gourmet Recipe Manager'
    info['URI'] = str(uri)
    # now we must create our image guy
    try:
        from PIL import PngImagePlugin
    except ImportError:
        import PngImagePlugin
    pnginfo = PngImagePlugin.PngInfo()

    for k, v in list(info.items()):
        pnginfo.add_text(k, v)
    im.save(thumbpath, pnginfo=pnginfo)
    # we must make all thumbnails permissions 700
    os.chmod(thumbpath, 0o700)
    return thumbpath
Esempio n. 42
0
 def compile_regexps(self):
     """Compile our regular expressions for the rezkonv format.
     """
     testtimer = TimeAction('mealmaster_importer.compile_regexps', 10)
     debug("start compile_regexps", 5)
     plaintext_importer.TextImporter.compile_regexps(self)
     self.start_matcher = re.compile(rzc_start_pattern)
     self.end_matcher = re.compile(r"^[=M-][=M-][=M-][=M-][=M-]\s*$")
     self.group_matcher = re.compile(
         r"^\s*([=M-][=M-][=M-][=M-][=M-]+)-*\s*([^-]+)\s*-*",
         re.IGNORECASE)
     self.ing_cont_matcher = re.compile(r"^\s*[-;]")
     self.ing_opt_matcher = re.compile(r"(.+?)\s*\(?\s*optional\)?\s*$",
                                       re.IGNORECASE)
     # or or the German, oder
     self.ing_or_matcher = re.compile(r"^[-= ]*[Oo][dD]?[eE]?[Rr][-= ]*$",
                                      re.IGNORECASE)
     self.variation_matcher = re.compile(
         r"^\s*(VARIATION|HINT|NOTES?|VERÄNDERUNG|VARIANTEN|TIPANMERKUNGEN)(:.*)?",
         re.IGNORECASE)
     # a crude ingredient matcher -- we look for two numbers, intermingled with spaces
     # followed by a space or more, followed by a two digit unit (or spaces)
     self.ing_num_matcher = re.compile(
         r"^\s*%(top)s%(num)s+\s+[A-Za-z ][A-Za-z ]? .*" % {
             'top': convert.DIVIDEND_REGEXP,
             'num': convert.NUMBER_REGEXP
         }, re.IGNORECASE)
     self.amt_field_matcher = convert.NUMBER_MATCHER
     # we build a regexp to match anything that looks like
     # this: ^\s*ATTRIBUTE: Some entry of some kind...$
     attrmatch = r"^\s*("
     self.mmf = rzc
     for k in list(self.mmf.recattrs.keys()):
         attrmatch += "%s|" % re.escape(k)
     attrmatch = r"%s):\s*(.*)\s*$" % attrmatch[0:-1]
     self.attr_matcher = re.compile(attrmatch)
     testtimer.end()
Esempio n. 43
0
def zipfile_to_filelist(fi, progress=None, name="zipfile"):
    """Take our zipfile and return a list of files.

    We're quite liberal in what we allow fi to be.  If fi is a string,
    we open it as a filename.  if fi is a file object, we handle it,
    even if it's an icky file object that needs some messy
    manipulation to work (i.e. a urllib.urlopen() object).
    """
    # handle filename
    if type(fi) in [unicode, str]:
        fi = open(fi, 'rb')
    # handle unseekable
    elif not hasattr(fi, 'seek'):
        # slurp up the file into a StringIO so we can seek within it
        debug('Slurping up file into StringIO', 1)
        tmpfi = StringIO.StringIO(
            read_socket_w_progress(fi, progress, _('Loading zip archive')))
        fi.close()
        fi = tmpfi
    # and now we actually do our work...
    debug('ZipFile(fi)', 1)
    zf = zipfile.ZipFile(fi)
    flist = []
    fbase = os.path.join(tempfile.tempdir, name)
    while os.path.exists(fbase):
        fbase = add_to_fn(fbase)
    os.mkdir(fbase)
    nlist = zf.namelist()
    totlen = float(len(nlist))
    for i, n in enumerate(nlist):
        debug('Unzipping item %s' % i, 1)
        if progress: progress(float(i) / totlen, _("Unzipping zip archive"))
        fn = os.path.join(fbase, n)
        ifi = open(fn, 'wb')
        ifi.write(zf.read(n))
        ifi.close()
        flist.append(fn)
    zf.close()
    debug('zipfile returning filelist %s' % flist, 1)
    return flist
Esempio n. 44
0
 def set_sensitive (self,w,val):
     debug('set_sensitive',0)
     if not w:
         #import traceback; traceback.print_stack()
         #print 'No widget to sensitize',w,val
         return
     try:
         w.set_sensitive(val)
         debug('%s.set_sensitive succeeded'%w,0)
     except AttributeError:
         # 2.6 will give gtk.Action a set_sensitive property, but for now...
         #if type(w)==gtk.Action:
         for p in w.get_proxies():
             debug('setting %s sensitivity to %s'%(w,val),0)
             #p.set_sensitive(val)
             p.set_property('sensitive',val)
Esempio n. 45
0
 def do_add_rec(self, rdict):
     """Add a recipe based on a dictionary of properties and values."""
     self.changed = True
     if not rdict.has_key('deleted'):
         rdict['deleted'] = 0
     if not rdict.has_key('id'):
         rdict['id'] = self.new_id()
     try:
         debug('Adding recipe %s' % rdict, 4)
         self.recipe_table.append(rdict)
         debug('Running add hooks %s' % self.add_hooks, 2)
         if self.add_hooks:
             self.run_hooks(self.add_hooks, self.recipe_table[-1])
         return self.recipe_table[-1]
     except:
         debug("There was a problem adding recipe%s" % rdict, -1)
         raise
Esempio n. 46
0
 def switch_context(self, hid):
     # set sensitivity for current context
     debug('switching context...', 0)
     self.get_history().gui_update()
Esempio n. 47
0
 def remove(self, obj):
     debug('Removing %s' % obj, 0)
     list.remove(self, obj)
     self.gui_update()
Esempio n. 48
0
 def gui_update(self):
     debug('gui_update', 0)
     if len(self) >= 1:
         undoables = [x.is_undo for x in self]
         if False in undoables:
             self.set_sensitive(self.undo_widget, True)
             debug('Sensitizing undo_widget', 0)
         else:
             self.set_sensitive(self.undo_widget, False)
             debug('Desensizing undo_widget', 0)
         if True in undoables:
             debug('Sensitizing redo_widget', 0)
             self.set_sensitive(self.redo_widget, True)
         else:
             debug('Desensitizing redo widget', 0)
             self.set_sensitive(self.redo_widget, False)
         if self[-1].reapplyable:
             debug('Sensitizing "reapply" widgets', 0)
             self.set_sensitive(self.reapply_widget, True)
             if self[-1].reapply_name:
                 if type(self.reapply_widget) == Gtk.MenuItem:
                     alabel = self.reapply_widget.get_children()[0]
                     alabel.set_text_with_mnemonic(self[-1].reapply_name)
                     alabel.set_use_markup(True)
     else:
         debug('Nothing to undo, desensitizing widgets', 0)
         self.set_sensitive(self.redo_widget, False)
         self.set_sensitive(self.undo_widget, False)
         self.set_sensitive(self.reapply_widget, False)
Esempio n. 49
0
 def reapply(self, *args):
     debug('Reapplying', 0)
     action = self[-1]
     action.reapply()
     for h in self.action_hooks:
         h(self, action, 'reapply')
Esempio n. 50
0
    sc = Gtk.Button('show changes')
    vb = Gtk.VBox()
    bb = Gtk.HButtonBox()
    bb.add(ub)
    bb.add(rb)
    bb.add(sc)
    vb.add(bb)
    vb.add(e)
    vb.add(tv)
    vb.add(sb)
    sb.show()
    w.add(vb)
    uhl = UndoHistoryList(ub, rb, signal='clicked')
    UndoableTextView(tv, uhl)
    UndoableEntry(e, uhl)
    UndoableGenericWidget(sb, uhl)
    w.show_all()
    w.connect('delete-event', lambda *args: Gtk.main_quit())

    def show_changes(*args):
        for c in uhl:
            if hasattr(c, 'initial_text'):
                print(c, ' initial: ', c.initial_text, ' current: ', c.text)
            else:
                print(c)

    ub.connect('clicked', lambda *args: debug('Undo clicked!', 0))
    sc.connect('clicked', show_changes)
    rb.connect('clicked', lambda *args: debug('Redo clicked!', 0))
    Gtk.main()
Esempio n. 51
0
def split_fields(strings, char=" "):
    testtimer = TimeAction('mealmaster_importer.split_fields', 10)
    debug("start split_fields", 10)
    fields = find_fields(strings, char)
    testtimer.end()
Esempio n. 52
0
    def run(self):
        """Import our recipe to our database.

        This must be called after self.d is already populated by scraping
        our web page.
        """
        debug('Scraping url %s' % self.url, 0)
        try:
            self.d = scrape_url(self.url, progress=self.prog)
        except:
            print('Trouble using default recipe filter to download %s' %
                  self.url)
            traceback.print_exc()
            print('We will use a generic importer instead.')
            self.d = {}
        debug('Scraping url returned %s' % self.d, 0)
        do_generic = not self.d
        if not do_generic:
            try:
                if self.prog:
                    self.prog(-1, 'Parsing webpage based on template.')
                self.get_url_based_on_template()
            except:
                if not self.interactive: raise
                do_generic = True
                print("""Automated HTML Import failed
                ***Falling back to generic import***

                We were attempting to scrape using the following rules:
                """)
                print(self.d)
                print("""The following exception was raised:""")
                traceback.print_exc()
                print(
                    """If you think automated import should have worked for the webpage you
                were importing, copy the output starting at "Automated HTML Import failed" into
                a bug report and submit it at the GitHub site

                https://github.com/thinkle/gourmet/issues

                Sorry automated import didn't work. I hope you like
                the new generic web importer!
                """)
        if do_generic:
            if not self.interactive:
                raise Exception("Unable to find importer for %s" % self.url)
            # Interactive we go...
            self.prog(
                -1,
                _("Don't recognize this webpage. Using generic importer..."))
            gs = GenericScraper()
            text, images = gs.scrape_url(self.url, progress=self.prog)
            if not text and not images:
                raise Exception("Unable to obtain text or images from url %s" %
                                self.url)
            from . import interactive_importer
            ii = interactive_importer.InteractiveImporter(self.rd)
            ii.set_text(text)
            ii.add_attribute('link', self.url)
            ii.set_images(images)
            ii.run()
            if self.prog: self.prog(1, _('Import complete.'))
            return
    def handle_line(self, line):
        if self.rec_start_matcher.match(line):
            debug('rec_start! %s' % line, 0)
            self.looking_for_title = True
            if self.rec: self.commit_rec()
            self.instr = ""
            self.mods = ""
            self.in_instructions = False
            self.in_mods = False
            self.in_ings = False
            self.in_attrs = False
            self.start_rec()
            return
        if self.reccol_headers:
            # we try to parse underlining after our standard ing headers.
            rcm = self.rec_col_underline_matcher.match(line)
            # if there is no underlining, use our headers themselves for fields
            if not rcm: rcm = self.reccol_headers
            debug('Found ing columns', 0)
            self.get_ing_cols(rcm)
            self.in_ings = True
            self.reccol_headers = False

        if self.dash_matcher.match(line): return

        rcm = self.rec_col_matcher.match(line)
        if rcm:
            self.reccol_headers = rcm
            self.looking_for_title = False
            self.in_attrs = False
            self.last_attr = ""
            return
        if self.blank_matcher.match(line):
            # blank line ends ingredients
            if self.in_ings:
                debug('blank line, end of ings', 0)
                self.in_ings = False
                self.in_instructions = True
                if self.ing: self.commit_ing()
            if self.in_instructions:
                debug('blank line added to instructions: %s' % line, 0)
                if self.in_mods: self.mods += "\n"
                else: self.instr += "\n"
            return
        if self.looking_for_title:
            debug('found my title! %s' % line.strip(), 0)
            self.rec['title'] = line.strip()
            self.looking_for_title = False
            self.in_attrs = True
            return
        if self.in_ings:
            debug('handling ingredient line %s' % line, 0)
            self.handle_ingline(line)
            return
        if self.in_attrs:
            debug('handing attrline %s' % line, 0)
            self.handle_attribute(line)
            return
        else:
            self.in_instructions = True
            if self.mods_matcher.match(line):
                self.in_mods = True
            if self.in_mods:
                debug('handling modifications line %s' % line, 0)
                self.add_to_attr('mods', line)
            else:
                debug('handling instructions line %s' % line, 0)
                self.add_to_attr('instr', line)
Esempio n. 54
0
    def handle_line(self, l):
        """Handle an individual line of a mealmaster file.

        We're quite loose at handling mealmaster files. We look at
        each line and determine what it is most likely to be:
        ingredients and instructions can be intermingled: instructions
        will simply be added to the instructions and ingredients to
        the ingredient list.  This may result in loss of information
        (for instructions that specifically follow ingredients) or in
        mis-parsing (for instructions that look like ingredients). But
        we're following, more or less, the specs laid out here
        <http://phprecipebook.sourceforge.net/docs/MM_SPEC.DOC>"""

        testtimer = TimeAction('mealmaster_importer.handle_line', 10)
        debug("start handle_line", 10)
        #gt.gtk_update()
        if self.start_matcher.match(l):
            debug("recipe start %s" % l, 4)
            if 'Windows Gourmet' in l:
                self.unit_length = 15
            self.new_rec()
            self.last_line_was = 'new_rec'
            self.in_variation = False
            return
        if self.end_matcher.match(l):
            debug("recipe end %s" % l, 4)
            self.commit_rec()
            self.last_line_was = 'end_rec'
            return
        groupm = self.group_matcher.match(l)
        if groupm:
            debug("new group %s" % l, 4)
            self.handle_group(groupm)
            self.last_line_was = 'group'
            return
        attrm = self.attr_matcher.match(l)
        if attrm:
            debug('Found attribute in %s' % l, 4)
            attr, val = attrm.groups()
            debug("Writing attribute, %s=%s" % (attr, val), 4)
            self.rec[self.mmf.recattrs[attr]] = val.strip()
            self.last_line_was = 'attr'
            return
        if not self.instr and self.blank_matcher.match(l):
            debug('ignoring blank line before instructions', 4)
            self.last_line_was = 'blank'
            return
        if self.variation_matcher.match(l):
            debug('in variation', 4)
            self.in_variation = True
        if self.is_ingredient(l) and not self.in_variation:
            debug('in ingredient', 4)
            contm = self.ing_cont_matcher.match(l)
            if contm:
                # only continuations after ingredients are ingredients
                if self.ingrs and self.last_line_was == 'ingr':
                    debug('continuing %s' % self.ingrs[-1][0], 4)
                    continuation = " %s" % l[contm.end():].strip()
                    self.ingrs[-1][0] += continuation
                    self.last_line_was = 'ingr'
                else:
                    self.instr += l
                    self.last_line_was = 'instr'
            else:
                self.last_line_was = 'ingr'
                self.ingrs.append([l, self.group])
        else:
            ## otherwise, we assume a line of instructions
            if self.last_line_was == 'blank': add_blank = True
            else: add_blank = False
            if self.in_variation:
                debug('Adding to instructions: %s' % l, 4)
                self.last_line_was = 'mod'
                add_to = 'mod'
            else:
                debug('Adding to modifications: %s' % l, 4)
                self.last_line_was = 'instr'
                add_to = 'instr'
            if getattr(self, add_to):
                if add_blank:
                    setattr(self, add_to, getattr(self, add_to) + "\n")
                setattr(self, add_to, getattr(self, add_to) + l.strip() + "\n")
            else:
                setattr(self, add_to, l.strip() + "\n")
        testtimer.end()
Esempio n. 55
0
 def undo_action():
     debug('undoable_modify_ing unmodifying %s' % orig_dic, 2)
     self.modify_ing(ing, orig_dic)
     if make_visible: make_visible(ing, orig_dic)
Esempio n. 56
0
 def __init__(self):
     debug('recipeManager.__init__()', 3)
     RecData.__init__(self)
     self.km = keymanager.KeyManager(rm=self)
Esempio n. 57
0
    def get_url_based_on_template (self):
        """Get URL based on template stored in d
        """
        self.start_rec()
        # Set link
        self.rec['link']=self.url
        # Add webpage as source
        if self.add_webpage_source:
            # add Domain as source
            domain = self.url.split('/')[2]
            src=self.d.get('source',None)
            add_str = '(%s)'%domain
            if isinstance(src, list):
                src.append(add_str)
            elif src:
                src = [src, add_str]
            else:
                src = domain # no parens if we're the only source
            self.d['source']=src
        for k,v in list(self.d.items()):
            debug('processing %s:%s'%(k,v),1)
            if self.prog: self.prog(-1,_('Importing recipe'))
            # parsed ingredients...
            if k=='ingredient_parsed':
                if not isinstance(v, list):
                    v = [v]
                for ingdic in v:

                    if self.prog: self.prog(-1,_('Processing ingredients'))
                    # we take a special keyword, "text", which gets
                    # parsed
                    if 'text' in ingdic:
                        d = self.rd.parse_ingredient(ingdic['text'],conv=self.conv)
                        if d:
                            for dk,dv in list(d.items()):
                                if dk not in ingdic or not ingdic[dk]:
                                    ingdic[dk]=dv
                        elif 'item' not in ingdic:
                            ingdic['item']=ingdic['text']
                        del ingdic['text']
                    self.start_ing(**ingdic)
                    self.commit_ing()
                continue

            # Listy stuff...
            elif isinstance(v, list):
                if k in self.JOIN_AS_PARAGRAPHS: v = "\n".join(v)
                else: v = " ".join(v)

            # Ingredients in blocks
            if k == 'ingredient_block':
                for l in v.split('\n'):
                    if self.prog: self.prog(-1,_('Processing ingredients.'))
                    dic=self.rd.parse_ingredient(l,conv=self.conv)
                    if dic:
                        self.start_ing(**dic)
                        self.commit_ing()

            elif k == 'image':
                try:
                    if v: img = get_image_from_tag(v,self.url)
                except:
                    print('Error retrieving image')
                    print('tried to retrieve image from %s'%v)
                else:
                    if img:
                        self.rec['image'] = img
            else: self.rec[k]=v
        #print 'COMMITTING RECIPE',self.rec
        self.commit_rec()
        if self.prog: self.prog(1,_('Import complete.'))
Esempio n. 58
0
 def do_action():
     debug('undoable_modify_ing modifying %s' % dic, 2)
     self.modify_ing(ing, dic)
     if make_visible: make_visible(ing, dic)
Esempio n. 59
0
 def characters(self, ch):
     debug('adding to %s bufs: %s' % (len(self.bufs), ch), 0)
     for buf in self.bufs:
         setattr(self, buf, getattr(self, buf) + ch)
Esempio n. 60
0
 def write_grouphead(self, name):
     debug('write_grouphead called with %s' % name, 0)
     group = (name, [])
     self.ings.append(group)  # add to our master
     self.ings = group[1]  # change current list to group list