class State(PClass): attrs = pset_field(Attr) props = pset_field(Prop) def __init__( self, attrs: Optional[Iterable[Attr]] = None, props: Optional[Iterable[Prop]] = None, ): self.attrs = s() if attrs is None else PSet(attrs) self.props = s() if props is None else PSet(props) def __or__(self, s: State): return State(self.attrs | s.attrs, self.props | s.props)
class BackendDescription(PClass): """ Represent one kind of storage backend we might be able to use. :ivar name: The human-meaningful name of this storage backend. :ivar needs_reactor: A flag which indicates whether this backend's API factory needs to have a reactor passed to it. :ivar needs_cluster_id: A flag which indicates whether this backend's API factory needs to have the cluster's unique identifier passed to it. :ivar api_factory: An object which can be called with some simple configuration data and which returns the API object implementing this storage backend. :ivar required_config: A set of the dataset configuration keys required to initialize this backend. :type required_config: ``PSet`` of ``unicode`` :ivar deployer_type: A constant from ``DeployerType`` indicating which kind of ``IDeployer`` the API object returned by ``api_factory`` is usable with. """ name = field(type=unicode, mandatory=True) needs_reactor = field(type=bool, mandatory=True) # XXX Eventually everyone will take cluster_id so we will throw this flag # out. needs_cluster_id = field(type=bool, mandatory=True) # Config "dataset" keys required to initialize this backend. required_config = pset_field(unicode) api_factory = field(mandatory=True) deployer_type = field( mandatory=True, invariant=lambda value: (value in DeployerType.iterconstants(), "Unknown deployer_type"), )
class _FlakyAnnotation(PClass): max_runs = field(int, mandatory=True, invariant=lambda x: (x > 0, "must run at least once")) min_passes = field(int, mandatory=True, invariant=lambda x: (x > 0, "must pass at least once")) jira_keys = pset_field(unicode, optional=False) __invariant__ = _flaky_invariants def to_dict(self): return { 'max_runs': self.max_runs, 'min_passes': self.min_passes, 'jira_keys': set(self.jira_keys), }
class _FlakyAnnotation(PClass): max_runs = field(int, mandatory=True, invariant=lambda x: (x > 0, "must run at least once")) min_passes = field(int, mandatory=True, invariant=lambda x: (x > 0, "must pass at least once")) jira_keys = pset_field(unicode, optional=False) __invariant__ = lambda x: ( (x.max_runs >= x.min_passes, "Can't pass more than we run"), (len(x.jira_keys) > 0, "Must provide a jira key"), ) def to_dict(self): return { 'max_runs': self.max_runs, 'min_passes': self.min_passes, 'jira_keys': set(self.jira_keys), }
class Task(PClass): """ A tree of actions with the same task UUID. """ _nodes = pmap_field(TaskLevel, (WrittenAction, WrittenMessage)) _completed = pset_field(TaskLevel) _root_level = TaskLevel(level=[]) def root(self): """ @return: The root L{WrittenAction}. """ return self._nodes[self._root_level] def is_complete(self): """ @return bool: True only if all messages in the task tree have been added to it. """ return self._root_level in self._completed def _insert_action(self, node): """ Add a L{WrittenAction} to the tree. Parent actions will be created as necessary. @param child: A L{WrittenAction} to add to the tree. @return: Updated L{Task}. """ task = self if ( node.end_message and node.start_message and (len(node.children) == node.end_message.task_level.level[-1] - 2)): # Possibly this action is complete, make sure all sub-actions # are complete: completed = True for child in node.children: if ( isinstance(child, WrittenAction) and child.task_level not in self._completed): completed = False break if completed: task = task.transform(["_completed"], lambda s: s.add(node.task_level)) task = task.transform(["_nodes", node.task_level], node) return task._ensure_node_parents(node) def _ensure_node_parents(self, child): """ Ensure the node (WrittenAction/WrittenMessage) is referenced by parent nodes. Parent actions will be created as necessary. @param child: A L{WrittenMessage} or L{WrittenAction} which is being added to the tree. @return: Updated L{Task}. """ task_level = child.task_level if task_level.parent() is None: return self parent = self._nodes.get(task_level.parent()) if parent is None: parent = WrittenAction( task_level=task_level.parent(), task_uuid=child.task_uuid) parent = parent._add_child(child) return self._insert_action(parent) def add(self, message_dict): """ Update the L{Task} with a dictionary containing a serialized Eliot message. @param message_dict: Dictionary whose task UUID matches this one. @return: Updated L{Task}. """ is_action = message_dict.get(ACTION_TYPE_FIELD) is not None written_message = WrittenMessage.from_dict(message_dict) if is_action: action_level = written_message.task_level.parent() action = self._nodes.get(action_level) if action is None: action = WrittenAction( task_level=action_level, task_uuid=message_dict[TASK_UUID_FIELD]) if message_dict[ACTION_STATUS_FIELD] == STARTED_STATUS: # Either newly created MissingAction, or one created by # previously added descendant of the action. action = action._start(written_message) else: action = action._end(written_message) return self._insert_action(action) else: # Special case where there is no action: if written_message.task_level.level == [1]: return self.transform([ "_nodes", self._root_level], written_message, [ "_completed"], lambda s: s.add(self._root_level)) else: return self._ensure_node_parents(written_message)
class Record(PRecord): value = pset_field((Something, int))
class Record(PRecord): value = pset_field(Something) value2 = pset_field(int)
class Record(PRecord): value = pset_field(int, optional=True)
class Record(PRecord): value = pset_field(int)
class Record(PRecord): value = pset_field((int, str))
class RecordContainingContainers(PRecord): map = pmap_field(str, str) vec = pvector_field(str) set = pset_field(str)
class TypedContainerObj(PClass): map = pmap_field(str, str) set = pset_field(str) vec = pvector_field(str)
class Columns(PRecord): all_columns = pvector_field(str) current_set = pset_field(str)
class Record(PRecord): value = pset_field(("record_test.Something", "record_test.Another"))
class Record(PRecord): value = pset_field("record_test.Something")
class Game(PClass): black_positions = pset_field(Position) white_positions = pset_field(Position)
class Record(PRecord): value = pset_field(int, initial=(1, 2))
class Ranker(PClass): _greater_than = pmap_field(str, PSet) _remaining_pairs = pset_field(PSet) _all_items = field(initial=pset()) @classmethod def new(cls, items): remaining = pset({pset(x) for x in combinations(items, 2)}) return cls(_remaining_pairs=remaining) def is_complete(self): return len(self._remaining_pairs) == 0 def add_ranking(self, larger, smaller): """ Decide that 'larger' is greater than 'smaller' """ key = pset([larger, smaller]) slf = self if slf.cmp_items(smaller, larger) > 0: raise ValueError(f"{smaller} is already greater than {larger}") if key not in slf._remaining_pairs: return slf # Set larger as being greater than smaller slf = slf.set(_remaining_pairs=slf._remaining_pairs.remove(key)) if larger not in slf._greater_than: slf = slf.set(_greater_than=slf._greater_than.set(larger, pset())) slf = slf.set( _greater_than=slf._greater_than.set( larger, slf._greater_than[larger].add(smaller)), _all_items=slf._all_items.add(larger).add(smaller), ) # Set larger as being greater than everything which smaller is greater than for item in slf.everying_less_than(larger): slf = slf.add_ranking(larger, item) return slf def sample(self): for item in self._remaining_pairs: return item def everying_less_than(self, item): return self._greater_than[item] def has_item(self, item): return item in self._all_items def sorted_items(self, *args, **kwargs): return self.sorted(self._all_items, *args, **kwargs) def sorted(self, items, *args, **kwargs): kwargs["key"] = self.key_func return sorted(items, *args, **kwargs) @property def key_func(self): return cmp_to_key(self.cmp_items) def cmp_items(self, a, b): if b in self._greater_than.get(a, {}): return 1 if a in self._greater_than.get(b, {}): return -1 return 0