def normalize_url(url, ref_base_url=None): ''' :param url: An absolute URL, absolute path or relative path. :type url: URL | string :param ref_base_url: Default absolute URL used to expand a path to a full URL. Uses ``smisk.core.request.url`` if not set. :type ref_base_url: URL :rtype: URL ''' is_relative_uri = False if '/' not in url: is_relative_uri = True u = URL() u.path = url url = u else: url = URL(url) # make a copy so we don't modify the original if not ref_base_url: if Application.current and Application.current.request: ref_base_url = Application.current.request.url else: ref_base_url = URL() if url.scheme is None: url.scheme = ref_base_url.scheme if url.user is None: url.user = ref_base_url.user if url.user is not None and url.password is None: url.password = ref_base_url.password if url.host is None: url.host = ref_base_url.host if url.port == 0: url.port = ref_base_url.port if is_relative_uri: base_path = ref_base_url.path if not base_path: base_path = '/' elif not base_path.endswith('/'): base_path = base_path + '/' url.path = base_path + url.path return url
def smisk_mvc_metadata(conf): '''This config filter configures the underlying Elixir and SQLAlchemy modules. ''' global log conf = conf.get('smisk.mvc.model') if not conf: return # Aquire required parameter "url" try: url = conf['url'] except KeyError: log.warn('missing required "url" parameter in "smisk.mvc.model" config') return # Parse url into an accessible structure from smisk.core import URL, Application url_st = URL(url) # Make a copy of the default options engine_opts = default_engine_opts.copy() # MySQL if url_st.scheme.lower() == 'mysql': if 'poolclass' not in conf: conf['poolclass'] = MySQLConnectionPool log.debug('MySQL: setting poolclass=%r', conf['poolclass']) if 'pool_size' in conf: log.debug('MySQL: disabling pool_size') del conf['pool_size'] if 'pool_size' in engine_opts: del engine_opts['pool_size'] elif 'pool_recycle' not in conf and 'pool_recycle' not in engine_opts: # In case of user-configured custom pool_class conf['pool_recycle'] = 3600 log.debug('MySQL: setting pool_recycle=%r', conf['pool_recycle']) elif 'poolclass' not in conf: # Others than MySQL should also use a kind of static pool conf['poolclass'] = SingleProcessPool # Demux configuration elixir_opts = {} for k,v in conf.items(): if k.startswith('elixir.'): elixir_opts[k[7:]] = v elif k != 'url': engine_opts[k] = v # Apply Elixir default options if elixir_opts: log.info('applying Elixir default options %r', elixir_opts) # We apply by iteration since options_defaults is not # guaranteed to be a real dict. for k,v in elixir_opts.items(): options_defaults[k] = v # Mask out password, since we're logging this if url_st.password: url_st.password = '******' def rebind_model_metadata(): # Dispose any previous connection if metadata.bind and hasattr(metadata.bind, 'dispose'): log.debug('disposing old connection %r', metadata.bind) try: metadata.bind.dispose() except Exception, e: if e.args and e.args[0] and 'SQLite objects created in a thread' in e.args[0]: log.debug('SQLite connections can not be disposed from other threads'\ ' -- simply leaving it to the GC') else: log.warn('failed to properly dispose the connection', exc_info=True) # Create, configure and bind engine if engine_opts: log.info('binding to %r with options %r', str(url_st), engine_opts) else: log.info('binding to %r', str(url_st)) metadata.bind = sql.create_engine(url, **engine_opts)