Exemplo n.º 1
0
class ScenarioResult(object):
    uuid = related.UUIDField()
    case = related.ChildField(Case, required=None)
    scenario = related.ChildField(Namespace, required=None)
    success = related.BooleanField(default=True)
    step_results = related.SequenceField(StepResult, default=[])
    suite = related.ChildField(Suite, required=False)
Exemplo n.º 2
0
class Company(object):
    name = related.StringField()
    uuid = related.UUIDField()
    email = related.RegexField("[^@]+@[^@]+", required=False)
    is_active = related.BooleanField(required=False)
    url = related.URLField(required=False)
    meta = related.ChildField(dict, required=False)
    nicknames = related.SequenceField(str, required=False)
    temperature = related.FloatField(required=False)
    guess = related.SetField(int, required=False)
    established = related.DateField('%m/%d/%Y', required=False)
    closed = related.DateField(required=False)  # default formatter (%Y-%m-%d)
Exemplo n.º 3
0
class Exam:
    """Represents a writable exam"""
    meta_uuid = related.UUIDField()
    generated_at = related.DateTimeField(default=datetime.now(),
                                         required=False)
    questions = related.SequenceField(ExamQuestion, required=False)
    title = related.StringField('')
    description = related.StringField(required=False)
    was_user_completed = related.BooleanField(False, required=False)
    user_name = related.StringField(required=False)
    completed_at = related.DateTimeField(required=False)

    def save(self, path: str):
        with open(path, "w") as file:
            related.to_yaml(self, file)

    def clear(self):
        """
        Clears this Exam instance from any user-input
        """
        self.was_user_completed = False
        self.user_name = None
        self.completed_at = None
        for question in self.questions:
            for ans in question.answers:
                ans.is_selected = False

    @property
    def max_score(self):
        return sum(q.points for q in self.questions)

    def get_score(self, meta, question_callback: Callable = None) -> int:
        """
        Calculates this Exam's total score.

        Args
            question_callback: called for each graded question with its score
        """
        if meta is None:
            return 0

        score = 0

        for question in self.questions:
            question_meta = meta.find_question(question.id)
            points = question.grade(question_meta)
            if question_callback:
                question_callback(question, points)
            score += points

        return score
Exemplo n.º 4
0
class Case(object):
    scenarios = related.SequenceField(Namespace)
    name = related.StringField(required=False, default=None)
    steps = related.SequenceField(Step, default=[])
    format = related.StringField(default="1.0")
    host = related.StringField(required=False)
    tags = related.SequenceField(str, required=False)
    headers = related.ChildField(Namespace, required=False)
    file_path = related.StringField(default=None)
    is_valid = related.BooleanField(default=True)
    uuid = related.UUIDField()

    @classmethod
    def prep_scenarios(cls, original, dir_path):
        updated = []
        counter = 1

        if isinstance(original, str):
            original = utils.parse_into_rows_of_dicts(original)

        for scenario in original or [{}]:
            if isinstance(scenario, str):
                scenario_file_path = os.path.join(dir_path, scenario)
                scenario = related.from_yaml(open(scenario_file_path),
                                             object_pairs_hook=dict)

            name = scenario.get("__name__") or "Scenario #%s" % counter
            scenario["__name__"] = name
            counter += 1
            updated.append(scenario)

        return updated

    @classmethod
    def loads(cls, content, file_path=None):
        try:
            as_dict = related.from_yaml(content,
                                        file_path=file_path,
                                        object_pairs_hook=dict)

            scenarios = as_dict.get("scenarios", [])
            dir_path = os.path.dirname(file_path)
            as_dict['scenarios'] = cls.prep_scenarios(scenarios, dir_path)

            return related.to_model(Case, as_dict)

        except Exception as e:
            # raise e
            get_logger().error("Failed to Load Case",
                               file_path=file_path,
                               error=str(e))
            return Case(file_path=file_path, is_valid=False, scenarios=[])

    def is_active(self, included, excluded):
        has_steps = len(self.steps) > 0
        is_included = not included or utils.overlap(included, self.tags)
        is_excluded = excluded and utils.overlap(excluded, self.tags)
        return self.is_valid and has_steps and is_included and not is_excluded

    @property
    def dir_path(self):
        return os.path.dirname(self.file_path)
Exemplo n.º 5
0
class DetectorUUID:
    uuid = related.UUIDField()
Exemplo n.º 6
0
class MyChild(object):
    my_int = related.IntegerField(key="int")
    my_float = related.FloatField(key="float")
    my_uuid = related.UUIDField(key="uuid")
Exemplo n.º 7
0
class ProblemSet:
    """Stores all question metadata and defaults"""
    uuid = related.UUIDField(required=False)
    title = related.StringField('')
    questions = related.MappingField(ExamQuestionMeta, 'id', required=False)
    question_defaults = related.ChildField(ExamQuestionMeta,
                                           ExamQuestionMeta.from_defaults(),
                                           required=False)

    def create_question(self, **kwargs) -> ExamQuestionMeta:
        """Creates a new Question from defaults"""
        return ExamQuestionMeta.from_defaults(self.question_defaults.__dict__,
                                              kwargs)

    def insert_question(self, allow_edit: bool, id: str,
                        **kwargs) -> ExamQuestionMeta:
        found_question = self.find_question(id)
        if found_question:
            if not allow_edit:
                raise KeyError("Question with specified `id` already exists")
            sum_dict = combine_dictionaries(found_question.__dict__, kwargs)
            new_question = self.create_question(**sum_dict)
        else:
            new_question = self.create_question(**kwargs)
        self.questions[id] = new_question
        return new_question

    def find_question(self, id: str) -> ExamQuestionMeta:
        """
        Returns the question with specified `id` if it exists; otherwise None
        """
        return self.questions.get(id, None)

    def generate_exam(self,
                      num_questions: int,
                      description: str,
                      title: str = None) -> Exam:
        """
        Creates an Exam instance from randomly selected questions and answers
        Args:
            num_questions: the number of questions to include
            description: exam description shown to user
            title: short exam title
        """
        questions_meta = weighted_random(self.questions.items(),
                                         lambda q: q[1].likelihood,
                                         num_questions)
        questions = [
            ExamQuestion.from_meta(id, meta) for id, meta in questions_meta
        ]
        now = datetime.now()
        return Exam(meta_uuid=self.uuid,
                    generated_at=now,
                    title=title or self.title,
                    questions=questions,
                    description=description)

    def ensure_exam_compatibility(self, exam: Exam) -> None:
        """
        Checks whether the `exam` was created from this problem set.

        Raises
            SchemeError: if the `exam` isn't compatible
        """
        def fail(reason):
            raise SchemeError(
                f"Problem set `{self.title}` does not match the exam `{self.title}` ({reason})"
            )

        if self.uuid != exam.meta_uuid:
            fail('UUID')

        # check for missing questions
        for question in exam.questions:
            if self.find_question(question.id) is None:
                fail(f"missing question: {question.id}")

    def save(self, path: str) -> None:
        """
        Saves this object instance as YAML to the specified path
        """
        self.validate()
        with open(path, "w") as file:
            related.to_yaml(self,
                            file,
                            suppress_empty_values=True,
                            suppress_map_key_values=True)

    def validate(self):
        """Validates object state"""
        for key, question in self.questions.items():
            question.validate()

    @staticmethod
    def from_file(path: str):
        with open(path, "r") as file:
            obj = related.from_yaml(file, ProblemSet)
            obj.validate()
            return obj