def get(self, library_class): matching_libraries = [ i for i in self.libraries_by_name.values() if isinstance(i, library_class) ] if not matching_libraries: raise ProgrammerError( 'No library "%s" found in the config.web.frontend_libraries' % library_class) elif len(matching_libraries) > 1: raise ProgrammerError( 'More than "%s" found in the config.web.frontend_libraries' % library_class) return matching_libraries[0]
def stop_thread(self, join=True): self.running = False if self.httpd_thread and join: self.httpd_thread.join(5) if self.httpd_thread.is_alive(): raise ProgrammerError('Timed out after 5 seconds waiting for httpd serving thread to end') self.httpd_thread = None
def __init__(self, stacked=False, justified=False): super(PillLayout, self).__init__(key='pill', justified=justified) if all([stacked, justified]): raise ProgrammerError( 'Pills must be stacked or justified, but not both') self.stacked = stacked self.justified = justified
def get_widget_class_for(self, task): config = ExecutionContext.get_context().config for widget_class in config.workflowui.task_widgets: if issubclass(widget_class, TaskWidget) and widget_class.displays(task): return widget_class raise ProgrammerError('no Widget found to display %s' % task)
def __init__(self, allowed_options, prefix=None, xs=None, sm=None, md=None, lg=None, xl=None): self.prefix = prefix self.allowed_options = allowed_options all_options = {'xs':xs, 'sm':sm, 'md':md, 'lg':lg, 'xl':xl} self.device_options = {DeviceClass(device_class_name): option_value for (device_class_name, option_value) in all_options.items() if option_value} if not all([i in self.allowed_options for i in self.device_options.values()]): raise ProgrammerError('Illegal option. Allowed options: %s, got: %s' % (self.allowed_options, self.device_options))
def __init__(self, collapse_below_device_class, center_contents=False, fixed_to=None, align_toggle_left=False, collapse_brand_with_content=False, colour_theme=None, bg_scheme=None, text=None): super().__init__(fixed_to=fixed_to, center_contents=center_contents, colour_theme=colour_theme, bg_scheme=bg_scheme) self.collapse_below_device_class = DeviceClass( collapse_below_device_class) self.collapse_brand_with_content = collapse_brand_with_content self.align_toggle_left = align_toggle_left if not self.collapse_below_device_class.one_smaller: raise ProgrammerError( ('There is no device class smaller than %s' % self.collapse_below_device_class) + ' It does not make sense to collapse only ' 'if the viewport is smaller than the smallest device') self.text = text self.collapsing_content = None
def installed_version(self): latest_declared_version = self.get_versions()[-1] installed_version_string = self.distribution.version if str(latest_declared_version.version_number) != '.'.join(installed_version_string.split('.')[:2]): raise ProgrammerError('Installed version %s of %s, does not match the latest declared version %s' % (installed_version_string, self.name, latest_declared_version)) return latest_declared_version
def read(self): with io.open(self.filename, 'rb') as dhtml_file: def strain(name, attrs): if name == 'title': return True if name == 'div' and dict(attrs).get('id', None) in self.ids: return True return False soup = BeautifulSoup(dhtml_file, "lxml", parse_only=SoupStrainer(strain)) parser = html_parser.HTMLParser() self.title = parser.unescape( soup.title.decode_contents()) if soup.title else _('Untitled') for an_id in self.ids: found_elements = soup.find_all(id=an_id) if found_elements: number_of_ids = len(found_elements) if number_of_ids != 1: raise ProgrammerError( 'Expected to find one element with id "%s", but found %s' % (an_id, number_of_ids)) [element] = found_elements self.elements[an_id] = element.decode_contents() else: self.elements[an_id] = '' self.original_encoding = soup.original_encoding
def __init__(self, *column_definitions): super(ColumnLayout, self).__init__() if not all([ isinstance(column_definition, six.string_types + (ColumnOptions, )) for column_definition in column_definitions ]): raise ProgrammerError( 'All column definitions are expected be either a ColumnOptions object of a column name, got %s' % six.text_type(column_definitions)) self.added_column_definitions = [] self.add_slots = False self.add_gutters = True self.alignment = Alignment() self.content_justification = ContentJustification() self.columns = OrderedDict( ) #: A dictionary containing the added columns, keyed by column name. self.column_definitions = OrderedDict() for column_definition in column_definitions: if isinstance(column_definition, six.string_types): name, options = column_definition, ColumnOptions( column_definition) else: name, options = column_definition.name, column_definition self.column_definitions[name] = options
def get_collaborator(self, account): collaborators = self.collaborators.filter_by(account=account) count = collaborators.count() if count == 1: return collaborators.one() if count > 1: raise ProgrammerError('There can be only one Collaborator per account. Here is more than one.') return None
def check_grids_nesting(self): for widget, parents_set in self.parent_widget_pairs(set([])): if isinstance(widget.layout, ColumnLayout): if not any( isinstance(parent.layout, Container) for parent in parents_set): raise ProgrammerError(('%s does not have a parent with Layout of type %s.' % (widget, Container))+\ ' %s has a ColumnLayout, and thus needs to have an anchestor with a Container Layout.' % widget)
def __init__(self, *column_definitions): if not all([ isinstance(column_definition, tuple) for column_definition in column_definitions ]): raise ProgrammerError('All column definitions are expected a tuple of the form (name, %s), got %s' %\ (ResponsiveSize, column_definitions)) self.added_sizes = [] super(ColumnLayout, self).__init__(*column_definitions)
def __init__(self, left=None, right=None): super(ResponsiveFloat, self).__init__() if left and right: raise ProgrammerError( 'Both left= and right= have been given. Specify left or right, not both.' ) self.left = ResponsivePull('left', left) self.right = ResponsivePull('right', right)
def reahl_scope(): try: return ExecutionContext.get_context_id() except NoContextFound: message = 'Database code can normally only be executed by code executed as part of handling a Request.' message += ' Such code is then executed within the context of, for example, a database transaction.' message += ' Looks like you attempted to execute database code from the wrong place, since no such context' message += ' could be found.' raise ProgrammerError(message)
def tear_down_attributes(self): for generator in reversed(self.attribute_generators): try: next(generator) except StopIteration: pass else: name = generator.__qualname__ raise ProgrammerError('%s is yielding more than one element. \'new_\' methods should only yield a single element' % name)
def __init__(self, url, config): self.config = config self.connection_uri = url uri_parts = urllib_parse.urlparse(url) self.user_name = self.unquote(uri_parts.username) self.password = self.unquote(uri_parts.password) self.host = self.unquote(uri_parts.hostname) self.port = uri_parts.port self.database_name = self.unquote(uri_parts.path[1:] if uri_parts.path.startswith('/') else uri_parts.path) if not self.database_name: raise ProgrammerError('Please specify a database name in reahlsystem.connection_uri')
def set_brand(self, brand_html_element): """Sets `brand_html_element` to be used as branding. :param brand_html_element: An :class:`~reahl.web.ui.HTMLElement` to be used as branding. """ if self.brand: raise ProgrammerError('Brand has already been set to: %s' % self.brand) self.contents_container.insert_child(0, brand_html_element) brand_html_element.append_class('navbar-brand') self.brand = brand_html_element
def __init__(self, size, left=False, right=False): super().__init__() self.size = size if left and right: self.side = 'x' elif left: self.side = 'l' elif right: self.side = 'r' else: raise ProgrammerError( 'Left and right are both False: Set at least one')
def set_brand(self, brand_htmlwidget): """Sets `brand_widget` to be used as branding. :param brand_htmlwidget: An :class:`~reahl.web.ui.HTMLWidget` to be used as branding. """ if self.brand: raise ProgrammerError('Brand has already been set to: %s' % self.brand) self.insert_brand_widget(brand_htmlwidget) brand_htmlwidget.append_class('navbar-brand') self.brand = brand_htmlwidget return self.brand
def __init__(self, stacked=False, content_alignment=None, content_justification=None): super().__init__(key='pill', content_alignment=content_alignment, content_justification=content_justification) if all([stacked, content_alignment or content_justification]): raise ProgrammerError( 'Pills must be stacked, aligned or justified, but you cannot give all options together' ) self.stacked = stacked
def create_view(self, relative_path, user_interface, file_path=None): if not user_interface is self: raise ProgrammerError('get_file called on %s with %s as user_interface' % (self, user_interface)) file_url_path = file_path filename = self.filesystem_path(file_url_path) logging.debug('Finding a static file on filesystem %s' % filename) if self.is_dynamic(filename): statics = self.statics(file_url_path) slot_contents = {'main_slot': DJHTMLWidget.factory(statics['div'])} return UrlBoundView(user_interface, file_url_path, statics['title'], slot_contents, cacheable=True) elif self.is_static(filename): return FileView(user_interface, FileOnDisk(filename, file_url_path)) raise CannotCreate()
def __init__(self, key=None, content_alignment=None, content_justification=None): super().__init__() if content_alignment and content_justification: raise ProgrammerError( 'Cannot set content_alignment and content_justfication at the same time' ) self.content_alignment = ContentAlignment(content_alignment) self.content_justification = ContentJustification( content_justification) self.key = key
def schedule(self, phase, scheduling_migration, scheduling_context, to_call, *args, **kwargs): if phase == 'drop_fk': self.current_drop_fk_phase.append( (to_call, scheduling_migration, scheduling_context, args, kwargs)) else: try: self.phases[phase].append((to_call, scheduling_migration, scheduling_context, args, kwargs)) except KeyError as e: raise ProgrammerError('A phase with name<%s> does not exist.' % phase)
def add_toggle(self, target_html_element, text=None): """Adds a link that toggles the display of the given `target_html_element`. :param target_html_element: A :class:`~reahl.web.ui.HTMLElement` :keyword text: Text to be used on the toggle link. """ if not target_html_element.css_id_is_set: raise ProgrammerError( '%s has no css_id set. A toggle is required to have a css_id' % target_html_element) target_html_element.append_class('collapse') toggle = CollapseToggle(self.view, target_html_element, text=text) self.contents_container.add_child(toggle) return toggle
def add_toggle(self, target_html_element, text=None, left_aligned=False): """Adds a link that toggles the display of the given `target_html_element`. :param target_html_element: A :class:`~reahl.web.ui.HTMLElement` :param text: Text to be used on the toggle link. If None, the boostrap navbar-toggler-icon is used :keyword left_aligned: If True, ensure that the toggle is to the far left. """ if not target_html_element.css_id_is_set: raise ProgrammerError('%s has no css_id set. A toggle is required to have a css_id' % target_html_element) target_html_element.append_class('collapse') toggle = CollapseToggle(self.view, target_html_element, text=text) index = 1 if (self.brand and not left_aligned) else 0 self.main_container.insert_child(index, toggle) self.toggle = toggle return toggle
def customise_widget(self): super().customise_widget() if not self.widget.css_id_is_set: raise ProgrammerError('%s has no css_id set. A %s can only be used with a Widget that has a css_id' % (self.widget, self.__class__)) collapsing_content = Div(self.view, css_id='%s_collapsable' % self.widget.css_id) collapsing_content.append_class('navbar-collapse') self.collapsing_content = collapsing_content self.contents_container.add_child(collapsing_content) self.contents_container = collapsing_content self.add_toggle(collapsing_content, text=self.text, left_aligned=self.align_toggle_left) toggle_size = self.collapse_below_device_class.one_smaller self.nav.append_class('navbar-expand-%s' % toggle_size.name)
def __init__(self, fixed_to=None, full=False, center_contents=False, colour_theme=None, bg_scheme=None): super(NavbarLayout, self).__init__() if fixed_to and full: raise ProgrammerError( 'Both fixed_to and full are given. Give fixed_to or full, but not both' ) self.fixed = NavbarFixed(fixed_to) self.full = HTMLAttributeValueOption('navbar-full', full) self.center_contents = center_contents self.colour_theme = ColourTheme(colour_theme) self.bg_scheme = BackgroundScheme(bg_scheme) self.brand = None self.contents_container = None
def __init__(self, collapse_below_device_class, fixed_to=None, full=False, center_contents=False, colour_theme=None, bg_scheme=None, text=None): super(ResponsiveLayout, self).__init__(fixed_to=fixed_to, full=full, center_contents=center_contents, colour_theme=colour_theme, bg_scheme=bg_scheme) self.collapse_below_device_class = DeviceClass( collapse_below_device_class) if not self.collapse_below_device_class.one_smaller: raise ProgrammerError(('There is no device class smaller than %s' % self.collapse_below_device_class)+\ ' It does not make sense to collapse only if the viewport is smaller than the smallest device') self.text = text
def customise_widget(self): super(ResponsiveLayout, self).customise_widget() if not self.widget.css_id_is_set: raise ProgrammerError('%s has no css_id set. A %s can only be used with a Widget that has a css_id' % \ (self.widget, self.__class__)) collapsable = Div(self.view, css_id='%s_collapsable' % self.widget.css_id) collapsable.append_class('collapse') toggle_widget = CollapseToggle( self.view, collapsable, text=self.text, hide_for_size=self.collapse_below_device_class) toggle_size = self.collapse_below_device_class.one_smaller collapsable.append_class('navbar-toggleable-%s' % toggle_size.class_label) self.contents_container.add_child(toggle_widget) self.contents_container.add_child(collapsable) self.contents_container = collapsable
def execute(self, sql, login_username=None, password=None, database_name=None): login_args = {} if not (database_name or self.database_name): raise ProgrammerError('no database name specified') login_args['dbname'] = database_name or self.database_name if self.host: login_args['host'] = self.host if self.port: login_args['port'] = self.port login_args['user'] = login_username or getpass.getuser() if password: login_args['password'] = password with psycopg2.connect(**login_args) as connection: connection.set_isolation_level( psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT) with connection.cursor() as cursor: return cursor.execute(sql)