def connect_read_only(): from frappe.database import Database local.read_only_db = Database(local.conf.slave_host, local.conf.slave_db_name, local.conf.slave_db_password) # swap db connections local.master_db = local.db local.db = local.read_only_db
def connect(site=None, db_name=None): """Connect to site database instance. :param site: If site is given, calls `frappe.init`. :param db_name: Optional. Will use from `site_config.json`.""" from frappe.database import Database if site: init(site) local.db = Database(user=db_name or local.conf.db_name) set_user("Administrator")
def connect_replica(): from frappe.database import Database user = local.conf.db_name password = local.conf.db_password if local.conf.different_credentials_for_replica: user = local.conf.replica_db_name password = local.conf.replica_db_password local.replica_db = Database(host=local.conf.replica_host, user=user, password=password) # swap db connections local.primary_db = local.db local.db = local.replica_db
class HelpDatabase(object): def __init__(self): self.make_database() self.connect() def make_database(self): dbman = DbManager(get_root_connection()) # make database if not help_db_name in dbman.get_database_list(): dbman.create_user(help_db_name, help_db_name) dbman.create_database(help_db_name) dbman.grant_all_privileges(help_db_name, help_db_name) dbman.flush_privileges() def connect(self): self.db = Database(user=help_db_name, password=help_db_name) def make_table(self): if not 'help' in self.db.get_tables(): self.db.sql( '''create table help(path text, content text, fulltext(content)) COLLATE=utf8mb4_unicode_ci ENGINE=MyISAM CHARACTER SET=utf8mb4''') def search(self, words): return self.db.sql( 'select path, content from help where match(content) against (%s) limit 10', words) def sync_pages(self): self.db.sql('truncate help') for app in os.listdir('../apps'): docs_folder = '../apps/{app}/{app}/docs/user'.format(app=app) if os.path.exists(docs_folder): for basepath, folders, files in os.walk(docs_folder): for fname in files: if fname.rsplit('.', 1)[-1] in ('md', 'html'): fpath = os.path.join(basepath, fname) with open(fpath, 'r') as f: #relpath = os.path.relpath(fpath, '../apps/{app}'.format(app=app)) self.db.sql( '''insert into help(path, content) values (%s, %s)''', (fpath, f.read()))
def get_conn(): db_instance = Database() conversions.update({ FIELD_TYPE.NEWDECIMAL: float, FIELD_TYPE.DATETIME: frappe.utils.get_datetime, UnicodeWithAttrs: conversions[text_type] }) return pymysql.connect( db_instance.host, db_instance.user, db_instance.password, charset='utf8mb4', use_unicode=True, conv=conversions, local_infile=db_instance.local_infile, db=db_instance.user, )
class HelpDatabase(object): def __init__(self): self.make_database() self.connect() def make_database(self): dbman = DbManager(get_root_connection()) # make database if not help_db_name in dbman.get_database_list(): dbman.create_user(help_db_name, help_db_name) dbman.create_database(help_db_name) dbman.grant_all_privileges(help_db_name, help_db_name) dbman.flush_privileges() def connect(self): self.db = Database(user=help_db_name, password=help_db_name) def make_table(self): if not 'help' in self.db.get_tables(): self.db.sql('''create table help(path text, content text, fulltext(content)) COLLATE=utf8mb4_unicode_ci ENGINE=MyISAM CHARACTER SET=utf8mb4''') def search(self, words): return self.db.sql('select path, content from help where match(content) against (%s) limit 10', words) def sync_pages(self): self.db.sql('truncate help') for app in os.listdir('../apps'): docs_folder = '../apps/{app}/{app}/docs/user'.format(app=app) if os.path.exists(docs_folder): for basepath, folders, files in os.walk(docs_folder): for fname in files: if fname.rsplit('.', 1)[-1] in ('md', 'html'): fpath = os.path.join(basepath, fname) with open(fpath, 'r') as f: #relpath = os.path.relpath(fpath, '../apps/{app}'.format(app=app)) self.db.sql('''insert into help(path, content) values (%s, %s)''', (fpath, f.read()))
def migrate(): frappe.flags.mute_emails = True source = Database(user='******', password='******') # users = source.sql('select * from tabUser', as_dict=1) # for u in users: # frappe.get_doc(dict( # doctype='User', # name=u.name, # first_name=u.first_name, # last_name=u.last_name, # email=u.email # )).insert(ignore_if_duplicate=True) # print u.name # frappe.db.sql('delete from `tabService Provider`') # partners = source.sql('select * from `tabFrappe Partner`', as_dict=True) # for p in partners: # d = frappe.get_doc(dict( # doctype='Service Provider', # title=p.partner_name, # country=p.country, # image=p.logo, # introduction=p.introduction, # details=markdown(p.description), # address=p.partner_address, # discuss_ids=p.community_members, # website=p.partner_website, # github_id=p.github_id, # owner=p.owner, # creation=p.creation, # email= p.email, # phone=p.phone, # route=p.route, # show_in_website=p.show_in_website # )).insert(ignore_if_duplicate=True, ignore_mandatory=True) # print d.name # jobs = source.sql('select * from `tabFrappe Job`', as_dict=True) # frappe.db.sql('delete from `tabPortal Job`') # for j in jobs: # if not frappe.db.exists('Country', j.country): # frappe.get_doc(dict(doctype='Country', country_name=j.country)).insert() # d = frappe.get_doc(dict( # doctype='Portal Job', # title=j.job_title, # company_name=j.company_name, # country=j.country, # status='Open' if j.status=='Assigned' else j.status, # job_type={ # 'ERP Implementation': 'Implementation', # 'Core Development': 'Feature Development', # 'Website Development': 'Website Development', # 'Other': 'App Development' # }.get(j.job_type, None) or j.job_type, # description= markdown(j.job_detail), # owner=j.owner, # creation=j.creation, # route=j.route, # show_in_website=j.show_in_website # )).insert(ignore_if_duplicate=True, ignore_mandatory=True) # print d.name apps = source.sql('select * from `tabFrappe App`', as_dict=True) frappe.db.sql('delete from `tabFrappe App`') for a in apps: d = frappe.get_doc(dict( doctype='Frappe App', app_name = a.app_name, badge = a.badge, category = a.category, route = a.route, url = a.url, repository_url = a.repository_url, published = 1, description = markdown(a.description), owner=a.owner, creation=a.creation, )).insert(ignore_if_duplicate=True, ignore_mandatory=True) print d.name
def connect(self): if self.global_help_setup: self.db = Database(user=self.help_db_name, password=self.help_db_name) else: self.db = frappe.db
class HelpDatabase(object): def __init__(self): self.global_help_setup = frappe.conf.get('global_help_setup') if self.global_help_setup: bench_name = os.path.basename(os.path.abspath(frappe.get_app_path('frappe')).split('/apps/')[0]) self.help_db_name = hashlib.sha224(bench_name).hexdigest()[:15] def make_database(self): '''make database for global help setup''' if not self.global_help_setup: return dbman = DbManager(get_root_connection()) dbman.drop_database(self.help_db_name) # make database if not self.help_db_name in dbman.get_database_list(): try: dbman.create_user(self.help_db_name, self.help_db_name) except Exception as e: # user already exists if e.args[0] != 1396: raise dbman.create_database(self.help_db_name) dbman.grant_all_privileges(self.help_db_name, self.help_db_name) dbman.flush_privileges() def connect(self): if self.global_help_setup: self.db = Database(user=self.help_db_name, password=self.help_db_name) else: self.db = frappe.db def make_table(self): if not 'help' in self.db.get_tables(): self.db.sql('''create table help( path varchar(255), content text, title text, intro text, full_path text, fulltext(title), fulltext(content), index (path)) COLLATE=utf8mb4_unicode_ci ENGINE=MyISAM CHARACTER SET=utf8mb4''') def search(self, words): self.connect() return self.db.sql(''' select title, intro, path from help where title like %s union select title, intro, path from help where match(content) against (%s) limit 10''', ('%'+words+'%', words)) def get_content(self, path): self.connect() query = '''select title, content from help where path like "{path}%" order by path desc limit 1''' result = None if not path.endswith('index'): result = self.db.sql(query.format(path=os.path.join(path, 'index'))) if not result: result = self.db.sql(query.format(path=path)) return {'title':result[0][0], 'content':result[0][1]} if result else {} def sync_pages(self): self.db.sql('truncate help') doc_contents = '<ol>' apps = os.listdir('../apps') if self.global_help_setup else frappe.get_installed_apps() for app in apps: docs_folder = '../apps/{app}/{app}/docs/user'.format(app=app) self.out_base_path = '../apps/{app}/{app}/docs'.format(app=app) if os.path.exists(docs_folder): app_name = getattr(frappe.get_module(app), '__title__', None) or app.title() doc_contents += '<li><a data-path="/{app}/index">{app_name}</a></li>'.format( app=app, app_name=app_name) for basepath, folders, files in os.walk(docs_folder): files = self.reorder_files(files) for fname in files: if fname.rsplit('.', 1)[-1] in ('md', 'html'): fpath = os.path.join(basepath, fname) with open(fpath, 'r') as f: try: content = frappe.render_template(text_type(f.read(), 'utf-8'), {'docs_base_url': '/assets/{app}_docs'.format(app=app)}) relpath = self.get_out_path(fpath) relpath = relpath.replace("user", app) content = markdown(content) title = self.make_title(basepath, fname, content) intro = self.make_intro(content) content = self.make_content(content, fpath, relpath) self.db.sql('''insert into help(path, content, title, intro, full_path) values (%s, %s, %s, %s, %s)''', (relpath, content, title, intro, fpath)) except jinja2.exceptions.TemplateSyntaxError: print("Invalid Jinja Template for {0}. Skipping".format(fpath)) doc_contents += "</ol>" self.db.sql('''insert into help(path, content, title, intro, full_path) values (%s, %s, %s, %s, %s)''', ('/documentation/index', doc_contents, 'Documentation', '', '')) def make_title(self, basepath, filename, html): if '<h1>' in html: title = html.split("<h1>", 1)[1].split("</h1>", 1)[0] elif 'index' in filename: title = basepath.rsplit('/', 1)[-1].title().replace("-", " ") else: title = filename.rsplit('.', 1)[0].title().replace("-", " ") return title def make_intro(self, html): intro = "" if '<p>' in html: intro = html.split('<p>', 1)[1].split('</p>', 1)[0] if 'Duration' in html: intro = "Help Video: " + intro return intro def make_content(self, html, path, relpath): if '<h1>' in html: html = html.split('</h1>', 1)[1] if '{next}' in html: html = html.replace('{next}', '') target = path.split('/', 3)[-1] app_name = path.split('/', 3)[2] html += get_improve_page_html(app_name, target) soup = BeautifulSoup(html, 'html.parser') for link in soup.find_all('a'): if link.has_attr('href'): url = link['href'] if '/user' in url: data_path = url[url.index('/user'):] if '.' in data_path: data_path = data_path[: data_path.rindex('.')] if data_path: link['data-path'] = data_path.replace("user", app_name) parent = self.get_parent(relpath) if parent: parent_tag = soup.new_tag('a') parent_tag.string = parent['title'] parent_tag['class'] = 'parent-link' parent_tag['data-path'] = parent['path'] soup.find().insert_before(parent_tag) return soup.prettify() def build_index(self): for data in self.db.sql('select path, full_path, content from help'): self.make_index(data[0], data[1], data[2]) def make_index(self, original_path, full_path, content): '''Make index from index.txt''' if '{index}' in content: path = os.path.dirname(full_path) files = [] # get files from index.txt index_path = os.path.join(path, "index.txt") if os.path.exists(index_path): with open(index_path, 'r') as f: files = f.read().splitlines() # files not in index.txt for f in os.listdir(path): if not os.path.isdir(os.path.join(path, f)): name, extn = f.rsplit('.', 1) if name not in files \ and name != 'index' and extn in ('md', 'html'): files.append(name) links_html = "<ol class='index-links'>" for line in files: fpath = os.path.join(os.path.dirname(original_path), line) title = self.db.sql('select title from help where path like %s', os.path.join(fpath, 'index') + '%') if not title: title = self.db.sql('select title from help where path like %s', fpath + '%') if title: title = title[0][0] links_html += "<li><a data-path='{fpath}'> {title} </a></li>".format( fpath=fpath, title=title) # else: # bad entries in .txt files # print fpath links_html += "</ol>" html = content.replace('{index}', links_html) self.db.sql('update help set content=%s where path=%s', (html, original_path)) def get_out_path(self, path): return '/' + os.path.relpath(path, self.out_base_path) def get_parent(self, child_path): if 'index' in child_path: child_path = child_path[: child_path.rindex('index')] if child_path[-1] == '/': child_path = child_path[:-1] child_path = child_path[: child_path.rindex('/')] out = None if child_path: parent_path = child_path + "/index" out = self.get_content(parent_path) #if parent is documentation root else: parent_path = "/documentation/index" out = {} out['title'] = "Documentation" if not out: return None out['path'] = parent_path return out def reorder_files(self, files): pos = 0 if 'index.md' in files: pos = files.index('index.md') elif 'index.html' in files: pos = files.index('index.html') if pos: files[0], files[pos] = files[pos], files[0] return files
class HelpDatabase(object): def __init__(self): self.global_help_setup = frappe.conf.get('global_help_setup') if self.global_help_setup: bench_name = os.path.basename( os.path.abspath( frappe.get_app_path('frappe')).split('/apps/')[0]) self.help_db_name = hashlib.sha224( bench_name.encode('utf-8')).hexdigest()[:15] def make_database(self): '''make database for global help setup''' if not self.global_help_setup: return dbman = DbManager(get_root_connection()) dbman.drop_database(self.help_db_name) # make database if not self.help_db_name in dbman.get_database_list(): try: dbman.create_user(self.help_db_name, self.help_db_name) except Exception as e: # user already exists if e.args[0] != 1396: raise dbman.create_database(self.help_db_name) dbman.grant_all_privileges(self.help_db_name, self.help_db_name) dbman.flush_privileges() def connect(self): if self.global_help_setup: self.db = Database(user=self.help_db_name, password=self.help_db_name) else: self.db = frappe.db def make_table(self): if not 'help' in self.db.get_tables(): self.db.sql('''create table help( path varchar(255), content text, title text, intro text, full_path text, fulltext(title), fulltext(content), index (path)) COLLATE=utf8mb4_unicode_ci ENGINE=MyISAM CHARACTER SET=utf8mb4''') def search(self, words): self.connect() return self.db.sql( ''' select title, intro, path from help where title like %s union select title, intro, path from help where match(content) against (%s) limit 10''', ('%' + words + '%', words)) def get_content(self, path): self.connect() query = '''select title, content from help where path like "{path}%" order by path desc limit 1''' result = None if not path.endswith('index'): result = self.db.sql( query.format(path=os.path.join(path, 'index'))) if not result: result = self.db.sql(query.format(path=path)) return { 'title': result[0][0], 'content': result[0][1] } if result else {} def sync_pages(self): self.db.sql('truncate help') doc_contents = '<ol>' apps = os.listdir( '../apps' ) if self.global_help_setup else frappe.get_installed_apps() for app in apps: # Expect handling of cloning docs apps in bench docs_app = frappe.get_hooks('docs_app', app, app)[0] docs_folder = '../apps/{app}/{app}/docs/user'.format(app=app) self.out_base_path = '../apps/{app}/{app}/docs'.format(app=app) if os.path.exists(docs_folder): app_name = getattr(frappe.get_module(app), '__title__', None) or app.title() doc_contents += '<li><a data-path="/{app}/index">{app_name}</a></li>'.format( app=app, app_name=app_name) for basepath, folders, files in os.walk(docs_folder): files = self.reorder_files(files) for fname in files: if fname.rsplit('.', 1)[-1] in ('md', 'html'): fpath = os.path.join(basepath, fname) with io.open(fpath, 'r', encoding='utf-8') as f: try: content = frappe.render_template( f.read(), { 'docs_base_url': '/assets/{app}_docs'.format( app=app) }) relpath = self.get_out_path(fpath) relpath = relpath.replace("user", app) content = markdown(content) title = self.make_title( basepath, fname, content) intro = self.make_intro(content) content = self.make_content( content, fpath, relpath, app, docs_app) self.db.sql( '''insert into help(path, content, title, intro, full_path) values (%s, %s, %s, %s, %s)''', (relpath, content, title, intro, fpath)) except jinja2.exceptions.TemplateSyntaxError: print( "Invalid Jinja Template for {0}. Skipping" .format(fpath)) doc_contents += "</ol>" self.db.sql( '''insert into help(path, content, title, intro, full_path) values (%s, %s, %s, %s, %s)''', ('/documentation/index', doc_contents, 'Documentation', '', '')) def make_title(self, basepath, filename, html): if '<h1>' in html: title = html.split("<h1>", 1)[1].split("</h1>", 1)[0] elif 'index' in filename: title = basepath.rsplit('/', 1)[-1].title().replace("-", " ") else: title = filename.rsplit('.', 1)[0].title().replace("-", " ") return title def make_intro(self, html): intro = "" if '<p>' in html: intro = html.split('<p>', 1)[1].split('</p>', 1)[0] if 'Duration' in html: intro = "Help Video: " + intro return intro def make_content(self, html, path, relpath, app_name, doc_app): if '<h1>' in html: html = html.split('</h1>', 1)[1] if '{next}' in html: html = html.replace('{next}', '') target = path.split('/', 3)[-1] if app_name != doc_app: target = target.replace(app_name, doc_app + '/www') app_name = path.split('/', 3)[2] html += get_improve_page_html(app_name, target) soup = BeautifulSoup(html, 'html.parser') self.fix_links(soup, app_name) self.fix_images(soup, app_name) parent = self.get_parent(relpath) if parent: parent_tag = soup.new_tag('a') parent_tag.string = parent['title'] parent_tag['class'] = 'parent-link' parent_tag['data-path'] = parent['path'] soup.find().insert_before(parent_tag) return soup.prettify() def fix_links(self, soup, app_name): for link in soup.find_all('a'): if link.has_attr('href'): url = link['href'] if '/user' in url: data_path = url[url.index('/user'):] if '.' in data_path: data_path = data_path[:data_path.rindex('.')] if data_path: link['data-path'] = data_path.replace("user", app_name) def fix_images(self, soup, app_name): for img in soup.find_all('img'): if img.has_attr('src'): url = img['src'] if '/docs/' in url: img['src'] = url.replace( '/docs/', '/assets/{0}_docs/'.format(app_name)) def build_index(self): for data in self.db.sql('select path, full_path, content from help'): self.make_index(data[0], data[1], data[2]) def make_index(self, original_path, full_path, content): '''Make index from index.txt''' if '{index}' in content: path = os.path.dirname(full_path) files = [] # get files from index.txt index_path = os.path.join(path, "index.txt") if os.path.exists(index_path): with open(index_path, 'r') as f: files = f.read().splitlines() # files not in index.txt for f in os.listdir(path): if not os.path.isdir(os.path.join(path, f)) and len( f.rsplit('.', 1)) == 2: name, extn = f.rsplit('.', 1) if name not in files \ and name != 'index' and extn in ('md', 'html'): files.append(name) links_html = "<ol class='index-links'>" for line in files: fpath = os.path.join(os.path.dirname(original_path), line) title = self.db.sql( 'select title from help where path like %s', os.path.join(fpath, 'index') + '%') if not title: title = self.db.sql( 'select title from help where path like %s', fpath + '%') if title: title = title[0][0] links_html += "<li><a data-path='{fpath}'> {title} </a></li>".format( fpath=fpath, title=title) # else: # bad entries in .txt files # print fpath links_html += "</ol>" html = content.replace('{index}', links_html) self.db.sql('update help set content=%s where path=%s', (html, original_path)) def get_out_path(self, path): return '/' + os.path.relpath(path, self.out_base_path) def get_parent(self, child_path): if 'index' in child_path: child_path = child_path[:child_path.rindex('index')] if child_path[-1] == '/': child_path = child_path[:-1] child_path = child_path[:child_path.rindex('/')] out = None if child_path: parent_path = child_path + "/index" out = self.get_content(parent_path) #if parent is documentation root else: parent_path = "/documentation/index" out = {} out['title'] = "Documentation" if not out: return None out['path'] = parent_path return out def reorder_files(self, files): pos = 0 if 'index.md' in files: pos = files.index('index.md') elif 'index.html' in files: pos = files.index('index.html') if pos: files[0], files[pos] = files[pos], files[0] return files
def migrate(): frappe.flags.mute_emails = True source = Database(user='******', password='******') users = source.sql('select * from tabUser', as_dict=1) for u in users: if validate_email_add(u.email.strip()): frappe.get_doc(dict( doctype='User', name=u.name, first_name=u.first_name, last_name=u.last_name, email=u.email )).insert(ignore_if_duplicate=True) print u.name print "sync auth" auth = source.sql('select * from __Auth where name != "Administrator"', as_dict=1) for user in auth: frappe.db.sql("""insert into __Auth (doctype, name, fieldname, password, salt, encrypted) values (%s, %s, %s, %s, %s, %s)""", (user.doctype, user.name, user.fieldname, user.password, user.salt, user.encrypted), debug=1) print user.name frappe.db.sql('delete from `tabService Provider`') partners = source.sql('select * from `tabFrappe Partner`', as_dict=True) for p in partners: d = frappe.get_doc(dict( doctype='Service Provider', title=p.partner_name, country=p.country, image=p.logo, introduction=p.introduction, details=markdown(p.description), address=p.partner_address, discuss_ids=p.community_members, website=p.partner_website, github_id=p.github_id, owner=p.owner, creation=p.creation, email= p.email, phone=p.phone, route=p.route, show_in_website=p.show_in_website )).insert(ignore_if_duplicate=True, ignore_mandatory=True) print d.name jobs = source.sql('select * from `tabFrappe Job`', as_dict=True) frappe.db.sql('delete from `tabPortal Job`') for j in jobs: if not frappe.db.exists('Country', j.country): frappe.get_doc(dict(doctype='Country', country_name=j.country)).insert() d = frappe.get_doc(dict( doctype='Portal Job', title=j.job_title, company_name=j.company_name, country=j.country, status='Open' if j.status=='Assigned' else j.status, job_type={ 'ERP Implementation': 'Implementation', 'Core Development': 'Feature Development', 'Website Development': 'Website Development', 'Other': 'App Development' }.get(j.job_type, None) or j.job_type, description= markdown(j.job_detail), owner=j.owner, creation=j.creation, route=j.route, show_in_website=j.show_in_website )).insert(ignore_if_duplicate=True, ignore_mandatory=True) print d.name apps = source.sql('select * from `tabFrappe App`', as_dict=True) frappe.db.sql('delete from `tabFrappe App`') for a in apps: d = frappe.get_doc(dict( doctype='Frappe App', app_name = a.app_name, badge = a.badge, category = a.category, route = a.route, url = a.url, repository_url = a.repository_url, published = 1, description = markdown(a.description), owner=a.owner, creation=a.creation, )).insert(ignore_if_duplicate=True, ignore_mandatory=True) print d.name
def connect(self): self.db = Database(user=help_db_name, password=help_db_name)
def migrate(): frappe.flags.mute_emails = True source = Database(user='******', password='******') users = source.sql('select * from tabUser', as_dict=1) for u in users: if validate_email_add(u.email.strip()) and not frappe.db.exists("User", u.email): frappe.get_doc(dict( doctype='User', name=u.name, first_name=u.first_name, last_name=u.last_name, email=u.email )).insert(ignore_if_duplicate=True) auth_details = source.sql('select * from __Auth where name = %s', u.email, as_dict=1) if auth_details: auth = auth_details[0] if not frappe.db.sql("select doctype from __Auth where name = %s", auth.name): frappe.db.sql("""insert into __Auth (doctype, name, fieldname, password, salt, encrypted) values (%s, %s, %s, %s, %s, %s)""", (auth.doctype, auth.name, auth.fieldname, auth.password, auth.salt, auth.encrypted)) print u.name frappe.db.sql('delete from `tabService Provider`') partners = source.sql('select * from `tabFrappe Partner`', as_dict=True) for p in partners: d = frappe.get_doc(dict( doctype='Service Provider', title=p.partner_name, country=p.country, image=p.logo, introduction=p.introduction, details=markdown(p.description), address=p.partner_address, discuss_ids=p.community_members, website=p.partner_website, github_id=p.github_id, owner=p.owner, creation=p.creation, email= p.email, phone=p.phone, route=p.route, show_in_website=p.show_in_website )).insert(ignore_if_duplicate=True, ignore_mandatory=True) print d.name jobs = source.sql('select * from `tabFrappe Job`', as_dict=True) frappe.db.sql('delete from `tabPortal Job`') for j in jobs: if not frappe.db.exists('Country', j.country): frappe.get_doc(dict(doctype='Country', country_name=j.country)).insert() d = frappe.get_doc(dict( doctype='Portal Job', title=j.job_title, company_name=j.company_name, country=j.country, status='Open' if j.status=='Assigned' else j.status, job_type={ 'ERP Implementation': 'Implementation', 'Core Development': 'Feature Development', 'Website Development': 'Website Development', 'Other': 'App Development' }.get(j.job_type, None) or j.job_type, description= markdown(j.job_detail), owner=j.owner, creation=j.creation, route=j.route, show_in_website=j.show_in_website )).insert(ignore_if_duplicate=True, ignore_mandatory=True) print d.name apps = source.sql('select * from `tabFrappe App`', as_dict=True) frappe.db.sql('delete from `tabFrappe App`') for a in apps: d = frappe.get_doc(dict( doctype='Frappe App', app_name = a.app_name, badge = a.badge, category = a.category, route = a.route, url = a.url, repository_url = a.repository_url, published = 1, description = markdown(a.description), owner=a.owner, creation=a.creation, )).insert(ignore_if_duplicate=True, ignore_mandatory=True) print d.name