def setUp(self): directory = os.path.dirname(os.path.realpath(__file__)) delogx = os.path.dirname(os.path.dirname(directory)) sys.path.insert(0, delogx) filename = os.path.join(directory, 'test_app', 'config.json') from DelogX.utils.config import Config self.config = Config(filename)
def __init__(self, app_path, framework, config='config.json'): '''Initialize DelogX object. Args: app_path (str): Absolute path of the blog application. framework (Flask): Flask application object. config (str): Config file of DelogX, defaults `config.json`. ''' self.framework = framework app_path = os.path.realpath(app_path) config = Path.abs_path(app_path, config) config = Config(config) runtime = Config() module_path = os.path.dirname(os.path.realpath(__file__)) runtime.let('path.app', app_path) runtime.let('path.module', module_path) ver_file = os.path.join(module_path, 'VERSION') with codecs.open(ver_file, encoding='utf-8') as f: version = ''.join(f.readlines()).strip() runtime.let('blog.version', version) self.config = config self.runtime = runtime self.markdown_ext = list() self.init_runtime() self.init_plugins() self.init_bundles() self.init_route() self.update_header()
class DelogFeed(Plugin): config = None feed_url = None feed_limit = 10 def run(self): self.config = Config(os.path.join(self.workspace, 'config.json')) self.feed_url = self.config.get('delog_feed.url') self.feed_limit = self.config.get('delog_feed.limit') if not self.feed_url: self.feed_url = '/feed' if not self.feed_limit: self.feed_limit = 10 self.feed_url = Path.format_url(self.feed_url) if not self.feed_url.endswith('/'): self.feed_url += '/' self.blog.add_url_rule(self.feed_url, 'delog_feed', self.make_feed) self.manager.add_filter('dx_render', self.add_link) def add_link(self, render): site_name = self.blog.default_conf('site.name') copy = render.lower() search = '<head>' tag = ('<link href="{href}" rel="alternate" ' 'title="{title}" type="application/atom+xml">').format( href=self.feed_url, title=site_name) try: index = copy.index(search) + len(search) render = render[:index] + tag + render[index:] except ValueError: render = render + tag return render def make_feed(self): site_name = self.blog.default_conf('site.name') feed = AtomFeed(site_name, feed_url=request.url, url=request.url_root) posts = self.blog.post_bundle.get_list(1, self.feed_limit) for post in posts: post = self.manager.do_filter('dx_post', post) ext_url = request.url_root if ext_url.endswith('/'): ext_url = ext_url[:-1] ext_url = ext_url + post.cooked_url update_time = datetime.datetime.fromtimestamp(post.time) content = Markdown.markdown(post.markdown, self.blog.markdown_ext) feed.add(title=post.title, title_type='text', content=content, content_type='html', url=ext_url, author=site_name, updated=update_time, published=update_time) return feed.get_response()
def run(self): self.config = Config(os.path.join(self.workspace, 'config.json')) self.feed_url = self.config.get('delog_feed.url') self.feed_limit = self.config.get('delog_feed.limit') if not self.feed_url: self.feed_url = '/feed' if not self.feed_limit: self.feed_limit = 10 self.feed_url = Path.format_url(self.feed_url) if not self.feed_url.endswith('/'): self.feed_url += '/' self.blog.add_url_rule(self.feed_url, 'delog_feed', self.make_feed) self.manager.add_filter('dx_render', self.add_link)
def run(self): conf = self.blog.default_conf self.config = Config(os.path.join(self.workspace, 'config.json')) self.i18n = I18n( Path.format_url(self.workspace, 'locale'), conf('local.locale')) self.tags_url = self.config.get('delog_tags.url') if not self.tags_url: self.tags_url = '/tag' self.tags_url = Path.format_url(self.tags_url) tag_rule = Path.format_url(self.tags_url, '<tag_id>/') tag_list_rule = Path.format_url(tag_rule, '<int:number>/') self.blog.add_url_rule(tag_rule, 'delog_tag', self.make_tag) self.blog.add_url_rule( tag_list_rule, 'delog_tag_list', self.make_tag_list) self.manager.add_action('dx_post_update', self.load_tags)
def __init__(self, directory, locale): '''Initialize i18n manager. Args: directory (str): Name of the i18n directory. locale (str): Current locale. ''' self.directory = directory self.locale = locale self.data = Config(os.path.join(directory, locale, 'locale.json'))
def init(init_args): '''Create a new blog application.''' module_path = os.path.dirname(os.path.realpath(__file__)) sys.path.append(os.path.dirname(module_path)) from DelogX.utils.config import Config cwd = os.getcwd() defaults = os.path.join(module_path, 'defaults') if os.listdir(cwd) and not init_args.force: print('''The current directory is not empty,\n''' '''use `delogx init --force' if you want to overwrite.''') return locale_dir = os.path.join(module_path, 'locale') locales = list() for lang in os.listdir(locale_dir): if os.path.isdir(os.path.join(locale_dir, lang)): locales.append(lang) locale = '' if init_args.locale and init_args.locale in locales: locale = init_args.locale elif init_args.locale: print('''Unknown locale '{}'. Abort.'''.format(init_args.locale)) sys.exit(1) else: while locale not in locales: print('Choose Language({0}):'.format(','.join(locales))) locale = input('> ') copytree(defaults, cwd) print('Setting language', locale) config = Config(os.path.join(cwd, 'config.json')) config.let('local.locale', locale) config.save() print('Creating demo post') post_dir = os.path.join(cwd, 'posts') print(' Creating {0}'.format(post_dir)) if os.path.isfile(post_dir): os.remove(post_dir) if not os.path.exists(post_dir): os.makedirs(post_dir) post_path = os.path.join(post_dir, 'hello-delogx.md') print(' Copying {0}'.format(post_path)) shutil.copyfile(os.path.join(locale_dir, locale, 'hello-delogx.md'), post_path) print('Creating demo page') page_dir = os.path.join(cwd, 'pages') print(' Creating {0}'.format(page_dir)) if os.path.isfile(page_dir): os.remove(page_dir) if not os.path.exists(page_dir): os.makedirs(page_dir) page_path = os.path.join(page_dir, 'demo.md') print(' Copying {0}'.format(page_path)) shutil.copyfile(os.path.join(locale_dir, locale, 'demo.md'), page_path) print('''Blog created successfully, edit 'config.json' to configure.''')
def load(self, plugin_name): '''Load a plugin by name. Args: plugin_name (str): Name of the plugin. Returns: object: Entry object of the plugin. ''' plugin_dir = os.path.join(self.directory, plugin_name) plugin_meta = os.path.join(plugin_dir, 'plugin.json') name_re = re.compile(r'^[A-Za-z_][0-9A-Za-z_]*$') if (not os.path.isfile(plugin_meta) or name_re.match(plugin_name) is None): return None init_py = os.path.join(plugin_dir, '__init__.py') if not os.path.exists(init_py): open(init_py, 'a').close() meta = Config(plugin_meta) entry_name = meta.get('entry').strip(". \n\r\t") author = meta.get('author', '') version = meta.get('version', '') description = meta.get('description', '') if not entry_name or plugin_name in self.plugins: return None module_name = [plugin_name] module_name.extend(entry_name.split('.')[:-1]) module_name = '.'.join(module_name) class_name = ''.join(entry_name.split('.')[-1:]) module = importlib.import_module(module_name) entry = getattr(module, class_name)(self.blog) entry.name = plugin_name entry.workspace = plugin_dir self.plugins[plugin_name] = { 'entry': entry, 'author': author, 'version': version, 'description': description } return entry
class DelogTags(Plugin): config = None tags_url = None i18n = None def run(self): conf = self.blog.default_conf self.config = Config(os.path.join(self.workspace, 'config.json')) self.i18n = I18n( Path.format_url(self.workspace, 'locale'), conf('local.locale')) self.tags_url = self.config.get('delog_tags.url') if not self.tags_url: self.tags_url = '/tag' self.tags_url = Path.format_url(self.tags_url) tag_rule = Path.format_url(self.tags_url, '<tag_id>/') tag_list_rule = Path.format_url(tag_rule, '<int:number>/') self.blog.add_url_rule(tag_rule, 'delog_tag', self.make_tag) self.blog.add_url_rule( tag_list_rule, 'delog_tag_list', self.make_tag_list) self.manager.add_action('dx_post_update', self.load_tags) def load_tags(self, *args, **kwargs): post = kwargs.get('post') if not post: return post.tags = list() title = post.title title_split = list(filter(None, title.split('::', 1))) if title_split: post.title = title_split[0].strip() tags = ''.join(title_split[1:]).split(',') post.tags = list(filter(None, list(map(str.strip, tags)))) tags_link = list() tags_html = '<div class="post-tags">{0}</div>' for tag in post.tags: tags_link.append('<a href="{0}">{1}</a>'.format( Path.format_url(self.tags_url, Path.urlencode(tag)), tag)) if tags_link: tags_html = tags_html.format(' '.join(tags_link)) post.content = tags_html + post.content def make_tag(self, tag_id): return self.make_tag_list(tag_id, 1) def make_tag_list(self, tag_id, number): tag_id = Path.urldecode(tag_id) conf = self.blog.default_conf list_size = conf('local.list_size') bundle = self.blog.post_bundle.bundle_list tagged = [ post for post in bundle.values() if not post.hidden and tag_id in post.tags ] list_count = int(math.ceil(float(len(tagged)) / float(list_size))) if not 0 < number <= list_count: abort(404) if tagged is None or list_count < 1: abort(404) post_list = tagged[ list_size * (number - 1):list_size * number ] for post in post_list: post = self.blog.plugin_manager.do_filter('dx_post', post) prev_page = next_page = True if number == 1: prev_page = False if number == list_count: next_page = False list_url = Path.format_url(self.tags_url, tag_id) url = list_url if list_url.endswith('/') else list_url + '/' web_title = self.i18n.get('{0} - Page {1}', tag_id, number) return self.blog.get_render( 'list.html', posts=post_list, list_id=number, list_url=url, prev_page=prev_page, next_page=next_page, web_title=web_title)
class TestConfig(unittest.TestCase): def setUp(self): directory = os.path.dirname(os.path.realpath(__file__)) delogx = os.path.dirname(os.path.dirname(directory)) sys.path.insert(0, delogx) filename = os.path.join(directory, 'test_app', 'config.json') from DelogX.utils.config import Config self.config = Config(filename) def test_string(self): self.assertEqual(self.config.get('entry_a.key_1_1'), 'String') def test_number(self): self.assertEqual(self.config.get('entry_a.key_1_2'), 1000) self.assertAlmostEqual(self.config.get('entry_a.key_1_3'), -30.75) def test_null(self): self.assertIsNone(self.config.get('entry_b.key_2_1')) def test_bool(self): self.assertTrue(self.config.get('entry_b.key_2_2')) self.assertFalse(self.config.get('entry_b.key_2_3')) def test_list(self): equal_list = ["List_1_1", "List_1_2"] self.assertListEqual(self.config.get('entry_c.key_3_1'), equal_list) def test_nest(self): self.assertEqual(self.config.get('entry_c.key_3_2.key_3_2_1.test_1'), 'Test 1') self.assertEqual( self.config.get('entry_c.key_3_2.key_3_2_1.key_3_2_2.test_2'), 'Test 2') self.assertEqual(self.config.get('entry_c.key_3_2.key_3_2_3.test_3'), 'Test 3') def test_let(self): self.config.let('test', 'Test A') self.config.let('test2.a.b.c', 'Test B') self.config.let('entry_a.test', 'Test C') self.config.let('entry_a.test2', 'Test D') self.assertEqual(self.config.get('test'), 'Test A') self.assertEqual(self.config.get('test2.a.b.c'), 'Test B') self.assertEqual(self.config.get('entry_a.test'), 'Test C') self.assertEqual(self.config.get('entry_a.test2'), 'Test D') def test_delete(self): self.config.let('test', 'Test A') self.config.let('test2.a.b.c', 'Test B') self.assertEqual(self.config.get('test'), 'Test A') self.assertEqual(self.config.get('test2.a.b.c'), 'Test B') value_a = self.config.delete('test') value_b = self.config.delete('test2.a.b.c') self.assertEqual(value_a, 'Test A') self.assertEqual(value_b, 'Test B') self.assertIsNone(self.config.get('test')) self.assertIsNone(self.config.get('test2.a.b.c'))