def i18n(key, *args): key = smart_unicode(key) if not args: # 获取 if key.startswith('_'): # 以_开头的,摘1后,返回原值 return key[1:] lang = get_language() key1 = '%s-%s' % (key, lang) i18n_data = get_i18n_data_from_request() matched_value = i18n_data.get(key1) or i18n_data.get(key) if not matched_value: matched_lang_data = default_i18n_data.get(lang) or {} if matched_lang_data: matched_value = matched_lang_data.get(key) return matched_value or key elif len(args) <= 2: if len(args) == 2: # 指定了 lang 的 value, lang = args lang = smart_unicode(lang).strip().lower() key = '%s-%s' % (key, lang) else: # 没有指定lang,设定默认值 value = args[0] set_i18n_data_to_request(key, value) # 设置的 # at last return ''
def get_pay_request_data(self, price, title, content, notify_url='', return_url='', out_trade_no='', note=''): price = to_float(price) if not price: return # ignore price = '%.2f' % price out_trade_no = smart_unicode(out_trade_no) if len(out_trade_no) < 10: # 作为前缀,自动生成 out_trade_no = self.get_out_trade_no(prefix=out_trade_no) # 不限制 subject、 body, 反正太长了自己会出错 data = dict( total_amount=price, subject=smart_unicode(title), # max length 256 body=smart_unicode(content), # max length 128 out_trade_no=out_trade_no, ) if note: data['passback_params'] = note if notify_url: # alipay 会进行通知 data['notify_url'] = notify_url if return_url: # url 跳转回来,成功支付后 data['return_url'] = return_url return data
def get_templates_info(): templates_info = {} templates_folder = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'src') if not os.path.isdir(templates_folder): return templates_info filenames = os.listdir(templates_folder) for name in filenames: filepath = os.path.join(templates_folder, name) if os.path.isdir(filepath): sub_names = os.listdir(filepath) for sub_name in sub_names: sub_path = os.path.join(filepath, sub_name) if os.path.isfile(sub_path): ext = os.path.splitext(sub_name)[-1].lower() with open(sub_path, 'rb') as f: raw_content = f.read() just_name = os.path.splitext(sub_name)[0] if ext in ['.html', '.htm']: templates_info[just_name] = smart_unicode(raw_content) elif ext == '.jade': templates_info[just_name] = smart_unicode(convert_jade_to_html(raw_content)) elif os.path.isfile(filepath): ext = os.path.splitext(name)[-1].lower() with open(filepath, 'rb') as f: raw_content = f.read() just_name = os.path.splitext(name)[0] if ext in ['.html', '.htm']: templates_info[just_name] = smart_unicode(raw_content) elif ext == '.jade': templates_info[just_name] = smart_unicode(convert_jade_to_html(raw_content)) return templates_info
def _func(*args, **kwargs): #the real func g = get_g() if cache_name == 'no_cache': # 不对结果缓存 return func(*args, **kwargs) # 获得/创建容器 if not hasattr(g, cache_name): setattr(g, cache_name, {}) # 准备key值,可以在容器内进行匹配 values = list(args) + kwargs.keys() + kwargs.values() key_list = [] for value in values: if isinstance(value, dict) and '_id' in value: key_list.append(smart_unicode(value['_id'])) else: key_list.append(smart_unicode(value)) key = "-".join(key_list) if key: key = get_md5(key) # 可以避免key太长了 else: # 如果是empty,每次的get_hash_key都是不一样的,意味着直接调用cache_result的,都会失效 key = '_' # 如不匹配,则进行计算,并存入容器 if key not in getattr(g, cache_name): # 仅判断key的存在,不做key对应的值是否存在 result = func(*args, **kwargs) getattr(g, cache_name)[key] = result return getattr(g, cache_name).get(key) # 返回匹配值
def post_url_path(self): url_path = self.get_meta_value('url', '') or self.get_meta_value( 'url_path', '') if url_path and not isinstance(url_path, basestring): url_path = smart_unicode(url_path) if not url_path: # 如果是用户自己指定的url,则不管对错,都保存; 反之则是通过relative_path解析一个url url_path = self.path.rsplit('.', 1)[0] url_path = slugify(url_path, auto=True).lower() # 不能以slash开头,并且确保小写 else: # 用户自己声明的 url,不做大小写处理,保留原始状态 url_path = slugify(url_path, must_lower=False) # 替代掉不适合做url的字符 # url_path是全小写 if '%' in url_path: # 被编码的url,特别是wordpress转过来的 _url_path = urllib.unquote(smart_str(url_path)) if url_path != _url_path: url_path = smart_unicode(_url_path) url_path = url_path.lstrip('/') url_path = re.sub(r'/{2,}', '/', url_path) url_path = url_path or '--' # 可能存在空的情况... url_path = url_path.strip().lower() return url_path
def cut_content_by_words(content, max_words, mark=u'...'): if not isinstance(max_words, int): return content if max_words < 1: return content if max_words > 2000: max_words = 2000 # 最大不能超过这个,不然性能问题 content = smart_unicode(content) iter_found = re.finditer(ur'[\w\-_/]+|[\u1100-\ufde8]', content) n = 0 end = 0 for i in iter_found: end = i.end() n += 1 if n >= max_words: break if end: new_content = content[:end] if len(content) > end: mark = smart_unicode(mark) new_content += mark new_content = UnicodeWithAttrs(new_content) new_content.has_more = True return new_content else: return content
def get_data_obj_from_POST(keys=None): # 从 request.POST 中获得一个dict类型的数据对象 pure_keys = get_pure_form_keys(keys) data_obj = {} _data = request.form.to_dict() for k, v in _data.items(): if k.endswith('@list'): k = k[:-5] v = [row.strip() for row in v.split('\n') if row.strip()] elif k.endswith('@json'): k = k[:-5] try: v = json.loads(v) except: pass elif v in ['yes', 'no', 'true', 'false']: # bool 性质的 if v in ['yes', 'true']: v = True else: v = False else: v = auto_type(v) if 'title' in k: # 有 title 关键字的 key, 必须处理为字符串的形式 v = smart_unicode(v) if isinstance(v, int) and v >= 1024000: v = smart_unicode(v) if k not in pure_keys: # 防止多余的参数进来,特别如果是callback_func 直接是一个 db_doc 的 update 函数,会有漏洞 continue else: data_obj[k] = v return data_obj
def set_meta(self, key, value): # 生成 HTML 的 head_meta if not key or not value: return '' key = smart_unicode(key).replace('"', "'") value = html_escape(smart_unicode(value).replace('"', "'")) meta_content = '<meta name="%s" content="%s">\n' % (key, value) return meta_content
def join(objects, link_str=' '): link_str = smart_unicode(link_str) if all([isinstance(obj, (str, unicode, int, float)) for obj in objects]): # 内部元素,必须都是字符串类型的 objects = [smart_unicode(obj) for obj in objects] return link_str.join(objects) else: return objects
def unqote_url_path_to_unicode(url_path): if not isinstance(url_path, string_types): return url_path url_path = smart_unicode(url_path) if '%' in url_path: # 被编码的url,特别是wordpress转过来的 _url_path = smart_unicode(urllib.unquote(smart_str(url_path))) if url_path != _url_path: url_path = _url_path return url_path return url_path
def get_template_info(template_dir): info = {} template_dir = template_dir.strip().rstrip('/') if not os.path.isdir(template_dir): return info # ignore filepaths = get_all_sub_files(template_dir, accept_func=os.path.isfile, max_tried_times=1000) for filepath in filepaths: relative_path = get_relative_path( filepath, root=template_dir).lower() # lower case if not os.path.isfile(filepath): continue if not is_real(filepath) or is_a_hidden_path(relative_path): continue if relative_path.startswith('readme.') and is_a_markdown_file( relative_path): # 模板 readme 上的信息 with open(filepath, 'rb') as f: raw_markdown_content = smart_unicode(f.read()) compiled_markdown_content = compile_markdown(raw_markdown_content) compiled_markdown_content_meta = compiled_markdown_content.metadata readme_info = dict(content=compiled_markdown_content, metadata=compiled_markdown_content_meta ) # raw_content=raw_markdown_content, info['_readme'] = readme_info else: path_without_ext, ext = os.path.splitext(relative_path) ext = ext.strip('.').lower() if ext not in allowed_exts: continue with open(filepath, 'rb') as f: raw_content = f.read() raw_content = smart_unicode(raw_content) # to unicode info[relative_path] = raw_content matched_compiler = template_resource_compilers.get(ext) if matched_compiler: new_ext, compile_func = matched_compiler try: compiled_content = compile_func(raw_content) new_key = path_without_ext + '.' + new_ext.strip('.') info[new_key] = compiled_content except Exception as e: error_message = getattr(e, 'message', None) if error_message: try: print('%s error: %s' % (relative_path, error_message)) except: pass info['_route'] = get_templates_route_info(info) return info
def js_view(title, url=None, group_id=None, view_type='', **kwargs): if url is None: # 默认值, 这样图片调用的时候, 只要一个传入就可以了 url = title url = smart_unicode(url) if isinstance(title, (tuple, list)) and len(title) == 2: title, thumbnail = title # 图片类型的 else: title = smart_unicode(title) mime_type = guess_type(title) or '' if mime_type.startswith('image/'): thumbnail = title # title 本身就是一张图片 title = kwargs.get('alt') or os.path.split(title)[ -1] # 文件名作为 title title = smart_unicode(title) else: thumbnail = '' if not view_type: # 自动推断 if thumbnail: view_type = 'image' elif url.endswith('.mp4'): view_type = 'video' else: link_mime_type = guess_type(url) or '' if link_mime_type.startswith('image/'): view_type = 'image' else: view_type = 'iframe' class_name = kwargs.get('class_name') or '' css_class = 'js_view js_view_%s %s' % (view_type, class_name) if group_id: css_class += ' js_view_group ' else: group_id = '' dom_id = get_a_random_dom_id() html_content = render_api_template('js_view', view_type=view_type, title=title, thumbnail=thumbnail, url=url, css_class=css_class, uuid=dom_id, group_id=group_id, return_html=True, **kwargs) return html_content
def get_cos_client(secret_id, secret_key, region): region = smart_unicode(region.strip()) secret_id = smart_unicode(secret_id.strip()) secret_key = smart_unicode(secret_key.strip()) cache_key = "%s-%s-%s" % (secret_id, secret_key, region) cached_client = cos_cached_clients.get(cache_key) if cached_client: return cached_client config = CosConfig(Region=region, SecretId=secret_id, SecretKey=secret_key, Token=None) # 获取配置对象 cos_client = CosS3Client(config) cos_cached_clients[cache_key] = cos_client return cos_client
def deal_nav_items(nav_items): new_nav_items = [] if not nav_items: return [] if not isinstance(nav_items, (list, tuple)): return [] for nav_item in nav_items: if isinstance(nav_item, dict): new_nav_items.append(nav_item) elif isinstance(nav_item, (list, tuple)) and len(nav_item) == 2: # nav_item 是一个 list,主要是在 Template API 中调用,因为代码量会低一些 name, url = nav_item new_nav_items.append( dict(name=smart_unicode(name), url=smart_unicode(url))) return new_nav_items
def format(self, format_str='%H:%M / %d-%m-%Y'): if not isinstance(self.core, datetime.datetime): return self.core or '-' utc_offset = just_get_site_config('utc_offset') try: utc_offset = float(utc_offset) except: utc_offset = 8 if utc_offset > 12 or utc_offset < -12: utc_offset = 8 if utc_offset is None: utc_offset = 8 # default value if not isinstance(utc_offset, (int, float)): utc_offset = 8 format_str = smart_str(format_str[:200]) # 可以处理中文等unicode字符 date = self.core + datetime.timedelta(0, utc_offset * 3600) date_year = date.year if date_year <= 1900: date = date.replace(year=1900) result = date.strftime(format_str) result = result.replace('1900', str(date_year), 1) else: result = date.strftime(format_str) return smart_unicode(result)
def dump_pages(node, private_key, pages_dir, old_pages_data=None): pages_data = get_pages_data(pages_dir) if not pages_data: print('no pages data') return if old_pages_data: changed_filepaths = [] for k, v in pages_data.items(): if not isinstance(v, string_types): continue if not isinstance(k, string_types): continue if '.' not in k: continue old_value = old_pages_data.get(k) or '' old_value = smart_unicode(old_value) if v != old_value: changed_filepaths.append(k) if changed_filepaths: pages_data['__changed_filepaths'] = changed_filepaths return update_bucket_configs(node=node, private_key=private_key, configs=pages_data, config_type='pages')
def get_doc_url_for_template_api(doc, url_prefix, url_root=None, hit_url_path=False): # hit_url_path=True 的时候,post 上有 url_path, 但跟 post.url 直接调用的逻辑不亦一样 # post.url 相当于有一个动态的 url_prefix if not doc or not isinstance(doc, dict): return "" if not isinstance(url_prefix, string_types): return "" if url_root and not isinstance(url_root, string_types): return "" url_prefix = url_prefix.strip("/") doc_path = get_path_from_record(doc) if not doc_path: return "" url_path = "" if hit_url_path: url_path = smart_unicode(doc.get("url_path") or "").strip("/") if url_path: return "/%s/%s" % (url_prefix, url_path) if not url_root or not isinstance(url_root, string_types): return "/%s/%s" % (url_prefix, doc_path) else: relative_path = get_relative_path(doc_path.lower(), url_root.lower(), return_name_if_fail=False) if not relative_path: return "/%s/%s" % (url_prefix, doc_path) else: return "/%s/%s" % (url_prefix, relative_path)
def csv_to_list(raw_content, max_rows=None, max_columns=None, return_max_length=False, auto_fill=False): # auto_fill 表示会自动补充缺失的空 cell file_io = BytesIO(smart_str(raw_content)) csv_reader = csv.reader(file_io) result = [] i = 0 max_length = 0 if max_rows is None: max_rows = 9999 for row in csv_reader: row = [smart_unicode(s).strip().replace('\\n', '\n') for s in row] if max_columns: # 一行最多允许多少列数据 row = row[:max_columns] if len(row) > max_length: max_length = len(row) result.append(row) if i >= max_rows: break i += 1 if auto_fill: # 自动补全 result = [row + [''] * (max_length - len(row)) for row in result] if return_max_length: return result, max_length else: return result
def pure(*args, **kwargs): # 对 pure css 的处理 do_grid = True caller = kwargs.pop('caller', None) if not caller or not hasattr(caller, '__call__'): return '' inner_html = caller() factors_devices = [ 'pure-u', # 总是, # 全填满的时候相当于phone 'pure-u-sm', # ≥ 568px # phone 横 'pure-u-md', # ≥ 768px # ipad 'pure-u-lg', # ≥ 1024px # ipad 横 & 普通桌面 'pure-u-xl', # ≥ 1280px # 大桌面 ] html_class = smart_unicode(kwargs.get('class') or '') html_class_list = html_class.split('.') html_class = ' '.join(html_class_list) if len(args): for i, raw_factor in enumerate(args): grid_factor = get_grid_factor(raw_factor) grid_value, grid_base = grid_factor try: prefix = factors_devices[i] except: break grid_class = '%s-%s-%s' % (prefix, grid_value, grid_base) html_class += ' %s' % grid_class do_grid = False if do_grid: # 外部的 grid 包裹 return '%s\n<div class="pure-g">\n%s\n</div>' % (Html.load('pure'), inner_html) else: # 某个具体 grid html_class = html_class.replace('"', '') + ' pure_cell' return '\n<div class="%s">\n%s\n</div>' % (html_class, inner_html)
def load_theme_from_template_folder_for_bucket(bucket, prefix="template"): if not has_bucket(bucket): return info = {} prefix = prefix.strip().strip("/") template_paths = get_paths_under(bucket, under=prefix) for _relative_path in template_paths: relative_path = _relative_path.replace("%s/"%prefix, "", 1) raw_content = get_raw_content_by_path(bucket, _relative_path) if not raw_content: continue path_without_ext, ext = os.path.splitext(relative_path) ext = ext.lower().strip('.') if ext not in allowed_exts: continue raw_content = smart_unicode(raw_content) # to unicode info[relative_path] = raw_content matched_compiler = server_side_template_resource_compilers.get(ext) if matched_compiler: new_ext, compile_func = matched_compiler try: compiled_content = compile_func(raw_content) new_key = path_without_ext + '.' + new_ext.strip('.') info[new_key] = compiled_content except Exception as e: pass info["_route"] = get_templates_route_info(info) set_bucket_configs(bucket, info, config_type='pages') return info
def to_doc_path(path_or_doc): if isinstance(path_or_doc, dict): path = path_or_doc.get('path') else: path = path_or_doc path = smart_unicode(path).strip('/').strip()[:500].lower() return path
def get_link_title_id_in_wiki_syntax(line): # 已经去除头尾的 [[ 与 ]] 了 # 要考虑有多个 | ,多个 # 的情况... # get_link_title_id_in_wiki_syntax("hello") # get_link_title_id_in_wiki_syntax("hello | title #id") # get_link_title_id_in_wiki_syntax("hello #id |title") # get_link_title_id_in_wiki_syntax("hello #more |title # id | title2") line = smart_unicode(line.strip()) if line.startswith("#"): line = line[1:] is_tag = True else: is_tag = False link_id_c = re.search("#([^#|]+)(\||$)", line) if link_id_c: link_id = link_id_c.group(1).strip() else: link_id = "" link_title_c = re.search("\|([^#|]+)(#|$)", line) if link_title_c: link_title = link_title_c.group(1).strip() else: link_title = "" link_parts = re.split("[#|]", line) if link_parts: link = link_parts[0].strip() else: link = "" if is_tag: link = "#" + link return link, link_title, link_id
def call_binop(self, context, operator, left, right): if isinstance(left, Undefined): left = '' if isinstance(right, Undefined): right = '' if isinstance(left, (str, unicode)) and isinstance(right, (str, unicode)): if operator in ['/', '//', '*', '**', '-']: return '%s%s%s' % (smart_unicode(left), operator, smart_unicode(right)) if operator == '**': if left > 500 or right > 5: return self.undefined('the power operator is unavailable') else: return left**right elif operator == '+' and isinstance(left, (tuple, list)) and isinstance( right, (tuple, list)): return list(left) + list(right) elif operator == '+' and isinstance(left, (int, float)) and isinstance( right, (int, float)): return left + right elif operator == '+' and _get_is_string_or_number( left) and _get_is_string_or_number(right): return '%s%s' % (left, right) else: # todo 这里要优化 # 字符串的操作符是不允许的 types = [type(left), type(right)] types = list(set(types)) # 去重 if (left > 999999999999 or right > 999999999999) and\ not (isinstance(left, string_types) and isinstance(right, string_types)): return left or right #return self.undefined('the power operator is unavailable') elif len(types) == 2 and (unicode in types or str in types) and ( float in types or int in types): # 字符串的操作,如果是不同类型的,比如string*n是不允许的 return '' elif operator == '/' and not right: # 会产生错误,除以0 return '' else: return SandboxedEnvironment.call_binop(self, context, operator, left, right)
def string_to_list(value): if not value: return [] if isinstance(value, string_types) and value: if ',' in value: ls = value.split(',') elif u',' in value: ls = value.split(u',') else: ls = value.split(' ') ls = [item.strip() for item in ls if item] return unique_list(ls) elif type(value) in [list, tuple]: value = unique_list(value) return [smart_unicode(row).strip() for row in value if row] else: return [smart_unicode(value)]
def post_tags(self): # every tag is unicode tags = self.get_meta_value('tags') or self.get_meta_value('tag') tags = string_to_list(tags) if not isinstance(tags, (list, tuple)): tags = [] tags = [smart_unicode(tag) for tag in tags] # make sure it's unicode # 从 wiki link 语法中提取的 tags post_doc_links, wiki_tags = get_linked_docs_from_markdown_content( self.relative_path, self.raw_content) for wiki_tag in wiki_tags: wiki_tag = smart_unicode(wiki_tag) if wiki_tag not in tags: tags.append(wiki_tag) return tags
def register_domain(node, private_key, domain, admin_password=None): message = dict(domain=domain, ) if admin_password: message['admin_password'] = smart_unicode(admin_password) return send_message(node=node, private_key=private_key, action='register_domain', message=message)
def context_call(self, context_obj, *args, **kwargs): # 一般只是本地的 jade 才会调用到,外部的实际走evn_call if not hasattr(context_obj, '__call__'): # 不可 call, 可能仅仅是 property return context_obj if isinstance(context_obj, Undefined): return '' try: value = old_context_call(self, context_obj, *args, **kwargs) if value is None: value = Undefined() return value except HTTPException as e: raise e except TemplateDebugException as e: raise e except TypeError as e: if hasattr(e, 'message') and 'not callable' in e.message: # 被调用的函数不可被call,返回原始值 return context_obj else: # sentry_client.captureException() message = getattr(e, 'message', None) or '' if message: return message error_info = 'context_call error:* %s, ** %s; %s' % ( smart_unicode(args), smart_unicode(kwargs), message) return error_info except Exception as e: if isinstance(context_obj, Macro): pass else: if sentry_client: sentry_client.captureException() # todo 目前这个错误还是会进行捕获 message = getattr(e, 'message', None) or '' object_name = getattr(context_obj, '__name__', None) or '' if DEBUG: print 'context_call error\n', context_obj, args, kwargs if message: error_info = message else: error_info = 'context_call error: %s, * %s, ** %s; %s' % ( object_name, smart_unicode(args), smart_unicode(kwargs), message) return '<error>%s</error>' % error_info
def set_name_by_wechat_user_id(wechat_user_id, name): if not isinstance(wechat_user_id, string_types) or not isinstance( name, string_types): return name = smart_unicode(name) if not name: return return hset("wechat_names", wechat_user_id, name)
def get_paths_by_type(bucket, data_type, offset=0, limit=10000, reverse=False, prefix_to_ignore=None, date_start=None, date_end=None): paths = [] if not bucket: return [] site_configs = get_bucket_site_configs(bucket) utc_offset = to_float(site_configs.get('utc_offset', 8), default_if_fail=8) if date_start: date_start = date_to_timestamp(to_date(date_start), utc_offset=utc_offset) if date_end: date_end = date_to_timestamp(to_date(date_end), utc_offset=utc_offset) should_hit_date = False if date_start or date_end: should_hit_date = True if should_hit_date and not prefix_to_ignore: prefix_to_ignore = '_' if prefix_to_ignore: prefix_to_ignore = smart_unicode(prefix_to_ignore) order_bucket = get_bucket_name_for_order(bucket, data_type) result = zrange(order_bucket, offset=offset, limit=limit, reverse=reverse) for path, order_value in result: if should_hit_date: order_value = to_float(order_value) if order_value < 10000000: continue if date_start and order_value < date_start: continue if date_end and order_value > date_end: continue path = smart_unicode(path) if prefix_to_ignore and path.startswith(prefix_to_ignore): continue paths.append(path) return paths
def is_same_url(url1, url2, check_GET=False): if not isinstance(url1, (str, unicode)): return False if not isinstance(url2, (str, unicode)): return False if url1.startswith('https://'): url1 = url1.replace('https://', 'http://', 1) if url2.startswith('https://'): url2 = url1.replace('https://', 'http://', 1) url1 = smart_unicode(url1) url2 = smart_unicode(url2) if check_GET: return url1 == url2 else: # 构建两个url去除GET参数后的 url1 = url1.split('?')[0].rstrip('/').rstrip() url2 = url2.split('?')[0].rstrip('/').rstrip() return url1 == url2