def winrate_app(environ, start_response): status = '200 OK' response_headers = [('Content-type', 'text/html'), ('Cache-Control', 'no-cache'), ('Cache-Control', 'must-revalidate')] start_response(status, response_headers) engine = Engine(loader=FileLoader(['']), extensions=[CoreExtension()]) template = engine.get_template('winrate_template.html') player_wins = winrate.download_current_player_wins() leaderboard = winrate.compute_win_rate_leaderboard(player_wins) ranked_leaderboard = [ (str(index + 1), name, "{:.2f}%".format(probability * 100)) for index, (name, probability) in enumerate(leaderboard) ] preview_leaderboard = "" for rank, name, percentile in ranked_leaderboard[:3]: preview_leaderboard += "{}. {} {} ".format(rank, name, percentile) response_body = template.render({ "preview_leaderboard": preview_leaderboard, "leaderboard": ranked_leaderboard }) yield response_body.encode()
def setUp(self): from wheezy.template.engine import Engine from wheezy.template.ext.core import CoreExtension from wheezy.template.loader import DictLoader self.templates = {} self.engine = Engine(loader=DictLoader(templates=self.templates), extensions=[CoreExtension()])
def tohtml(self): # TODO temporary path = os.path.join(os.path.dirname(__file__), 'reader.html.template') loader = DictLoader({'reader': open(path).read()}) engine = Engine(loader=loader, extensions=[CoreExtension()]) template = engine.get_template('reader') return template.render({'feed': self}).encode('utf-8')
def __init__(self, output_filename, mz_dtype=np.float64, intensity_dtype=np.float32): self.mz_dtype = mz_dtype self.intensity_dtype = intensity_dtype self.run_id = os.path.splitext(output_filename)[0] self.filename = self.run_id + ".imzML" self.ibd_filename = self.run_id + ".ibd" self.xml = open(self.filename, 'w') self.ibd = open(self.ibd_filename, 'w') self.sha1 = hashlib.sha1() self.ibd_offset = 0 self.uuid = uuid.uuid4() self._write_ibd(self.uuid.bytes_le) self.wheezy_engine = Engine(loader=DictLoader( {'imzml': IMZML_TEMPLATE}), extensions=[CoreExtension()]) self.imzml_template = self.wheezy_engine.get_template('imzml') self.spectra = [] from collections import namedtuple self.Spectrum = namedtuple('Spectrum', [ 'coords', 'mz_len', 'mz_offset', 'mz_enc_len', 'int_len', 'int_offset', 'int_enc_len' ])
class EngineTestCase(unittest.TestCase): """Test the ``Engine``.""" def setUp(self) -> None: self.templates: typing.Dict[str, str] = {"a": ""} self.engine = Engine( loader=DictLoader(templates=self.templates), extensions=[CoreExtension()], ) def test_template_not_found(self) -> None: """Raises IOError.""" self.assertRaises(IOError, lambda: self.engine.get_template("x")) def test_import_not_found(self) -> None: """Raises IOError.""" self.assertRaises(IOError, lambda: self.engine.import_name("x")) def test_remove_unknown_name(self) -> None: """Invalidate name that is not known to engine.""" self.engine.remove("x") def test_remove_name(self) -> None: """Invalidate name that is known to engine.""" # self.templates["a"] = "" self.engine.compile_import("a") self.engine.compile_template("a") self.engine.remove("a")
class EngineSyntaxErrorTestCase(unittest.TestCase): """Test the ``Engine``.""" def setUp(self) -> None: self.templates: typing.Dict[str, str] = {} self.engine = Engine( loader=DictLoader(templates=self.templates), extensions=[CoreExtension()], ) def test_compile_template_error(self) -> None: """Raises SyntaxError.""" self.templates[ "x" ] = """ @if : @end """ self.assertRaises( SyntaxError, lambda: self.engine.compile_template("x") ) def test_compile_import_error(self) -> None: """Raises SyntaxError.""" self.templates[ "m" ] = """ @def x(): @# ignore @if : @end @end """ self.assertRaises(SyntaxError, lambda: self.engine.compile_import("m"))
def tohtml(self): if DictLoader is None: raise ImportError('dep wheezy.template needed') loader = DictLoader({'reader': open('reader.html.template').read()}) engine = Engine(loader=loader, extensions=[CoreExtension()]) template = engine.get_template('reader') return template.render({'feed': self}).encode('utf-8')
def render(self, source, ctx=None): from wheezy.template.engine import Engine from wheezy.template.ext.core import CoreExtension from wheezy.template.loader import DictLoader loader = DictLoader({'test.html': source}) engine = Engine(loader=loader, extensions=[CoreExtension()]) template = engine.get_template('test.html') return template.render(ctx or {})
def render(self, result): """Take the function return value and renders a html document.""" templateFile = result["templatePath"] context = result["context"] searchPath = [""] engine = Engine(loader=FileLoader(searchPath), extensions=[CoreExtension(), CodeExtension()]) template = engine.get_template(templateFile) return template.render(context)
def render( self, source: str, ctx: typing.Optional[typing.Mapping[str, typing.Any]] = None, ) -> str: loader = DictLoader({"test.html": source}) engine = Engine(loader=loader, extensions=[CoreExtension()]) template = engine.get_template("test.html") return template.render(ctx or {})
def tohtml(self): if DictLoader is None: raise ImportError('dep wheezy.template needed') path = os.path.join(os.path.dirname(__file__), 'reader.html.template') loader = DictLoader({'reader': open(path).read()}) engine = Engine(loader=loader, extensions=[CoreExtension()]) template = engine.get_template('reader') return template.render({'feed': self}).encode('utf-8')
def content(self, source, filename): engine = Engine( loader=Loader(source), extensions=[ CoreExtension(token_start='\\$'), CodeExtension(token_start='\\$'), ]) engine.global_vars.update({'warn': warn}) return engine.get_template(filename).render({})
def generate_source(argsstring, options, version, enums, functions_by_category, passthru, extensions, types, raw_enums): template_pattern = re.compile("(.*).template") # Sort by categories and sort the functions inside the categories functions_by_category = sorted(functions_by_category, key=lambda x: x[0]) functions_by_category = list( map(lambda c: (c[0], sorted(c[1], key=lambda x: x.name)), functions_by_category)) template_namespace = { 'passthru': passthru, 'functions': functions_by_category, 'enums': enums, 'options': options, 'version': version, 'extensions': extensions, 'types': types, 'raw_enums': raw_enums, 'args': argsstring } if not os.path.isdir(options.template_dir): print('%s is not a directory' % options.template_dir) exit(1) if os.path.exists(options.outdir) and not os.path.isdir(options.outdir): print('%s is not a directory' % options.outdir) exit(1) if not os.path.exists(options.outdir): os.mkdir(options.outdir) engine = Engine(loader=FileLoader([options.template_dir]), extensions=[CoreExtension(), CodeExtension()]) generatedFiles = 0 allFiles = 0 for template_path in glob('%s/*.template' % os.path.abspath(options.template_dir)): infile = os.path.basename(template_path) outfile = '%s/%s' % (options.outdir, template_pattern.match(infile).group(1)) template = engine.get_template(infile) allFiles += 1 with open(outfile, 'w') as out: out.write(template.render(template_namespace)) print("Successfully generated %s" % outfile) generatedFiles += 1 print("Generated %d of %d files" % (generatedFiles, allFiles))
def render(self, source, ctx=None): from wheezy.template.engine import Engine from wheezy.template.ext.core import CoreExtension from wheezy.template.loader import DictLoader loader = DictLoader({'test.html': source}) engine = Engine( loader=loader, extensions=[CoreExtension()]) template = engine.get_template('test.html') return template.render(ctx or {})
def main(name): searchpath = [name] engine = Engine(loader=FileLoader(searchpath), extensions=[CoreExtension(token_start='#')]) engine = Engine(loader=PreprocessLoader(engine), extensions=[CoreExtension()]) engine.global_vars.update({'h': escape}) template = engine.get_template('welcome.html') return template.render
def init_templates(): """ Initialize all templates. """ global g_template_dic searchpath = ['mportal/templates'] engine = Engine(loader=FileLoader(searchpath),extensions=[CoreExtension()]) g_template_dic['login'] = engine.get_template('login.html') g_template_dic['console'] = engine.get_template('console.html') g_template_dic['not_found'] = engine.get_template('not_found.html') g_template_dic['redirect'] = engine.get_template('redirect.html')
def build_modo_bash(commands=[], headless="", render_range={}): searchpath = [TEMPLATES] engine = Engine(loader=FileLoader(searchpath), extensions=[CoreExtension()]) template = engine.get_template('modo_batch.sh') return template.render({ 'modo_cl': headless, 'commands': commands, 'render_range': render_range })
def build_modo_preview_render_command(pathaliases=None, scenes={}): searchpath = [TEMPLATES] engine = Engine(loader=FileLoader(searchpath), extensions=[CoreExtension()]) template = engine.get_template('modo_preview_render_commands.txt') if pathaliases: for key in pathaliases: '{} "{}"'.format(key, os.path.normpath(pathaliases[key])) return template.render({'pathaliases': pathaliases, 'scenes': scenes})
def main(argv: typing.Optional[typing.List[str]] = None) -> int: args = parse_args(argv or sys.argv[1:]) if not args: return 2 ts = args.token_start extensions = [CoreExtension(ts), CodeExtension(ts)] extensions.extend(args.extensions) engine = Engine(FileLoader(args.searchpath), extensions) engine.global_vars.update({"h": escape}) t = engine.get_template(args.template) sys.stdout.write(t.render(load_context(args.context))) return 0
def get(self): fortunes = db_session.query(Fortune).all() fortunes.append(Fortune(id=0, message="Additional fortune added at request time.")) fortunes.sort(key=attrgetter("message")) engine = Engine(loader=FileLoader(["views"]), extensions=[CoreExtension()]) template = engine.get_template("fortune.html") for f in fortunes: f.message = bleach.clean(f.message) template_html = template.render({"fortunes": fortunes}) response = HTTPResponse() response.write(template_html) return response
def __init__(self, path): self.path = path template_dct = { 'docker': templates.docker, } engine = Engine(loader=DictLoader(template_dct), extensions=[CoreExtension(), CodeExtension()]) self.templates = { name: engine.get_template(name) for name in template_dct }
def to_autopkg(self, outfile): searchpath = [os.path.join(os.path.dirname(os.path.abspath(__file__)), 'templates')] engine = Engine( loader=FileLoader(searchpath), extensions=[CoreExtension()] ) template = engine.get_template('redist-packages.autopkg') autopkg = template.render({'package': self}) with open(outfile, 'w') as f: f.write(autopkg) return autopkg
def build_modo_render_command_win(pathaliases=None, scenes={}): searchpath = [TEMPLATES] engine = Engine(loader=FileLoader(searchpath), extensions=[CoreExtension()]) template = engine.get_template('modo_render_commands_win.txt') if pathaliases: for key in pathaliases: '{} "{}"'.format(key, os.path.normpath(pathaliases[key])) for scene in scenes: scenes[scene]['path'] = format_filename(scenes[scene]['path'], 'win32') return template.render({'pathaliases': pathaliases, 'scenes': scenes})
def generate(filename, serial_no, settings, data): path = Path(__file__).parent / 'views' searchpath = [str(path)] engine = Engine(loader=FileLoader(searchpath), extensions=[CoreExtension()]) engine.global_vars.update({'format_value': format_value}) template = engine.get_template('template.html') with open(filename, 'w') as f: f.write( template.render({ 'data': data, 'serial_no': serial_no, 'noun': settings['dut'] }))
def to_autopkg(self, outfile): searchpath = [ os.path.join(os.path.dirname(os.path.abspath(__file__)), 'templates') ] engine = Engine(loader=FileLoader(searchpath), extensions=[CoreExtension()]) template = engine.get_template('redist-packages.autopkg') autopkg = template.render({'package': self}) with open(outfile, 'w') as f: f.write(autopkg) return autopkg
def main(args=None): if not json: # pragma: nocover print('error: json module is not available') return 1 args = parse_args(args or sys.argv[1:]) if not args: return 2 ts = args.token_start extensions = [CoreExtension(ts), CodeExtension(ts)] extensions.extend(args.extensions) engine = Engine(FileLoader(args.searchpath), extensions) engine.global_vars.update({'h': escape}) t = engine.get_template(args.template) sys.stdout.write(t.render(load_context(args.context))) return 0
def generate_source(options, version, enums, functions_by_category, passthru, extensions, types, raw_enums): template_pattern = re.compile("(.*).template") # Sort by categories and sort the functions inside the categories functions_by_category = sorted(functions_by_category ,key=lambda x: x[0]) functions_by_category = list(map(lambda c: (c[0], sorted(c[1], key=lambda x: x.name)) ,functions_by_category)) template_namespace = {'passthru' : passthru, 'functions' : functions_by_category, 'enums' : enums, 'options' : options, 'version' : version, 'extensions': extensions, 'types': types, 'raw_enums': raw_enums} if not os.path.isdir(options.template_dir): print ('%s is not a directory' % options.template_dir) exit(1) if os.path.exists(options.outdir) and not os.path.isdir(options.outdir): print ('%s is not a directory' % options.outdir) exit(1) if not os.path.exists(options.outdir): os.mkdir(options.outdir) engine = Engine(loader=FileLoader([options.template_dir]),extensions=[CoreExtension(),CodeExtension()]) generatedFiles = 0 allFiles = 0; for template_path in glob('%s/*.template' % os.path.abspath(options.template_dir)): infile = os.path.basename(template_path) outfile = '%s/%s' % (options.outdir, template_pattern.match(infile).group(1)) template = engine.get_template(infile) allFiles += 1 with open(outfile, 'w') as out: out.write(template.render(template_namespace)) print("Successfully generated %s" % outfile) generatedFiles += 1; print("Generated %d of %d files" % (generatedFiles, allFiles))
def __init__(self, path): self.path = path template_dct = { 'docker': templates.docker, } engine = Engine( loader=DictLoader(template_dct), extensions=[ CoreExtension(), CodeExtension() ] ) self.templates = { name: engine.get_template(name) for name in template_dct }
def preprocess_template( self, runtime_engine: Engine, name: str, ctx: typing.Mapping[str, typing.Any], ) -> None: self.lock.acquire(True) try: if name not in runtime_engine.renders: source = self.engine.render(name, ctx, {}, {}) loader = runtime_engine.loader.loaders[0] # type: ignore loader.templates[name] = source runtime_engine.compile_template(name) del loader.templates[name] finally: self.lock.release()
def post_setup(self, path=None, name=None): # Post setup hook if path: self.path = path else: self.path = os.path.dirname(inspect.getfile(self.__class__)) if name: self.name = name else: self.name = "%s %s " % (self.default_workspace_category, "Plugin") self.name = name # Plugin personal template engine self.templateEngine = Engine( loader=FileLoader([self.path, os.path.join(utils.scriptdir, 'html')]), extensions=[CoreExtension(), CodeExtension()] ) help_path = os.path.join(self.path, 'readme.html') if os.path.exists(help_path): self.help_tab_html_filename = 'readme.html' else: self.help_tab_html_filename = None
def setUp(self) -> None: templates = {"tmpl1.html": "x1", "shared/master.html": "x2"} engine = Engine( loader=DictLoader(templates=templates), extensions=[CoreExtension()], ) self.loader = PreprocessLoader(engine, {"x": 1})
class Wheezy(BaseEngine): app_dirname = 'wheezy_templates' def __init__(self, params): params = params.copy() options = params.pop('OPTIONS').copy() super().__init__(params) self.template_context_processors = options.pop('context_processors', []) if 'loader' not in options: options['loader'] = FileLoader(self.template_dirs) options.setdefault('autoescape', True) options.setdefault('auto_reload', settings.DEBUG) self.engine = Engine(loader=options['loader'], extensions=[CoreExtension()]) self.engine.global_vars.update({ 'e': escape, 'escape': escape, 'static': static }) def get_template(self, template_name): try: return Template(self.engine.get_template(template_name), self) except OSError as exc: raise TemplateDoesNotExist(template_name, backend=self) from exc
def build_modo_batch(commands=[], headless=""): import ntpath searchpath = [TEMPLATES] engine = Engine(loader=FileLoader(searchpath), extensions=[CoreExtension()]) template = engine.get_template('modo_batch.bat') win_commands = [] for command in commands: win_commands.append(ntpath.normpath(format_filename(command, 'win32'))) headless = ntpath.normpath( r"C:\Program Files\Luxology\modo\11.0v1\modo_cl.exe") return template.render({ 'modo_cl': ntpath.normpath(headless), 'commands': win_commands })
def runtime_engine_factory(loader: Loader) -> Engine: engine = Engine( loader=loader, extensions=[ CoreExtension(), ], ) return engine
def setUp(self): from wheezy.template.engine import Engine from wheezy.template.ext.core import CoreExtension from wheezy.template.loader import DictLoader self.templates = {} self.engine = Engine( loader=DictLoader(templates=self.templates), extensions=[CoreExtension()])
def parse_toplevel_config(self, config): super().parse_toplevel_config(config) if GIFormatter.engine is None: module_path = os.path.dirname(__file__) searchpath = [os.path.join(module_path, "html_templates")] + Formatter.engine.loader.searchpath GIFormatter.engine = Engine( loader=FileLoader(searchpath, encoding='UTF-8'), extensions=[CoreExtension(), CodeExtension()]) GIFormatter.engine.global_vars.update({'e': html.escape})
def __init__(self, searchpath): Formatter.__init__(self) self._symbol_formatters = { FunctionSymbol: self._format_function, FunctionMacroSymbol: self._format_function_macro, CallbackSymbol: self._format_callback, ConstantSymbol: self._format_constant, ExportedVariableSymbol: self._format_constant, AliasSymbol: self._format_alias, StructSymbol: self._format_struct, EnumSymbol: self._format_enum, ParameterSymbol: self._format_parameter_symbol, ReturnItemSymbol: self._format_return_item_symbol, FieldSymbol: self._format_field_symbol, SignalSymbol: self._format_signal_symbol, VFunctionSymbol: self._format_vfunction_symbol, PropertySymbol: self._format_property_symbol, ClassSymbol: self._format_class_symbol, InterfaceSymbol: self._format_interface_symbol, } self._ordering = [InterfaceSymbol, ClassSymbol, FunctionSymbol, FunctionMacroSymbol, SignalSymbol, PropertySymbol, StructSymbol, VFunctionSymbol, EnumSymbol, ConstantSymbol, ExportedVariableSymbol, AliasSymbol, CallbackSymbol] if HtmlFormatter.theme_path: self.__load_theme_templates(searchpath, HtmlFormatter.theme_path) if HtmlFormatter.extra_theme_path: self.__load_theme_templates(searchpath, HtmlFormatter.extra_theme_path) searchpath.append(os.path.join(HERE, "html_templates")) self.engine = Engine( loader=FileLoader(searchpath, encoding='UTF-8'), extensions=[CoreExtension(), CodeExtension()] ) self.all_scripts = set() self.all_stylesheets = set() self._docstring_formatter = GtkDocStringFormatter()
def parse_config(self, config): """Banana banana """ self.add_anchors = bool(config.get("html_add_anchors")) self.number_headings = bool(config.get("html_number_headings")) if self.theme_path: self.__load_theme_templates(self.searchpath, self.theme_path) if self.extra_theme_path: self.__load_theme_templates(self.searchpath, self.extra_theme_path) self.searchpath.append(os.path.join(HERE, "templates")) self.engine = Engine(loader=FileLoader(self.searchpath, encoding='UTF-8'), extensions=[CoreExtension(), CodeExtension()]) self.engine.global_vars.update({'e': html.escape}) self._docstring_formatter.parse_config(config)
def generate_source(options, version, enums, functions_by_category, passthru, extensions): generated_warning = '/* WARNING: This file was automatically generated */\n/* Do not edit. */\n' template_pattern = re.compile("(.*).template") template_namespace = {'passthru' : passthru, 'functions' : functions_by_category, 'enums' : enums, 'options' : options, 'version' : version, 'extensions': extensions} if not os.path.isdir(options.template_dir): print ('%s is not a directory' % options.template_dir) exit(1) if os.path.exists(options.outdir) and not os.path.isdir(options.outdir): print ('%s is not a directory' % options.outdir) exit(1) if not os.path.exists(options.outdir): os.mkdir(options.outdir) engine = Engine(loader=FileLoader([options.template_dir]), extensions=[CoreExtension()]) generatedFiles = 0 allFiles = 0; for template_path in glob('%s/*.template' % os.path.abspath(options.template_dir)): infile = os.path.basename(template_path) outfile = '%s/%s' % (options.outdir, template_pattern.match(infile).group(1)) template = engine.get_template(infile) allFiles += 1 with open(outfile, 'w') as out: out.write(generated_warning) out.write(template.render(template_namespace)) print("Successfully generated %s" % outfile) generatedFiles += 1; print("Generated %d of %d files" % (generatedFiles, allFiles))
def render(outname, templatename, newcontext=None): engine = Engine( loader=FileLoader(['templates'], 'UTF-8'), extensions=[CoreExtension()] ) template = engine.get_template(templatename) context = { 'title': WLOG_TITLE, 'wlog_url': WLOG_URL, 'site_url': SITE_URL, 'version': VERSION, 'categories': MAIN_CATEGORIES, } if newcontext: context.update(newcontext) output = template.render(context) with open("output/{}.html".format(outname), 'w') as f: f.write(output.encode('utf-8'))
class EngineTestCase(unittest.TestCase): """ Test the ``Engine``. """ def setUp(self): from wheezy.template.engine import Engine from wheezy.template.loader import DictLoader self.engine = Engine( loader=DictLoader(templates={}), extensions=[]) def test_template_not_found(self): """ Raises IOError. """ self.assertRaises(IOError, lambda: self.engine.get_template('x')) def test_import_not_found(self): """ Raises IOError. """ self.assertRaises(IOError, lambda: self.engine.import_name('x')) def test_remove_unknown_name(self): """ Invalidate name that is not known to engine. """ self.engine.remove('x') def test_remove_name(self): """ Invalidate name that is known to engine. """ self.engine.templates['x'] = 'x' self.engine.renders['x'] = 'x' self.engine.modules['x'] = 'x' self.engine.remove('x')
def generate_html(self, filename, template_file="Default.html"): engine = Engine( loader=FileLoader(['templates']), extensions=[CoreExtension()] ) template = engine.get_template(template_file) try: file = open(filename, "w") try: clients_list_descendant = list(reversed(sorted(self.clients_hours.items(), key=lambda x: x[1]))) file.write(template.render({'clients_hours':clients_list_descendant, 'total_hours':str(self.total_hours_booked), 'unbooked_timeranges':self.get_unbooked_hours(), 'total_hours_unbooked': self.total_hours_unbooked})) finally: file.close() except IOError: pass
def __init__(self, searchpath): Formatter.__init__(self) self._symbol_formatters = { FunctionSymbol: self._format_function, FunctionMacroSymbol: self._format_function_macro, CallbackSymbol: self._format_callback, ConstantSymbol: self._format_constant, ExportedVariableSymbol: self._format_constant, AliasSymbol: self._format_alias, StructSymbol: self._format_struct, EnumSymbol: self._format_enum, ParameterSymbol: self._format_parameter_symbol, ReturnItemSymbol: self._format_return_item_symbol, FieldSymbol: self._format_field_symbol, SignalSymbol: self._format_signal_symbol, VFunctionSymbol: self._format_vfunction_symbol, PropertySymbol: self._format_property_symbol, ClassSymbol: self._format_class_symbol, InterfaceSymbol: self._format_interface_symbol, } self._ordering = [InterfaceSymbol, ClassSymbol, FunctionSymbol, FunctionMacroSymbol, SignalSymbol, PropertySymbol, StructSymbol, VFunctionSymbol, EnumSymbol, ConstantSymbol, ExportedVariableSymbol, AliasSymbol, CallbackSymbol] if HtmlFormatter.theme_path: theme_templates_path = os.path.join( HtmlFormatter.theme_path, 'templates') if os.path.exists(theme_templates_path): searchpath.insert(0, theme_templates_path) searchpath.append(os.path.join(HERE, "html_templates")) self.engine = Engine( loader=FileLoader(searchpath, encoding='UTF-8'), extensions=[CoreExtension(), CodeExtension()] ) self.all_scripts = set() self.all_stylesheets = set() self._docstring_formatter = GtkDocStringFormatter()
class TemplateTestCase(unittest.TestCase): """ Test the ``CodeExtension`` compiled templates. """ def setUp(self): from wheezy.template.engine import Engine from wheezy.template.ext.code import CodeExtension from wheezy.template.ext.core import CoreExtension from wheezy.template.loader import DictLoader self.templates = {} self.engine = Engine( loader=DictLoader(templates=self.templates), extensions=[CoreExtension(), CodeExtension()]) def render(self, source): self.templates['test.html'] = source template = self.engine.get_template('test.html') return template.render({}) def test_code_single_line(self): assert '1' == self.render('@(i = 1)@i!s') def test_code_continue_newline(self): assert '1' == self.render('@(i = 1)\\\n@i!s') def test_code_separated_lines(self): assert '\n1' == self.render('@(i = 1)\n@i!s') def test_code_with_markup1(self): assert 'x = 1' == self.render('x@(i = 1) = @i!s') def test_code_with_markup2(self): assert 'x = 1' == self.render('x @(i = 1)= @i!s') def test_code_multiline(self): assert 'x = 1' == self.render("""\ x \ @( i = 1 )\ = @i!s""")
def __init__(self, output_filename, mz_dtype=np.float64, intensity_dtype=np.float32): self.mz_dtype = mz_dtype self.intensity_dtype = intensity_dtype self.run_id = os.path.splitext(output_filename)[0] self.filename = self.run_id + ".imzML" self.ibd_filename = self.run_id + ".ibd" self.xml = open(self.filename, 'w') self.ibd = open(self.ibd_filename, 'w') self.sha1 = hashlib.sha1() self.ibd_offset = 0 self.uuid = uuid.uuid4() self._write_ibd(self.uuid.bytes_le) self.wheezy_engine = Engine(loader=DictLoader({'imzml': IMZML_TEMPLATE}), extensions=[CoreExtension()]) self.imzml_template = self.wheezy_engine.get_template('imzml') self.spectra = [] from collections import namedtuple self.Spectrum = namedtuple('Spectrum', ['coords', 'mz_len', 'mz_offset', 'mz_enc_len', 'int_len', 'int_offset', 'int_enc_len'])
def __init__(self, searchpath): Formatter.__init__(self) self._symbol_formatters = { FunctionSymbol: self._format_function, FunctionMacroSymbol: self._format_function_macro, CallbackSymbol: self._format_callback, ConstantSymbol: self._format_constant, ExportedVariableSymbol: self._format_constant, AliasSymbol: self._format_alias, StructSymbol: self._format_struct, EnumSymbol: self._format_enum, ClassSymbol: self._format_class, SectionSymbol: self._format_class, ParameterSymbol: self._format_parameter_symbol, ReturnValueSymbol : self._format_return_value_symbol, FieldSymbol: self._format_field_symbol, } self._summary_formatters = { FunctionSymbol: self._format_function_summary, FunctionMacroSymbol: self._format_function_macro_summary, CallbackSymbol: self._format_callback_summary, ConstantSymbol: self._format_constant_summary, ExportedVariableSymbol: self._format_exported_variable_summary, AliasSymbol: self._format_alias_summary, StructSymbol: self._format_struct_summary, EnumSymbol: self._format_enum_summary, } self._ordering = [FunctionSymbol, FunctionMacroSymbol, StructSymbol, EnumSymbol, ConstantSymbol, ExportedVariableSymbol, AliasSymbol, CallbackSymbol] module_path = os.path.dirname(__file__) searchpath.append (os.path.join(module_path, "templates")) self.engine = Engine( loader=FileLoader(searchpath, encoding='UTF-8'), extensions=[CoreExtension()] )
class HtmlFormatter (Formatter): def __init__(self, searchpath): Formatter.__init__(self) self._symbol_formatters = { FunctionSymbol: self._format_function, FunctionMacroSymbol: self._format_function_macro, CallbackSymbol: self._format_callback, ConstantSymbol: self._format_constant, ExportedVariableSymbol: self._format_constant, AliasSymbol: self._format_alias, StructSymbol: self._format_struct, EnumSymbol: self._format_enum, ClassSymbol: self._format_class, SectionSymbol: self._format_class, ParameterSymbol: self._format_parameter_symbol, ReturnValueSymbol : self._format_return_value_symbol, FieldSymbol: self._format_field_symbol, } self._summary_formatters = { FunctionSymbol: self._format_function_summary, FunctionMacroSymbol: self._format_function_macro_summary, CallbackSymbol: self._format_callback_summary, ConstantSymbol: self._format_constant_summary, ExportedVariableSymbol: self._format_exported_variable_summary, AliasSymbol: self._format_alias_summary, StructSymbol: self._format_struct_summary, EnumSymbol: self._format_enum_summary, } self._ordering = [FunctionSymbol, FunctionMacroSymbol, StructSymbol, EnumSymbol, ConstantSymbol, ExportedVariableSymbol, AliasSymbol, CallbackSymbol] module_path = os.path.dirname(__file__) searchpath.append (os.path.join(module_path, "templates")) self.engine = Engine( loader=FileLoader(searchpath, encoding='UTF-8'), extensions=[CoreExtension()] ) def _get_extension (self): return "html" def _format_link (self, link, title): out = '' template = self.engine.get_template('link.html') out += '%s' % template.render ({'link': link, 'link_title': title}) return out def _format_type_tokens (self, type_tokens): out = '' link_before = False for tok in type_tokens: if isinstance (tok, Link): out += self._format_link (tok.get_link(), tok.title) link_before = True else: if link_before: out += ' ' out += tok link_before = False return out def _format_linked_symbol (self, symbol): out = "" if isinstance (symbol, QualifiedSymbol): out += self._format_type_tokens (symbol.type_tokens) elif hasattr (symbol, "link"): out += self._format_link (symbol.link.get_link(), symbol.link.title) if type (symbol) == ParameterSymbol: out += ' ' + symbol.argname if type (symbol) == FieldSymbol and symbol.member_name: template = self.engine.get_template('inline_code.html') member_name = template.render ({'code': symbol.member_name}) if symbol.is_function_pointer: out = member_name out += "()" else: out += ' ' + member_name return out def _format_callable_prototype (self, return_value, function_name, parameters, is_pointer): template = self.engine.get_template('callable_prototype.html') param_offset = ' ' * (len (function_name) + 2) if is_pointer: param_offset += 3 * ' ' callable_ = Callable (return_value, function_name, parameters) return template.render ({'callable': callable_, 'param_offset': param_offset, 'is_pointer': is_pointer, }) def __format_parameter_detail (self, name, detail): template = self.engine.get_template('parameter_detail.html') return template.render ({'name': name, 'detail': detail, }) def _format_callable_summary (self, return_value, function_name, is_callable, is_pointer, flags): template = self.engine.get_template('callable_summary.html') return template.render({'return_value': return_value, 'function_name': function_name, 'is_callable': is_callable, 'is_pointer': is_pointer, 'flags': flags }) def _format_function_summary (self, func): return self._format_callable_summary ( self._format_linked_symbol (func.return_value), self._format_linked_symbol (func), True, False, []) def _format_callback_summary (self, callback): return self._format_callable_summary ( self._format_linked_symbol (callback.return_value), self._format_linked_symbol (callback), True, True, []) def _format_function_macro_summary (self, func): return self._format_callable_summary ( "#define ", self._format_linked_symbol (func), True, False, []) def _format_constant_summary (self, constant): template = self.engine.get_template('constant_summary.html') constant_link = self._format_linked_symbol (constant) return template.render({'constant': constant_link}) def _format_exported_variable_summary (self, extern): template = self.engine.get_template('exported_variable_summary.html') extern_link = self._format_linked_symbol (extern) return template.render({'extern': extern_link}) def _format_alias_summary (self, alias): template = self.engine.get_template('alias_summary.html') alias_link = self._format_linked_symbol (alias) return template.render({'alias': alias_link}) def _format_struct_summary (self, struct): template = self.engine.get_template('struct_summary.html') struct_link = self._format_linked_symbol (struct) return template.render({'struct': struct_link}) def _format_enum_summary (self, enum): template = self.engine.get_template('enum_summary.html') enum_link = self._format_linked_symbol (enum) return template.render({'enum': enum_link}) def _format_summary (self, summaries, summary_type): if not summaries: return None template = self.engine.get_template('summary.html') return template.render({'summary_type': summary_type, 'summaries': summaries }) def _format_symbols_toc_section (self, symbols_type, symbols_list): summary_formatter = self._summary_formatters.get(symbols_type) if not summary_formatter: return (None, None) toc_section_summaries = [] detailed_descriptions = [] for element in symbols_list.symbols: summary = summary_formatter(element) if summary: toc_section_summaries.append (summary) if element.detailed_description: detailed_descriptions.append (element.detailed_description) if not toc_section_summaries: return (None, None) summary = self._format_summary (toc_section_summaries, symbols_list.name) toc_section = TocSection (summary, symbols_list.name) symbol_descriptions = None if detailed_descriptions: symbol_descriptions = SymbolDescriptions (detailed_descriptions, symbols_list.name) return (toc_section, symbol_descriptions) def _format_struct (self, struct): raw_code = self._format_raw_code (struct.raw_text) members_list = self._format_members_list (struct.members, 'Fields') template = self.engine.get_template ("struct.html") out = template.render ({"struct": struct, "raw_code": raw_code, "members_list": members_list}) return (out, False) def _format_enum (self, enum): for member in enum.members: template = self.engine.get_template ("enum_member.html") member.detailed_description = template.render ({ 'link': member.link, 'detail': member.formatted_doc, 'value': str (member.enum_value)}) members_list = self._format_members_list (enum.members, 'Members') template = self.engine.get_template ("enum.html") out = template.render ({"enum": enum, "members_list": members_list}) return (out, False) def _format_class(self, klass): if klass.parsed_page and not klass.symbols: klass.formatted_contents = doc_tool.page_parser.render_parsed_page(klass.parsed_page) toc_sections = [] symbols_details = [] for symbols_type in self._ordering: symbols_list = klass.typed_symbols.get(symbols_type) if not symbols_list: continue toc_section, symbols_descriptions = \ self._format_symbols_toc_section (symbols_type, symbols_list) if toc_section: toc_sections.append(toc_section) if symbols_descriptions: symbols_details.append (symbols_descriptions) hierarchy = None if hasattr (klass, 'hierarchy') and klass.hierarchy: hierarchy = [] children = [] for p in klass.hierarchy: hierarchy.append(self._format_linked_symbol (p)) for c in klass.children.itervalues(): children.append(self._format_linked_symbol (c)) template = self.engine.get_template ("hierarchy.html") hierarchy = template.render ({'hierarchy': hierarchy, 'children': children, 'klass': klass}) template = self.engine.get_template('class.html') out = template.render ({'klass': klass, 'hierarchy': hierarchy, 'toc_sections': toc_sections, 'stylesheet': self.__stylesheet, 'symbols_details': symbols_details}) return (out, True) def _format_prototype (self, function, is_pointer, title): return_value = self._format_linked_symbol (function.return_value) parameters = [] for param in function.parameters: parameters.append (self._format_linked_symbol(param)) return self._format_callable_prototype (return_value, title, parameters, is_pointer) def _format_raw_code (self, code): template = self.engine.get_template('raw_code.html') return template.render ({'code': code}) def _format_parameter_symbol (self, parameter): return (self.__format_parameter_detail (parameter.argname, parameter.formatted_doc), False) def _format_field_symbol (self, field): field_id = self._format_linked_symbol (field) return (self.__format_parameter_detail (field_id, field.formatted_doc), False) def _format_return_value_symbol(self, return_value): if not return_value or not return_value.formatted_doc: return ('', False) template = self.engine.get_template('return_value.html') return (template.render ({'return_value': return_value}), False) def _format_callable(self, callable_, callable_type, title, is_pointer=False, flags=None): template = self.engine.get_template('callable.html') for p in callable_.parameters: p.do_format() parameters = [p.detailed_description for p in callable_.parameters if p.detailed_description is not None] prototype = self._format_prototype (callable_, is_pointer, title) return_value_detail = None if callable_.return_value: callable_.return_value.do_format() return_value_detail = callable_.return_value.detailed_description out = template.render ({'prototype': prototype, 'callable': callable_, 'return_value': return_value_detail, 'parameters': parameters, 'callable_type': callable_type, 'flags': flags}) return (out, False) def _format_members_list(self, members, member_designation): template = self.engine.get_template('member_list.html') return template.render ({'members': members, 'member_designation': member_designation}) def _format_function(self, function): return self._format_callable (function, "method", function.link.title) def _format_callback (self, callback): return self._format_callable (callback, "callback", callback.link.title, is_pointer=True) def _format_function_macro(self, function_macro): template = self.engine.get_template('callable.html') prototype = self._format_raw_code (function_macro.original_text) for p in function_macro.parameters: p.do_format() parameters = [p.detailed_description for p in function_macro.parameters if p.detailed_description is not None] return_value_detail = None if function_macro.return_value: function_macro.return_value.do_format() return_value_detail = function_macro.return_value.detailed_description out = template.render ({'prototype': prototype, 'callable': function_macro, 'return_value': return_value_detail, 'parameters': parameters, 'callable_type': "function macro", 'flags': None}) return (out, False) def _format_alias (self, alias): template = self.engine.get_template('alias.html') aliased_type = self._format_linked_symbol (alias.aliased_type) return (template.render ({'alias': alias, 'aliased_type': aliased_type}), False) def _format_constant(self, constant): template = self.engine.get_template('constant.html') definition = self._format_raw_code (constant.original_text) out = template.render ({'definition': definition, 'constant': constant}) return (out, False) def _format_symbol (self, symbol): format_function = self._symbol_formatters.get(type(symbol)) if format_function: return format_function (symbol) return (None, False) def _format_api_index (self, columns, rows): template = self.engine.get_template('API_index.html') rows.sort (key=lambda row: row[0].title) formatted_rows = [] for row in rows: formatted_row = [] for field in row: if isinstance(field, Link): formatted_row.append (self._format_link(field.get_link(), field.title)) else: formatted_row.append (field) formatted_rows.append (formatted_row) out = template.render ({'columns': columns, 'rows': formatted_rows, 'stylesheet': self.__stylesheet}) return out def _format_class_hierarchy (self, dot_graph): f = tempfile.NamedTemporaryFile(suffix='.svg', delete=False) dot_graph.draw(f, prog='dot', format='svg', args="-Grankdir=LR") f.close() with open (f.name, 'r') as f: contents = f.read() os.unlink(f.name) template = self.engine.get_template('object_hierarchy.html') return template.render ({'graph': contents, 'stylesheet': self.__stylesheet}) def _get_style_sheet (self): return "style.css" def _get_extra_files (self): dir_ = os.path.dirname(__file__) return [os.path.join (dir_, self.__stylesheet), os.path.join (dir_, "API_index.js"), os.path.join (dir_, "home.png"),] def format (self): self.__stylesheet = self._get_style_sheet() Formatter.format(self)
""", }, { "title": "These don't solve my problem", "body": """ Please contact me. There are two ways to contact me for help. For both methods, describe your problem in as much detail as possible. The more I know about your issue right off the start, the less questions I have to ask you. Also, please provide information about your phone (model, Android version, etc.). <ol> <li> Open the app and select <i>Email Developer</i>. This will automatically add information about your device and your settings to the email. </li> <li> <a href="/contact">Fill out this form</a>. </li> </ol> """, }, ] from wheezy.template.engine import Engine from wheezy.template.ext.core import CoreExtension from wheezy.template.loader import FileLoader searchpath = ["."] engine = Engine(loader=FileLoader(searchpath), extensions=[CoreExtension()]) template = engine.get_template("template.html") f = open("smsfix.html", "w") f.write(template.render({"pagetitle": "SMS Time Fix Help", "topics": topics})) f.close()
${PAYPAL} ''', }, { 'title': "I have a feature request", 'body': ''' <a href="/contact">Contact me</a> ''', }, { 'title': "These don't solve my problem", 'body': ''' <a href="/contact">Contact me</a>. Please describe your problem in as much detail as possible. The more I know about your issue right off the start, the less questions I have to ask you. Also, please provide information about your phone (model, Android version, etc.). ''', }, ] from wheezy.template.engine import Engine from wheezy.template.ext.core import CoreExtension from wheezy.template.loader import FileLoader searchpath = ['.'] engine = Engine( loader=FileLoader(searchpath), extensions=[CoreExtension()] ) template = engine.get_template('template.html') f = open('prioritysms.html', 'w') f.write(template.render({'pagetitle': 'Priority SMS Help', 'topics': topics})) f.close()
people = [Person(p.handle, p.name) for p in config.people] problems = [Problem(config.week.contest_id, p.letter, p.name) for p in config.week.problems] contest_ids = set(p.contest_id for p in problems) assert len(contest_ids) == 1 contest_id = int(contest_ids.pop()) solves = dict() for person in people: response = api.get_user_contest_submissions(person.handle, contest_id) solves[person] = set(s.problem.index for s in response if s.problem.contestId == contest_id and s.verdict == "OK") people = sorted(people, key=lambda p: len(solves[p]), reverse=True) template_input_path = config.template.input_path engine = Engine(loader=FileLoader([template_input_path]), extensions=[CoreExtension()]) index_template = engine.get_template(config.template.index_local_path) model = {"announcement": announcement, "people": people, "problems": problems, "solves": solves, "title": title} index_html = index_template.render(model) with open(os.path.join(config.template.output_path, "index.html"), "r") as f: existing_index_html = f.read() updated_file = calculate_sha1(index_html) != calculate_sha1(existing_index_html) if updated_file: with open(os.path.join(config.template.output_path, "index.html"), "w") as f: f.write(index_html) with open(os.path.join(config.template.output_path, "last_modified.json"), "w") as f:
# region: wheezy.template try: from wheezy.template.engine import Engine from wheezy.template.loader import DictLoader from wheezy.template.ext.core import CoreExtension except ImportError: test_wheezy_template = None else: engine = Engine(loader=DictLoader({'x': s("""\ @require(table) <table> @for row in table: <tr> @for key, value in row.items(): <td>@key!h</td><td>@value!s</td> @end </tr> @end </table> """)}), extensions=[CoreExtension()]) engine.global_vars.update({'h': escape}) wheezy_template = engine.get_template('x') def test_wheezy_template(): return wheezy_template.render(ctx) # region: Jinja2 try:
call(['org-export','html','--infile',n['f'],'--outfile',n['export_to'],'--bootstrap' ]) # update again, see if everything exported file_df = export_info(file_df) need_update = file_df.query('export_date != export_date or export_date < mt') if len(need_update) != 0: print("some files failed to update: %s!"%(",".join(need_update['title']))) # export_to is relative to this script. should be relative to index.html # remove '../' file_df['uri'] = [ re.sub('^\.\./','',x) for x in file_df['export_to'] ] # index template from wheezy.template.engine import Engine from wheezy.template.ext.core import CoreExtension from wheezy.template.loader import FileLoader engine = Engine(loader=FileLoader(['../src/']), extensions=[CoreExtension()]) template = engine.get_template('index.tmp') # write it out index_str = template.render({'file_df': file_df,'title': 'WF log'}) with open('../index.html','w') as indexf: indexf.write(index_str) # ## Gopher def html_to_goph(x): x = re.sub('(org|html)$', 'txt', x) x = re.sub('html/', '/gopher/', x) return(x) for i, n in need_update.iterrows():
class HtmlFormatter(Formatter): """ Banana banana """ theme_path = None add_anchors = False number_headings = False def __init__(self, searchpath): Formatter.__init__(self) self._symbol_formatters = { FunctionSymbol: self._format_function, FunctionMacroSymbol: self._format_function_macro, CallbackSymbol: self._format_callback, ConstantSymbol: self._format_constant, ExportedVariableSymbol: self._format_constant, AliasSymbol: self._format_alias, StructSymbol: self._format_struct, EnumSymbol: self._format_enum, ParameterSymbol: self._format_parameter_symbol, ReturnItemSymbol: self._format_return_item_symbol, FieldSymbol: self._format_field_symbol, SignalSymbol: self._format_signal_symbol, VFunctionSymbol: self._format_vfunction_symbol, PropertySymbol: self._format_property_symbol, ClassSymbol: self._format_class_symbol, InterfaceSymbol: self._format_interface_symbol, } self._ordering = [InterfaceSymbol, ClassSymbol, FunctionSymbol, FunctionMacroSymbol, SignalSymbol, PropertySymbol, StructSymbol, VFunctionSymbol, EnumSymbol, ConstantSymbol, ExportedVariableSymbol, AliasSymbol, CallbackSymbol] if HtmlFormatter.theme_path: theme_templates_path = os.path.join( HtmlFormatter.theme_path, 'templates') if os.path.exists(theme_templates_path): searchpath.insert(0, theme_templates_path) searchpath.append(os.path.join(HERE, "html_templates")) self.engine = Engine( loader=FileLoader(searchpath, encoding='UTF-8'), extensions=[CoreExtension(), CodeExtension()] ) self.all_scripts = set() self.all_stylesheets = set() self._docstring_formatter = GtkDocStringFormatter() # pylint: disable=no-self-use def __init_section_numbers(self, root): if not HtmlFormatter.number_headings: return {} targets = [] ctr = 0 while len(targets) <= 1: ctr += 1 if ctr > 5: return {} targets = root.xpath('.//*[self::h%s]' % ctr) section_numbers = {} for i in range(ctr, 6): section_numbers['h%d' % i] = 0 section_numbers['first'] = ctr return section_numbers # pylint: disable=no-self-use def __update_section_number(self, target, section_numbers): if target.tag not in section_numbers: return None prev = section_numbers.get('prev') cur = int(target.tag[1]) if cur < prev: for i in range(cur + 1, 6): section_numbers['h%d' % i] = 0 section_numbers[target.tag] += 1 section_numbers['prev'] = cur section_number = u'' for i in range(section_numbers['first'], cur + 1): if section_number: section_number += '.' section_number += unicode(section_numbers['h%d' % i]) return section_number # pylint: disable=too-many-locals def write_page(self, page, output): root = etree.HTML(unicode(page.detailed_description)) id_nodes = {n.attrib['id']: "".join([x for x in n.itertext()]) for n in root.xpath('.//*[@id]')} section_numbers = self.__init_section_numbers(root) targets = root.xpath( './/*[self::h1 or self::h2 or self::h3 or ' 'self::h4 or self::h5 or self::img]') for target in targets: section_number = self.__update_section_number( target, section_numbers) if 'id' in target.attrib: continue if target.tag == 'img': text = target.attrib.get('alt') else: text = "".join([x for x in target.itertext()]) if not text: continue id_ = id_from_text(text) ref_id = id_ index = 1 while id_ in id_nodes: id_ = '%s%s' % (ref_id, index) index += 1 if section_number: target.text = '%s %s' % (section_number, target.text or '') target.attrib['id'] = id_ id_nodes[id_] = text empty_links = root.xpath('.//a[not(text()) and not(*)]') for link in empty_links: href = link.attrib.get('href') if href and href.startswith('#'): title = id_nodes.get(href.strip('#')) if title: link.text = title else: warn('bad-local-link', "Empty anchor link to %s in %s points nowhere" % (href, page.source_file)) link.text = "FIXME broken link to %s" % href page.detailed_description = lxml.html.tostring( root, doctype="<!DOCTYPE html>", encoding='unicode', include_meta_content_type=True) return Formatter.write_page(self, page, output) # pylint: disable=no-self-use def _get_extension(self): return "html" def get_output_folder(self): return os.path.join(super(HtmlFormatter, self).get_output_folder(), 'html') def _format_link(self, link, title): out = '' if not link: assert link print "Issue here plz check", title return title template = self.engine.get_template('link.html') out += '%s' % template.render({'link': link, 'link_title': title}) return out def _format_type_tokens(self, type_tokens): out = '' link_before = False for tok in type_tokens: if isinstance(tok, Link): ref = tok.get_link() if ref: out += self._format_link(ref, tok.title) link_before = True else: if link_before: out += ' ' out += tok.title link_before = False else: if link_before: out += ' ' out += tok link_before = False return out # pylint: disable=unidiomatic-typecheck def _format_linked_symbol(self, symbol): out = "" if isinstance(symbol, QualifiedSymbol): out += self._format_type_tokens(symbol.type_tokens) # FIXME : ugly elif hasattr(symbol, "link") and type(symbol) != FieldSymbol: out += self._format_link(symbol.link.get_link(), symbol.link.title) if type(symbol) == ParameterSymbol: out += ' ' + symbol.argname elif type(symbol) == FieldSymbol and symbol.member_name: out += self._format_type_tokens(symbol.qtype.type_tokens) template = self.engine.get_template('inline_code.html') member_name = template.render({'code': symbol.member_name}) if symbol.is_function_pointer: out = member_name out += "()" else: out += ' ' + member_name return out def _format_callable_prototype(self, return_value, function_name, parameters, is_pointer): template = self.engine.get_template('callable_prototype.html') return template.render({'return_value': return_value, 'name': function_name, 'parameters': parameters, 'is_pointer': is_pointer}) def __format_parameter_detail(self, name, detail, extra=None): extra = extra or {} template = self.engine.get_template('parameter_detail.html') return template.render({'name': name, 'detail': detail, 'extra': extra}) def _format_symbol_descriptions(self, symbols_list): detailed_descriptions = [] for element in symbols_list.symbols: if element.skip: continue if element.detailed_description: detailed_descriptions.append(element.detailed_description) symbol_type = symbols_list.name symbol_descriptions = None if detailed_descriptions: symbol_descriptions = SymbolDescriptions(detailed_descriptions, symbol_type) return symbol_descriptions def _format_struct(self, struct): raw_code = None if struct.raw_text is not None: raw_code = self._format_raw_code(struct.raw_text) members_list = self._format_members_list(struct.members, 'Fields') template = self.engine.get_template("struct.html") out = template.render({"symbol": struct, "struct": struct, "raw_code": raw_code, "members_list": members_list}) return (out, False) def _format_enum(self, enum): for member in enum.members: template = self.engine.get_template("enum_member.html") member.detailed_description = template.render({ 'link': member.link, 'detail': member.formatted_doc, 'value': str(member.enum_value)}) raw_code = None if enum.raw_text is not None: raw_code = self._format_raw_code(enum.raw_text) members_list = self._format_members_list(enum.members, 'Members') template = self.engine.get_template("enum.html") out = template.render({"symbol": enum, "enum": enum, "raw_code": raw_code, "members_list": members_list}) return (out, False) def prepare_page_attributes(self, page): """ Banana banana """ page.output_attrs['html']['scripts'] = OrderedSet() page.output_attrs['html']['stylesheets'] = OrderedSet() page.output_attrs['html']['extra_html'] = [] page.output_attrs['html']['extra_footer_html'] = [] if HtmlFormatter.add_anchors: page.output_attrs['html']['scripts'].add( os.path.join(HERE, 'html_assets', 'css.escape.js')) Formatter.prepare_page_attributes(self, page) def patch_page(self, page, symbol): raise NotImplementedError # pylint: disable=too-many-locals def _format_page(self, page): symbols_details = [] for symbols_type in self._ordering: symbols_list = page.typed_symbols.get(symbols_type) if not symbols_list: continue symbols_descriptions = self._format_symbol_descriptions( symbols_list) if symbols_descriptions: symbols_details.append(symbols_descriptions) template = self.engine.get_template('page.html') scripts = page.output_attrs['html']['scripts'] stylesheets = page.output_attrs['html']['stylesheets'] scripts_basenames = [os.path.basename(script) for script in scripts] stylesheets_basenames = [os.path.basename(stylesheet) for stylesheet in stylesheets] self.all_stylesheets.update(stylesheets) self.all_scripts.update(scripts) out = template.render( {'page': page, 'source_file': os.path.basename(page.source_file), 'scripts': scripts_basenames, 'stylesheets': stylesheets_basenames, 'assets_path': self._get_assets_path(), 'extra_html': page.output_attrs['html']['extra_html'], 'extra_footer_html': page.output_attrs['html']['extra_footer_html'], 'symbols_details': symbols_details}) return (out, True) def _format_prototype(self, function, is_pointer, title): if function.return_value: return_value = self._format_linked_symbol(function.return_value[0]) else: return_value = None parameters = [] for param in function.parameters: parameters.append(self._format_linked_symbol(param)) return self._format_callable_prototype(return_value, title, parameters, is_pointer) def _format_raw_code(self, code): code = cgi.escape(code) template = self.engine.get_template('raw_code.html') return template.render({'code': code}) def _format_parameter_symbol(self, parameter): return (self.__format_parameter_detail( parameter.argname, parameter.formatted_doc, extra=parameter.extension_contents), False) def _format_field_symbol(self, field): field_id = self._format_linked_symbol(field) template = self.engine.get_template('field_detail.html') return (template.render({'symbol': field, 'name': field_id, 'detail': field.formatted_doc}), False) def _format_return_item_symbol(self, return_item): template = self.engine.get_template('return_item.html') return_item.formatted_link = self._format_linked_symbol(return_item) return (template.render({'return_item': return_item}), False) def _format_return_value_symbol(self, return_value): template = self.engine.get_template('multi_return_value.html') if return_value[0] is None: return_value = return_value[1:] return template.render({'return_items': return_value}) def _format_callable(self, callable_, callable_type, title, is_pointer=False): template = self.engine.get_template('callable.html') parameters = [p.detailed_description for p in callable_.parameters if p.detailed_description is not None] prototype = self._format_prototype(callable_, is_pointer, title) return_value_detail = self._format_return_value_symbol( callable_.return_value) tags = {} if callable_.comment: tags = dict(callable_.comment.tags) tags.pop('returns', None) tags.pop('topic', None) out = template.render({'prototype': prototype, 'symbol': callable_, 'return_value': return_value_detail, 'parameters': parameters, 'callable_type': callable_type, 'tags': tags, 'extra': callable_.extension_contents}) return (out, False) def _format_signal_symbol(self, signal): title = "%s_callback" % re.sub('-', '_', signal.link.title) return self._format_callable(signal, "signal", title) def _format_vfunction_symbol(self, vmethod): return self._format_callable(vmethod, "virtual method", vmethod.link.title) def _format_property_symbol(self, prop): type_link = self._format_linked_symbol(prop.prop_type) template = self.engine.get_template('property_prototype.html') prototype = template.render({'property_name': prop.link.title, 'property_type': type_link}) template = self.engine.get_template('property.html') res = template.render({'symbol': prop, 'prototype': prototype, 'property': prop, 'extra': prop.extension_contents}) return (res, False) def _format_hierarchy(self, klass): hierarchy = [] children = [] for _ in klass.hierarchy: hierarchy.append(self._format_linked_symbol(_)) for _ in klass.children.itervalues(): children.append(self._format_linked_symbol(_)) if hierarchy or children: template = self.engine.get_template("hierarchy.html") hierarchy = template.render({'hierarchy': hierarchy, 'children': children, 'klass': klass}) return hierarchy def _format_class_symbol(self, klass): hierarchy = self._format_hierarchy(klass) template = self.engine.get_template('class.html') return (template.render({'symbol': klass, 'klass': klass, 'hierarchy': hierarchy}), False) def _format_interface_symbol(self, interface): hierarchy = self._format_hierarchy(interface) template = self.engine.get_template('interface.html') return (template.render({'symbol': interface, 'hierarchy': hierarchy}), False) def _format_members_list(self, members, member_designation): template = self.engine.get_template('member_list.html') return template.render({'members': members, 'member_designation': member_designation}) def _format_function(self, function): return self._format_callable(function, "method", function.link.title) def _format_callback(self, callback): return self._format_callable(callback, "callback", callback.link.title, is_pointer=True) def _format_function_macro(self, function_macro): template = self.engine.get_template('callable.html') prototype = self._format_raw_code(function_macro.original_text) parameters = [] for _ in function_macro.parameters: if not _.detailed_description: continue parameters.append(_.detailed_description) return_value_detail = self._format_return_value_symbol( function_macro.return_value) out = template.render({'prototype': prototype, 'symbol': function_macro, 'return_value': return_value_detail, 'parameters': parameters, 'callable_type': "function macro", 'flags': None, 'tags': {}, 'extra': function_macro.extension_contents}) return (out, False) def _format_alias(self, alias): template = self.engine.get_template('alias.html') aliased_type = self._format_linked_symbol(alias.aliased_type) return (template.render({'symbol': alias, 'alias': alias, 'aliased_type': aliased_type}), False) def _format_constant(self, constant): template = self.engine.get_template('constant.html') definition = self._format_raw_code(constant.original_text) out = template.render({'symbol': constant, 'definition': definition, 'constant': constant}) return (out, False) def _format_symbol(self, symbol): format_function = self._symbol_formatters.get(type(symbol)) if format_function: return format_function(symbol) return (None, False) def _format_object_hierarchy_symbol(self, symbol): dot_graph = _create_hierarchy_graph(symbol.hierarchy) tmp_file = tempfile.NamedTemporaryFile(suffix='.svg', delete=False) dot_graph.draw(tmp_file, prog='dot', format='svg', args="-Grankdir=LR") tmp_file.close() with open(tmp_file.name, 'r') as _: contents = _.read() os.unlink(_.name) pagename = 'object_hierarchy.html' template = self.engine.get_template(pagename) res = template.render({'graph': contents, 'assets_path': self._get_assets_path()}) return (res, False) def _get_extra_files(self): res = [] if HtmlFormatter.theme_path: theme_files = os.listdir(HtmlFormatter.theme_path) for file_ in theme_files: if file_ == 'templates': pass src = os.path.join(HtmlFormatter.theme_path, file_) dest = os.path.basename(src) res.append((src, dest)) for script_path in self.all_scripts: dest = os.path.join('js', os.path.basename(script_path)) res.append((script_path, dest)) for stylesheet_path in self.all_stylesheets: dest = os.path.join('css', os.path.basename(stylesheet_path)) res.append((stylesheet_path, dest)) return res @staticmethod def add_arguments(parser): """Banana banana """ group = parser.add_argument_group( 'Html formatter', 'html formatter options') group.add_argument("--html-theme", action="store", dest="html_theme", help="html theme to use", default='default') group.add_argument("--html-add-anchors", action="store_true", dest="html_add_anchors", help="Add anchors to html headers", default='default') group.add_argument("--html-number-headings", action="store_true", dest="html_number_headings", help="Enable html headings numbering") @staticmethod def parse_config(doc_repo, config): """Banana banana """ html_theme = config.get('html_theme', 'default') if html_theme == 'default': default_theme = os.path.join(HERE, '..', 'default_theme-%s' % THEME_VERSION) html_theme = os.path.abspath(default_theme) info("Using default theme") else: html_theme = config.get_path('html_theme') info("Using theme located at %s" % html_theme) HtmlFormatter.theme_path = html_theme HtmlFormatter.add_anchors = bool(config.get("html_add_anchors")) HtmlFormatter.number_headings = bool( config.get("html_number_headings"))
class MainWindow(QMainWindow): workspace_updated = pyqtSignal() def __init__(self): super(MainWindow, self).__init__() #self.app = app self.apps = [] self.apps_dict = {} # Initiate logging self.logView = QTreeWidget() self.logView.setColumnCount(2) self.logView.expandAll() self.logView.itemClicked.connect(self.onLogItemClicked) self.logView.itemDoubleClicked.connect(self.onLogItemDoubleClicked) self.logView.setHeaderLabels(['ID', 'Message']) self.logView.setUniformRowHeights(True) self.logView.hideColumn(0) logHandler = Logger(self, self.logView) logging.getLogger().addHandler(logHandler) #sys.stdout = Logger( self.logView, sys.__stdout__) #sys.stderr = Logger( self.logView, sys.__stderr__, QColor(255,0,0) ) logging.info('Welcome to Pathomx v%s' % (VERSION_STRING)) # Central variable for storing application configuration (load/save from file? self.config = QSettings() if self.config.value('/Pathomx/Is_setup', False) != True: logging.info("Setting up initial configuration...") self.onResetConfig() logging.info('Done') # Do version upgrade availability check # FIXME: Do check here; if not done > 2 weeks if StrictVersion(self.config.value('/Pathomx/Latest_version', '0.0.0')) > StrictVersion(VERSION_STRING): # We've got an upgrade logging.warning('A new version (v%s) is available' % self.config.value('/Pathomx/Update/Latest_version', '0.0.0')) # Create database accessor self.db = db.databaseManager() self.data = None # deprecated self.datasets = [] # List of instances of data.datasets() // No data loaded by default self.experiment = dict() self.layout = None # No map by default #self.linestyles = styles.LineStyleHandler() # The following holds tabs & pathway objects for gpml imported pathways self.gpmlpathways = [] self.tab_handlers = [] self.url_handlers = defaultdict(list) self.app_launchers = {} self.app_launcher_categories = defaultdict(list) self.file_handlers = {} # Create templating engine self.templateEngine = Engine( loader=FileLoader([os.path.join(utils.scriptdir, 'html')]), extensions=[CoreExtension(), CodeExtension()] ) self.templateEngine.global_vars.update({'tr': tr}) self.update_view_callback_enabled = True self.printer = QPrinter() QNetworkProxyFactory.setUseSystemConfiguration(True) # UI setup etc self.menuBars = { 'file': self.menuBar().addMenu(tr('&File')), 'plugins': self.menuBar().addMenu(tr('&Plugins')), 'appearance': self.menuBar().addMenu(tr('&Appearance')), 'resources': self.menuBar().addMenu(tr('&Resources')), 'database': self.menuBar().addMenu(tr('&Database')), 'help': self.menuBar().addMenu(tr('&Help')), } # FILE MENU aboutAction = QAction(QIcon.fromTheme("help-about"), 'About', self) aboutAction.setStatusTip(tr('About Pathomx')) aboutAction.triggered.connect(self.onAbout) self.menuBars['file'].addAction(aboutAction) newAction = QAction(QIcon(os.path.join(utils.scriptdir, 'icons', 'document.png')), tr('&New Blank Workspace'), self) newAction.setShortcut('Ctrl+N') newAction.setStatusTip(tr('Create new blank workspace')) newAction.triggered.connect(self.onClearWorkspace) self.menuBars['file'].addAction(newAction) openAction = QAction(QIcon(os.path.join(utils.scriptdir, 'icons', 'folder-open-document.png')), tr('&Open…'), self) openAction.setShortcut('Ctrl+O') openAction.setStatusTip(tr('Open previous analysis workspace')) openAction.triggered.connect(self.onOpenWorkspace) #self.menuBars['file'].addAction(openAction) openAction = QAction(QIcon(os.path.join(utils.scriptdir, 'icons', 'folder-open-document.png')), tr('&Open Workflow…'), self) openAction.setStatusTip(tr('Open an analysis workflow')) openAction.triggered.connect(self.onOpenWorkflow) self.menuBars['file'].addAction(openAction) self.menuBars['file'].addSeparator() saveAction = QAction(QIcon(os.path.join(utils.scriptdir, 'icons', 'disk.png')), tr('&Save'), self) saveAction.setShortcut('Ctrl+S') saveAction.setStatusTip(tr('Save current workspace for future use')) saveAction.triggered.connect(self.onSaveWorkspace) #self.menuBars['file'].addAction(saveAction) saveAsAction = QAction(QIcon(os.path.join(utils.scriptdir, 'icons', 'disk--pencil.png')), tr('Save &As…'), self) saveAsAction.setShortcut('Ctrl+A') saveAsAction.setStatusTip(tr('Save current workspace for future use')) saveAsAction.triggered.connect(self.onSaveWorkspaceAs) #self.menuBars['file'].addAction(saveAsAction) saveAsAction = QAction(QIcon(os.path.join(utils.scriptdir, 'icons', 'disk--pencil.png')), tr('Save Workflow As…'), self) saveAsAction.setStatusTip(tr('Save current workflow for future use')) saveAsAction.triggered.connect(self.onSaveWorkflowAs) self.menuBars['file'].addAction(saveAsAction) self.menuBars['file'].addSeparator() #printAction = QAction(QIcon(os.path.join(utils.scriptdir, 'icons', 'printer.png')), tr('&Print…'), self) #printAction.setShortcut('Ctrl+P') #printAction.setStatusTip(tr('Print current figure')) #printAction.triggered.connect(self.onPrint) #self.menuBars['file'].addAction(printAction) self.menuBars['file'].addSeparator() # DATABASE MENU explore_dbAction = QAction(QIcon(os.path.join(utils.scriptdir, 'icons', 'database-explore.png')), tr('&Explore database…'), self) explore_dbAction.setStatusTip('Explore database') explore_dbAction.triggered.connect(self.onDBExplore) self.menuBars['database'].addAction(explore_dbAction) load_identitiesAction = QAction(QIcon(os.path.join(utils.scriptdir, 'icons', 'database-import.png')), tr('&Load database unification…'), self) load_identitiesAction.setStatusTip('Load additional unification mappings into database') load_identitiesAction.triggered.connect(self.onLoadIdentities) self.menuBars['database'].addAction(load_identitiesAction) self.menuBars['database'].addSeparator() reload_databaseAction = QAction(QIcon(os.path.join(utils.scriptdir, 'icons', 'exclamation-red.png')), tr('&Reload database'), self) reload_databaseAction.setStatusTip('Reload pathway & metabolite database') reload_databaseAction.triggered.connect(self.onReloadDB) self.menuBars['database'].addAction(reload_databaseAction) # PLUGINS MENU change_pluginsAction = QAction(tr('&Manage plugins…'), self) change_pluginsAction.setStatusTip('Find, activate, deactivate and remove plugins') change_pluginsAction.triggered.connect(self.onChangePlugins) self.menuBars['plugins'].addAction(change_pluginsAction) check_pluginupdatesAction = QAction(tr('&Check for updated plugins'), self) check_pluginupdatesAction.setStatusTip('Check for updates to installed plugins') check_pluginupdatesAction.triggered.connect(self.onCheckPluginUpdates) #self.menuBars['plugins'].addAction(check_pluginupdatesAction) FIXME: Add a plugin-update check linemarkerstyleAction = QAction('Line and marker styles…', self) linemarkerstyleAction.setStatusTip(tr('Set line and marker styles for data classes')) linemarkerstyleAction.triggered.connect(self.onLineMarkerStyles) self.menuBars['appearance'].addAction(linemarkerstyleAction) matlabpathAction = QAction('Edit MATLAB path…', self) matlabpathAction.setStatusTip(tr('Set MATLAB path')) matlabpathAction.triggered.connect(self.onMATLABPathEdit) self.menuBars['resources'].addAction(matlabpathAction) aboutAction = QAction(QIcon.fromTheme("help-about"), 'Introduction', self) aboutAction.setStatusTip(tr('About Pathomx')) aboutAction.triggered.connect(self.onAbout) self.menuBars['help'].addAction(aboutAction) self.menuBars['help'].addSeparator() goto_pathomx_websiteAction = QAction(tr('&Pathomx homepage'), self) goto_pathomx_websiteAction.setStatusTip('Go to the Pathomx website') goto_pathomx_websiteAction.triggered.connect(self.onGoToPathomxWeb) self.menuBars['help'].addAction(goto_pathomx_websiteAction) goto_pathomx_docsAction = QAction(tr('&Pathomx documentation'), self) goto_pathomx_docsAction.setStatusTip('Read latest Pathomx documentation') goto_pathomx_docsAction.triggered.connect(self.onGoToPathomxDocs) self.menuBars['help'].addAction(goto_pathomx_docsAction) goto_pathomx_demosAction = QAction(tr('&Pathomx demos'), self) goto_pathomx_demosAction.setStatusTip('Watch Pathomx demo videos') goto_pathomx_demosAction.triggered.connect(self.onGoToPathomxDemos) self.menuBars['help'].addAction(goto_pathomx_demosAction) self.menuBars['help'].addSeparator() do_registerAction = QAction(tr('&Register Pathomx'), self) do_registerAction.setStatusTip('Register Pathomx for release updates') do_registerAction.triggered.connect(self.onDoRegister) self.menuBars['help'].addAction(do_registerAction) # GLOBAL WEB SETTINGS QNetworkProxyFactory.setUseSystemConfiguration(True) QWebSettings.setMaximumPagesInCache(0) QWebSettings.setObjectCacheCapacities(0, 0, 0) QWebSettings.clearMemoryCaches() resources.matlab.set_exec_path( self.config.value('/Resources/MATLAB_path', 'matlab') ) self.resources = { 'MATLAB': resources.matlab, 'R': resources.r, } self.plugins = {} # Dict of plugin shortnames to data self.plugins_obj = {} # Dict of plugin name references to objs (for load/save) self.pluginManager = PluginManagerSingleton.get() self.pluginManager.m = self self.plugin_places = [] self.core_plugin_path = os.path.join(utils.scriptdir, 'plugins') self.plugin_places.append(self.core_plugin_path) user_application_data_paths = QStandardPaths.standardLocations(QStandardPaths.DataLocation) if user_application_data_paths: self.user_plugin_path = os.path.join(user_application_data_paths[0], 'plugins') utils.mkdir_p(self.user_plugin_path) self.plugin_places.append(self.user_plugin_path) self.application_data_path = os.path.join(user_application_data_paths[1]) logging.info("Searching for plugins...") for place in self.plugin_places: logging.info(place) self.tools = defaultdict(list) self.pluginManager.setPluginPlaces(self.plugin_places) self.pluginManager.setPluginInfoExtension('pathomx-plugin') categories_filter = { "Import": plugins.ImportPlugin, "Processing": plugins.ProcessingPlugin, "Identification": plugins.IdentificationPlugin, "Analysis": plugins.AnalysisPlugin, "Visualisation": plugins.VisualisationPlugin, "Export": plugins.ExportPlugin, "Scripting": plugins.ScriptingPlugin, } self.pluginManager.setCategoriesFilter(categories_filter) self.pluginManager.collectPlugins() plugin_categories = ["Import", "Processing", "Identification", "Analysis", "Visualisation", "Export", "Scripting"] # categories_filter.keys() apps = defaultdict(list) self.appBrowsers = {} self.plugin_names = dict() self.plugin_metadata = dict() # Loop round the plugins and print their names. for category in plugin_categories: for plugin in self.pluginManager.getPluginsOfCategory(category): plugin_image = os.path.join(os.path.dirname(plugin.path), 'icon.png') if not os.path.isfile(plugin_image): plugin_image = None try: resource_list = plugin.details.get('Documentation','Resources').split(',') except: resource_list = [] metadata = { 'id': plugin.plugin_object.__class__.__name__, # __module__, 'image': plugin_image, 'image_forward_slashes': plugin_image.replace('\\', '/'), # Slashes fix for CSS in windows 'name': plugin.name, 'version': plugin.version, 'description': plugin.description, 'author': plugin.author, 'resources': resource_list, 'info': plugin, 'path': os.path.dirname(plugin.path), 'module': os.path.basename(plugin.path), 'shortname': os.path.basename(plugin.path), 'is_core_plugin': plugin.path.startswith(self.core_plugin_path) } self.plugins[metadata['shortname']] = metadata self.plugin_names[id(plugin.plugin_object)] = plugin.name plugin.plugin_object.post_setup(path=os.path.dirname(plugin.path), name=plugin.name, metadata=metadata) apps[category].append(metadata) self.stack = QStackedWidget() self.threadpool = QThreadPool() logging.info("Multithreading with maximum %d threads" % self.threadpool.maxThreadCount()) self.setCentralWidget(self.stack) self.stack.setCurrentIndex(0) self.workspace_count = 0 # Auto-increment self.workspace_parents = {} self.workspace_index = {} # id -> obj self.workspace = QTreeWidget() self.workspace.setColumnCount(4) self.workspace.expandAll() self.workspace.setHeaderLabels(['', 'ID', ' ◎', ' ⚑']) # ,'#']) self.workspace.setUniformRowHeights(True) self.workspace.hideColumn(1) self.editor = WorkspaceEditor(self) self.setCentralWidget(self.editor) app_category_icons = { "Import": QIcon(os.path.join(utils.scriptdir, 'icons', 'disk--arrow.png')), "Processing": QIcon(os.path.join(utils.scriptdir, 'icons', 'ruler-triangle.png')), "Identification": QIcon(os.path.join(utils.scriptdir, 'icons', 'target.png')), "Analysis": QIcon(os.path.join(utils.scriptdir, 'icons', 'calculator.png')), "Visualisation": QIcon(os.path.join(utils.scriptdir, 'icons', 'star.png')), "Export": QIcon(os.path.join(utils.scriptdir, 'icons', 'disk--pencil.png')), "Scripting": QIcon(os.path.join(utils.scriptdir, 'icons', 'script-text.png')), } template = self.templateEngine.get_template('apps.html') for category in plugin_categories: self.addWorkspaceItem(None, None, category, app_category_icons[category]) self.workspace.setSelectionMode(QAbstractItemView.SingleSelection) self.workspace.currentItemChanged.connect(self.onWorkspaceStackChange) self.toolbox = QToolBox(self) for category in plugin_categories: panel = ToolPanel(self, tools=self.tools[category]) self.toolbox.addItem(panel, app_category_icons[category], category) self.toolDock = QDockWidget(tr('Toolkit')) self.toolDock.setWidget(self.toolbox) self.workspaceDock = QDockWidget(tr('Workspace')) self.workspaceDock.setWidget(self.workspace) self.workspace.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.workspace.setColumnWidth(0, 298 - 25 * 2) self.workspace.setColumnWidth(2, 24) self.workspace.setColumnWidth(3, 24) self.workspaceDock.setMinimumWidth(300) self.workspaceDock.setMaximumWidth(300) self.dataView = QTreeView(self) self.dataModel = data.DataTreeModel(self.datasets) self.dataView.setModel(self.dataModel) self.dataView.hideColumn(0) self.dataDock = QDockWidget(tr('Data')) self.dataDock.setWidget(self.dataView) self.dataDock.setMinimumWidth(300) self.dataDock.setMaximumWidth(300) self.logDock = QDockWidget(tr('Log')) self.logDock.setWidget(self.logView) self.addDockWidget(Qt.LeftDockWidgetArea, self.logDock) self.addDockWidget(Qt.LeftDockWidgetArea, self.dataDock) self.addDockWidget(Qt.LeftDockWidgetArea, self.workspaceDock) self.addDockWidget(Qt.LeftDockWidgetArea, self.toolDock) self.tabifyDockWidget(self.toolDock, self.workspaceDock) self.tabifyDockWidget(self.workspaceDock, self.dataDock) self.tabifyDockWidget(self.dataDock, self.logDock) self.toolDock.raise_() self.dbtool = ui.DbApp(self) self.dbBrowser = self.dbtool.dbBrowser self.setWindowTitle(tr('Pathomx')) self.progressBar = QProgressBar(self.statusBar()) self.progressBar.setMaximumSize(QSize(170, 19)) self.progressBar.setRange(0, 100) self.statusBar().addPermanentWidget(self.progressBar) self.progressTracker = {} # Dict storing values for each view/object logging.info('Ready.') self.statusBar().showMessage(tr('Ready')) self.showMaximized() # Do version upgrade check if StrictVersion(self.config.value('/Pathomx/Current_version', '0.0.0')) < StrictVersion(VERSION_STRING): # We've got an upgrade self.onAbout() self.config.setValue('/Pathomx/Current_version', VERSION_STRING) if self.config.value('/Pathomx/Offered_registration', False) != True: self.onDoRegister() self.config.setValue('/Pathomx/Offered_registration', True) def onLogItemClicked(self, item): # When an item in the log viewer is clicked, center on the associated Tool # this will fail if there is none (i.e. non-tool log item) so wrapped in an try, except. try: item.tool.editorItem.centerSelf() except: pass def onLogItemDoubleClicked(self, item): # When an item in the log viewer is clicked, center on the associated Tool # this will fail if there is none (i.e. non-tool log item) so wrapped in an try, except. try: item.tool.show() except: pass def onMATLABPathEdit(self): dialog = ui.MATLABPathDialog(self, path=self.config.value('/Resources/MATLAB_path', 'matlab')) if dialog.exec_(): path = dialog.path.text() resources.matlab.set_exec_path( path ) self.config.setValue('/Resources/MATLAB_path', path) def onChangePlugins(self): dialog = plugins.dialogPluginManagement(self) if dialog.exec_(): pass def onCheckPluginUpdates(self): pass def onDBExplore(self): self.dbtool.show() # Init application configuration def onResetConfig(self): # Defaults not set, apply now and save complete config file self.config.setValue('Pathomx/Is_setup', True) self.config.setValue('Pathomx/Current_version', '0.0.0') self.config.setValue('Pathomx/Update/Latest_version', '0.0.0') self.config.setValue('Pathomx/Update/Last_checked', None) self.config.setValue('Pathomx/Offered_registration', False) self.config.setValue('Plugins/Active', []) self.config.setValue('Plugins/Disabled', []) self.config.setValue('Plugins/Available', []) self.config.setValue('Plugins/Paths', []) self.config.setValue('/Resources/MATLAB_path', 'matlab') # UI Events def onGoToPathomxWeb(self): QDesktopServices.openUrl(QUrl('http://pathomx.org')) def onGoToPathomxDemos(self): QDesktopServices.openUrl(QUrl('http://pathomx.org/demos')) def onGoToPathomxDocs(self): QDesktopServices.openUrl(QUrl('http://docs.pathomx.org/')) def onDoRegister(self): # Pop-up a registration window; take an email address and submit to # register for update-announce. dlg = ui.DialogRegister(self) if dlg.exec_(): # Perform registration data = { 'name': dlg.name.text(), 'email': dlg.email.text(), 'country': dlg.country.currentText(), 'research': dlg.research.text(), 'institution': dlg.institution.text(), 'type': dlg.type.currentText(), 'register': dlg.register.checked(), } # Send data to server; # http://register.pathomx.org POST def onLineMarkerStyles(self): dlg = ui.MatchLineStyleManagerDialog(self) if dlg.exec_(): self.onRefreshAllViews() def onRefreshAllViews(self): for t in self.apps: t.views.style_updated.emit() def onBrowserNav(self, url): # Interpret internal URLs for message passing to display Compound, Reaction, Pathway data in the sidebar interface # then block the continued loading if url.isRelative() and url.hasFragment(): # Local #url; pass to default handler pass if url.scheme() == 'pathomx': # Take string from pathomx:// onwards, split on / app = url.host() if app == 'app-manager': app, action = url.path().strip('/').split('/') if action == 'add': a = self.app_launchers[app]() # Update workspace viewer self.workspace_updated.emit() # Notify change to workspace layout elif app == 'db': kind, id, action = url.path().strip('/').split('/') # View an object if action == 'view': if kind == 'pathway' and id in self.db.pathways: pathway = self.db.pathways[id] self.generatedbBrowserView(template='db/pathway.html', data={ 'title': pathway.name, 'object': pathway, }) elif kind == 'reaction' and id in self.db.reactions: reaction = self.db.reactions[id] self.generatedbBrowserView(template='db/reaction.html', data={ 'title': reaction.name, 'object': reaction, }) elif kind == 'compound' and id in self.db.compounds: compound = self.db.compounds[id] self.generatedbBrowserView(template='db/compound.html', data={ 'title': compound.name, 'object': compound, }) elif kind == 'protein' and id in self.db.proteins: protein = self.db.proteins[id] self.generatedbBrowserView(template='db/protein.html', data={ 'title': protein.name, 'object': protein, }) elif kind == 'gene' and id in self.db.genes: gene = self.db.genes[id] self.generatedbBrowserView(template='db/gene.html', data={ 'title': gene.name, 'object': gene, }) # Focus the database window self.dbtool.raise_() #metaviz/compound/%s/view elif app in self.url_handlers: for handler in self.url_handlers[app]: handler(url.path().strip('/')) # Store URL so we can reload the sidebar later self.dbBrowser_CurrentURL = url else: # It's an URL open in default browser QDesktopServices.openUrl(url) def onLoadIdentities(self): """ Open a data file""" filename, _ = QFileDialog.getOpenFileName(self, 'Load compound identities file', '') if filename: self.db.load_synonyms(filename) # Re-translate the datafile if there is one and refresh if self.data: self.data.translate(self.db) self.generateGraphView(regenerate_analysis=True) def onSaveAs(self): """ Save a copy of the graph as one of the supported formats""" # Note this will regenerate the graph with the current settings, with output type specified appropriately filename, _ = QFileDialog.getSaveFileName(self, 'Save current metabolic pathway map', '') if filename: fn, ext = os.path.splitext(filename) format = ext.replace('.', '') # Check format is supported if format in ['bmp', 'canon', 'dot', 'xdot', 'cmap', 'eps', 'fig', 'gd', 'gd2', 'gif', 'gtk', 'ico', 'imap', 'cmapx', 'imap_np', 'cmapx_np', 'ismap', 'jpg', 'jpeg', 'jpe', 'pdf', 'plain', 'plain-ext', 'png', 'ps', 'ps2', 'svg', 'svgz', 'tif', 'tiff', 'vml', 'vmlz', 'vrml', 'wbmp', 'webp', 'xlib']: self.generateGraph(filename, format) else: # Unsupported format error pass def onAbout(self): dlg = ui.DialogAbout(self) dlg.exec_() def onExit(self): self.Close(True) # Close the frame. def onReloadDB(self): self.db = db.databaseManager() def onRefresh(self): self.generateGraphView() def generatedbBrowserView(self, template='base.html', data={'title': '', 'object': {}, 'data': {}}): metadata = { 'htmlbase': os.path.join(utils.scriptdir, 'html'), # Current state data 'current_pathways': [], # self.config.value('/Pathways/Show').split(','), 'data': self.data, # Color schemes # 'rdbu9':['b2182b', 'd6604d', 'f4a582', '33a02c', 'fddbc7', 'f7f7f7', 'd1e5f0', '92c5de', '4393c3', '2166ac'] } template = self.templateEngine.get_template(template) self.dbBrowser.setHtml(template.render(dict(list(data.items()) + list(metadata.items()))), QUrl("~")) def onWorkspaceStackChange(self, item, previous): widget = self.workspace_index[item.text(1)] if widget: widget.show() widget.raise_() def addWorkspaceItem(self, widget, section, title, icon=None): tw = QTreeWidgetItem() wid = str(id(tw)) tw.setText(0, tr(title)) tw.setText(1, wid) if widget: widget._workspace_index = wid self.workspace_index[wid] = widget if icon: tw.setIcon(0, icon) if section: self.workspace_parents[section].addChild(tw) widget._workspace_section = self.workspace_parents[section] widget._workspace_tree_widget = tw else: self.workspace.addTopLevelItem(tw) self.workspace_parents[title] = tw tw.setExpanded(True) return tw def removeWorkspaceItem(self, widget): del self.workspace_index[widget._workspace_index] widget._workspace_section.removeChild(widget._workspace_tree_widget) def setWorkspaceStatus(self, workspace_item, status): status_icons = { 'active': QIcon(os.path.join(utils.scriptdir, 'icons', 'flag-green.png')), 'render': QIcon(os.path.join(utils.scriptdir, 'icons', 'flag-purple.png')), 'waiting': QIcon(os.path.join(utils.scriptdir, 'icons', 'flag-yellow.png')), 'error': QIcon(os.path.join(utils.scriptdir, 'icons', 'flag-red.png')), 'paused': QIcon(os.path.join(utils.scriptdir, 'icons', 'flag-white.png')), 'done': QIcon(os.path.join(utils.scriptdir, 'icons', 'flag-checker.png')), 'clear': QIcon(None) } if status not in list(status_icons.keys()): status = 'clear' workspace_item.setIcon(3, status_icons[status]) self.workspace.update(self.workspace.indexFromItem(workspace_item)) # Keep things ticking QCoreApplication.processEvents() if status == 'active': # Starting self.updateProgress(workspace_item, 0) elif status == 'clear' or status == 'error': self.updateProgress(workspace_item, None) elif status == 'done': # Flash done then clear in a bit self.updateProgress(workspace_item, 1) statusclearCallback = functools.partial(self.setWorkspaceStatus, workspace_item, 'clear') workspace_item.status_timeout = QTimer.singleShot(1000, statusclearCallback) def clearWorkspaceStatus(self, workspace_item): self.setWorkspaceStatus(workspace_item, 'clear') def updateProgress(self, workspace_item, progress): if progress == None: if id(workspace_item) in self.progressTracker: del(self.progressTracker[id(workspace_item)]) if len(self.progressTracker) == 0: self.progressBar.reset() return else: self.progressTracker[id(workspace_item)] = progress m = 100.0 / len(self.progressTracker) pt = sum([n * m for n in list(self.progressTracker.values())]) if self.progressBar.value() < pt: # Don't go backwards it's annoying FIXME: once hierarchical prediction; stack all things that 'will' start self.progressBar.setValue(pt) # Keep things ticking #QCoreApplication.processEvents() def register_url_handler(self, identifier, url_handler): self.url_handlers[identifier].append(url_handler) ### OPEN/SAVE WORKSPACE def onOpenWorkspace(self): self.openWorkspace('/Users/mxf793/Desktop/test.mpw') def openWorkspace(self, fn): pass def onSaveWorkspace(self): self.saveWorkspace('/Users/mxf793/Desktop/test.mpw') def onSaveWorkspaceAs(self): self.saveWorkspace('/Users/mxf793/Desktop/test.mpw') def saveWorkspace(self, fn): pass ### RESET WORKSPACE def onClearWorkspace(self): reply = QMessageBox.question(self, "Clear Workspace", "Are you sure you want to clear the workspace? Everything will be deleted.", QMessageBox.Yes | QMessageBox.No) if reply == QMessageBox.Yes: self.clearWorkspace() def clearWorkspace(self): for v in self.apps[:]: # Copy as v.delete modifies the self.apps list v.delete() # Remove all workspace datasets del self.datasets[:] self.workspace_updated.emit() ### OPEN/SAVE WORKFLOWS def onSaveWorkflowAs(self): filename, _ = QFileDialog.getSaveFileName(self, 'Save current workflow', '', "Pathomx Workflow Format (*.mpf)") if filename: self.saveWorkflow(filename) def saveWorkflow(self, fn): root = et.Element("Workflow") root.set('xmlns:mpwfml', "http://pathomx.org/schema/Workflow/2013a") s = et.SubElement(root, "Styles") s = styles.linestyles.getXMLMatchDefinitionsLineStyles(s) # Build a JSONable object representing the entire current workspace and write it to file for v in self.apps: app = et.SubElement(root, "App") app.set("id", v.id) name = et.SubElement(app, "Name") name.text = v.name plugin = et.SubElement(app, "Plugin") plugin.set("version", '1.0') plugin.text = v.plugin.__class__.__name__ plugin_class = et.SubElement(app, "Launcher") plugin_class.text = v.__class__.__name__ position = et.SubElement(app, "EditorXY") position.set("x", str(v.editorItem.x())) position.set("y", str(v.editorItem.y())) config = et.SubElement(app, "Config") for ck, cv in list(v.config.config.items()): co = et.SubElement(config, "ConfigSetting") co.set("id", ck) t = type(cv).__name__ co.set("type", type(cv).__name__) co = utils.CONVERT_TYPE_TO_XML[t](co, cv) datasources = et.SubElement(app, "DataInputs") # Build data inputs table (outputs are pre-specified by the object; this == links) for sk, si in list(v.data.i.items()): if si: # Something on this interface cs = et.SubElement(datasources, "Input") cs.set("id", sk) cs.set("manager", si.manager.id) cs.set("interface", si.manager_interface) tree = et.ElementTree(root) tree.write(fn) # , pretty_print=True) def onOpenWorkflow(self): """ Open a data file""" filename, _ = QFileDialog.getOpenFileName(self, 'Open new workflow', '', "Pathomx Workflow Format (*.mpf)") if filename: self.openWorkflow(filename) def openWorkflow(self, fn): logging.info("Loading workflow... %s" % fn) # Wipe existing workspace self.clearWorkspace() # Load from file tree = et.parse(fn) workflow = tree.getroot() s = workflow.find('Styles') styles.linestyles.setXMLMatchDefinitionsLineStyles(s) appref = {} logging.info("...Loading apps.") for xapp in workflow.findall('App'): # FIXME: This does not work with multiple launchers/plugin - define as plugin.class? # Check plugins loaded etc. logging.info(('- %s' % xapp.find('Name').text)) app = self.app_launchers["%s.%s" % (xapp.find("Plugin").text, xapp.find("Launcher").text)](auto_consume_data=False, name=xapp.find('Name').text) editorxy = xapp.find('EditorXY') app.editorItem.setPos(QPointF(float(editorxy.get('x')), float(editorxy.get('y')))) #app = self.app_launchers[ item.find("launcher").text ]() #app.set_name( ) appref[xapp.get('id')] = app config = {} for xconfig in xapp.findall('Config/ConfigSetting'): #id="experiment_control" type="unicode" value="monocyte at intermediate differentiation stage (GDS2430_2)"/> if xconfig.get('type') in utils.CONVERT_TYPE_FROM_XML: v = utils.CONVERT_TYPE_FROM_XML[xconfig.get('type')](xconfig) config[xconfig.get('id')] = v app.config.set_many(config, trigger_update=False) logging.info("...Linking objects.") # Now build the links between objects; we need to force these as data is not present for xapp in workflow.findall('App'): app = appref[xapp.get('id')] for idef in xapp.findall('DataInputs/Input'): app.data._consume_action(idef.get('id'), appref[idef.get('manager')].data.o[idef.get('interface')]) logging.info("Load complete.") # Focus the home tab & refresh the view self.workspace_updated.emit()
class MultiTemplateTestCase(unittest.TestCase): """ Test the ``CoreExtension`` compiled templates. """ def setUp(self): from wheezy.template.engine import Engine from wheezy.template.ext.core import CoreExtension from wheezy.template.loader import DictLoader self.templates = {} self.engine = Engine( loader=DictLoader(templates=self.templates), extensions=[CoreExtension()]) def render(self, name, ctx): template = self.engine.get_template(name) return template.render(ctx) def test_extends(self): self.templates.update({ 'master.html': """\ @def say_hi(name): Hello, @name! @end @say_hi('John')""", 'tmpl.html': """\ @extends('master.html') @def say_hi(name): Hi, @name! @end """ }) assert ' Hi, John!\n' == self.render('tmpl.html', {}) assert ' Hello, John!\n' == self.render('master.html', {}) def test_super(self): self.templates.update({ 'master.html': """\ @def say_hi(name): Hello, @name!\ @end @say_hi('John')""", 'tmpl.html': """\ @extends('master.html') @def say_hi(name): @super_defs['say_hi'](name)!!\ @end """ }) assert ' Hello, John!!!' == self.render('tmpl.html', {}) def test_include(self): self.templates.update({ 'footer.html': """\ @require(name) Thanks, @name""", 'tmpl.html': """\ Welcome to my site. @include('footer.html') """ }) ctx = {'name': 'John'} assert """\ Welcome to my site. Thanks, John""" == self.render('tmpl.html', ctx) assert 'Thanks, John' == self.render('footer.html', ctx) def test_import(self): self.templates.update({ 'helpers.html': """\ @def say_hi(name): Hi, @name\ @end""", 'tmpl.html': """\ @import 'helpers.html' as helpers @helpers.say_hi('John')""" }) assert """\ Hi, John""" == self.render('tmpl.html', {}) def test_import_dynamic(self): self.templates.update({ 'helpers.html': """\ @def say_hi(name): Hi, @name\ @end""", 'tmpl.html': """\ @require(helpers_impl) @import helpers_impl as helpers @helpers.say_hi('John')""" }) assert """\ Hi, John""" == self.render('tmpl.html', {'helpers_impl': 'helpers.html'}) def test_from_import(self): self.templates.update({ 'helpers.html': """\ @def say_hi(name): Hi, @name\ @end""", 'tmpl.html': """\ @from 'helpers.html' import say_hi @say_hi('John')""" }) assert """\ Hi, John""" == self.render('tmpl.html', {}) def test_from_import_dynamic(self): self.templates.update({ 'helpers.html': """\ @def say_hi(name): Hi, @name\ @end""", 'tmpl.html': """\ @require(helpers_impl) @from helpers_impl import say_hi @say_hi('John')""" }) assert """\ Hi, John""" == self.render('tmpl.html', {'helpers_impl': 'helpers.html'}) def test_from_import_as(self): self.templates.update({ 'share/helpers.html': """\ @def say_hi(name): Hi, @name\ @end""", 'tmpl.html': """\ @from 'share/helpers.html' import say_hi as hi @hi('John')""" }) assert """\ Hi, John""" == self.render('tmpl.html', {})
class TemplateTestCase(unittest.TestCase): """ Test the ``CoreExtension`` compiled templates. """ def setUp(self): from wheezy.template.engine import Engine from wheezy.template.ext.core import CoreExtension from wheezy.template.loader import DictLoader self.templates = {} self.engine = Engine( loader=DictLoader(templates=self.templates), extensions=[CoreExtension()]) def render(self, ctx, source): self.templates['test.html'] = source template = self.engine.get_template('test.html') return template.render(ctx) def test_markup(self): ctx = {} assert 'Hello' == self.render(ctx, 'Hello') def test_comment(self): assert 'Hello World' == self.render({}, """\ Hello\\ @# comment World""") def test_var(self): ctx = { 'username': '******' } assert 'Welcome, John!' == self.render(ctx, """\ @require(username) Welcome, @username!""") def test_if(self): template = """\ @require(n) @if n > 0: Positive\\ @elif n == 0: Zero\\ @else: Negative\\ @end """ assert ' Positive' == self.render({'n': 1}, template) assert ' Zero' == self.render({'n': 0}, template) assert ' Negative' == self.render({'n': -1}, template) def test_for(self): ctx = { 'colors': ['red', 'yellow'] } assert ' red\n yellow\n' == self.render(ctx, """\ @require(colors) @for color in colors: @color @end """) def test_def(self): assert 'Welcome, John!' == self.render({}, """\ @def welcome(name): Welcome, @name!\\ @end @welcome('John')""") def test_def_empty(self): assert '.' == self.render({}, """\ @def title(): @end @title().""") def test_def_syntax_error_compound(self): self.assertRaises(SyntaxError, lambda: self.render({}, """\ @def welcome(name): @if name: Welcome, @name!\\ @end @end @welcome('John')""")) def test_def_no_syntax_error(self): assert 'Welcome, John!' == self.render({}, """\ @def welcome(name): @#ignore @if name: Welcome, @name!\\ @end @end @welcome('John')""")
def __init__(self): super(MainWindow, self).__init__() #self.app = app self.apps = [] self.apps_dict = {} # Initiate logging self.logView = QTreeWidget() self.logView.setColumnCount(2) self.logView.expandAll() self.logView.itemClicked.connect(self.onLogItemClicked) self.logView.itemDoubleClicked.connect(self.onLogItemDoubleClicked) self.logView.setHeaderLabels(['ID', 'Message']) self.logView.setUniformRowHeights(True) self.logView.hideColumn(0) logHandler = Logger(self, self.logView) logging.getLogger().addHandler(logHandler) #sys.stdout = Logger( self.logView, sys.__stdout__) #sys.stderr = Logger( self.logView, sys.__stderr__, QColor(255,0,0) ) logging.info('Welcome to Pathomx v%s' % (VERSION_STRING)) # Central variable for storing application configuration (load/save from file? self.config = QSettings() if self.config.value('/Pathomx/Is_setup', False) != True: logging.info("Setting up initial configuration...") self.onResetConfig() logging.info('Done') # Do version upgrade availability check # FIXME: Do check here; if not done > 2 weeks if StrictVersion(self.config.value('/Pathomx/Latest_version', '0.0.0')) > StrictVersion(VERSION_STRING): # We've got an upgrade logging.warning('A new version (v%s) is available' % self.config.value('/Pathomx/Update/Latest_version', '0.0.0')) # Create database accessor self.db = db.databaseManager() self.data = None # deprecated self.datasets = [] # List of instances of data.datasets() // No data loaded by default self.experiment = dict() self.layout = None # No map by default #self.linestyles = styles.LineStyleHandler() # The following holds tabs & pathway objects for gpml imported pathways self.gpmlpathways = [] self.tab_handlers = [] self.url_handlers = defaultdict(list) self.app_launchers = {} self.app_launcher_categories = defaultdict(list) self.file_handlers = {} # Create templating engine self.templateEngine = Engine( loader=FileLoader([os.path.join(utils.scriptdir, 'html')]), extensions=[CoreExtension(), CodeExtension()] ) self.templateEngine.global_vars.update({'tr': tr}) self.update_view_callback_enabled = True self.printer = QPrinter() QNetworkProxyFactory.setUseSystemConfiguration(True) # UI setup etc self.menuBars = { 'file': self.menuBar().addMenu(tr('&File')), 'plugins': self.menuBar().addMenu(tr('&Plugins')), 'appearance': self.menuBar().addMenu(tr('&Appearance')), 'resources': self.menuBar().addMenu(tr('&Resources')), 'database': self.menuBar().addMenu(tr('&Database')), 'help': self.menuBar().addMenu(tr('&Help')), } # FILE MENU aboutAction = QAction(QIcon.fromTheme("help-about"), 'About', self) aboutAction.setStatusTip(tr('About Pathomx')) aboutAction.triggered.connect(self.onAbout) self.menuBars['file'].addAction(aboutAction) newAction = QAction(QIcon(os.path.join(utils.scriptdir, 'icons', 'document.png')), tr('&New Blank Workspace'), self) newAction.setShortcut('Ctrl+N') newAction.setStatusTip(tr('Create new blank workspace')) newAction.triggered.connect(self.onClearWorkspace) self.menuBars['file'].addAction(newAction) openAction = QAction(QIcon(os.path.join(utils.scriptdir, 'icons', 'folder-open-document.png')), tr('&Open…'), self) openAction.setShortcut('Ctrl+O') openAction.setStatusTip(tr('Open previous analysis workspace')) openAction.triggered.connect(self.onOpenWorkspace) #self.menuBars['file'].addAction(openAction) openAction = QAction(QIcon(os.path.join(utils.scriptdir, 'icons', 'folder-open-document.png')), tr('&Open Workflow…'), self) openAction.setStatusTip(tr('Open an analysis workflow')) openAction.triggered.connect(self.onOpenWorkflow) self.menuBars['file'].addAction(openAction) self.menuBars['file'].addSeparator() saveAction = QAction(QIcon(os.path.join(utils.scriptdir, 'icons', 'disk.png')), tr('&Save'), self) saveAction.setShortcut('Ctrl+S') saveAction.setStatusTip(tr('Save current workspace for future use')) saveAction.triggered.connect(self.onSaveWorkspace) #self.menuBars['file'].addAction(saveAction) saveAsAction = QAction(QIcon(os.path.join(utils.scriptdir, 'icons', 'disk--pencil.png')), tr('Save &As…'), self) saveAsAction.setShortcut('Ctrl+A') saveAsAction.setStatusTip(tr('Save current workspace for future use')) saveAsAction.triggered.connect(self.onSaveWorkspaceAs) #self.menuBars['file'].addAction(saveAsAction) saveAsAction = QAction(QIcon(os.path.join(utils.scriptdir, 'icons', 'disk--pencil.png')), tr('Save Workflow As…'), self) saveAsAction.setStatusTip(tr('Save current workflow for future use')) saveAsAction.triggered.connect(self.onSaveWorkflowAs) self.menuBars['file'].addAction(saveAsAction) self.menuBars['file'].addSeparator() #printAction = QAction(QIcon(os.path.join(utils.scriptdir, 'icons', 'printer.png')), tr('&Print…'), self) #printAction.setShortcut('Ctrl+P') #printAction.setStatusTip(tr('Print current figure')) #printAction.triggered.connect(self.onPrint) #self.menuBars['file'].addAction(printAction) self.menuBars['file'].addSeparator() # DATABASE MENU explore_dbAction = QAction(QIcon(os.path.join(utils.scriptdir, 'icons', 'database-explore.png')), tr('&Explore database…'), self) explore_dbAction.setStatusTip('Explore database') explore_dbAction.triggered.connect(self.onDBExplore) self.menuBars['database'].addAction(explore_dbAction) load_identitiesAction = QAction(QIcon(os.path.join(utils.scriptdir, 'icons', 'database-import.png')), tr('&Load database unification…'), self) load_identitiesAction.setStatusTip('Load additional unification mappings into database') load_identitiesAction.triggered.connect(self.onLoadIdentities) self.menuBars['database'].addAction(load_identitiesAction) self.menuBars['database'].addSeparator() reload_databaseAction = QAction(QIcon(os.path.join(utils.scriptdir, 'icons', 'exclamation-red.png')), tr('&Reload database'), self) reload_databaseAction.setStatusTip('Reload pathway & metabolite database') reload_databaseAction.triggered.connect(self.onReloadDB) self.menuBars['database'].addAction(reload_databaseAction) # PLUGINS MENU change_pluginsAction = QAction(tr('&Manage plugins…'), self) change_pluginsAction.setStatusTip('Find, activate, deactivate and remove plugins') change_pluginsAction.triggered.connect(self.onChangePlugins) self.menuBars['plugins'].addAction(change_pluginsAction) check_pluginupdatesAction = QAction(tr('&Check for updated plugins'), self) check_pluginupdatesAction.setStatusTip('Check for updates to installed plugins') check_pluginupdatesAction.triggered.connect(self.onCheckPluginUpdates) #self.menuBars['plugins'].addAction(check_pluginupdatesAction) FIXME: Add a plugin-update check linemarkerstyleAction = QAction('Line and marker styles…', self) linemarkerstyleAction.setStatusTip(tr('Set line and marker styles for data classes')) linemarkerstyleAction.triggered.connect(self.onLineMarkerStyles) self.menuBars['appearance'].addAction(linemarkerstyleAction) matlabpathAction = QAction('Edit MATLAB path…', self) matlabpathAction.setStatusTip(tr('Set MATLAB path')) matlabpathAction.triggered.connect(self.onMATLABPathEdit) self.menuBars['resources'].addAction(matlabpathAction) aboutAction = QAction(QIcon.fromTheme("help-about"), 'Introduction', self) aboutAction.setStatusTip(tr('About Pathomx')) aboutAction.triggered.connect(self.onAbout) self.menuBars['help'].addAction(aboutAction) self.menuBars['help'].addSeparator() goto_pathomx_websiteAction = QAction(tr('&Pathomx homepage'), self) goto_pathomx_websiteAction.setStatusTip('Go to the Pathomx website') goto_pathomx_websiteAction.triggered.connect(self.onGoToPathomxWeb) self.menuBars['help'].addAction(goto_pathomx_websiteAction) goto_pathomx_docsAction = QAction(tr('&Pathomx documentation'), self) goto_pathomx_docsAction.setStatusTip('Read latest Pathomx documentation') goto_pathomx_docsAction.triggered.connect(self.onGoToPathomxDocs) self.menuBars['help'].addAction(goto_pathomx_docsAction) goto_pathomx_demosAction = QAction(tr('&Pathomx demos'), self) goto_pathomx_demosAction.setStatusTip('Watch Pathomx demo videos') goto_pathomx_demosAction.triggered.connect(self.onGoToPathomxDemos) self.menuBars['help'].addAction(goto_pathomx_demosAction) self.menuBars['help'].addSeparator() do_registerAction = QAction(tr('&Register Pathomx'), self) do_registerAction.setStatusTip('Register Pathomx for release updates') do_registerAction.triggered.connect(self.onDoRegister) self.menuBars['help'].addAction(do_registerAction) # GLOBAL WEB SETTINGS QNetworkProxyFactory.setUseSystemConfiguration(True) QWebSettings.setMaximumPagesInCache(0) QWebSettings.setObjectCacheCapacities(0, 0, 0) QWebSettings.clearMemoryCaches() resources.matlab.set_exec_path( self.config.value('/Resources/MATLAB_path', 'matlab') ) self.resources = { 'MATLAB': resources.matlab, 'R': resources.r, } self.plugins = {} # Dict of plugin shortnames to data self.plugins_obj = {} # Dict of plugin name references to objs (for load/save) self.pluginManager = PluginManagerSingleton.get() self.pluginManager.m = self self.plugin_places = [] self.core_plugin_path = os.path.join(utils.scriptdir, 'plugins') self.plugin_places.append(self.core_plugin_path) user_application_data_paths = QStandardPaths.standardLocations(QStandardPaths.DataLocation) if user_application_data_paths: self.user_plugin_path = os.path.join(user_application_data_paths[0], 'plugins') utils.mkdir_p(self.user_plugin_path) self.plugin_places.append(self.user_plugin_path) self.application_data_path = os.path.join(user_application_data_paths[1]) logging.info("Searching for plugins...") for place in self.plugin_places: logging.info(place) self.tools = defaultdict(list) self.pluginManager.setPluginPlaces(self.plugin_places) self.pluginManager.setPluginInfoExtension('pathomx-plugin') categories_filter = { "Import": plugins.ImportPlugin, "Processing": plugins.ProcessingPlugin, "Identification": plugins.IdentificationPlugin, "Analysis": plugins.AnalysisPlugin, "Visualisation": plugins.VisualisationPlugin, "Export": plugins.ExportPlugin, "Scripting": plugins.ScriptingPlugin, } self.pluginManager.setCategoriesFilter(categories_filter) self.pluginManager.collectPlugins() plugin_categories = ["Import", "Processing", "Identification", "Analysis", "Visualisation", "Export", "Scripting"] # categories_filter.keys() apps = defaultdict(list) self.appBrowsers = {} self.plugin_names = dict() self.plugin_metadata = dict() # Loop round the plugins and print their names. for category in plugin_categories: for plugin in self.pluginManager.getPluginsOfCategory(category): plugin_image = os.path.join(os.path.dirname(plugin.path), 'icon.png') if not os.path.isfile(plugin_image): plugin_image = None try: resource_list = plugin.details.get('Documentation','Resources').split(',') except: resource_list = [] metadata = { 'id': plugin.plugin_object.__class__.__name__, # __module__, 'image': plugin_image, 'image_forward_slashes': plugin_image.replace('\\', '/'), # Slashes fix for CSS in windows 'name': plugin.name, 'version': plugin.version, 'description': plugin.description, 'author': plugin.author, 'resources': resource_list, 'info': plugin, 'path': os.path.dirname(plugin.path), 'module': os.path.basename(plugin.path), 'shortname': os.path.basename(plugin.path), 'is_core_plugin': plugin.path.startswith(self.core_plugin_path) } self.plugins[metadata['shortname']] = metadata self.plugin_names[id(plugin.plugin_object)] = plugin.name plugin.plugin_object.post_setup(path=os.path.dirname(plugin.path), name=plugin.name, metadata=metadata) apps[category].append(metadata) self.stack = QStackedWidget() self.threadpool = QThreadPool() logging.info("Multithreading with maximum %d threads" % self.threadpool.maxThreadCount()) self.setCentralWidget(self.stack) self.stack.setCurrentIndex(0) self.workspace_count = 0 # Auto-increment self.workspace_parents = {} self.workspace_index = {} # id -> obj self.workspace = QTreeWidget() self.workspace.setColumnCount(4) self.workspace.expandAll() self.workspace.setHeaderLabels(['', 'ID', ' ◎', ' ⚑']) # ,'#']) self.workspace.setUniformRowHeights(True) self.workspace.hideColumn(1) self.editor = WorkspaceEditor(self) self.setCentralWidget(self.editor) app_category_icons = { "Import": QIcon(os.path.join(utils.scriptdir, 'icons', 'disk--arrow.png')), "Processing": QIcon(os.path.join(utils.scriptdir, 'icons', 'ruler-triangle.png')), "Identification": QIcon(os.path.join(utils.scriptdir, 'icons', 'target.png')), "Analysis": QIcon(os.path.join(utils.scriptdir, 'icons', 'calculator.png')), "Visualisation": QIcon(os.path.join(utils.scriptdir, 'icons', 'star.png')), "Export": QIcon(os.path.join(utils.scriptdir, 'icons', 'disk--pencil.png')), "Scripting": QIcon(os.path.join(utils.scriptdir, 'icons', 'script-text.png')), } template = self.templateEngine.get_template('apps.html') for category in plugin_categories: self.addWorkspaceItem(None, None, category, app_category_icons[category]) self.workspace.setSelectionMode(QAbstractItemView.SingleSelection) self.workspace.currentItemChanged.connect(self.onWorkspaceStackChange) self.toolbox = QToolBox(self) for category in plugin_categories: panel = ToolPanel(self, tools=self.tools[category]) self.toolbox.addItem(panel, app_category_icons[category], category) self.toolDock = QDockWidget(tr('Toolkit')) self.toolDock.setWidget(self.toolbox) self.workspaceDock = QDockWidget(tr('Workspace')) self.workspaceDock.setWidget(self.workspace) self.workspace.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.workspace.setColumnWidth(0, 298 - 25 * 2) self.workspace.setColumnWidth(2, 24) self.workspace.setColumnWidth(3, 24) self.workspaceDock.setMinimumWidth(300) self.workspaceDock.setMaximumWidth(300) self.dataView = QTreeView(self) self.dataModel = data.DataTreeModel(self.datasets) self.dataView.setModel(self.dataModel) self.dataView.hideColumn(0) self.dataDock = QDockWidget(tr('Data')) self.dataDock.setWidget(self.dataView) self.dataDock.setMinimumWidth(300) self.dataDock.setMaximumWidth(300) self.logDock = QDockWidget(tr('Log')) self.logDock.setWidget(self.logView) self.addDockWidget(Qt.LeftDockWidgetArea, self.logDock) self.addDockWidget(Qt.LeftDockWidgetArea, self.dataDock) self.addDockWidget(Qt.LeftDockWidgetArea, self.workspaceDock) self.addDockWidget(Qt.LeftDockWidgetArea, self.toolDock) self.tabifyDockWidget(self.toolDock, self.workspaceDock) self.tabifyDockWidget(self.workspaceDock, self.dataDock) self.tabifyDockWidget(self.dataDock, self.logDock) self.toolDock.raise_() self.dbtool = ui.DbApp(self) self.dbBrowser = self.dbtool.dbBrowser self.setWindowTitle(tr('Pathomx')) self.progressBar = QProgressBar(self.statusBar()) self.progressBar.setMaximumSize(QSize(170, 19)) self.progressBar.setRange(0, 100) self.statusBar().addPermanentWidget(self.progressBar) self.progressTracker = {} # Dict storing values for each view/object logging.info('Ready.') self.statusBar().showMessage(tr('Ready')) self.showMaximized() # Do version upgrade check if StrictVersion(self.config.value('/Pathomx/Current_version', '0.0.0')) < StrictVersion(VERSION_STRING): # We've got an upgrade self.onAbout() self.config.setValue('/Pathomx/Current_version', VERSION_STRING) if self.config.value('/Pathomx/Offered_registration', False) != True: self.onDoRegister() self.config.setValue('/Pathomx/Offered_registration', True)