def get(self): # get the organisms, maps, and models response = yield gen.Task(AsyncHTTPClient().fetch, get_url('server_index', protocol='http')) if response.code == 200 and response.body is not None: server_index_json = response.body.decode('utf-8') else: server_index_json = None # get the cached maps and models index = local_index() # render the template template = env.get_template('homepage.html') data = template.render(escher=get_url('escher_min', 'local'), homepage_css=get_url('homepage_css', 'local'), favicon=get_url('favicon', 'local'), logo=get_url('logo', 'local'), documentation=get_url('documentation', protocol='https'), github=get_url('github'), github_releases=get_url('github_releases'), homepage_js=get_url('homepage_js', 'local'), map_download_url=get_url('map_download', 'local'), server_index_json=b64dump(server_index_json), local_index_json=b64dump(index), version=__version__, web_version=False) self.set_header("Content-Type", "text/html") self.serve(data)
def _draw_js( self, the_id, enable_editing, menu, enable_keys, dev, fill_screen, scroll_behavior, never_ask_before_quit, static_site_index_json, ): draw = ( "options = {{ enable_editing: {enable_editing},\n" "menu: {menu},\n" "enable_keys: {enable_keys},\n" "scroll_behavior: {scroll_behavior},\n" "fill_screen: {fill_screen},\n" "reaction_data: reaction_data_{the_id},\n" "metabolite_data: metabolite_data_{the_id},\n" "gene_data: gene_data_{the_id},\n" "never_ask_before_quit: {never_ask_before_quit},\n" ).format( the_id=the_id, enable_editing=json.dumps(enable_editing), menu=json.dumps(menu), enable_keys=json.dumps(enable_keys), scroll_behavior=json.dumps(scroll_behavior), fill_screen=json.dumps(fill_screen), never_ask_before_quit=json.dumps(never_ask_before_quit), ) # Add the specified options for option in self.options: val = getattr(self, option) if val is None: continue draw = draw + "{option}: {value},\n".format(option=option, value=json.dumps(val)) draw = draw + "};\n\n" # dev needs escher. dev_str = "" if dev else "escher." # parse the url in javascript, for building a static site if static_site_index_json: # get the relative location of the escher_download urls map_d = get_url("map_download", source="local") model_d = get_url("model_download", source="local") o = ( '%sstatic.load_map_model_from_url("%s", "%s", \n%s, \noptions, function(map_data_%s, model_data_%s, options) {\n' % (dev_str, map_d, model_d, static_site_index_json, the_id, the_id) ) draw = draw + o # make the builder draw = draw + ( "{dev_str}Builder(map_data_{the_id}, model_data_{the_id}, embedded_css_{the_id}, " 'd3.select("#{the_id}"), options);\n'.format(dev_str=dev_str, the_id=the_id) ) if static_site_index_json: draw = draw + "});\n" return draw
def load_map(self): """Load the map from input map_json using load_resource, or, secondarily, from map_name. """ map_json = self.map_json if map_json is not None: self.loaded_map_json = load_resource(self.map_json, 'map_json', safe=self.safe) elif self.map_name is not None: # get the name map_name = self.map_name map_name = map_name.replace('.json', '') # if the file is not present attempt to download cache_dir = get_cache_dir(name='maps') map_filename = join(cache_dir, map_name + '.json') if not isfile(map_filename): map_not_cached = 'Map "%s" not in cache. Attempting download from %s' % \ (map_name, get_url('escher_root')) warn(map_not_cached) try: map_url = map_name_to_url(self.map_name) download = urlopen(map_url) with open(map_filename, 'w') as outfile: outfile.write(download.read()) except HTTPError: raise ValueError('No map named %s found in cache or at %s' % \ (map_name, map_url)) with open(map_filename) as f: self.loaded_map_json = f.read()
def _json_for_name(name: str, kind: str): # check the name name = name.replace('.json', '') def match_in_index(name, index, kind): return [(obj['organism'], obj[kind + '_name']) for obj in index[kind + 's'] if obj[kind + '_name'] == name] try: index = server_index() except URLError: raise Exception('Could not connect to the Escher server') match = match_in_index(name, server_index(), kind) if len(match) == 0: raise Exception('Could not find the %s %s on the server' % (kind, name)) org, name = match[0] url = (get_url(kind + '_download') + '/'.join([url_escape(x, plus=False) for x in [org, name + '.json']])) print('Downloading %s from %s' % (kind.title(), url)) try: download = urlopen(url) except URLError: raise ValueError('No %s found in at %s' % (kind, url)) data = _decode_response(download) return data
def _embedded_css(self, url_source): """Return a css string to be embedded in the SVG. Returns self.embedded_css if it has been assigned. Otherwise, attempts to download the css file. Arguments --------- url_source: Whether to load from 'web' or 'local'. """ if self.embedded_css is not None: return self.embedded_css loc = get_url('builder_embed_css', source=url_source, local_host=self.local_host, protocol='https') try: download = urlopen(loc) except URLError: raise Exception(('Could not find builder_embed_css. Be sure to pass ' 'a local_host argument to Builder if js_source is dev or local ' 'and you are in an iPython notebook or a static html file.')) data = _decode_response(download) return data.replace('\n', ' ')
def _json_for_name(name: str, kind: str): # check the name name = name.replace('.json', '') def match_in_index(name, index, kind): return [(obj['organism'], obj[kind + '_name']) for obj in index[kind + 's'] if obj[kind + '_name'] == name] try: index = server_index() except URLError: raise Exception('Could not connect to the Escher server') match = match_in_index(name, server_index(), kind) if len(match) == 0: raise Exception(f'Could not find the {kind} {name} on the server') org, name = match[0] url = ( get_url(kind + '_download') + '/'.join([url_escape(x) for x in [org, name + '.json']]) ) print('Downloading %s from %s' % (kind.title(), url)) try: download = urlopen(url) except URLError: raise ValueError('No %s found in at %s' % (kind, url)) data = _decode_response(download) return data
def save_html(self, filepath): """Save an HTML file containing the map. :param string filepath: The name of the HTML file. TODO apply options from self """ # options = transform(self.options) # get options options = {} for key in self.traits(option=True): val = getattr(self, key) if val is not None: options[key] = val options_json = json.dumps(options) template = env.get_template('standalone.html') embedded_css_b64 = (b64dump(self.embedded_css) if self.embedded_css is not None else None) html = template.render( escher_url=get_url('escher_min'), embedded_css_b64=embedded_css_b64, map_data_json_b64=b64dump(self._loaded_map_json), model_data_json_b64=b64dump(self._loaded_model_json), options_json_b64=b64dump(options_json), ) with open(expanduser(filepath), 'wb') as f: f.write(html.encode('utf-8'))
def _embedded_css(self, url_source): """Return a css string to be embedded in the SVG. Returns self.embedded_css if it has been assigned. Otherwise, attempts to download the css file. Arguments --------- url_source: Whether to load from 'web' or 'local'. """ if self.embedded_css is not None: return self.embedded_css loc = get_url('builder_embed_css', source=url_source, local_host=self.local_host, protocol='https') try: download = urlopen(loc) except URLError: raise Exception(( 'Could not find builder_embed_css. Be sure to pass ' 'a local_host argument to Builder if js_source is dev or local ' 'and you are in an iPython notebook or a static html file.')) data = _decode_response(download) return data.replace('\n', ' ')
def _draw_js(self, the_id, enable_editing, menu, enable_keys, dev, fill_screen, scroll_behavior, never_ask_before_quit, static_site_index_json): draw = ("options = {{ enable_editing: {enable_editing},\n" "menu: {menu},\n" "enable_keys: {enable_keys},\n" "scroll_behavior: {scroll_behavior},\n" "fill_screen: {fill_screen},\n" "reaction_data: reaction_data_{the_id},\n" "metabolite_data: metabolite_data_{the_id},\n" "gene_data: gene_data_{the_id},\n" "never_ask_before_quit: {never_ask_before_quit},\n").format( the_id=the_id, enable_editing=json.dumps(enable_editing), menu=json.dumps(menu), enable_keys=json.dumps(enable_keys), scroll_behavior=json.dumps(scroll_behavior), fill_screen=json.dumps(fill_screen), never_ask_before_quit=json.dumps(never_ask_before_quit)) # Add the specified options for option in self.options: val = getattr(self, option) if val is None: continue draw = draw + "{option}: {value},\n".format(option=option, value=json.dumps(val)) draw = draw + "};\n\n" # dev needs escher. dev_str = '' if dev else 'escher.' # parse the url in javascript, for building a static site if static_site_index_json: # get the relative location of the escher_download urls map_d = get_url('map_download', source='local') model_d = get_url('model_download', source='local') o = ( '%sstatic.load_map_model_from_url("%s", "%s", \n%s, \noptions, function(map_data_%s, model_data_%s, options) {\n' % (dev_str, map_d, model_d, static_site_index_json, the_id, the_id)) draw = draw + o # make the builder draw = draw + ( '{dev_str}Builder(map_data_{the_id}, model_data_{the_id}, embedded_css_{the_id}, ' 'd3.select("#{the_id}"), options);\n'.format(dev_str=dev_str, the_id=the_id)) if static_site_index_json: draw = draw + '});\n' return draw
def server_index(): url = get_url('server_index', source='web', protocol='https') try: download = urlopen(url) except URLError: raise URLError('Could not contact Escher server') index = json.loads(download.read()) return index
def server_index(): url = get_url("server_index", source="web", protocol="https") try: download = urlopen(url) except URLError: raise URLError("Could not contact Escher server") data = _decode_response(download) index = json.loads(data) return index
def server_index(): url = get_url('server_index') try: download = urlopen(url) except URLError: raise URLError('Could not contact Escher server') data = _decode_response(download) index = json.loads(data) return index
def server_index(): url = get_url('server_index', source='web', protocol='https') try: download = urlopen(url) except URLError: raise URLError('Could not contact Escher server') data = _decode_response(download) index = json.loads(data) return index
def _json_for_name(name, kind, cache_dir): # check the name name = name.replace('.json', '') def match_in_index(name, index, kind): return [(obj['organism'], obj[kind + '_name']) for obj in index[kind + 's'] if obj[kind + '_name'] == name] # first check the local index match = match_in_index(name, local_index(cache_dir=cache_dir), kind) if len(match) == 0: path = None else: org, name = match[0] path = join(cache_dir, kind + 's', org, name + '.json') if path: # load the file with open(path, 'rb') as f: return f.read().decode('utf-8') # if the file is not present attempt to download else: try: index = server_index() except URLError: raise Exception( ('Could not find the %s %s in the cache, and could ' 'not connect to the Escher server' % (kind, name))) match = match_in_index(name, server_index(), kind) if len(match) == 0: raise Exception( 'Could not find the %s %s in the cache or on the server' % (kind, name)) org, name = match[0] url = (get_url(kind + '_download', source='web', protocol='https') + '/'.join( [url_escape(x, plus=False) for x in [org, name + '.json']])) warn('%s not in cache. Attempting download from %s' % (kind.title(), url)) try: download = urlopen(url) except URLError: raise ValueError('No %s found in cache or at %s' % (kind, url)) data = _decode_response(download) # save the file org_path = join(cache_dir, kind + 's', org) try: os.makedirs(org_path) except OSError: pass with open(join(org_path, name + '.json'), 'w') as outfile: outfile.write(data) return data
def test_bad_url(): with raises(Exception): get_url('bad-name') with raises(Exception): get_url('d3', source='bad-source') with raises(Exception): get_url('d3', protocol='bad-protocol')
def _json_for_name(name, kind, cache_dir): # check the name name = name.replace(".json", "") def match_in_index(name, index, kind): return [(obj["organism"], obj[kind + "_name"]) for obj in index[kind + "s"] if obj[kind + "_name"] == name] # first check the local index match = match_in_index(name, local_index(cache_dir=cache_dir), kind) if len(match) == 0: path = None else: org, name = match[0] path = join(cache_dir, kind + "s", org, name + ".json") if path: # load the file with open(path, "rb") as f: return f.read().decode("utf-8") # if the file is not present attempt to download else: try: index = server_index() except URLError: raise Exception( ("Could not find the %s %s in the cache, and could " "not connect to the Escher server" % (kind, name)) ) match = match_in_index(name, server_index(), kind) if len(match) == 0: raise Exception("Could not find the %s %s in the cache or on the server" % (kind, name)) org, name = match[0] url = get_url(kind + "_download", source="web", protocol="https") + "/".join( [url_escape(x, plus=False) for x in [org, name + ".json"]] ) warn("%s not in cache. Attempting download from %s" % (kind.title(), url)) try: download = urlopen(url) except URLError: raise ValueError("No %s found in cache or at %s" % (kind, url)) data = _decode_response(download) # save the file org_path = join(cache_dir, kind + "s", org) try: os.makedirs(org_path) except OSError: pass with open(join(org_path, name + ".json"), "w") as outfile: outfile.write(data) return data
def _json_for_name(name, kind, cache_dir): # check the name name = name.replace('.json', '') def match_in_index(name, index, kind): return [(obj['organism'], obj[kind + '_name']) for obj in index[kind + 's'] if obj[kind + '_name'] == name] # first check the local index match = match_in_index(name, local_index(cache_dir=cache_dir), kind) if len(match) == 0: path = None else: org, name = match[0] path = join(cache_dir, kind + 's', org, name + '.json') if path: # load the file with open(path, 'rb') as f: return f.read().decode('utf-8') # if the file is not present attempt to download else: try: index = server_index() except URLError: raise Exception(('Could not find the %s %s in the cache, and could ' 'not connect to the Escher server' % (kind, name))) match = match_in_index(name, server_index(), kind) if len(match) == 0: raise Exception('Could not find the %s %s in the cache or on the server' % (kind, name)) org, name = match[0] url = (get_url(kind + '_download', source='web', protocol='https') + '/'.join([url_escape(x, plus=False) for x in [org, name + '.json']])) warn('%s not in cache. Attempting download from %s' % (kind.title(), url)) try: download = urlopen(url) except URLError: raise ValueError('No %s found in cache or at %s' % (kind, url)) data = _decode_response(download) # save the file org_path = join(cache_dir, kind + 's', org) try: os.makedirs(org_path) except OSError: pass with open(join(org_path, name + '.json'), 'w') as outfile: outfile.write(data) return data
def generate_static_site(): print('Generating static site at %s' % top_directory) # index file template = env.get_template('homepage.html') def static_rel(path): return 'py/' + path data = template.render(d3=static_rel(get_url('d3', 'local')), boot_css=static_rel(get_url('boot_css', 'local')), homepage_css=static_rel(get_url('homepage_css', 'local')), favicon=static_rel(get_url('favicon', 'local')), logo=static_rel(get_url('logo', 'local')), documentation=get_url('documentation', protocol='https'), github=get_url('github', protocol='https'), github_releases=get_url('github_releases', protocol='https'), homepage_js=static_rel(get_url('homepage_js', 'local')), version=__version__, map_download_url=get_url('map_download', 'local'), web_version=True, server_index_url=static_rel(get_url('server_index', 'local'))) with open(join(top_directory, 'index.html'), 'wb') as f: f.write(data.encode('utf-8')) # viewer and builder # make the builder builder = Builder(safe=True, id='static_map') filepath = join(top_directory, 'builder') with open(join(root_directory, get_url('server_index', source='local')), 'r') as f: index_json = f.read() html = builder.save_html(filepath=filepath, overwrite=True, js_source='local', protocol=None, minified_js=True, static_site_index_json=index_json) # copy over the source maps escher_map = get_url('escher_min', 'local') + '.map' builder_css_map = get_url('builder_css_min', 'local') + '.map' shutil.copy(join(root_directory, escher_map), join(top_directory, 'builder', escher_map)) shutil.copy(join(root_directory, builder_css_map), join(top_directory, 'builder', builder_css_map))
def get(self, kind, path): # builder vs. viewer enable_editing = (kind=='builder') # Builder options builder_kwargs = {} for a in ['starting_reaction', 'model_name', 'map_name', 'map_json', 'reaction_no_data_color', 'reaction_no_data_size', 'metabolite_no_data_color', 'metabolite_no_data_size', 'hide_secondary_nodes']: args = self.get_arguments(a) if len(args)==1: builder_kwargs[a] = (True if args[0].lower()=='true' else (False if args[0].lower()=='false' else args[0])) # array args for a in ['quick_jump', 'metabolite_size_range', 'metabolite_color_range', 'reaction_size_range', 'reaction_color_range', 'gene_styles']: args = self.get_arguments(a + '[]') if len(args) > 0: builder_kwargs[a] = args # js source args = self.get_arguments('js_source') js_source = args[0] if len(args) == 1 else 'web' # if the server is running locally, then the embedded css must be loaded # asynchronously using the same server thread. if js_source in ['dev', 'local']: global PORT url = get_url('builder_embed_css', source='local', local_host='http://localhost:%d' % PORT) response = yield gen.Task(AsyncHTTPClient().fetch, url) if response.code != 200 or response.body is None: raise Exception('Could not load embedded_css from %s' % url) builder_kwargs['embedded_css'] = (response.body .decode('utf-8') .replace('\n', ' ')) # example data def load_data_file(rel_path): """Load a JSON file with relative path.""" try: with open(join(root_directory, rel_path), 'r') as f: return json.load(f) except: logging.warn('Could not load example_data file: %s' % rel_path) if len(self.get_arguments('example_data')) > 0: r_filepath = 'escher/example_data/reaction_data_iJO1366.json' builder_kwargs['reaction_data'] = load_data_file(r_filepath) m_filepath = 'escher/example_data/metabolite_data_iJO1366.json' builder_kwargs['metabolite_data'] = load_data_file(m_filepath) # make the builder builder = Builder(safe=True, **builder_kwargs) # display options display_kwargs = {'minified_js': True, 'scroll_behavior': 'pan', 'menu': 'all'} # keyword for a in ['menu', 'scroll_behavior', 'minified_js', 'auto_set_data_domain', 'never_ask_before_quit']: args = self.get_arguments(a) if len(args)==1: display_kwargs[a] = (True if args[0].lower()=='true' else (False if args[0].lower()=='false' else args[0])) html = builder._get_html(js_source=js_source, enable_editing=enable_editing, enable_keys=True, html_wrapper=True, fill_screen=True, height='100%', **display_kwargs) self.set_header("Content-Type", "text/html") self.serve(html)
def test_map_json_for_name_web(tmpdir): data = map_json_for_name("iJO1366.Central metabolism", cache_dir=str(tmpdir)) root = get_url("escher_root", protocol="https").rstrip("/") assert json.loads(data)[0]["schema"] == "/".join([root, "escher", "jsonschema", __schema_version__ + "#"])
def test_cdn(): url = get_url('boot_js', 'web') assert url == '//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/js/bootstrap.min.js'
def _get_html(self, js_source='web', menu='none', scroll_behavior='pan', html_wrapper=False, enable_editing=False, enable_keys=False, minified_js=True, fill_screen=False, height='800px', never_ask_before_quit=False, static_site_index_json=None): """Generate the Escher HTML. Arguments -------- js_source: Can be one of the following: 'web' - (Default) use js files from escher.github.io. 'local' - use compiled js files in the local escher installation. Works offline. 'dev' - use the local, uncompiled development files. Works offline. menu: Menu bar options include: 'none' - (Default) No menu or buttons. 'zoom' - Just zoom buttons (does not require bootstrap). 'all' - Menu and button bar (requires bootstrap). scroll_behavior: Scroll behavior options: 'pan' - (Default) Pan the map. 'zoom' - Zoom the map. 'none' - No scroll events. minified_js: If True, use the minified version of js files. If js_source is 'dev', then this option is ignored. html_wrapper: If True, return a standalone html file. enable_editing: Enable the editing modes (build, rotate, etc.). enable_keys: Enable keyboard shortcuts. height: The height of the HTML container. never_ask_before_quit: Never display an alert asking if you want to leave the page. By default, this message is displayed if enable_editing is True. static_site_index_json: The index, as a JSON string, for the static site. Use javascript to parse the URL options. Used for generating static pages (see static_site.py). """ if js_source not in ['web', 'local', 'dev']: raise Exception('Bad value for js_source: %s' % js_source) if menu not in ['none', 'zoom', 'all']: raise Exception('Bad value for menu: %s' % menu) if scroll_behavior not in ['pan', 'zoom', 'none']: raise Exception('Bad value for scroll_behavior: %s' % scroll_behavior) content = env.get_template('content.html') # if height is not a string if type(height) is int: height = "%dpx" % height elif type(height) is float: height = "%fpx" % height elif type(height) is str: height = str(height) # set the proper urls url_source = 'local' if (js_source=='local' or js_source=='dev') else 'web' is_dev = (js_source=='dev') d3_url = get_url('d3', url_source, self.local_host) d3_rel_url = get_url('d3', url_source) escher_url = ('' if js_source=='dev' else get_url('escher_min' if minified_js else 'escher', url_source, self.local_host)) jquery_url = ('' if not menu=='all' else get_url('jquery', url_source, self.local_host)) boot_css_url = ('' if not menu=='all' else get_url('boot_css', url_source, self.local_host)) boot_js_url = ('' if not menu=='all' else get_url('boot_js', url_source, self.local_host)) require_js_url = get_url('require_js', url_source, self.local_host) escher_css_url = get_url('builder_css', url_source, self.local_host) favicon_url = get_url('favicon', url_source, self.local_host) lh_string = ('' if self.local_host is None else self.local_host.rstrip('/') + '/') html = content.render(id=self.the_id, height=height, dev=is_dev, d3=d3_url, d3_rel=d3_rel_url, escher=escher_url, jquery=jquery_url, boot_css=boot_css_url, boot_js=boot_js_url, require_js=require_js_url, escher_css=escher_css_url, wrapper=html_wrapper, title='Escher ' + ('Builder' if enable_editing else 'Viewer'), favicon=favicon_url, host=lh_string, initialize_js=self._initialize_javascript(self.the_id, url_source), draw_js=self._draw_js(self.the_id, enable_editing, menu, enable_keys, is_dev, fill_screen, scroll_behavior, never_ask_before_quit, static_site_index_json)) return html
def test_load_resource_web(tmpdir): url = "/".join([get_url("map_download", protocol="https"), "Escherichia%20coli/iJO1366.Central%20metabolism.json"]) _ = json.loads(_load_resource(url, "name"))
def save_html(self, filepath=None, overwrite=False, js_source='web', protocol='https', menu='all', scroll_behavior='pan', enable_editing=True, enable_keys=True, minified_js=True, never_ask_before_quit=False, static_site_index_json=None): """Save an HTML file containing the map. :param string filepath: The HTML file will be saved to this location. When js_source is 'local', then a new directory will be created with this name. :param Boolean overwrite: Overwrite existing files. :param string js_source: Can be one of the following: - *web* (Default) - Use JavaScript files from escher.github.io. - *local* - Use compiled JavaScript files in the local Escher installation. Works offline. To make the dependencies available to the downloaded file, a new directory will be made with the name specified by filepath. - *dev* - No longer necessary with source maps. This now gives the same behavior as 'local'. :param string protocol: The protocol can be 'http', 'https', or None which indicates a 'protocol relative URL', as in //escher.github.io. Ignored if source is local. :param string menu: Menu bar options include: - *none* - No menu or buttons. - *zoom* - Just zoom buttons. - *all* (Default) - Menu and button bar. :param string scroll_behavior: Scroll behavior options: - *pan* - Pan the map. - *zoom* - Zoom the map. - *none* (Default) - No scroll events. :param Boolean enable_editing: Enable the map editing modes. :param Boolean enable_keys: Enable keyboard shortcuts. :param Boolean minified_js: If True, use the minified version of JavaScript and CSS files. :param number height: Height of the HTML container. :param Boolean never_ask_before_quit: Never display an alert asking if you want to leave the page. By default, this message is displayed if enable_editing is True. :param string static_site_index_json: The index, as a JSON string, for the static site. Use javascript to parse the URL options. Used for generating static pages (see static_site.py). """ filepath = expanduser(filepath) if js_source in ['local', 'dev']: if filepath is None: raise Exception( 'Must provide a filepath when js_source is not "web"') # make a directory directory = re.sub(r'\.html$', '', filepath) if exists(directory): if not overwrite: raise Exception('Directory already exists: %s' % directory) else: os.makedirs(directory) # add dependencies to the directory escher = get_url('escher_min' if minified_js else 'escher', 'local') favicon = get_url('favicon', 'local') for path in [escher, favicon]: if path is None: continue src = join(root_directory, path) dest = join(directory, path) dest_dir = dirname(dest) if not exists(dest_dir): os.makedirs(dest_dir) shutil.copy(src, dest) filepath = join(directory, 'index.html') else: if not filepath.endswith('.html'): filepath += '.html' if exists(filepath) and not overwrite: raise Exception('File already exists: %s' % filepath) html = self._get_html(js_source=js_source, menu=menu, scroll_behavior=scroll_behavior, html_wrapper=True, enable_editing=enable_editing, enable_keys=enable_keys, minified_js=minified_js, fill_screen=True, height="100%", never_ask_before_quit=never_ask_before_quit, static_site_index_json=static_site_index_json, protocol=protocol) if filepath is not None: with open(filepath, 'wb') as f: f.write(html.encode('utf-8')) return filepath else: from tempfile import mkstemp from os import write, close os_file, filename = mkstemp(suffix=".html", text=False) # binary write(os_file, html.encode('utf-8')) close(os_file) return filename
def test_no_protocol(): url = get_url('escher', 'web') assert url == '//unpkg.com/escher@%s/dist/escher.js' % __version__
def test_localhost(): url = get_url('escher', source='local', local_host='http://localhost:7778/') assert url == 'http://localhost:7778/escher/static/escher/escher.js'
def test_map_download_url(): url = get_url('map_download') assert url == ('https://escher.github.io/%s/%s/maps/' % (__schema_version__, __map_model_version__))
def test_urls(): # online url = get_url('builder_embed_css', source='web', protocol='https') assert url == 'https://escher.github.io/builder-embed-%s.css' % __version__ # no protocol url = get_url('escher', 'web') assert url == '//escher.github.io/escher-%s.js' % __version__ # local url = get_url('require_js', 'local') assert url == 'escher/lib/require.min.js' assert exists(join(root_directory, url)) # localhost url = get_url('require_js', source='local', local_host='http://localhost:7778/') assert url == 'http://localhost:7778/escher/lib/require.min.js' # cdn url = get_url('boot_js', 'web') assert url == '//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js' # download url = get_url('server_index', source='local') assert url == __schema_version__ + '/' + __map_model_version__ + '/index.json' url = get_url('map_download', protocol='https') assert url == 'https://escher.github.io/%s/%s/maps/' % ( __schema_version__, __map_model_version__) # raises with raises(Exception): get_url('bad-name') with raises(Exception): get_url('d3', source='bad-source') with raises(Exception): get_url('d3', protocol='bad-protocol')
def generate_static_site(): print('Generating static site at %s' % root_directory) # index file template = env.get_template('index.html') data = template.render(d3=get_url('d3', 'local'), boot_css=get_url('boot_css', 'local'), index_css=get_url('index_css', 'local'), favicon=get_url('favicon', 'local'), logo=get_url('logo', 'local'), documentation=get_url('documentation', protocol='https'), github=get_url('github', protocol='https'), github_releases=get_url('github_releases', protocol='https'), index_js=get_url('index_js', 'local'), index_gh_pages_js=get_url('index_gh_pages_js', 'local'), version=__version__, map_download=get_url('map_download', 'local'), web_version=True, server_index_url=get_url('server_index', 'local'), # server_index= # local_index= can_dev=False, # can_dev_js= ) with open(join(root_directory, 'index.html'), 'w') as f: f.write(data.encode('utf-8')) # viewer and builder for kind in ['viewer', 'builder']: for minified_js in [True, False]: js_source = 'local' enable_editing = (kind=='builder') # make the builder with open(join(root_directory, get_url('builder_embed_css', 'local')), 'r') as f: css = f.read() builder = Builder(embedded_css=css, safe=True, id='static') filepath = join(root_directory, '%s%s.html' % (kind, '' if minified_js else '_not_minified')) with open(join(root_directory, get_url('server_index', source='local')), 'r') as f: index_json = f.read() html = builder.save_html(filepath=filepath, js_source=js_source, minified_js=minified_js, enable_editing=enable_editing, static_site_index_json=index_json)
def test_bad_url(): with raises(Exception): get_url('bad-name')
def _get_html(self, js_source='web', menu='none', scroll_behavior='pan', html_wrapper=False, enable_editing=False, enable_keys=False, minified_js=True, fill_screen=False, height='800px', never_ask_before_quit=False, static_site_index_json=None, protocol=None, ignore_bootstrap=False): """Generate the Escher HTML. Arguments -------- js_source: Can be one of the following: 'web' - (Default) use js files from unpkg. 'local' - Use compiled js files in the local escher installation. Works offline. 'dev' - No longer necessary with source maps. This now gives the same behavior as 'local'. menu: Menu bar options include: 'none' - (Default) No menu or buttons. 'zoom' - Just zoom buttons (does not require bootstrap). 'all' - Menu and button bar (requires bootstrap). scroll_behavior: Scroll behavior options: 'pan' - (Default) Pan the map. 'zoom' - Zoom the map. 'none' - No scroll events. minified_js: If True, use the minified version of JavaScript files. html_wrapper: If True, return a standalone html file. enable_editing: Enable the editing modes (build, rotate, etc.). enable_keys: Enable keyboard shortcuts. height: The height of the HTML container. never_ask_before_quit: Never display an alert asking if you want to leave the page. By default, this message is displayed if enable_editing is True. static_site_index_json: The index, as a JSON string, for the static site. Use javascript to parse the URL options. Used for generating static pages (see static_site.py). protocol: The protocol can be 'http', 'https', or None which indicates a 'protocol relative URL', as in //escher.github.io. Ignored if source is local. ignore_bootstrap: Deprecated """ if js_source not in ['web', 'local', 'dev']: raise Exception('Bad value for js_source: %s' % js_source) if menu not in ['none', 'zoom', 'all']: raise Exception('Bad value for menu: %s' % menu) if scroll_behavior not in ['pan', 'zoom', 'none']: raise Exception('Bad value for scroll_behavior: %s' % scroll_behavior) content = env.get_template('content.html') # if height is not a string if type(height) is int: height = "%dpx" % height elif type(height) is float: height = "%fpx" % height elif type(height) is str: height = str(height) # set the proper urls url_source = 'local' if (js_source == 'local' or js_source == 'dev') else 'web' local_host = self.local_host # get the urls escher_url = get_url(('escher_min' if minified_js else 'escher'), url_source, local_host, protocol) favicon_url = get_url('favicon', url_source, local_host, protocol) # for static site map_download_url = get_url('map_download', url_source, local_host, protocol) model_download_url = get_url('model_download', url_source, local_host, protocol) # local host lh_string = ('' if local_host is None else local_host.rstrip('/') + '/') # options options = { 'menu': menu, 'enable_keys': enable_keys, 'enable_editing': enable_editing, 'scroll_behavior': scroll_behavior, 'fill_screen': fill_screen, 'never_ask_before_quit': never_ask_before_quit, 'reaction_data': self.reaction_data, 'metabolite_data': self.metabolite_data, 'gene_data': self.gene_data, } # Add the specified options for option in self.options: val = getattr(self, option) if val is None: continue options[option] = val html = content.render( # standalone title='Escher ' + ('Builder' if enable_editing else 'Viewer'), favicon_url=favicon_url, # content wrapper=html_wrapper, height=height, id=self.the_id, escher_url=escher_url, # dump json id_json=json_dump_and_escape(self.the_id), options_json=json_dump_and_escape(options), map_download_url_json=json_dump_and_escape(map_download_url), model_download_url_json=json_dump_and_escape(model_download_url), builder_embed_css_json=json_dump_and_escape(self.embedded_css), # alreay json map_data_json=escape_json_or_null(self.loaded_map_json), model_data_json=escape_json_or_null(self.loaded_model_json), static_site_index_json=escape_json_or_null(static_site_index_json), ) return html
def test_local(): url = get_url('escher_min', 'local') assert url == 'escher/static/escher/escher.min.js' assert exists(join(root_directory, url))
def save_html(self, filepath=None, overwrite=False, js_source='web', protocol='https', menu='all', scroll_behavior='pan', enable_editing=True, enable_keys=True, minified_js=True, never_ask_before_quit=False, static_site_index_json=None): """Save an HTML file containing the map. :param string filepath: The HTML file will be saved to this location. When js_source is 'local', then a new directory will be created with this name. :param Boolean overwrite: Overwrite existing files. :param string js_source: Can be one of the following: - *web* (Default) - Use JavaScript files from escher.github.io. - *local* - Use compiled JavaScript files in the local Escher installation. Works offline. To make the dependencies available to the downloaded file, a new directory will be made with the name specified by filepath. - *dev* - No longer necessary with source maps. This now gives the same behavior as 'local'. :param string protocol: The protocol can be 'http', 'https', or None which indicates a 'protocol relative URL', as in //escher.github.io. Ignored if source is local. :param string menu: Menu bar options include: - *none* - No menu or buttons. - *zoom* - Just zoom buttons. - *all* (Default) - Menu and button bar (requires Bootstrap). :param string scroll_behavior: Scroll behavior options: - *pan* - Pan the map. - *zoom* - Zoom the map. - *none* (Default) - No scroll events. :param Boolean enable_editing: Enable the map editing modes. :param Boolean enable_keys: Enable keyboard shortcuts. :param Boolean minified_js: If True, use the minified version of JavaScript and CSS files. :param number height: Height of the HTML container. :param Boolean never_ask_before_quit: Never display an alert asking if you want to leave the page. By default, this message is displayed if enable_editing is True. :param string static_site_index_json: The index, as a JSON string, for the static site. Use javascript to parse the URL options. Used for generating static pages (see static_site.py). """ filepath = expanduser(filepath) if js_source in ['local', 'dev']: if filepath is None: raise Exception('Must provide a filepath when js_source is not "web"') # make a directory directory = re.sub(r'\.html$', '', filepath) if exists(directory): if not overwrite: raise Exception('Directory already exists: %s' % directory) else: os.makedirs(directory) # add dependencies to the directory escher = get_url('escher_min' if minified_js else 'escher', 'local') builder_css = get_url('builder_css_min' if minified_js else 'builder_css', 'local') d3 = get_url('d3', 'local') favicon = get_url('favicon', 'local') if menu == 'all': boot_css = get_url('boot_css', 'local') boot_js = get_url('boot_js', 'local') jquery = get_url('jquery', 'local') boot_font_eot = get_url('boot_font_eot', 'local') boot_font_svg = get_url('boot_font_svg', 'local') boot_font_woff = get_url('boot_font_woff', 'local') boot_font_woff2 = get_url('boot_font_woff2', 'local') boot_font_ttf = get_url('boot_font_ttf', 'local') else: boot_css = boot_js = jquery = None boot_font_eot = boot_font_svg = None boot_font_woff = boot_font_woff2 = boot_font_ttf = None for path in [escher, builder_css, boot_css, boot_js, jquery, d3, favicon, boot_font_eot, boot_font_svg, boot_font_woff, boot_font_woff2, boot_font_ttf]: if path is None: continue src = join(root_directory, path) dest = join(directory, path) dest_dir = dirname(dest) if not exists(dest_dir): os.makedirs(dest_dir) shutil.copy(src, dest) filepath = join(directory, 'index.html') else: if not filepath.endswith('.html'): filepath += '.html' if exists(filepath) and not overwrite: raise Exception('File already exists: %s' % filepath) html = self._get_html(js_source=js_source, menu=menu, scroll_behavior=scroll_behavior, html_wrapper=True, enable_editing=enable_editing, enable_keys=enable_keys, minified_js=minified_js, fill_screen=True, height="100%", never_ask_before_quit=never_ask_before_quit, static_site_index_json=static_site_index_json, protocol=protocol) if filepath is not None: with open(filepath, 'wb') as f: f.write(html.encode('utf-8')) return filepath else: from tempfile import mkstemp from os import write, close os_file, filename = mkstemp(suffix=".html", text=False) # binary write(os_file, html.encode('utf-8')) close(os_file) return filename
def test_download(): url = get_url('server_index', source='local') assert url == '../' + __schema_version__ + '/' + __map_model_version__ + '/index.json' url = get_url('map_download', protocol='https') assert url == 'https://escher.github.io/%s/%s/maps/' % ( __schema_version__, __map_model_version__)
def test_load_resource_web(tmpdir): url = '/'.join([ get_url('map_download', protocol='https'), 'Escherichia%20coli/iJO1366.Central%20metabolism.json' ]) _ = json.loads(_load_resource(url, 'name'))
def test_online(): url = get_url('escher', source='web', protocol='https') assert url == 'https://unpkg.com/escher@%s/dist/escher.js' % __version__
def test_local(): url = get_url('boot_js', 'local') assert url == 'escher/static/lib/bootstrap.min.js' assert exists(join(root_directory, url))
def _get_html(self, js_source='web', menu='none', scroll_behavior='pan', html_wrapper=False, enable_editing=False, enable_keys=False, minified_js=True, fill_screen=False, height='800px', never_ask_before_quit=False, static_site_index_json=None, protocol=None, ignore_bootstrap=False): """Generate the Escher HTML. Arguments -------- js_source: Can be one of the following: 'web' - (Default) use js files from escher.github.io. 'local' - use compiled js files in the local escher installation. Works offline. 'dev' - use the local, uncompiled development files. Works offline. menu: Menu bar options include: 'none' - (Default) No menu or buttons. 'zoom' - Just zoom buttons (does not require bootstrap). 'all' - Menu and button bar (requires bootstrap). scroll_behavior: Scroll behavior options: 'pan' - (Default) Pan the map. 'zoom' - Zoom the map. 'none' - No scroll events. minified_js: If True, use the minified version of JavaScript and CSS files. html_wrapper: If True, return a standalone html file. enable_editing: Enable the editing modes (build, rotate, etc.). enable_keys: Enable keyboard shortcuts. height: The height of the HTML container. never_ask_before_quit: Never display an alert asking if you want to leave the page. By default, this message is displayed if enable_editing is True. static_site_index_json: The index, as a JSON string, for the static site. Use javascript to parse the URL options. Used for generating static pages (see static_site.py). protocol: The protocol can be 'http', 'https', or None which indicates a 'protocol relative URL', as in //escher.github.io. Ignored if source is local. ignore_bootstrap: Do not use Bootstrap for buttons, even if it available. This is used to embed Escher in a Jupyter notebook where it conflicts with the Jupyter Boostrap installation. """ if js_source not in ['web', 'local', 'dev']: raise Exception('Bad value for js_source: %s' % js_source) if menu not in ['none', 'zoom', 'all']: raise Exception('Bad value for menu: %s' % menu) if scroll_behavior not in ['pan', 'zoom', 'none']: raise Exception('Bad value for scroll_behavior: %s' % scroll_behavior) content = env.get_template('content.html') # if height is not a string if type(height) is int: height = "%dpx" % height elif type(height) is float: height = "%fpx" % height elif type(height) is str: height = str(height) # set the proper urls url_source = 'local' if (js_source=='local' or js_source=='dev') else 'web' local_host = self.local_host # get the urls d3_url = get_url('d3', url_source, local_host, protocol) escher_url = get_url(('escher_min' if minified_js else 'escher'), url_source, local_host, protocol) if menu == 'all' and not ignore_bootstrap: jquery_url = get_url('jquery', url_source, local_host, protocol) boot_css_url = get_url('boot_css', url_source, local_host, protocol) boot_js_url = get_url('boot_js', url_source, local_host, protocol) else: jquery_url = boot_css_url = boot_js_url = None escher_css_url = get_url(('builder_css_min' if minified_js else 'builder_css'), url_source, local_host, protocol) favicon_url = get_url('favicon', url_source, local_host, protocol) # for static site map_download_url = get_url('map_download', url_source, local_host, protocol) model_download_url = get_url('model_download', url_source, local_host, protocol) # local host lh_string = ('' if local_host is None else local_host.rstrip('/') + '/') # options options = { 'menu': menu, 'enable_keys': enable_keys, 'enable_editing': enable_editing, 'scroll_behavior': scroll_behavior, 'fill_screen': fill_screen, 'ignore_bootstrap': ignore_bootstrap, 'never_ask_before_quit': never_ask_before_quit, 'reaction_data': self.reaction_data, 'metabolite_data': self.metabolite_data, 'gene_data': self.gene_data, } # Add the specified options for option in self.options: val = getattr(self, option) if val is None: continue options[option] = val html = content.render( # standalone title='Escher ' + ('Builder' if enable_editing else 'Viewer'), jquery_url=jquery_url, boot_js_url=boot_js_url, boot_css_url=boot_css_url, escher_css_url=escher_css_url, favicon_url=favicon_url, # content wrapper=html_wrapper, height=height, id=self.the_id, d3_url=d3_url, escher_url=escher_url, # dump json id_json=json_dump_and_escape(self.the_id), options_json=json_dump_and_escape(options), map_download_url_json=json_dump_and_escape(map_download_url), model_download_url_json=json_dump_and_escape(model_download_url), builder_embed_css_json=json_dump_and_escape(self.embedded_css), # alreay json map_data_json=escape_json_or_null(self.loaded_map_json), model_data_json=escape_json_or_null(self.loaded_model_json), static_site_index_json=escape_json_or_null(static_site_index_json), ) return html
def test_index_url(): url = get_url('server_index') assert url == ('https://escher.github.io/%s/%s/index.json' % (__schema_version__, __map_model_version__))
def test_map_json_for_name_web(tmpdir): data = map_json_for_name('iJO1366.Central metabolism', cache_dir=str(tmpdir)) root = get_url('escher_root', protocol='https').rstrip('/') assert json.loads(data)[0]['schema'] == '/'.join( [root, 'escher', 'jsonschema', __schema_version__ + '#'])
def test_online(): url = get_url('escher') assert url == 'https://unpkg.com/escher@%s/dist/escher.js' % __version__
def test_no_protocol(): url = get_url('escher', 'web') assert url == '//npmcdn.com/escher-vis@%s/js/dist/escher.js' % __version__
def _get_html(self, js_source='web', menu='none', scroll_behavior='pan', html_wrapper=False, enable_editing=False, enable_keys=False, minified_js=True, fill_screen=False, height='800px', never_ask_before_quit=False, static_site_index_json=None): """Generate the Escher HTML. Arguments -------- js_source: Can be one of the following: 'web' - (Default) use js files from escher.github.io. 'local' - use compiled js files in the local escher installation. Works offline. 'dev' - use the local, uncompiled development files. Works offline. menu: Menu bar options include: 'none' - (Default) No menu or buttons. 'zoom' - Just zoom buttons (does not require bootstrap). 'all' - Menu and button bar (requires bootstrap). scroll_behavior: Scroll behavior options: 'pan' - (Default) Pan the map. 'zoom' - Zoom the map. 'none' - No scroll events. minified_js: If True, use the minified version of js files. If js_source is 'dev', then this option is ignored. html_wrapper: If True, return a standalone html file. enable_editing: Enable the editing modes (build, rotate, etc.). enable_keys: Enable keyboard shortcuts. height: The height of the HTML container. never_ask_before_quit: Never display an alert asking if you want to leave the page. By default, this message is displayed if enable_editing is True. static_site_index_json: The index, as a JSON string, for the static site. Use javascript to parse the URL options. Used for generating static pages (see static_site.py). """ if js_source not in ['web', 'local', 'dev']: raise Exception('Bad value for js_source: %s' % js_source) if menu not in ['none', 'zoom', 'all']: raise Exception('Bad value for menu: %s' % menu) if scroll_behavior not in ['pan', 'zoom', 'none']: raise Exception('Bad value for scroll_behavior: %s' % scroll_behavior) content = env.get_template('content.html') # if height is not a string if type(height) is int: height = "%dpx" % height elif type(height) is float: height = "%fpx" % height elif type(height) is str: height = str(height) # set the proper urls url_source = 'local' if (js_source == 'local' or js_source == 'dev') else 'web' is_dev = (js_source == 'dev') d3_url = get_url('d3', url_source, self.local_host) d3_rel_url = get_url('d3', url_source) escher_url = ('' if js_source == 'dev' else get_url( 'escher_min' if minified_js else 'escher', url_source, self.local_host)) jquery_url = ('' if not menu == 'all' else get_url( 'jquery', url_source, self.local_host)) boot_css_url = ('' if not menu == 'all' else get_url( 'boot_css', url_source, self.local_host)) boot_js_url = ('' if not menu == 'all' else get_url( 'boot_js', url_source, self.local_host)) require_js_url = get_url('require_js', url_source, self.local_host) escher_css_url = get_url('builder_css', url_source, self.local_host) favicon_url = get_url('favicon', url_source, self.local_host) lh_string = ('' if self.local_host is None else self.local_host.rstrip('/') + '/') html = content.render( id=self.the_id, height=height, dev=is_dev, d3=d3_url, d3_rel=d3_rel_url, escher=escher_url, jquery=jquery_url, boot_css=boot_css_url, boot_js=boot_js_url, require_js=require_js_url, escher_css=escher_css_url, wrapper=html_wrapper, title='Escher ' + ('Builder' if enable_editing else 'Viewer'), favicon=favicon_url, host=lh_string, initialize_js=self._initialize_javascript(self.the_id, url_source), draw_js=self._draw_js(self.the_id, enable_editing, menu, enable_keys, is_dev, fill_screen, scroll_behavior, never_ask_before_quit, static_site_index_json)) return html
def test_localhost(): url = get_url('boot_js', source='local', local_host='http://localhost:7778/') assert url == 'http://localhost:7778/escher/static/lib/bootstrap.min.js'
def generate_static_site(): print('Generating static site at %s' % top_directory) # index file template = env.get_template('homepage.html') def static_rel(path): return 'py/' + path data = template.render( d3=static_rel(get_url('d3', 'local')), boot_css=static_rel(get_url('boot_css', 'local')), homepage_css=static_rel(get_url('homepage_css', 'local')), favicon=static_rel(get_url('favicon', 'local')), logo=static_rel(get_url('logo', 'local')), documentation=get_url('documentation', protocol='https'), github=get_url('github', protocol='https'), github_releases=get_url('github_releases', protocol='https'), homepage_js=static_rel(get_url('homepage_js', 'local')), version=__version__, map_download_url=get_url('map_download', 'local'), web_version=True, server_index_url=static_rel(get_url('server_index', 'local'))) with open(join(top_directory, 'index.html'), 'wb') as f: f.write(data.encode('utf-8')) # viewer and builder # make the builder builder = Builder(safe=True, id='static_map') filepath = join(top_directory, 'builder') with open(join(root_directory, get_url('server_index', source='local')), 'r') as f: index_json = f.read() html = builder.save_html(filepath=filepath, overwrite=True, js_source='local', protocol=None, minified_js=True, static_site_index_json=index_json) # copy over the source maps escher_map = get_url('escher_min', 'local') + '.map' builder_css_map = get_url('builder_css_min', 'local') + '.map' shutil.copy(join(root_directory, escher_map), join(top_directory, 'builder', escher_map)) shutil.copy(join(root_directory, builder_css_map), join(top_directory, 'builder', builder_css_map))
def test_download(): url = get_url('server_index', source='local') assert url == '../' + __schema_version__ + '/' + __map_model_version__ + '/index.json' url = get_url('map_download', protocol='https') assert url == 'https://escher.github.io/%s/%s/maps/' % (__schema_version__, __map_model_version__)
def test__load_resource_web(tmpdir): url = '/'.join([get_url('map_download', protocol='https'), 'Escherichia%20coli/iJO1366.Central%20metabolism.json']) _ = json.loads(_load_resource(url, 'name'))
def test_online(): url = get_url('builder_css', source='web', protocol='https') assert url == 'https://npmcdn.com/escher-vis@%s/css/dist/builder.css' % __version__
def test_map_json_for_name_web(tmpdir): data = map_json_for_name('iJO1366.Central metabolism', cache_dir=str(tmpdir)) root = get_url('escher_root', protocol='https').rstrip('/') assert json.loads(data)[0]['schema'] == '/'.join([root, 'escher', 'jsonschema', __schema_version__ + '#'])
def get(self): # get the organisms, maps, and models response = yield gen.Task(AsyncHTTPClient().fetch, get_url('server_index', protocol='http')) if response.code == 200 and response.body is not None: server_index = response.body.decode('utf-8') else: server_index = json.dumps(None) # get the cached maps and models index = local_index() # render the template template = env.get_template('index.html') data = template.render(d3=get_url('d3', 'local'), boot_css=get_url('boot_css', 'local'), index_css=get_url('index_css', 'local'), favicon=get_url('favicon', 'local'), logo=get_url('logo', 'local'), documentation=get_url('documentation', protocol='https'), github=get_url('github'), github_releases=get_url('github_releases'), index_js=get_url('index_js', 'local'), index_gh_pages_js=get_url('index_gh_pages_js', 'local'), map_download=get_url('map_download', 'local'), # server_index_url= server_index=server_index, local_index=json.dumps(index), can_dev=CAN_DEV, can_dev_js=json.dumps(CAN_DEV), version=__version__, web_version=False) self.set_header("Content-Type", "text/html") self.serve(data)
def test_urls(): # online url = get_url('builder_embed_css', source='web', protocol='https') assert url == 'https://escher.github.io/builder-embed-%s.css' % __version__ # no protocol url = get_url('escher', 'web') assert url == '//escher.github.io/escher-%s.js' % __version__ # local url = get_url('require_js', 'local') assert url == 'escher/lib/require.min.js' assert exists(join(root_directory, url)) # localhost url = get_url('require_js', source='local', local_host='http://localhost:7778/') assert url == 'http://localhost:7778/escher/lib/require.min.js' # cdn url = get_url('boot_js', 'web') assert url == '//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js' # download url = get_url('server_index', source='local') assert url == __schema_version__ + '/index.json' url = get_url('map_download', protocol='https') assert url == 'https://escher.github.io/%s/maps/' % __schema_version__ # raises with raises(Exception): get_url('bad-name') with raises(Exception): get_url('d3', source='bad-source') with raises(Exception): get_url('d3', protocol='bad-protocol')