def requested_depts_ids(self, value): values = set(s for s in listify(value) if s) self.requested_any_dept = 'All' in values if self.requested_any_dept: values.remove('All') from uber.models.department import Department self._set_relation_ids('requested_depts', Department, list(values))
def __init__(self, hostnames, rpc_method, *args, **kwargs): from sideboard.lib import listify self.hostnames, self.method, self.args, self.kwargs = listify( hostnames), rpc_method, args, kwargs self.results, self.websockets, self._client_ids = {}, {}, {} on_startup(self._subscribe) on_shutdown(self._unsubscribe)
def assigned_depts_ids(self, value): values = set(s for s in listify(value) if s) for membership in list(self.dept_memberships): if membership.department_id not in values: # Manually remove dept_memberships to ensure the associated # rows in the dept_membership_dept_role table are deleted. self.dept_memberships.remove(membership) from uber.models.department import Department self._set_relation_ids('assigned_depts', Department, list(values))
def process_bind_param(self, value, dialect): """ Our MultiChoice options may be in one of three forms: a single string, a single integer, or a list of strings. We want to end up with a single comma-separated string. We also want to make sure an object has only unique values in its MultiChoice columns. Therefore, we listify() the object to make sure it's in list form, we convert it to a set to make all the values unique, and we map the values inside it to strings before joining them with commas because the join function can't handle a list of integers. """ return ','.join(map(str, list(set(listify(value))))) if value else ''
def signups_requiring_notification( self, session, from_time, to_time, options=None): """ Returns a dict of AttractionSignups that require notification. The keys of the returned dict are the amount of advanced notice, given in seconds. A key of -1 indicates confirmation notices after a signup. The query generated by this method looks horrific, but is surprisingly efficient. """ advance_checkin = max(0, self.advance_checkin) subqueries = [] for advance_notice in sorted(set([-1] + self.advance_notices)): event_filters = [AttractionEvent.attraction_id == self.id] if advance_notice == -1: notice_ident = cast( AttractionSignup.attraction_event_id, UnicodeText) notice_param = bindparam( 'confirm_notice', advance_notice).label('advance_notice') else: advance_notice = max(0, advance_notice) + advance_checkin notice_delta = timedelta(seconds=advance_notice) event_filters += [ AttractionEvent.start_time >= from_time + notice_delta, AttractionEvent.start_time < to_time + notice_delta] notice_ident = func.concat( AttractionSignup.attraction_event_id, '_{}'.format(advance_notice)) notice_param = bindparam( 'advance_notice_{}'.format(advance_notice), advance_notice).label('advance_notice') subquery = session.query(AttractionSignup, notice_param).filter( AttractionSignup.is_unchecked_in, AttractionSignup.attraction_event_id.in_( session.query(AttractionEvent.id).filter(*event_filters)), not_(exists().where(and_( AttractionNotification.ident == notice_ident, AttractionNotification.attraction_event_id == AttractionSignup.attraction_event_id, AttractionNotification.attendee_id == AttractionSignup.attendee_id)))).with_labels() subqueries.append(subquery) query = subqueries[0].union(*subqueries[1:]) if options: query = query.options(*listify(options)) query.order_by(AttractionSignup.id) return groupify(query, lambda x: x[0], lambda x: x[1])
def requested_depts_ids(self, value): from uber.models.department import DeptMembershipRequest values = set(None if s in ('None', 'All') else s for s in listify(value) if s != '') for membership in list(self.dept_membership_requests): if membership.department_id not in values: self.dept_membership_requests.remove(membership) department_ids = set( str(d.department_id) for d in self.dept_membership_requests) for department_id in values: if department_id not in department_ids: self.dept_membership_requests.append( DeptMembershipRequest(department_id=department_id, attendee_id=self.id))
def ldap_auth(username, password): if not username or not password: return False try: ssl_material = ( config['ldap.cacert'], config['ldap.cert'], config['ldap.key'] ) server_kwargs = {} tls_kwargs = {} if config['ldap.url'].startswith('ldaps') or any(ssl_material): server_kwargs['use_ssl'] = True else: server_kwargs['use_ssl'] = False server_kwargs['host'] = config['ldap.url'] if config['ldap.cacert']: tls_kwargs['ca_certs_file'] = config['ldap.cacert'] # if we specify a CA certs file, assume we want to validate it tls_kwargs['validate'] = ssl.CERT_REQUIRED if tls_kwargs: server_kwargs['tls'] = ldap3.Tls(**tls_kwargs) server = ldap3.Server(**server_kwargs) except: log.error('Error initializing LDAP server', exc_info=True) raise # attempt to bind on each base DN that was configured for basedn in listify(config['ldap.basedn']): dn = '{}={},{}'.format(config['ldap.userattr'], username, basedn) log.debug('attempting to bind with dn {}', dn) try: connection = ldap3.Connection(server, user=dn, password=password) connection.start_tls() is_bound = connection.bind() except: log.warning("Error binding to LDAP server with dn", exc_info=True) raise if is_bound: return True # we couldn't auth on anything return False
def ldap_auth(username, password): if not username or not password: return False try: conn = ldap.initialize(config['ldap.url']) force_start_tls = False if config['ldap.cacert']: ldap.set_option(ldap.OPT_X_TLS_CACERTFILE, config['ldap.cacert']) force_start_tls = True if config['ldap.cert']: ldap.set_option(ldap.OPT_X_TLS_CERTFILE, config['ldap.cert']) force_start_tls = True if config['ldap.key']: ldap.set_option(ldap.OPT_X_TLS_KEYFILE, config['ldap.key']) force_start_tls = True if force_start_tls: conn.start_tls_s() else: conn.set_option(ldap.OPT_X_TLS_DEMAND, config['ldap.start_tls']) except: log.error('Error initializing LDAP connection', exc_info=True) raise for basedn in listify(config['ldap.basedn']): dn = '{}={},{}'.format(config['ldap.userattr'], username, basedn) log.debug('attempting to bind with dn {}', dn) try: conn.simple_bind_s(dn, password) except ldap.INVALID_CREDENTIALS as x: continue except: log.warning("Error binding to LDAP server with dn", exc_info=True) raise else: return True
def assert_read_result(self, expected, query, data=None): expected = listify(expected) actual = Session.crud.read(query, data) assert len(expected) == actual['total'] assert sorted(expected, key=lambda m: m.get('id', m.get('_model'))) \ == sorted(actual['results'], key=lambda m: m.get('id', m.get('_model')))
def extract(self, models, *fields): return [{f: m[f] for f in fields if f in m} for m in listify(models)]
def JSONColumnMixin(column_name, fields, admin_only=False): """ Creates a new mixin class with a JSON column named column_name. The newly created mixin class will have a SQLAlchemy JSON Column, named `column_name`, along with two other attributes column_name_fields and column_name_qualified_fields which describe the fields that the JSON Column is expected to hold. For example:: >>> SocialMediaMixin = JSONColumnMixin('social_media', ['Twitter', 'LinkedIn']) >>> SocialMediaMixin.social_media Column('social_media', JSON(), table=None, nullable=False, default=ColumnDefault({}), server_default=DefaultClause('{}', for_update=False)) >>> SocialMediaMixin._social_media_fields OrderedDict([('twitter', 'Twitter'), ('linked_in', 'LinkedIn')]) >>> SocialMediaMixin._social_media_qualified_fields OrderedDict([('social_media__twitter', 'twitter'), ('social_media__linked_in', 'linked_in')]) Instances of the newly created mixin class have convenience accessors for the attributes defined by `fields`, both directly and using their fully qualified forms:: >>> sm = SocialMediaMixin() >>> sm.twitter = 'https://twitter.com/MAGFest' # Get and set "twitter" directly >>> sm.twitter 'https://twitter.com/MAGFest' >>> sm.social_media__twitter # Get and set qualified "social_media__twitter" 'https://twitter.com/MAGFest' >>> sm.social_media__twitter = '@MAGFest' >>> sm.social_media__twitter '@MAGFest' >>> sm.social_media # Actual column updated appropriately {'linked_in': '', 'twitter': '@MAGFest'} Args: column_name (str): The name of the column. fields (list): A list of field names you expect the column to hold. This can be: - A single string, if you're only expecting the column to hold a single field. - A list of strings, which will be treated as the column labels, and converted from CamelCase to under_score for the fields. - A map of {string: string}, which will be treated as a mapping of field names to field labels. Returns: type: A new mixin class with a JSON column named column_name. """ # noqa: E501 fields_name = '_{}_fields'.format(column_name) qualified_fields_name = '_{}_qualified_fields'.format(column_name) if isinstance(fields, Mapping): fields = OrderedDict([(fieldify(k), v) for k, v in fields.items()]) else: fields = OrderedDict([(fieldify(s), s) for s in listify(fields)]) qualified_fields = OrderedDict([(column_name + '__' + s, s) for s in fields.keys()]) column = Column(column_name, JSON, default={}, server_default='{}') attrs = { column_name: column, fields_name: fields, qualified_fields_name: qualified_fields } _Mixin = type(camel(column_name) + 'Mixin', (object, ), attrs) def _Mixin__init__(self, *args, **kwargs): setattr(self, column_name, {}) for attr in getattr(self.__class__, fields_name).keys(): setattr(self, attr, kwargs.pop(attr, '')) super(_Mixin, self).__init__(*args, **kwargs) _Mixin.__init__ = _Mixin__init__ def _Mixin__declare_last__(cls): setattr(getattr(cls, column_name), 'admin_only', admin_only) column = cls.__table__.columns.get(column_name) setattr(column, 'admin_only', admin_only) _Mixin.__declare_last__ = classmethod(_Mixin__declare_last__) def _Mixin__unqualify(cls, name): if name in getattr(cls, qualified_fields_name): return getattr(cls, qualified_fields_name)[name] else: return name _Mixin.unqualify = classmethod(_Mixin__unqualify) def _Mixin__getattr__(self, name): name = self.unqualify(name) if name in getattr(self.__class__, fields_name): return getattr(self, column_name).get(name, '') else: return super(_Mixin, self).__getattr__(name) _Mixin.__getattr__ = _Mixin__getattr__ def _Mixin__setattr__(self, name, value): name = self.unqualify(name) if name in getattr(self.__class__, fields_name): fields = getattr(self, column_name) if fields.get(name) != value: fields[name] = value super(_Mixin, self).__setattr__(column_name, dict(fields)) else: super(_Mixin, self).__setattr__(name, value) _Mixin.__setattr__ = _Mixin__setattr__ return _Mixin
def assert_read_result(self, expected, query, data=None): expected = listify(expected) actual = Session.crud.read(query, data) self.assertEqual(len(expected), actual['total']) self.assertEqual(sorted(expected, key=lambda m: m.get('id', m.get('_model'))), sorted(actual['results'],key=lambda m: m.get('id', m.get('_model'))))
def banned(self): return listify(self.watch_list or self.watchlist_guess)
def groupify(items, keys, val_key=None): """ Groups a list of items into nested OrderedDicts based on the given keys. `keys` may be a string, a callable, or a list thereof. `val_key` may be `None`, a string, or a callable. Defaults to `None`. Examples:: >>> from json import dumps >>> >>> class Reminder: ... def __init__(self, when, where, what): ... self.when = when ... self.where = where ... self.what = what ... def __repr__(self): ... return 'Reminder({0.when}, {0.where}, {0.what})'.format(self) ... >>> reminders = [ ... Reminder('Fri', 'Home', 'Eat cereal'), ... Reminder('Fri', 'Work', 'Feed Ivan'), ... Reminder('Sat', 'Home', 'Sleep in'), ... Reminder('Sat', 'Home', 'Play Zelda'), ... Reminder('Sun', 'Home', 'Sleep in'), ... Reminder('Sun', 'Work', 'Reset database')] >>> >>> print(dumps(groupify(reminders, None), indent=2, default=repr)) ... [ ... "Reminder(Fri, Home, Eat cereal)", ... "Reminder(Fri, Work, Feed Ivan)", ... "Reminder(Sat, Home, Sleep in)", ... "Reminder(Sat, Home, Play Zelda)", ... "Reminder(Sun, Home, Sleep in)", ... "Reminder(Sun, Work, Reset database)" ... ] >>> >>> print(dumps(groupify(reminders, 'when'), indent=2, default=repr)) ... { ... "Fri": [ ... "Reminder(Fri, Home, Eat cereal)", ... "Reminder(Fri, Work, Feed Ivan)" ... ], ... "Sat": [ ... "Reminder(Sat, Home, Sleep in)", ... "Reminder(Sat, Home, Play Zelda)" ... ], ... "Sun": [ ... "Reminder(Sun, Home, Sleep in)", ... "Reminder(Sun, Work, Reset database)" ... ] ... } >>> >>> print(dumps(groupify(reminders, ['when', 'where']), ... indent=2, default=repr)) ... { ... "Fri": { ... "Home": [ ... "Reminder(Fri, Home, Eat cereal)" ... ], ... "Work": [ ... "Reminder(Fri, Work, Feed Ivan)" ... ] ... }, ... "Sat": { ... "Home": [ ... "Reminder(Sat, Home, Sleep in)", ... "Reminder(Sat, Home, Play Zelda)" ... ] ... }, ... "Sun": { ... "Home": [ ... "Reminder(Sun, Home, Sleep in)" ... ], ... "Work": [ ... "Reminder(Sun, Work, Reset database)" ... ] ... } ... } >>> >>> print(dumps(groupify(reminders, ['when', 'where'], 'what'), ... indent=2)) ... { ... "Fri": { ... "Home": [ ... "Eat cereal" ... ], ... "Work": [ ... "Feed Ivan" ... ] ... }, ... "Sat": { ... "Home": [ ... "Sleep in", ... "Play Zelda" ... ] ... }, ... "Sun": { ... "Home": [ ... "Sleep in" ... ], ... "Work": [ ... "Reset database" ... ] ... } ... } >>> >>> print(dumps(groupify(reminders, ... lambda r: '{0.when} - {0.where}'.format(r), ... 'what'), indent=2)) ... { ... "Fri - Home": [ ... "Eat cereal" ... ], ... "Fri - Work": [ ... "Feed Ivan" ... ], ... "Sat - Home": [ ... "Sleep in", ... "Play Zelda" ... ], ... "Sun - Home": [ ... "Sleep in" ... ], ... "Sun - Work": [ ... "Reset database" ... ] ... } >>> """ if not keys: return items keys = listify(keys) last_key = keys[-1] call_val_key = callable(val_key) groupified = OrderedDict() for item in items: current = groupified for key in keys: attr = key(item) if callable(key) else getattr(item, key) if attr not in current: current[attr] = [] if key is last_key else OrderedDict() current = current[attr] if val_key: value = val_key(item) if call_val_key else getattr(item, val_key) else: value = item current.append(value) return groupified
def __init__(self, hostnames, rpc_method, *args, **kwargs): from sideboard.lib import listify self.hostnames, self.method, self.args, self.kwargs = listify(hostnames), rpc_method, args, kwargs self.results, self.websockets, self._client_ids = {}, {}, {} on_startup(self._subscribe) on_shutdown(self._unsubscribe)