class APAS(Request):

    full_name = 'Aprobación de pasantía'

    GO_TRABAJO_FINAL_MAESTRIA = 'TFM'
    GO_TESIS_MAESTRIA = 'TSM'
    GO_TESIS_DOCTORADO = 'TSD'
    GO_CHOICES = ((GO_TRABAJO_FINAL_MAESTRIA, 'Trabajo Final de Maestría'),
                  (GO_TESIS_MAESTRIA, 'Tesis de Maestría'),
                  (GO_TESIS_DOCTORADO, 'Tesis de Doctorado'))

    date_start = DateField(required=True,
                           display='Fecha de inicio de la pasantía',
                           default=datetime.date.today)
    date_finish = DateField(required=True,
                            display='Fecha de finalización de la pasantía',
                            default=datetime.date.today)
    place = StringField(required=True,
                        display='Lugar: Ciudad, País',
                        default='')
    format_present = BooleanField(
        required=True,
        default=False,
        display='¿Presenta el formato de solicitud de movilidad saliente?')
    institut = StringField(
        required=True,
        display='Institución donde se va a desarrollar la pasantía',
        default='')
    grade_option = StringField(required=True,
                               display='Tipo de tesis/trabajo final',
                               choices=GO_CHOICES,
                               default=GO_TESIS_MAESTRIA)
    internship_period = StringField(
        required=True,
        display='Periodo en el que se va a desarrollar la pasantía',
        choices=Request.PERIOD_CHOICES,
        default=Request.PERIOD_DEFAULT)
    enrolled_thesis = BooleanField(
        required=True,
        default=False,
        display='¿Tiene inscrita la asignatura tesis/trabajo final?')

    regulation_list = []  # List of regulations

    str_cm = [
        'realizar pasantía en la institución {} en {}, como parte del desarrollo de su {}',
        ', desde el {} hasta el {}. El estudiante deberá estar debidamente matriculado'
        + ' en el periodo {}.', 'debido a que'
    ]

    list_analysis = [
        'Perfil de {}', 'El estudiante {}tiene inscrita la asignatura {}.',
        'Estancia de investigación del {} al {}.', 'Lugar: {}.',
        'El estudiante {}presenta el formato de solicitud de movilidad saliente.'
    ]

    def cm(self, docx):
        paragraph = docx.add_paragraph()
        paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY
        paragraph.paragraph_format.space_after = Pt(0)
        self.cm_answer(paragraph)

    def cm_answer(self, paragraph):
        paragraph.add_run(self.str_council_header + ' ')
        # pylint: disable=no-member
        paragraph.add_run(self.get_approval_status_display().upper() +
                          ' ').font.bold = True
        paragraph.add_run(self.str_cm[0].format(
            self.institut, self.place, self.get_grade_option_display()))
        if self.is_affirmative_response_approval_status():
            self.cm_af(paragraph)
        else:
            self.cm_ng(paragraph)

    def pcm(self, docx):
        self.pcm_analysis(docx)
        self.pcm_answer(docx)

    def pcm_answer(self, docx):
        paragraph = docx.add_paragraph()
        paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY
        paragraph.paragraph_format.space_after = Pt(0)
        paragraph.add_run(self.str_answer + ': ').font.bold = True
        paragraph.add_run(self.str_comittee_header + ' ')
        # pylint: disable=no-member
        paragraph.add_run(self.get_advisor_response_display().upper() +
                          ' ').font.bold = True
        paragraph.add_run(self.str_cm[0].format(
            self.institut, self.place, self.get_grade_option_display()))
        if self.is_affirmative_response_approval_status():
            self.cm_af(paragraph)
        else:
            self.cm_ng(paragraph)

    def cm_af(self, paragraph):
        paragraph.add_run(self.str_cm[1].format(
            string_to_date(str(self.date_start)),
            string_to_date(str(self.date_finish)),
            self.internship_period,
        ))

    def cm_ng(self, paragraph):
        paragraph.add_run(' ' + self.str_cm[2] + ' ' + self.council_decision +
                          '.')

    def pcm_analysis(self, docx):
        if self.grade_option in [
                self.GO_TESIS_MAESTRIA, self.GO_TESIS_DOCTORADO
        ]:
            profile = 'investigación'
        else:
            profile = 'profundización'
        final_analysis = []
        final_analysis += [self.list_analysis[0].format(profile)]
        ets = '' if self.enrolled_thesis else 'no '
        # pylint: disable=no-member
        final_analysis += [
            self.list_analysis[1].format(ets, self.get_grade_option_display())
        ]
        final_analysis += [
            self.list_analysis[2].format(string_to_date(str(self.date_start)),
                                         string_to_date(str(self.date_finish)))
        ]
        final_analysis += [self.list_analysis[3].format(self.place)]
        pss = '' if self.format_present else 'no '
        final_analysis += [self.list_analysis[4].format(pss)]
        for extra_a in self.extra_analysis:
            final_analysis += [extra_a]
        add_analysis_paragraph(docx, final_analysis)
Exemple #2
0
class StoryLine(EmbeddedDocument):
    id = StringField(max_length=512, unique=True)
    in_branch = ListField(BooleanField(), default=4*[False])
 class EvilHuman(Human):
     evil = BooleanField(default=True)
     meta = {"abstract": True}
Exemple #4
0
class NetworkModel(Document):
    track_length = IntField(required=True)
    track_time = FloatField(required=True)
    history = DictField(required=False)
    model_filename = StringField(required=False)
    model_file = FileField(required=False)
    hiperparams_opt = BooleanField(default=False)
    keras_model = None

    # Net params define optimal setup. Analysis params is for optimization
    params_training = DictField(required=False)
    analysis_params = {}

    meta = {'allow_inheritance': True}

    def __init__(self, *args, **values):
        super().__init__(*args, **values)
        if self.id is None:
            self.save()
        self.model_filename = ''.join(['Models/', str(self.id)])

    def train_network(self):
        pass

    def evaluate_track_input(self, track):
        pass

    def validate_test_data_accuracy(self, n_axes, normalized=True):
        pass

    def validate_test_data_mse(self, n_axes):
        pass

    def build_model(self):
        pass

    def convert_history_to_db_format(self, history_training):
        for k, v in history_training.history.items():
            for i in range(len(history_training.history[k])):
                history_training.history[k][i] = float(history_training.history[k][i])
        self.history = history_training.history

    def load_model_from_file(self, only_local_files=False):
        load_success = False
        try:
            self.keras_model = load_model(self.model_filename, compile=True)
            load_success = True
        except (ValueError, OSError) as e:
            if not only_local_files:
                try:
                    print("Local model not available, loading from db")
                    self.keras_model = self.build_model()
                    weights = pickle.loads(self.model_file.read())
                    if weights is not None and self.keras_model is not None:
                        self.keras_model.set_weights(weights)
                        load_success = True
                    else:
                        raise TypeError

                except TypeError:
                    print("Weights not available in DB")
        return load_success

    def save_model_file_to_db(self):
        self.model_file.put(pickle.dumps(self.keras_model.get_weights()))

    def update_model_file_to_db(self):
        self.model_file.replace(pickle.dumps(self.keras_model.get_weights()))

    def plot_loss_model(self, train=True, val=True):
        plt.xlabel('Epoch')
        plt.ylabel('Loss')
        if train:
            plt.plot(np.arange(1, len(self.history['loss']) + 1, 1), self.history['loss'], label="Train loss")
        if val:
            plt.plot(np.arange(1, len(self.history['val_loss']) + 1, 1), self.history['val_loss'], label="Val loss")
        plt.legend()
        plt.show()

    def plot_mse_model(self, train=True, val=True):
        plt.xlabel('Epoch')
        plt.ylabel('MSE')
        if train:
            plt.plot(np.arange(1, len(self.history['mse']) + 1, 1), self.history['mse'], label="Train mse")
        if val:
            plt.plot(np.arange(1, len(self.history['val_mse']) + 1, 1), self.history['val_mse'], label="Val mse")
        # plt.legend()
        plt.show()

    def plot_accuracy_model(self, train=True, val=True, categorical=False):
        plt.xlabel('Epoch')
        plt.ylabel('Loss')
        plt.title('Model Accuracy')
        if categorical:
            if train:
                plt.plot(np.arange(1, len(self.history['categorical_accuracy']) + 1, 1),
                         self.history['categorical_accuracy'], label="Train categorical accuracy")
            if val:
                plt.plot(np.arange(1, len(self.history['val_categorical_accuracy']) + 1, 1),
                         self.history['val_categorical_accuracy'], label="Val categorical accuracy")
        else:
            if train:
                plt.plot(np.arange(1, len(self.history['acc']) + 1, 1), self.history['acc'],
                         label="Train accuracy")
            if val:
                plt.plot(np.arange(1, len(self.history['val_acc']) + 1, 1), self.history['val_acc'],
                         label="Val accuracy")

        plt.legend()
        plt.show()

    def is_valid_network_track_time(self, track_time):
        if (self.track_time * 0.85) <= track_time <= (self.track_time * 1.15):
            return True
        else:
            return False
Exemple #5
0
class Job(db.Document):
    created_at = DateTimeField(required=True)
    last_modified_at = DateTimeField(required=True,
                                     default=datetime.datetime.utcnow)
    task_id = StringField(required=True)
    job_id = StringField(required=True)
    executions = ListField(ReferenceField("JobExecution"))
    task = ReferenceField("Task",
                          required=True,
                          reverse_delete_rule=mongoengine.CASCADE)
    image = StringField(required=False)
    command = StringField(required=False)
    request_ip = StringField(required=False)
    metadata = DictField(required=False)
    scheduled = BooleanField(required=True, default=False)

    meta = {
        "ordering": ["-last_modified_at"],
        "indexes":
        ["last_modified_at", "job_id", {
            "fields": ["task_id", "job_id"]
        }],
    }

    def save(self, *args, **kwargs):
        if self.executions is None:
            self.executions = []

        if not self.created_at:
            self.created_at = datetime.datetime.utcnow()
        self.last_modified_at = datetime.datetime.utcnow()

        return super(Job, self).save(*args, **kwargs)

    def create_execution(self, image, command):
        from fastlane.models.job_execution import JobExecution

        ex_id = str(uuid4())
        ex = JobExecution(
            execution_id=ex_id,
            image=image,
            command=command,
            created_at=datetime.datetime.utcnow(),
            task=self.task,
            job=self,
        )
        ex.save()
        self.executions.append(ex)
        self.save()

        return ex

    def get_metadata(self, blacklist_fn):
        if "envs" in self.metadata:
            envs = self.metadata["envs"]
            self.metadata["envs"] = words_redacted(envs, blacklist_fn)

        return self.metadata

    def to_dict(
        self,
        include_log=False,
        include_error=False,
        include_executions=True,
        blacklist_fn=None,
    ):
        if blacklist_fn is None:
            meta = self.metadata
        else:
            meta = self.get_metadata(blacklist_fn)

        res = {
            "createdAt": self.created_at.isoformat(),
            "image": self.image,
            "command": self.command,
            "lastModifiedAt": self.last_modified_at.isoformat(),
            "taskId": self.task.task_id,
            "scheduled": self.scheduled,
            "executionCount": len(self.executions),
            "requestIPAddress": self.request_ip,
            "metadata": meta,
        }

        if include_executions:
            executions = [
                ex.to_dict(include_log, include_error) for ex in list(
                    reversed(
                        sorted(self.executions, key=lambda ex: ex.created_at)))
                [:20]
            ]
            res["executions"] = executions

        return res

    @classmethod
    def get_by_id(cls, task_id, job_id):
        from fastlane.models.task import Task

        if task_id is None or task_id == "" or job_id is None or job_id == "":
            raise RuntimeError(
                "Task ID and Job ID are required and can't be None or empty.")

        task = Task.objects(task_id=task_id).first()
        job = cls.objects(task=task, job_id=job_id).first()

        return job

    def get_execution_by_id(self, execution_id):
        for job_execution in self.executions:
            if job_execution.execution_id == execution_id:
                return job_execution

        return None

    def get_last_execution(self):
        if not self.executions:
            return None

        return self.executions[-1]

    @classmethod
    def get_unfinished_executions(cls, app):
        from fastlane.models.job_execution import JobExecution

        query = {
            "$or": [
                {
                    "status": JobExecution.Status.pulling
                },
                {
                    "status": JobExecution.Status.running
                },
            ]
        }
        executions = JobExecution.objects(__raw__=query)

        execs = []

        for execution in executions:
            enqueued_id = execution.job.metadata.get("enqueued_id")

            if enqueued_id is not None and (
                    app.jobs_queue.is_scheduled(enqueued_id)
                    or app.jobs_queue.is_enqueued(enqueued_id)):
                continue

            execs.append((execution.job, execution))

        return execs

    @classmethod
    def get_unscheduled_jobs(cls, app):
        query = {
            "$or": [
                {
                    "metadata.startIn": {
                        "$exists": True
                    }
                },
                {
                    "metadata.startAt": {
                        "$exists": True
                    }
                },
                {
                    "metadata.cron": {
                        "$exists": True
                    }
                },
            ]
        }
        jobs = Job.objects(__raw__=query)

        unscheduled = []

        for job in jobs:
            if "enqueued_id" not in job.metadata:
                unscheduled.append(job)

                continue

            enqueued_id = job.metadata["enqueued_id"]

            if not app.jobs_queue.is_scheduled(
                    enqueued_id) and not app.jobs_queue.is_enqueued(
                        enqueued_id):
                unscheduled.append(job)

        return list(unscheduled)

    def enqueue(self, app, execution_id, image=None, command=None):
        if image is None:
            image = self.image

        if command is None:
            command = self.command

        if image is None or command is None:
            raise RuntimeError("Can't enqueue job with no image or command.")

        logger = app.logger.bind(
            operation="enqueue_job",
            job_id=self.job_id,
            task_id=self.task.task_id,
            execution_id=execution_id,
            image=image,
            command=command,
        )

        args = [
            self.task.task_id,
            str(self.job_id),
            str(execution_id), image, command
        ]

        logger.info("Job enqueued.")

        return app.jobs_queue.enqueue(Categories.Job, *args)

    def schedule_job(self, app, details):
        logger = app.logger.bind(operation="schedule_job")

        if self.image is None or self.command is None:
            logger.warn("No image or command found in job.")

            return None

        start_at = details.get("startAt", None)
        start_in = details.get("startIn", None)
        cron = details.get("cron", None)

        args = [
            str(self.task.task_id),
            str(self.job_id),
            None,
            self.image,
            self.command,
        ]

        queue_job_id = None

        if start_at is not None:
            logger.debug("Enqueuing job execution in the future...",
                         start_at=start_at)
            enqueued_id = app.jobs_queue.enqueue_at(int(start_at),
                                                    Categories.Job, *args)
            #  future_date = datetime.utcfromtimestamp(int(start_at))
            #  result = scheduler.enqueue_at(future_date, run_job, *args)
            self.metadata["enqueued_id"] = enqueued_id
            queue_job_id = enqueued_id
            self.save()
            logger.info("Job execution enqueued successfully.",
                        start_at=start_at)
        elif start_in is not None:
            #  future_date = datetime.now(tz=timezone.utc) + start_in
            logger.debug("Enqueuing job execution in the future...",
                         start_in=start_in)
            enqueued_id = app.jobs_queue.enqueue_in(start_in, Categories.Job,
                                                    *args)
            #  result = scheduler.enqueue_at(future_date, run_job, *args)
            self.metadata["enqueued_id"] = enqueued_id
            queue_job_id = enqueued_id
            self.save()
            logger.info("Job execution enqueued successfully.",
                        start_in=start_in)
        elif cron is not None:
            logger.debug("Enqueuing job execution using cron...", cron=cron)
            enqueued_id = app.jobs_queue.enqueue_cron(cron, Categories.Job,
                                                      *args)
            self.metadata["enqueued_id"] = enqueued_id
            queue_job_id = enqueued_id
            self.metadata["cron"] = cron
            self.scheduled = True
            self.save()
            logger.info("Job execution enqueued successfully.", cron=cron)

        return queue_job_id
Exemple #6
0
class Playlist(Document):
    title = StringField(unique=True, required=True)
    isPrivate = BooleanField()
    songs = ListField(ReferenceField(Song), reverse_delete_rule=NULLIFY)
Exemple #7
0
class User(Document):
    # The following fields describe the attributes of a user
    email = EmailField(required=True, unique=True)
    password = StringField(default=None,
                           max_length=64,
                           null=False,
                           min_length=6)
    first_name = StringField(required=True, max_length=255)
    last_name = StringField(required=True, max_length=255)
    profile = EmbeddedDocumentField(document_type=UserProfile, default=None)
    admin_profile = EmbeddedDocumentField(document_type=AdminProfile,
                                          default=None)

    # The following fields describe the simulation properties saved to a users
    # Document for later retrieval
    # Note: It is necessary to use `sim_api.schemas.ConfigurationSchema`,
    # `sim_api.schemas.AlloySchema` and
    # `sim_api.schemas.SimulationResultsSchema` to validate these before
    # dumping to the database if we want to ensure validity.
    last_configuration = DictField(default=None)
    last_alloy_store = DictField(default=None)
    last_simulation_results = DictField(default=None)
    last_simulation_invalid_fields = DictField(default=None)

    # Store the number of simulations the user has run
    simulations_count = LongField(default=0)

    # Store alloys for the user
    saved_alloys = EmbeddedDocumentListField(document_type=Alloy)

    # Some rather useful metadata information that's not core to the
    # definition of a user
    active = BooleanField(default=True)
    is_admin = BooleanField(default=False, db_field='admin')
    disable_admin = BooleanField(default=False)
    verified = BooleanField(default=False)
    # Make sure when converting these that it follows ISO8601 format as
    # defined in settings.DATETIME_FMT
    created = DateTimeField(
        default=datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ'), null=False)
    last_updated = DateTimeField(default=None, null=False)
    last_login = DateTimeField()

    ratings = EmbeddedDocumentListField(document_type=Rating)
    login_data = EmbeddedDocumentListField(document_type=LoginData)

    # Define the collection and indexing for this document
    meta = {
        'collection':
        'users',
        'indexes': [
            # This create text indexes for advanced text search
            {
                'fields': ['$first_name', '$last_name', '$email'],
                # For a text index, the weight of an indexed field denotes
                # the significance of the field relative to the other indexed
                # fields in terms of the text search score.
                # 2 times (i.e. 10:1) the impact as a term match in the
                # last_name and email fields
                # 10:9 impact as a term match in the last_name:first_name
                'weights': {
                    'last_name': 4,
                    'first_name': 2,
                    'email': 5
                }
            }
        ]
    }

    def set_password(self, raw_password: str) -> None:
        """
        Helper utility method to save an encrypted password using the
        Bcrypt Flask extension.
        """
        self.password = bcrypt.generate_password_hash(
            password=raw_password,
            rounds=current_app.config.get('BCRYPT_LOG_ROUNDS')).decode()

    def to_dict(self) -> dict:
        """Simple Document.User helper method to get a Python dict back."""
        last_login = None
        last_updated = None
        if self.last_login is not None:
            last_login = self.last_login.isoformat()
        if self.last_updated is not None:
            last_updated = self.last_updated.isoformat()

        # We set a default profile that we always send to the client
        profile = {
            'aim': None,
            'highest_education': None,
            'sci_tech_exp': None,
            'phase_transform_exp': None
        }
        if self.profile is not None:
            profile = self.profile.to_dict()

        user = {
            'email': self.email,
            'first_name': self.first_name,
            'last_name': self.last_name,
            'active': self.active,
            'admin': self.is_admin,
            'verified': self.verified,
            'last_updated': str(last_updated),
            'created': str(self.created.isoformat()),
            'last_login': str(last_login),
            'profile': profile
        }

        if self.admin_profile is not None:
            user['admin_profile'] = self.admin_profile.to_dict()

        return user

    def to_json(self, *args, **kwargs):
        """
        Override the default method to customise the way a JSON format is
        transformed.
        """
        return json.dumps(self.to_dict(), cls=JSONEncoder)

    # MongoEngine allows you to create custom cleaning rules for your documents
    # when calling save(). By providing a custom clean() method you can do
    # any pre validation / data cleaning. This might be useful if you want to
    # ensure a default value based on other document values.
    def clean(self):
        """
        Ensures a multitude of business logic is checked before we save the
        User to the database. These include the following:
          - Password must be set by calling `new_user.set_password(raw_pw)`
          - Every time a User object is saved the `User.last_updated` datetime
            is set to the current `utcnow()` datetime.
          - Update the `User.is_admin` boolean based on other criteria.
          - By default, if there is not `User.ratings` or `User.login_data`
            we make a Python list as the default.
        """
        if self.password is None:
            raise PasswordValidationError()

        if self.last_updated is None:
            self.last_updated = self.created
        else:
            self.last_updated = datetime.utcnow()

        self.is_admin = (not self.disable_admin
                         and self.admin_profile is not None)

        if not self.ratings:
            self.ratings = []

        if not self.login_data:
            self.login_data = []

    # noinspection PyMethodParameters
    @queryset_manager
    def as_dict(cls, queryset) -> list:
        """Adding an additional QuerySet context method to return a list of
        `sim_api.models.Users` Documents instead of a QuerySet.

        Usage:
            users_list = User.as_dict()

        Args:
            queryset: the queryset that must is accepted as part of the Mongo
                      BSON parameter.

        Returns:
            A list with every Users Document object converted to dict.
        """
        return [obj.to_dict() for obj in queryset]

    def __str__(self):
        return self.to_json()
Exemple #8
0
class Coupon(Post):
    code = StringField(unique=True)
    discountType = StringField(choices=['percent', 'dollar'])
    discount = FloatField()
    storeWide = BooleanField(default=False)
    applicableProducts = ListField(ReferenceField('Product'))
    uses = IntField(default=0)
    maxUses = IntField(default=-1)

    @classmethod
    def schema(cls):
        return super().schema() + [{
            'name': 'code',
            'niceName': 'Code',
            'controlType': 'input'
        }, {
            'name':
            'discountType',
            'niceName':
            'Discount Type',
            'controlType':
            'select',
            'options': [{
                'key': 'Percent',
                'value': 'percent'
            }, {
                'key': 'Dollar',
                'value': 'dollar'
            }]
        }, {
            'name': 'discount',
            'niceName': 'Discount',
            'controlType': 'input',
            'type': 'number'
        }, {
            'name': 'storeWide',
            'niceName': 'Store wide',
            'controlType': 'checkbox'
        }, {
            'name': 'applicableProducts',
            'niceName': 'Applicable Products',
            'controlType': 'post-select',
            'type': 'models.Product',
            'multiple': True
        }, {
            'name': 'maxUses',
            'niceName': 'Max Uses',
            'controlType': 'input',
            'type': 'number'
        }]

    def serialize(self):
        return {
            **super().serialize(), 'code':
            self.code,
            'discountType':
            self.discountType,
            'discount':
            self.discount,
            'storeWide':
            self.storeWide,
            'applicableProducts':
            list(map(lambda p: str(p.id), self.applicableProducts)),
            'uses':
            self.uses,
            'maxUses':
            self.maxUses
        }
Exemple #9
0
class HardwareStream(IStream):
    log_level = IntField(default=StreamLogLevel.LOG_LEVEL_INFO, required=True)

    input = EmbeddedDocumentField(InputUrls, default=InputUrls())
    have_video = BooleanField(default=constants.DEFAULT_HAVE_VIDEO,
                              required=True)
    have_audio = BooleanField(default=constants.DEFAULT_HAVE_AUDIO,
                              required=True)
    audio_select = IntField(default=constants.INVALID_AUDIO_SELECT,
                            required=True)
    loop = BooleanField(default=constants.DEFAULT_LOOP, required=True)
    avformat = BooleanField(default=constants.DEFAULT_AVFORMAT, required=True)
    restart_attempts = IntField(default=constants.DEFAULT_RESTART_ATTEMPTS,
                                required=True)
    auto_exit_time = IntField(default=constants.DEFAULT_AUTO_EXIT_TIME,
                              required=True)

    # runtime
    _status = StreamStatus.NEW
    _cpu = 0.0
    _timestamp = 0
    _idle_time = 0
    _rss = 0
    _loop_start_time = 0
    _restarts = 0
    _start_time = 0
    _input_streams = str()
    _output_streams = str()

    def __init__(self, *args, **kwargs):
        super(HardwareStream, self).__init__(*args, **kwargs)

    def get_type(self):
        raise NotImplementedError('subclasses must override get_type()!')

    def reset(self):
        self._status = StreamStatus.NEW
        self._cpu = 0.0
        self._timestamp = 0
        self._idle_time = 0
        self._rss = 0
        self._loop_start_time = 0
        self._restarts = 0
        self._start_time = 0
        self._input_streams = str()
        self._output_streams = str()

    def update_runtime_fields(self, params: dict):
        assert self.get_id() == params[StreamFields.ID]
        assert self.get_type() == params[StreamFields.TYPE]
        self._status = StreamStatus(params[StreamFields.STATUS])
        self._cpu = params[StreamFields.CPU]
        self._timestamp = params[StreamFields.TIMESTAMP]
        self._idle_time = params[StreamFields.IDLE_TIME]
        self._rss = params[StreamFields.RSS]
        self._loop_start_time = params[StreamFields.LOOP_START_TIME]
        self._restarts = params[StreamFields.RESTARTS]
        self._start_time = params[StreamFields.START_TIME]
        self._input_streams = params[StreamFields.INPUT_STREAMS]
        self._output_streams = params[StreamFields.OUTPUT_STREAMS]

    def to_dict(self) -> dict:
        front = super(HardwareStream, self).to_dict()
        front[StreamFields.STATUS] = self._status
        front[StreamFields.CPU] = self._cpu
        front[StreamFields.TIMESTAMP] = self._timestamp
        front[StreamFields.IDLE_TIME] = self._idle_time
        front[StreamFields.RSS] = self._rss
        front[StreamFields.LOOP_START_TIME] = self._loop_start_time
        front[StreamFields.RESTARTS] = self._restarts
        front[StreamFields.START_TIME] = self._start_time
        front[StreamFields.INPUT_STREAMS] = self._input_streams
        front[StreamFields.OUTPUT_STREAMS] = self._output_streams
        # runtime
        work_time = self._timestamp - self._start_time
        quality = 100 - (100 * self._idle_time /
                         work_time) if work_time else 100
        front[StreamFields.QUALITY] = quality
        return front

    def config(self) -> dict:
        conf = super(HardwareStream, self).config()
        conf[ConfigFields.FEEDBACK_DIR_FIELD] = self.generate_feedback_dir()
        conf[ConfigFields.LOG_LEVEL_FIELD] = self.get_log_level()
        conf[ConfigFields.AUTO_EXIT_TIME_FIELD] = self.get_auto_exit_time()
        conf[ConfigFields.LOOP_FIELD] = self.get_loop()
        conf[ConfigFields.AVFORMAT_FIELD] = self.get_avformat()
        conf[ConfigFields.HAVE_VIDEO_FIELD] = self.get_have_video()  # required
        conf[ConfigFields.HAVE_AUDIO_FIELD] = self.get_have_audio()  # required
        conf[ConfigFields.RESTART_ATTEMPTS_FIELD] = self.get_restart_attempts()
        conf[ConfigFields.INPUT_FIELD] = self.input.to_mongo(
        )  # required empty in timeshift_player

        audio_select = self.get_audio_select()
        if audio_select != constants.INVALID_AUDIO_SELECT:
            conf[ConfigFields.AUDIO_SELECT_FIELD] = audio_select
        return conf

    def generate_feedback_dir(self):
        return '{0}/{1}/{2}'.format(self._settings.feedback_directory,
                                    self.get_type(), self.get_id())

    def generate_http_link(self,
                           playlist_name=constants.DEFAULT_HLS_PLAYLIST
                           ) -> OutputUrl:
        oid = OutputUrl.generate_id()
        http_root = self._generate_http_root_dir(oid)
        link = '{0}/{1}'.format(http_root, playlist_name)
        return OutputUrl(oid, self._settings.generate_http_link(link),
                         http_root)

    def generate_vod_link(self,
                          playlist_name=constants.DEFAULT_HLS_PLAYLIST
                          ) -> OutputUrl:
        oid = OutputUrl.generate_id()
        vods_root = self._generate_vods_root_dir(oid)
        link = '{0}/{1}'.format(vods_root, playlist_name)
        return OutputUrl(oid, self._settings.generate_vods_link(link),
                         vods_root)

    def generate_cod_link(self,
                          playlist_name=constants.DEFAULT_HLS_PLAYLIST
                          ) -> OutputUrl:
        oid = OutputUrl.generate_id()
        cods_root = self._generate_cods_root_dir(oid)
        link = '{0}/{1}'.format(cods_root, playlist_name)
        return OutputUrl(oid, self._settings.generate_cods_link(link),
                         cods_root)

    def get_log_level(self):
        return self.log_level

    def get_audio_select(self):
        return self.audio_select

    def get_have_video(self):
        return self.have_video

    def get_have_audio(self):
        return self.have_audio

    def get_loop(self):
        return self.loop

    def get_avformat(self):
        return self.avformat

    def get_restart_attempts(self):
        return self.restart_attempts

    def get_auto_exit_time(self):
        return self.auto_exit_time

    def generate_input_playlist(self, header=True) -> str:
        result = '#EXTM3U\n' if header else ''
        stream_type = self.get_type()
        if stream_type == constants.StreamType.RELAY or \
                stream_type == constants.StreamType.ENCODE or \
                stream_type == constants.StreamType.TIMESHIFT_PLAYER or \
                stream_type == constants.StreamType.VOD_ENCODE or \
                stream_type == constants.StreamType.VOD_RELAY:
            for out in self.input.urls:
                result += '#EXTINF:-1 tvg-id="{0}" tvg-name="{1}" tvg-logo="{2}" group-title="{3}",{4}\n{5}\n'.format(
                    self.tvg_id, self.tvg_name, self.tvg_logo, self.group,
                    self.name, out.uri)

        return result

    @classmethod
    def make_stream(cls, settings):
        stream = cls()
        stream._settings = settings
        stream.input = InputUrls(urls=[InputUrl(id=InputUrl.generate_id())])
        stream.output = OutputUrls(
            urls=[OutputUrl(id=OutputUrl.generate_id())])
        return stream

    # private
    def _generate_http_root_dir(self, oid: int):
        return '{0}/{1}/{2}/{3}'.format(self._settings.hls_directory,
                                        self.get_type(), self.get_id(), oid)

    def _generate_vods_root_dir(self, oid: int):
        return '{0}/{1}/{2}/{3}'.format(self._settings.vods_directory,
                                        self.get_type(), self.get_id(), oid)

    def _generate_cods_root_dir(self, oid: int):
        return '{0}/{1}/{2}/{3}'.format(self._settings.cods_directory,
                                        self.get_type(), self.get_id(), oid)

    def _fixup_http_output_urls(self):
        for idx, val in enumerate(self.output.urls):
            url = val.uri
            if url == constants.DEFAULT_TEST_URL:
                return

            parsed_uri = urlparse(url)
            if parsed_uri.scheme == 'http':
                filename = os.path.basename(parsed_uri.path)
                self.output.urls[idx] = self.generate_http_link(filename)

    def _fixup_vod_output_urls(self):
        for idx, val in enumerate(self.output.urls):
            url = val.uri
            if url == constants.DEFAULT_TEST_URL:
                return

            parsed_uri = urlparse(url)
            if parsed_uri.scheme == 'http':
                filename = os.path.basename(parsed_uri.path)
                self.output.urls[idx] = self.generate_vod_link(filename)

    def _fixup_cod_output_urls(self):
        for idx, val in enumerate(self.output.urls):
            url = val.uri
            if url == constants.DEFAULT_TEST_URL:
                return

            parsed_uri = urlparse(url)
            if parsed_uri.scheme == 'http':
                filename = os.path.basename(parsed_uri.path)
                self.output.urls[idx] = self.generate_cod_link(filename)
Exemple #10
0
class Media(Document):
    owner = LazyReferenceField('User', required=True)
    folder = StringField(required=True)
    filename = StringField(unique_with=('folder', 'private'))
    file = FileField()
    dir = BooleanField()
    container = BooleanField(default=False)
    metadata = DictField()
    processing = BooleanField(default=False)
    percentDone = FloatField()
    private = BooleanField(default=False)
    associatedMedia = ListField(
        LazyReferenceField('Media', reverse_delete_rule=PULL))

    if MongoSettings.DEFAULT_CONNECT_URI != MongoSettings.MEDIA_CONNECT_URI:
        meta = {'db_alias': 'media-db'}

    @classmethod
    def post_save(cls, sender, document: Media, **kwargs):
        message = None
        if not (document.private or document.processing):
            message = {
                'type': 'update',
                'payload': {
                    'folder': document.folder,
                    'created': kwargs['created']
                }
            }
        elif document.processing:
            message = {
                'type': 'processing update',
                'payload': {
                    'id': str(document.id),
                    'percentDone': document.percentDone
                }
            }

        if message:
            # Workaround to allow sending in normal and async methods as mediaBrowserManger.broadcast is async
            try:
                loop = asyncio.get_running_loop()
            except RuntimeError:
                loop = None

            if loop and loop.is_running():
                loop.create_task(mediaBrowserManager.broadcast(message))
            else:
                asyncio.run(mediaBrowserManager.broadcast(message))

    def serialize(self, associatedMedia: Optional[bool] = False):
        out = {
            'id': str(self.id),
            'owner': str(self.owner.id),
            'folder': self.folder,
            'filename': self.filename
        }
        if self.dir and not associatedMedia:
            out['dir'] = self.dir
        if self.container:
            out['container'] = self.container
            size = 0
            for subMedia in self.associatedMedia:
                subMedia = subMedia.fetch()
                if subMedia.file:
                    size += subMedia.file.length
            out['size'] = size
        if self.file:
            out['mimetype'] = self.file.content_type
            out['size'] = self.file.length
        if self.metadata:
            out['metadata'] = self.metadata
        if self.associatedMedia and not associatedMedia:
            out['associatedMedia'] = list(
                map(lambda m: m.fetch().serialize(True), self.associatedMedia))
        if self.processing:
            out['processing'] = self.processing
            out['percentDone'] = self.percentDone
        if self.private:
            out['private'] = self.private
        return out
Exemple #11
0
class Product(Post):
    sku = StringField()
    img = ListField(ReferenceField('Media', reverse_delete_rule=PULL))
    price = DecimalField(precision=2)
    digital = BooleanField(default=False)
    taxable = BooleanField(default=True)

    hasStock = BooleanField(default=False)
    stock = IntField()

    totalReviews = IntField(default=0)
    avgReviewScore = FloatField(default=0)

    def addReview(self, score):
        self.avgReviewScore = ((self.avgReviewScore * self.totalReviews) +
                               int(score)) / (self.totalReviews + 1)
        self.totalReviews = self.totalReviews + 1

    @classmethod
    def schema(cls):
        return super().schema() + [{
            'name': 'sku',
            'niceName': 'SKU',
            'controlType': 'input'
        }, {
            'name': 'img',
            'niceName': 'Images',
            'controlType': 'media-browser',
            'multiple': True
        }, {
            'name': 'price',
            'niceName': 'Price',
            'controlType': 'input',
            'type': 'number'
        }, {
            'name': 'digital',
            'niceName': 'Digital',
            'controlType': 'checkbox'
        }, {
            'name': 'taxable',
            'niceName': 'Taxable',
            'controlType': 'checkbox'
        }, {
            'name': 'hasStock',
            'niceName': 'Has Stock',
            'controlType': 'checkbox'
        }, {
            'name': 'stock',
            'niceName': 'Stock',
            'controlType': 'input',
            'type': 'number',
            'validators': {
                'required': True
            }
        }]

    def serialize(self):
        return {
            **super().serialize(),
            'sku': self.sku,
            'img': list(map(lambda m: str(m.id), self.img)),
            'price': float(self.price) if self.price else None,
            "digital": self.digital,
            "taxable": self.taxable,
            'hasStock': self.hasStock,
            'stock': self.stock,
            'totalReviews': self.totalReviews,
            'avgReviewScore': round(self.avgReviewScore,
                                    1)  # Round to 1 decimal place
        }
Exemple #12
0
class OutputPlateDefinitionModel(EmbeddedDocument):
    plate_id = StringField(min_length=1, max_length=512, required=True)
    meta_data_id = StringField(min_length=1, max_length=512, required=True)
    description = StringField(min_length=1, max_length=512, required=True)
    use_provided_values = BooleanField(required=True)
Exemple #13
0
 class OUser(User):
     repos = ListField(ReferenceField(Repo))
     private = BooleanField(
         default=False)  #The permission access level to OnToology
Exemple #14
0
class FileContentUnit(ContentUnit):
    """
    A content unit representing content that is of type *file*.

    :ivar downloaded: Indicates whether all of the files associated with the
        unit have been downloaded.
    :type downloaded: bool
    """

    downloaded = BooleanField(default=True)

    meta = {
        'abstract': True,
        'indexes': [
            'downloaded'
        ]
    }

    @classmethod
    def pre_save_signal(cls, sender, document, **kwargs):
        """
        The signal that is triggered before a unit is saved.
        Ensures the _storage_path is populated.

        :param sender: sender class
        :type sender: object
        :param document: Document that sent the signal
        :type document: FileContentUnit
        """
        super(FileContentUnit, cls).pre_save_signal(sender, document, **kwargs)
        if not document._storage_path:
            document.set_storage_path()

    def set_storage_path(self, filename=None):
        """
        Set the storage path.
        This is a total hack to support existing single-file units with a
        _storage_path that includes the file name.

        :param filename: An optional filename to appended to the path.
        :rtype filename: str
        """
        path = FileStorage.get_path(self)
        if filename:
            if not os.path.isabs(filename):
                path = os.path.join(path, filename)
            else:
                raise ValueError(_('must be relative path'))
        self._storage_path = path

    def import_content(self, path, location=None):
        """
        Import a content file into platform storage.
        The (optional) *location* may be used to specify a path within the unit
        storage where the content is to be stored.
        For example:
          import_content('/tmp/file') will store 'file' at: _storage_path
          import_content('/tmp/file', 'a/b/c) will store 'file' at: _storage_path/a/b/c

        :param path: The absolute path to the file to be imported.
        :type path: str
        :param location: The (optional) location within the unit storage path
            where the content is to be stored.
        :type location: str

        :raises ImportError: if the unit has not been saved.
        :raises PulpCodedException: PLP0037 if *path* is not an existing file.
        """
        if not self._last_updated:
            raise ImportError("Content unit must be saved before associated content"
                              " files can be imported.")
        if not os.path.isfile(path):
            raise exceptions.PulpCodedException(error_code=error_codes.PLP0037, path=path)
        with FileStorage() as storage:
            storage.put(self, path, location)

    def save_and_import_content(self, path, location=None):
        """
        Saves this unit to the database, then calls safe_import_content.

        :param path: The absolute path to the file to be imported
        :type path: str
        :param location: The (optional) location within the unit storage path
            where the content is to be stored.
        :type location: str
        """
        self.save()
        self.safe_import_content(path, location)

    def safe_import_content(self, path, location=None):
        """
        If import_content raises exception, cleanup and raise the exception

        :param path: The absolute path to the file to be imported
        :type path: str
        :param location: The (optional) location within the unit storage path
            where the content is to be stored.
        :type location: str
        """
        try:
            self.import_content(path, location)
        except:  # noqa
            self.clean_orphans()
            raise

    def clean_orphans(self):
        """
        Exposes the ability to clean up this unit as an orphan.
        """
        orphan_manger = factory.content_orphan_manager()
        orphan_manger.delete_orphan_content_units_by_type(self._content_type_id, self.id)

    def get_symlink_name(self):
        """
        Provides the name that should be used when creating a symlink.
        :return: file name as it appears in a published repository
        :rtype: str
        """
        raise NotImplemented()
Exemple #15
0
class EncodeStream(Stream):
    def __init__(self, *args, **kwargs):
        super(EncodeStream, self).__init__(*args, **kwargs)

    deinterlace = BooleanField(default=constants.DEFAULT_DEINTERLACE, required=True)
    frame_rate = IntField(default=constants.INVALID_FRAME_RATE, required=True)
    volume = FloatField(default=constants.DEFAULT_VOLUME, required=True)
    video_codec = StringField(default=constants.DEFAULT_VIDEO_CODEC, required=True)
    audio_codec = StringField(default=constants.DEFAULT_AUDIO_CODEC, required=True)
    audio_channels_count = IntField(default=constants.INVALID_AUDIO_CHANNELS_COUNT, required=True)
    size = EmbeddedDocumentField(Size, default=Size())
    video_bit_rate = IntField(default=constants.INVALID_VIDEO_BIT_RATE, required=True)
    audio_bit_rate = IntField(default=constants.INVALID_AUDIO_BIT_RATE, required=True)
    logo = EmbeddedDocumentField(Logo, default=Logo())
    aspect_ratio = EmbeddedDocumentField(Rational, default=Rational())

    def get_type(self):
        return constants.StreamType.ENCODE

    def config(self) -> dict:
        conf = super(EncodeStream, self).config()
        conf[DEINTERLACE_FIELD] = self.get_deinterlace()
        frame_rate = self.get_frame_rate()
        if frame_rate != constants.INVALID_FRAME_RATE:
            conf[FRAME_RATE_FIELD] = frame_rate
        conf[VOLUME_FIELD] = self.get_volume()
        conf[VIDEO_CODEC_FIELD] = self.get_video_codec()
        conf[AUDIO_CODEC_FIELD] = self.get_audio_codec()
        audio_channels = self.get_audio_channels_count()
        if audio_channels != constants.INVALID_AUDIO_CHANNELS_COUNT:
            conf[AUDIO_CHANNELS_COUNT_FIELD] = audio_channels

        if self.size.is_valid():
            conf[SIZE_FIELD] = str(self.size)

        vid_rate = self.get_video_bit_rate()
        if vid_rate != constants.INVALID_VIDEO_BIT_RATE:
            conf[VIDEO_BIT_RATE_FIELD] = vid_rate
        audio_rate = self.get_audio_bit_rate()
        if audio_rate != constants.INVALID_AUDIO_BIT_RATE:
            conf[AUDIO_BIT_RATE_FIELD] = self.get_audio_bit_rate()
        if self.logo.is_valid():
            conf[LOGO_FIELD] = self.logo.to_dict()
        if self.aspect_ratio.is_valid():
            conf[ASPCET_RATIO_FIELD] = str(self.aspect_ratio)
        return conf

    def get_deinterlace(self):
        return self.deinterlace

    def get_frame_rate(self):
        return self.frame_rate

    def get_volume(self):
        return self.volume

    def get_video_codec(self):
        return self.video_codec

    def get_audio_codec(self):
        return self.audio_codec

    def get_audio_channels_count(self):
        return self.audio_channels_count

    def get_video_bit_rate(self):
        return self.video_bit_rate

    def get_audio_bit_rate(self):
        return self.audio_bit_rate
Exemple #16
0
class EncodeStream(HardwareStream):
    def __init__(self, *args, **kwargs):
        super(EncodeStream, self).__init__(*args, **kwargs)

    relay_video = BooleanField(default=constants.DEFAULT_RELAY_VIDEO,
                               required=True)
    relay_audio = BooleanField(default=constants.DEFAULT_RELAY_AUDIO,
                               required=True)
    deinterlace = BooleanField(default=constants.DEFAULT_DEINTERLACE,
                               required=True)
    frame_rate = IntField(default=constants.INVALID_FRAME_RATE, required=True)
    volume = FloatField(default=constants.DEFAULT_VOLUME, required=True)
    video_codec = StringField(default=constants.DEFAULT_VIDEO_CODEC,
                              required=True)
    audio_codec = StringField(default=constants.DEFAULT_AUDIO_CODEC,
                              required=True)
    audio_channels_count = IntField(
        default=constants.INVALID_AUDIO_CHANNELS_COUNT, required=True)
    size = EmbeddedDocumentField(Size, default=Size())
    video_bit_rate = IntField(default=constants.INVALID_VIDEO_BIT_RATE,
                              required=True)
    audio_bit_rate = IntField(default=constants.INVALID_AUDIO_BIT_RATE,
                              required=True)
    logo = EmbeddedDocumentField(Logo, default=Logo())
    aspect_ratio = EmbeddedDocumentField(Rational, default=Rational())

    def get_type(self):
        return constants.StreamType.ENCODE

    def get_relay_video(self):
        return self.relay_video

    def get_relay_audio(self):
        return self.relay_audio

    def config(self) -> dict:
        conf = super(EncodeStream, self).config()
        conf[ConfigFields.RELAY_VIDEO_FIELD] = self.get_relay_video()
        conf[ConfigFields.RELAY_AUDIO_FIELD] = self.get_relay_audio()
        conf[ConfigFields.DEINTERLACE_FIELD] = self.get_deinterlace()
        frame_rate = self.get_frame_rate()
        if frame_rate != constants.INVALID_FRAME_RATE:
            conf[ConfigFields.FRAME_RATE_FIELD] = frame_rate
        conf[ConfigFields.VOLUME_FIELD] = self.get_volume()
        conf[ConfigFields.VIDEO_CODEC_FIELD] = self.get_video_codec()
        conf[ConfigFields.AUDIO_CODEC_FIELD] = self.get_audio_codec()
        audio_channels = self.get_audio_channels_count()
        if audio_channels != constants.INVALID_AUDIO_CHANNELS_COUNT:
            conf[ConfigFields.AUDIO_CHANNELS_COUNT_FIELD] = audio_channels

        if self.size.is_valid():
            conf[ConfigFields.SIZE_FIELD] = str(self.size)

        vid_rate = self.get_video_bit_rate()
        if vid_rate != constants.INVALID_VIDEO_BIT_RATE:
            conf[ConfigFields.VIDEO_BIT_RATE_FIELD] = vid_rate
        audio_rate = self.get_audio_bit_rate()
        if audio_rate != constants.INVALID_AUDIO_BIT_RATE:
            conf[ConfigFields.AUDIO_BIT_RATE_FIELD] = self.get_audio_bit_rate()
        if self.logo.is_valid():
            conf[ConfigFields.LOGO_FIELD] = self.logo.to_dict()
        if self.aspect_ratio.is_valid():
            conf[ConfigFields.ASPCET_RATIO_FIELD] = str(self.aspect_ratio)
        return conf

    def get_deinterlace(self):
        return self.deinterlace

    def get_frame_rate(self):
        return self.frame_rate

    def get_volume(self):
        return self.volume

    def get_video_codec(self):
        return self.video_codec

    def get_audio_codec(self):
        return self.audio_codec

    def get_audio_channels_count(self):
        return self.audio_channels_count

    def get_video_bit_rate(self):
        return self.video_bit_rate

    def get_audio_bit_rate(self):
        return self.audio_bit_rate

    def fixup_output_urls(self):
        return self._fixup_http_output_urls()

    @classmethod
    def make_stream(cls, settings):
        stream = cls()
        stream._settings = settings
        stream.input = InputUrls(urls=[InputUrl(id=InputUrl.generate_id())])
        stream.output = OutputUrls(
            urls=[OutputUrl(id=OutputUrl.generate_id())])
        return stream
Exemple #17
0
class Stream(EmbeddedDocument):
    meta = {'allow_inheritance': True, 'auto_create_index': True}

    def __init__(self, *args, **kwargs):
        super(Stream, self).__init__(*args, **kwargs)

    id = ObjectIdField(required=True, default=ObjectId,
                       unique=True, primary_key=True)
    name = StringField(default=DEFAULT_STREAM_NAME, max_length=MAX_STREAM_NAME_LENGTH,
                       min_length=MIN_STREAM_NAME_LENGTH, required=True)
    created_date = DateTimeField(default=datetime.now)  # for inner use
    log_level = IntField(default=constants.StreamLogLevel.LOG_LEVEL_INFO, required=True)

    input = EmbeddedDocumentField(Urls, default=Urls())
    output = EmbeddedDocumentField(Urls, default=Urls())
    have_video = BooleanField(default=constants.DEFAULT_HAVE_VIDEO, required=True)
    have_audio = BooleanField(default=constants.DEFAULT_HAVE_AUDIO, required=True)
    audio_select = IntField(default=constants.INVALID_AUDIO_SELECT, required=True)
    loop = BooleanField(default=constants.DEFAULT_LOOP, required=True)
    restart_attempts = IntField(default=constants.DEFAULT_RESTART_ATTEMPTS, required=True)
    auto_exit_time = IntField(default=constants.DEFAULT_AUTO_EXIT_TIME, required=True)

    # runtime
    _status = constants.StreamStatus.NEW
    _cpu = 0.0
    _timestamp = 0
    _rss = 0
    _loop_start_time = 0
    _restarts = 0
    _start_time = 0
    _input_streams = str()
    _output_streams = str()
    _feedback_dir = str()

    def set_feedback_dir(self, feedback_dir):
        self._feedback_dir = feedback_dir

    def reset(self):
        self._status = constants.StreamStatus.NEW
        self._cpu = 0.0
        self._timestamp = 0
        self._rss = 0
        self._loop_start_time = 0
        self._restarts = 0
        self._start_time = 0
        self._input_streams = str()
        self._output_streams = str()

    def update_runtime_fields(self, params: dict):
        assert self.get_id() == params[StreamFields.ID]
        assert self.get_type() == params[StreamFields.TYPE]
        self._status = constants.StreamStatus(params[StreamFields.STATUS])
        self._cpu = params[StreamFields.CPU]
        self._timestamp = params[StreamFields.TIMESTAMP]
        self._rss = params[StreamFields.RSS]
        self._loop_start_time = params[StreamFields.LOOP_START_TIME]
        self._restarts = params[StreamFields.RESTARTS]
        self._start_time = params[StreamFields.START_TIME]
        self._input_streams = params[StreamFields.INPUT_STREAMS]
        self._output_streams = params[StreamFields.OUTPUT_STREAMS]

    def to_front(self) -> dict:
        return {StreamFields.NAME: self.name, StreamFields.ID: self.get_id(), StreamFields.TYPE: self.get_type(),
                StreamFields.STATUS: self._status, StreamFields.CPU: self._cpu, StreamFields.TIMESTAMP: self._timestamp,
                StreamFields.RSS: self._rss, StreamFields.LOOP_START_TIME: self._loop_start_time,
                StreamFields.RESTARTS: self._restarts, StreamFields.START_TIME: self._start_time,
                StreamFields.INPUT_STREAMS: self._input_streams, StreamFields.OUTPUT_STREAMS: self._output_streams}

    def config(self) -> dict:
        conf = {
            ID_FIELD: self.get_id(),  # required
            TYPE_FIELD: self.get_type(),  # required
            FEEDBACK_DIR_FIELD: self.generate_feedback_dir(),  # required
            LOG_LEVEL_FIELD: self.get_log_level(),
            AUTO_EXIT_TIME_FIELD: self.get_auto_exit_time(),
            LOOP_FIELD: self.get_loop(),
            HAVE_VIDEO_FIELD: self.get_have_video(),  # required
            HAVE_AUDIO_FIELD: self.get_have_audio(),  # required
            RESTART_ATTEMPTS_FIELD: self.get_restart_attempts(),
            INPUT_FIELD: self.input.to_mongo(),  # required empty in timeshift_player
            OUTPUT_FIELD: self.output.to_mongo()  # required empty in timeshift_record
        }

        audio_select = self.get_audio_select()
        if audio_select != constants.INVALID_AUDIO_SELECT:
            conf[AUDIO_SELECT_FIELD] = audio_select
        return conf

    def generate_feedback_dir(self):
        return '{0}/{1}/{2}'.format(self._feedback_dir, self.get_type(), self.get_id())

    def get_log_level(self):
        return self.log_level

    def get_audio_select(self):
        return self.audio_select

    def get_have_video(self):
        return self.have_video

    def get_have_audio(self):
        return self.have_audio

    def get_id(self):
        return str(self.id)

    def get_type(self):
        raise NotImplementedError('subclasses must override get_type()!')

    def get_loop(self):
        return self.loop

    def get_restart_attempts(self):
        return self.restart_attempts

    def get_auto_exit_time(self):
        return self.auto_exit_time
Exemple #18
0
class Paper(Document, OParlDocument):
    type = 'https://schema.oparl.org/1.0/Paper'
    body = ReferenceField('Body', dbref=False, deref_location=False)
    name = StringField(fulltext=True)
    reference = StringField(fulltext=True)
    date = DateTimeField(datetime_format='date')
    paperType = StringField()
    relatedPaper = ListField(ReferenceField('Paper',
                                            dbref=False,
                                            deref_location=False),
                             default=[])
    superordinatedPaper = ListField(ReferenceField('Paper',
                                                   dbref=False,
                                                   deref_location=False),
                                    default=[])
    subordinatedPaper = ListField(ReferenceField('Paper',
                                                 dbref=False,
                                                 deref_location=False),
                                  default=[])
    mainFile = ReferenceField('File', dbref=False, deref_location=True)
    auxiliaryFile = ListField(ReferenceField('File',
                                             dbref=False,
                                             deref_location=True),
                              default=[])
    location = ListField(ReferenceField('Location',
                                        dbref=False,
                                        deref_location=False),
                         default=[])
    originatorPerson = ListField(ReferenceField('Person',
                                                dbref=False,
                                                deref_location=True),
                                 default=[])
    underDirectionOf = ListField(ReferenceField('Organization',
                                                dbref=False,
                                                deref_location=True),
                                 default=[])
    originatorOrganization = ListField(ReferenceField('Organization',
                                                      dbref=False,
                                                      deref_location=True),
                                       default=[])
    consultation = ListField(ReferenceField('Consultation',
                                            dbref=False,
                                            deref_location=True),
                             default=[])
    license = StringField()
    keyword = ListField(StringField(fulltext=True), default=[])
    created = DateTimeField(datetime_format='datetime', required=True)
    modified = DateTimeField(datetime_format='datetime', required=True)
    web = StringField()
    deleted = BooleanField()

    # Politik bei Uns Felder
    originalId = StringField(vendor_attribute=True)
    legacy = BooleanField(vendor_attribute=True)
    mirrorId = StringField(vendor_attribute=True)
    georeferenceStatus = StringField(vendor_attribute=True)
    georeferenceGenerated = DateTimeField(datetime_format='datetime',
                                          vendor_attribute=True)
    keywordUsergenerated = ListField(ReferenceField('KeywordUsergenerated'),
                                     vendor_attribute=True)
    locationOrigin = ListField(ReferenceField('LocationOrigin'),
                               vendor_attribute=True)

    # Felder zur Verarbeitung
    _object_db_name = 'paper'
    _attribute = 'paper'

    def __init__(self, *args, **kwargs):
        super(Document, self).__init__(*args, **kwargs)

    def __repr__(self):
        return '<Paper %r>' % self.name
Exemple #19
0
class Configuration(EmbeddedDocument):
    is_valid = BooleanField(default=False, required=True, null=False)
    method = StringField(null=False,
                         required=True,
                         choices=('Li98', 'Kirkaldy83'))
    grain_size = FloatField(null=False, required=True, validation=not_negative)
    nucleation_start = FloatField(null=False,
                                  required=True,
                                  validation=within_percentage_bounds)
    nucleation_finish = FloatField(null=False,
                                   required=True,
                                   validation=within_percentage_bounds)
    auto_calculate_ms = BooleanField(default=True, null=False, required=True)
    auto_calculate_bs = BooleanField(default=True, null=False, required=True)
    auto_calculate_ae = BooleanField(default=True, null=False, required=True)
    ms_temp = FloatField(default=0.0,
                         null=False,
                         required=True,
                         validation=not_negative)
    ms_rate_param = FloatField(default=0.0,
                               null=False,
                               required=True,
                               validation=not_negative)
    bs_temp = FloatField(default=0.0,
                         null=False,
                         required=True,
                         validation=not_negative)
    ae1_temp = FloatField(default=0.0,
                          null=False,
                          required=True,
                          validation=not_negative)
    ae3_temp = FloatField(default=0.0,
                          null=False,
                          required=True,
                          validation=not_negative)
    start_temp = FloatField(default=900,
                            null=False,
                            required=True,
                            validation=not_negative)
    cct_cooling_rate = FloatField(default=10,
                                  null=False,
                                  required=True,
                                  validation=not_negative)

    def to_dict(self) -> dict:
        """
        Simple EmbeddedDocument.Configuration helper method to get a Python dict
        """
        return {
            'is_valid': self.is_valid,
            'method': self.method,
            'grain_size': self.grain_size,
            'nucleation_start': self.nucleation_start,
            'nucleation_finish': self.nucleation_finish,
            'auto_calculate_ms': self.auto_calculate_ms,
            'auto_calculate_bs': self.auto_calculate_bs,
            'auto_calculate_ae': self.auto_calculate_ae,
            'ms_temp': self.ms_temp,
            'ms_rate_param': self.ms_rate_param,
            'bs_temp': self.bs_temp,
            'ae1_temp': self.ae1_temp,
            'ae3_temp': self.ae3_temp,
            'start_temp': self.start_temp,
            'cct_cooling_rate': self.cct_cooling_rate
        }

    # noinspection PyMethodParameters
    @queryset_manager
    def as_dict(cls, queryset) -> list:
        """Adding an additional QuerySet context method to return a list of
        `sim_api.models.Configuration` Documents instead of a QuerySet.

        Usage:
            config_list = Configuration.as_dict()

        Args:
            queryset: the queryset that must is accepted as part of the Mongo
                      BSON parameter.

        Returns:
            A list with every Configuration Document object converted to dict.
        """
        return [obj.to_dict() for obj in queryset]

    def __str__(self):
        return self.to_json()
Exemple #20
0
class Preferences(EmbeddedDocument):
    display_weeshes = BooleanField(default=True)
    display_events = BooleanField(default=True)
    search_distance = IntField(default=50)
    selected_network = StringField(default='PUBLIC')
    background_picture = ImageField()
class REINPRE(Request):
    RL_ANSWER_RENOV_MATRICULA = 'RM'
    RL_ANSWER_PAPA = 'PA'
    RL_ANSWER_CUPO_CREDITOS = 'CC'
    RL_ANSWER_SANCION = 'SA'
    RL_ANSWER_OTRO = 'OT'
    RL_ANSWER_CHOICES = ((
        RL_ANSWER_RENOV_MATRICULA,
        'No cumplir con los requisitos exigidos para la' +
        ' renovación de la matrícula, en los plazos señalados por la Universidad.'
    ), (
        RL_ANSWER_PAPA,
        'Presentar un Promedio Aritmético Ponderado Acumulado menor que tres punto cero (3.0).'
    ), (
        RL_ANSWER_CUPO_CREDITOS,
        'No disponer de un cupo de créditos suficiente para inscribir las asignaturas'
        + ' del plan de estudios pendientes de aprobación.'
    ), (RL_ANSWER_SANCION,
        'Recibir sanción disciplinaria de expulsión o suspensión impuesta de acuerdo'
        + ' con las normas vigentes.'), (RL_ANSWER_OTRO, 'Otro.'))

    full_name = 'Reingreso Pregrado'

    regulation_list = ['008|2008|CSU', '239|2009|VAC', '012|2014|VAC']

    reing_period = StringField(required=True,
                               display='Periodo de reingreso',
                               choices=Request.PERIOD_CHOICES,
                               default=Request.PERIOD_DEFAULT)
    loss_period = StringField(
        required=True,
        display='Periodo de perdida de calidad de estudiante',
        choices=Request.PERIOD_CHOICES,
        default=Request.PERIOD_DEFAULT)
    first_reing = BooleanField(required=True,
                               display='Primer reingreso',
                               default=True)
    admission_period = StringField(required=True,
                                   display='Periodo de admisión',
                                   choices=Request.PERIOD_CHOICES,
                                   default=Request.PERIOD_DEFAULT)
    periods_since = IntField(
        required=True,
        display='periodos desde pérdida de calidad de estudiante',
        default=0)
    papa = FloatField(required=True, display='PAPA', default=0.0)
    reason_of_loss = StringField(choices=RL_ANSWER_CHOICES,
                                 default=RL_ANSWER_OTRO,
                                 display='Razón pérdida calidad de estudiante')
    credits_minus_remaining = IntField(
        required=True,
        display='Cupo de créditos menos créditos pendientes',
        default=0)
    credits_remaining = IntField(required=True,
                                 display='Créditos restantes',
                                 default=0)
    credits_english = IntField(required=True,
                               display='Créditos inglés',
                               default=0)
    credits_add = IntField(
        required=True,
        display='Créditos requeridos para inscribir asignaturas',
        default=0)

    min_grade_12c = StringField(
        required=True,
        display='Promedio semestral mínimo requerido para mantener la ' +
        'calidad de estudiante con 12 créditos inscritos: ',
        default='')
    min_grade_15c = StringField(
        required=True,
        display='Promedio semestral mínimo requerido para mantener la ' +
        'calidad de estudiante con 15 créditos inscritos: ',
        default='')
    min_grade_18c = StringField(
        required=True,
        display='Promedio semestral mínimo requerido para mantener la ' +
        'calidad de estudiante con 18 créditos inscritos: ',
        default='')
    min_grade_21c = StringField(
        required=True,
        display='Promedio semestral mínimo requerido para mantener la ' +
        'calidad de estudiante con 21 créditos inscritos: ',
        default='')

    # Exiged credits
    exi_fund_m = IntField(
        required=True,
        display='Créditos de fundamentación obligatorios exigidos',
        default=0)
    exi_fund_o = IntField(
        required=True,
        display='Créditos de fundamentación optativos exigidos',
        default=0)
    exi_disc_m = IntField(
        required=True,
        display='Créditos disciplinares obligatorios exigidos',
        default=0)
    exi_disc_o = IntField(required=True,
                          display='Créditos disciplinares optativos exigidos',
                          default=0)
    exi_free = IntField(required=True,
                        display='Créditos de libre elección exigidos',
                        default=0)

    # Approved credits
    app_fund_m = IntField(
        required=True,
        display='Créditos de fundamentación obligatorios aprobados',
        default=0)
    app_fund_o = IntField(
        required=True,
        display='Créditos de fundamentación optativos aprobados',
        default=0)
    app_disc_m = IntField(
        required=True,
        display='Créditos disciplinares obligatorios aprobados',
        default=0)
    app_disc_o = IntField(required=True,
                          display='Créditos disciplinares optativos aprobados',
                          default=0)
    app_free = IntField(required=True,
                        display='Créditos de libre elección aprobados',
                        default=0)

    # Remaining credits
    rem_fund_m = IntField(
        required=True,
        display='Créditos de fundamentación obligatorios restantes',
        default=0)
    rem_fund_o = IntField(
        required=True,
        display='Créditos de fundamentación optativos restantes',
        default=0)
    rem_disc_m = IntField(
        required=True,
        display='Créditos disciplinares obligatorios restantes',
        default=0)
    rem_disc_o = IntField(required=True,
                          display='Créditos disciplinares optativos restantes',
                          default=0)
    rem_free = IntField(required=True,
                        display='Créditos de libre elección restantes',
                        default=0)

    comitee_act = StringField(required=True,
                              display='Número de acta de comité',
                              default='00')

    comitee_date = DateField(required=True,
                             display='Fecha de reunión del comité',
                             default=datetime.date.today)

    # Pre-cm variables
    request_in_date = BooleanField(display='Solicitud a tiempo', default=True)
    credits_granted = IntField(display='Créditos otorgados', default=0)

    str_pcm_pre = [
        # Used in pcm and cm:
        'reingreso por única vez a partir del periodo académico ',
        'Si el estudiante no renueva su matrícula en el semestre de reingreso, el acto'
        + ' académico expedido por el Consejo de Facultad queda sin efecto.',
        '1. Datos Generales:',
        '2. Información Académica:',
        '3. Resumen general de créditos del plan de estudios:',
        '*Sin incluir los créditos correspondientes al cumplimiento del requisito de'
        + ' suficiencia en idioma.',

        # Used only in pcm:
        'El estudiante ',
        ' tiene pendiente por aprobar ',
        ' créditos del plan de estudios de ',
        ' y ',
        ' créditos del requisito de nivelación',
        ' - inglés, con un cupo disponible para inscripción de ',
        ' créditos.',
        'El parágrafo del artículo 11 del ',
        'Superior Universitario establece: ',
        '"Los créditos adicionales que como resultado del ' +
        'proceso de clasificación en la admisión deba aprobar ' +
        'un estudiante de pregrado, se sumarán por única vez al "' +
        'cupo adicional de créditos para inscripción"',
        ', por lo tanto solo es viable otorgar ',
        ' crédito(s) para la inscripción de asignaturas pendientes del plan de estudios de ',

        # Extra credits (optional):
        'y otorga ',
        ' crédito(s) adicional(es) para culminar su plan de estudios. '
    ]

    str_analysis = [
        '{}a tenido otro reingreso después de 2009-01 (Artículo 46, {}). ' +
        'Universitas y SIA: Revisado.',
        'Si perdió calidad antes de 2009-01: Equivalencias incluyendo las asignaturas '
        +
        'perdidas. Comité Asesor asigna créditos a las que no tengan equivalencias '
        +
        '(Artículo 3, {}). Universitas y SIA: Pérdida de calidad de estudiante al '
        + 'finalizar {} por {}',
        '{}iene PAPA superior o igual a 2.7 (literal 3b – Artículo 3, {}; Artículo 46, '
        + '{}). SIA: PAPA de {}.',
        '{}ispone de un cupo suficiente de créditos: Cupo adicional de 10 créditos a lo sumo '
        +
        '(parágrafo 1 Artículo 46, {}). SIA: {} creditos. En caso de otorgarle un cupo adicional '
        +
        'de créditos, éste no podrá ser mayor que el requerido para inscribir las asignaturas '
        + 'pendientes del plan de estudios. (Artículo 6, {}).',
        'La solicitud {}se hace en fechas de calendario de sede.'
    ]

    str_pcm_pre_acadinfo = [
        'Periodo para el cual fue admitido en este plan de estudios',
        '¿Se trata de un primer reingreso?',
        'Si la respuesta es NO, el Comité Asesor no debe recomendar al Consejo '
        + 'de Facultad el reingreso',
        'Es caso de ser primer reingreso en ¿qué periodo académico perdió la '
        + 'calidad de estudiante?',
        'Al momento de presentar la solicitud ¿cuántos periodos académicos (incluido'
        +
        ' el periodo académico en que presentó la solicitud) han transcurridos a partir'
        + ' del periodo académico en que registró su última matrícula?',
        'En caso que la respuesta sea mayor de 6 periodos académicos no se debe '
        + 'recomendar el reingreso',
        'P.A.P.A.',
        'Causa de la pérdida de la calidad de estudiante',
        'Estudio de créditos',
        'Cupo de créditos menos créditos pendientes',
        'Créditos pendientes por ser aprobados del plan de estudios',
        'Créditos pendientes por ser aprobados de nivelación – Inglés',
        '¿Cuántos créditos adicionales requiere para inscribir asignaturas?',
        # Optional: Grade needed with N credits to keep student condition.
        'Al finalizar el semestre de reingreso para mantener la calidad de estudiante,'
        + ' deberá obtener un promedio semestral mínimo de:',
        'Si inscribe 12 Créditos',
        'Si inscribe 15 Créditos',
        'Si inscribe 18 Créditos',
        'Si inscribe 21 Créditos'
    ]

    str_out_date = [
        'reingreso por única vez a partir del periodo académico {}, porque el estudiante '
        +
        'presentó la solicitud fuera de las fechas establecidas en el Calendario Académico '
        + 'de la Sede Bogotá.'
    ]

    def rein_general_data_table(self, docx):
        # pylint: disable=no-member
        general_data = [
            ['Estudiante', self.student_name], ['DNI', self.student_dni],
            ['Plan de estudios',
             self.get_academic_program_display()],
            ['Código del plan de estudios', self.academic_program],
            ['Fecha de la solicitud',
             string_to_date(str(self.date))]
        ]

        case = 'REINGRESO'

        paragraph = docx.add_paragraph()
        paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY
        paragraph.paragraph_format.space_after = Pt(0)
        bullet = paragraph.add_run(self.str_pcm_pre[2])
        bullet.font.bold = True
        bullet.font.size = Pt(8)

        table_general_data(general_data, case, docx)

    def rein_academic_info(self, docx):
        paragraph = docx.add_paragraph()
        paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY
        paragraph.paragraph_format.space_after = Pt(0)
        bullet = paragraph.add_run(self.str_pcm_pre[3])
        bullet.font.bold = True
        bullet.font.size = Pt(8)

        table = docx.add_table(rows=13, cols=3)
        table.style = 'Table Grid'
        table.style.font.size = Pt(8)
        table.alignment = WD_ALIGN_PARAGRAPH.CENTER
        for cell in table.columns[0].cells:
            cell.width = 400000
        for cell in table.columns[1].cells:
            cell.width = 3200000
        for cell in table.columns[2].cells:
            cell.width = 1600000
        table.columns[0].width = 400000
        table.columns[1].width = 3200000
        table.columns[2].width = 1600000
        table.cell(0, 0).merge(table.cell(0, 1)).paragraphs[0].add_run(
            self.str_pcm_pre_acadinfo[0])
        table.cell(0, 2).paragraphs[0].add_run(self.admission_period)
        table.cell(0, 2).paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
        table.cell(1, 0).merge(table.cell(1, 1)).paragraphs[0].add_run(
            self.str_pcm_pre_acadinfo[1])

        if self.first_reing:
            table.cell(1, 2).paragraphs[0].add_run('Sí')
        else:
            table.cell(1, 2).paragraphs[0].add_run('No')

        table.cell(1, 2).paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
        table.cell(2, 0).merge(table.cell(2, 2)).paragraphs[0].add_run(
            self.str_pcm_pre_acadinfo[2])
        table.cell(3, 0).merge(table.cell(3, 1)).paragraphs[0].add_run(
            self.str_pcm_pre_acadinfo[3])
        table.cell(3, 2).paragraphs[0].add_run(self.loss_period)
        table.cell(3, 2).vertical_alignment = WD_ALIGN_VERTICAL.CENTER
        table.cell(3, 2).paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
        table.cell(4, 0).merge(table.cell(4, 1)).paragraphs[0].add_run(
            self.str_pcm_pre_acadinfo[4])
        table.cell(4, 2).paragraphs[0].add_run(str(self.periods_since))
        table.cell(4, 2).vertical_alignment = WD_ALIGN_VERTICAL.CENTER
        table.cell(4, 2).paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
        table.cell(5, 0).merge(table.cell(5, 2)).paragraphs[0].add_run(
            self.str_pcm_pre_acadinfo[5])
        table.cell(6, 0).merge(table.cell(6, 1)).paragraphs[0].add_run(
            self.str_pcm_pre_acadinfo[6])
        table.cell(6, 2).paragraphs[0].add_run(str(self.papa))
        table.cell(6, 2).paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
        table.cell(7, 0).merge(table.cell(7, 1)).paragraphs[0].add_run(
            self.str_pcm_pre_acadinfo[7])
        table.cell(7, 0).merge(table.cell(
            7, 1)).vertical_alignment = WD_ALIGN_VERTICAL.CENTER
        table.cell(7, 2).paragraphs[0].add_run(
            # pylint: disable=no-member
            self.get_reason_of_loss_display())
        table.cell(7, 2).paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
        table.cell(8, 0).merge(table.cell(8, 2)).paragraphs[0].add_run(
            self.str_pcm_pre_acadinfo[8]).font.bold = True
        table.cell(9, 0).paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
        table.cell(9, 0).paragraphs[0].add_run('1').font.bold = True
        table.cell(10, 0).paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
        table.cell(10, 0).paragraphs[0].add_run('2').font.bold = True
        table.cell(11, 0).paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
        table.cell(11, 0).paragraphs[0].add_run('3').font.bold = True
        table.cell(12, 0).paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
        table.cell(12, 0).paragraphs[0].add_run('4').font.bold = True
        table.cell(9, 1).paragraphs[0].add_run(self.str_pcm_pre_acadinfo[9])
        table.cell(10, 1).paragraphs[0].add_run(self.str_pcm_pre_acadinfo[10])
        table.cell(11, 1).paragraphs[0].add_run(self.str_pcm_pre_acadinfo[11])
        table.cell(12, 1).paragraphs[0].add_run(self.str_pcm_pre_acadinfo[12])
        table.cell(9,
                   2).paragraphs[0].add_run(str(self.credits_minus_remaining))
        table.cell(9, 2).paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
        table.cell(10, 2).paragraphs[0].add_run(str(self.credits_remaining))
        table.cell(10, 2).paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
        table.cell(11, 2).paragraphs[0].add_run(str(self.credits_english))
        table.cell(11, 2).paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
        table.cell(12, 2).paragraphs[0].add_run(str(self.credits_add))
        table.cell(12, 2).paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER

        # Optional: Grade needed with N credits to keep student condition.
        if self.reason_of_loss == self.RL_ANSWER_CUPO_CREDITOS:
            table = docx.add_table(rows=5, cols=2)
            for col in table.columns:
                for cell in col.cells:
                    cell.paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
            table.style = 'Table Grid'
            table.style.font.size = Pt(8)
            table.alignment = WD_ALIGN_PARAGRAPH.CENTER
            for cell in table.columns[0].cells:
                cell.width = 3100000
            for cell in table.columns[1].cells:
                cell.width = 2100000
            table.columns[0].width = 3100000
            table.columns[1].width = 2100000
            table.cell(0, 0).merge(table.cell(
                0, 1)).paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.LEFT
            table.cell(0, 0).merge(table.cell(0, 1)).paragraphs[0].add_run(
                self.str_pcm_pre_acadinfo[13])
            table.cell(1,
                       0).paragraphs[0].add_run(self.str_pcm_pre_acadinfo[14])
            table.cell(2,
                       0).paragraphs[0].add_run(self.str_pcm_pre_acadinfo[15])
            table.cell(3,
                       0).paragraphs[0].add_run(self.str_pcm_pre_acadinfo[16])
            table.cell(4,
                       0).paragraphs[0].add_run(self.str_pcm_pre_acadinfo[17])
            table.cell(1, 1).paragraphs[0].add_run(str(self.min_grade_12c))
            table.cell(2, 1).paragraphs[0].add_run(str(self.min_grade_15c))
            table.cell(3, 1).paragraphs[0].add_run(str(self.min_grade_18c))
            table.cell(4, 1).paragraphs[0].add_run(str(self.min_grade_21c))

    def rein_credits_summary(self, docx):
        paragraph = docx.add_paragraph()
        paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY
        paragraph.paragraph_format.space_after = Pt(0)
        bullet = paragraph.add_run(self.str_pcm_pre[4])
        bullet.font.bold = True
        bullet.font.size = Pt(8)

        credits_data = [[
            self.exi_fund_m, self.exi_fund_o, self.exi_disc_m, self.exi_disc_o,
            self.exi_free
        ],
                        [
                            self.app_fund_m, self.app_fund_o, self.app_disc_m,
                            self.app_disc_o, self.app_free
                        ],
                        [
                            self.rem_fund_m, self.rem_fund_o, self.rem_disc_m,
                            self.rem_disc_o, self.rem_free
                        ]]
        case = 'REINGRESO'
        table_credits_summary(docx, credits_data, case)

        paragraph = docx.add_paragraph()
        paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY
        paragraph.paragraph_format.space_after = Pt(0)
        bullet = paragraph.add_run(self.str_pcm_pre[5])
        bullet.font.size = Pt(8)

    def rein_recommends(self, docx):
        details = []
        details.append(
            # pylint: disable=no-member
            self.get_academic_program_display())

        # Migrate to case_utils?
        year = str(self.comitee_date)[0:4]
        month = str(self.comitee_date)[5:7]
        day = str(self.comitee_date)[8:10]
        details.append(day + '-' + month + '-' + year)
        details.append(self.comitee_act)
        details.append(str(self.comitee_date)[0:4])
        if self.advisor_response == self.ARCR_APROBAR:
            details.append(True)
        else:
            details.append(False)
        table_recommend(docx, details)

    def extra_credits(self, paragraph):
        paragraph.add_run(self.str_pcm_pre[18] + str(self.credits_granted) +
                          self.str_pcm_pre[19])

    def get_analysis(self):
        analysis = []
        modifier = 'No h' if self.first_reing else 'H'
        analysis.append(self.str_analysis[0].format(
            modifier, self.regulations['008|2008|CSU'][0]))
        analysis.append(self.str_analysis[1].format(
            self.regulations['239|2009|VAC'][0],
            # pylint: disable=no-member
            self.loss_period,
            self.get_reason_of_loss_display()))
        modifier = 'T' if self.papa >= 2.7 else 'No t'
        analysis.append(self.str_analysis[2].format(
            modifier, self.regulations['239|2009|VAC'][0],
            self.regulations['008|2008|CSU'][0], self.papa))
        modifier = 'D' if self.credits_remaining > 0 else 'No d'
        analysis.append(self.str_analysis[3].format(
            modifier, self.regulations['008|2008|CSU'][0],
            self.credits_remaining, self.regulations['012|2014|VAC'][0]))
        modifier = '' if self.request_in_date else 'no '
        analysis.append(self.str_analysis[4].format(modifier))
        return analysis + self.extra_analysis

    def pcm(self, docx):
        add_analysis_paragraph(docx, self.get_analysis())
        paragraph = docx.add_paragraph()
        paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY
        paragraph.paragraph_format.space_after = Pt(0)
        self.pcm_answer(paragraph)
        #if self.request_in_date: To ommit tables when the request isn't in time
        self.cm_pcm_paragraph(docx)
        self.rein_general_data_table(docx)
        self.rein_academic_info(docx)
        self.rein_credits_summary(docx)
        self.rein_recommends(docx)

    def cm(self, docx):
        paragraph = docx.add_paragraph()
        paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY
        paragraph.paragraph_format.space_after = Pt(0)
        #if self.request_in_date: To ommit tables when the request isn't in time
        self.cm_answer(paragraph)
        self.rein_general_data_table(docx)
        self.rein_academic_info(docx)
        self.rein_credits_summary(docx)
        self.rein_recommends(docx)

    def pcm_answer(self, paragraph):
        paragraph.add_run(self.str_answer + ':\n').font.bold = True
        paragraph.add_run(self.str_comittee_header + ' ')
        paragraph.add_run(
            # pylint: disable=no-member
            self.get_approval_status_display().upper() + ' ').font.bold = True
        if not self.request_in_date:
            self.out_of_date_answer(paragraph)
        else:
            aff = self.is_affirmative_response_advisor_response()
            self.standard_answer(paragraph, aff)

    def cm_pcm_paragraph(self, docx):
        if not self.request_in_date:
            return  # Skip when it's out of date
        para = docx.add_paragraph()
        para.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY
        para.paragraph_format.space_after = Pt(0)
        para.add_run(self.str_pcm_pre[6] + self.student_name +
                     self.str_pcm_pre[7] + str(self.credits_remaining))
        para.add_run(self.str_pcm_pre[8] +
                     # pylint: disable=no-member
                     self.get_academic_program_display())
        para.add_run(self.str_pcm_pre[9] + str(self.credits_english) +
                     self.str_pcm_pre[10])
        para.add_run(self.str_pcm_pre[11])
        para.add_run(str(self.credits_remaining +
                         self.credits_minus_remaining))
        para.add_run(self.str_pcm_pre[12])
        para = docx.add_paragraph()
        para.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY
        para.paragraph_format.space_after = Pt(0)
        para.add_run(self.str_pcm_pre[13] +
                     self.regulations['008|2008|CSU'][0])
        para.add_run(self.str_pcm_pre[14])
        para.add_run(self.str_pcm_pre[15]).font.italic = True
        para.add_run(self.str_pcm_pre[16] + str(self.credits_granted))
        para.add_run(self.str_pcm_pre[17])
        para.add_run(
            # pylint: disable=no-member
            self.get_academic_program_display() + '.')

    def cm_answer(self, paragraph):
        paragraph.add_run(self.str_council_header + ' ')
        paragraph.add_run(
            # pylint: disable=no-member
            self.get_approval_status_display().upper() + ' ').font.bold = True
        aff = self.is_affirmative_response_approval_status()
        self.standard_answer(paragraph, aff)

    def standard_answer(self, paragraph, affirmative):

        paragraph.add_run(self.str_pcm_pre[0])
        paragraph.add_run(self.academic_period + ' ')

        if self.credits_granted > 0:
            # Y otorga n créditos adicionales:
            self.extra_credits(paragraph)

        if affirmative:
            paragraph.add_run(self.str_pcm_pre[1])
        else:
            paragraph.add_run(self.council_decision + '.')

        paragraph.add_run('({}).'.format(self.regulations['012|2014|VAC'][0] +
                                         "; Artículo 46, " +
                                         self.regulations['008|2008|CSU'][0]))

    def out_of_date_answer(self, paragraph):
        paragraph.add_run(self.str_out_date[0].format(self.reing_period))
Exemple #22
0
class TEPR(Request):

    full_name = 'Tránsito entre programas'

    origin_program = StringField(min_length=4,
                                 max_length=4,
                                 choices=Request.PLAN_CHOICES,
                                 required=True,
                                 display='Programa Académico origen',
                                 default=Request.PI_ELECTRICA)
    academic_period_transit = StringField(max_length=10,
                                          required=True,
                                          display='Periodo de tránsito',
                                          choices=Request.PERIOD_CHOICES,
                                          default=Request.PERIOD_DEFAULT)
    available_places = BooleanField(display='Hay cupos en el plan de estudios',
                                    default=False)
    languaje = BooleanField(
        display='Cumple requisito de idioma en el plan destino', default=True)
    on_time = BooleanField(display='Cumple fechas establecidas', default=True)

    regulation_list = ['035|2014|VAC', '002|2011|CFA',
                       '241|2009|VAC']  # List of regulations

    str_cm = [
        'tránsito del programa {} ({}) al programa {} ({}), a partir del periodo académico {}',
        'debido a que {}.'
    ]

    str_pcm = [
        'En el programa hay {}cupos para tránsito.',
        'Viene del programa {} ({}).',
        'El estudiante {}cumple con la suficiencia de idioma exigida.',
        'La solicitud {}se hace luego de completar el plan de estudios y antes del grado (a menos'
        +
        ' que no se haya abierto convocatorio durante el periodo)(Parágrafo 2, {}).'
    ]

    def cm(self, docx):
        paragraph = docx.add_paragraph()
        paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY
        paragraph.add_run(self.str_council_header + ' ')
        self.cm_answer(paragraph)

    def cm_answer(self, paragraph):
        paragraph.add_run(
            # pylint: disable=no-member
            self.get_approval_status_display().upper() + ' ').font.bold = True
        paragraph.add_run(self.str_cm[0].format(
            # pylint: disable=no-member
            self.get_origin_program_display(),
            self.origin_program,
            self.get_academic_program_display(),
            self.academic_program,
            self.academic_period_transit) + ', ')
        paragraph.add_run(self.str_cm[1].format(self.council_decision))

    def pcm(self, docx):
        self.pcm_analysis(docx)
        paragraph = docx.add_paragraph()
        paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY
        paragraph.paragraph_format.space_after = Pt(0)
        paragraph.add_run(self.str_answer + ': ').bold = True
        paragraph = docx.add_paragraph()
        paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY
        paragraph.add_run(self.str_comittee_header + ' ')
        self.pcm_answer(paragraph)

    def pcm_analysis(self, docx):
        analysis_list = []
        analysis_list += [
            self.str_pcm[0].format('' if self.available_places else 'no ')
        ]
        analysis_list += [
            self.str_pcm[1].format(
                # pylint: disable=no-member
                self.get_origin_program_display(),
                self.origin_program,
            )
        ]
        analysis_list += [
            self.str_pcm[2].format('' if self.languaje else 'no ')
        ]
        analysis_list += [
            self.str_pcm[3].format(
                '' if self.on_time else 'no ',
                Request.regulations[self.regulation_list[2]][0])
        ]
        analysis_list += self.extra_analysis
        add_analysis_paragraph(docx, analysis_list)

    def pcm_answer(self, paragraph):
        paragraph.add_run(
            # pylint: disable=no-member
            self.get_approval_status_display().upper() + ' ').font.bold = True
        paragraph.add_run(self.str_cm[0].format(
            # pylint: disable=no-member
            self.get_origin_program_display(),
            self.origin_program,
            self.get_academic_program_display(),
            self.academic_program,
            self.academic_period_transit) + ', ')
        paragraph.add_run(self.str_cm[1].format(self.council_decision))

    def resource_analysis(self, docx):
        last_paragraph = docx.paragraphs[-1]
        self.pcm_answer(last_paragraph)

    def resource_pre_answer(self, docx):
        last_paragraph = docx.paragraphs[-1]
        self.pcm_answer(last_paragraph)

    def resource_answer(self, docx):
        last_paragraph = docx.paragraphs[-1]
        self.cm_answer(last_paragraph)
Exemple #23
0
class Request(DynamicDocument):

    meta = {'allow_inheritance': True}

    full_name = 'Petición sin tipo'

    decision_makers = (
        'Consejo de Facultad',
        'Comité Asesor',
        'Director de Tesis',
        'Comité de Matricula',
        'Consejo de Sede',
        'Consejo Superior Universitario',
    )
    decision_maker = decision_makers[0]

    # Request is in cm, pcm (or not)
    in_cm = True
    in_pcm = True

    # AS Approval Status
    AS_APLAZA = 'AL'
    AS_APRUEBA = 'AP'
    AS_EN_TRAMITE = 'ET'
    AS_EN_ESPERA = 'EE'
    AS_NO_APRUEBA = 'NA'
    AS_SE_INHIBE = 'SI'
    AS_CONSEJO_RECOMIENDA = 'FR'
    AS_CONSEJO_NO_RECOMIENDA = 'FN'
    AS_ANULADA = 'AN'
    AS_RENUNCIA = 'RN'
    AS_CHOICES = (
        (AS_APLAZA, 'Aplaza'),
        (AS_APRUEBA, 'Aprueba'),
        (AS_EN_TRAMITE, 'En trámite'),
        (AS_EN_ESPERA, 'En espera'),
        (AS_NO_APRUEBA, 'No Aprueba'),
        (AS_SE_INHIBE, 'Se Inhibe'),
        (AS_CONSEJO_RECOMIENDA, 'Consejo Recomienda'),
        (AS_CONSEJO_NO_RECOMIENDA, 'Consejo No Recomienda'),
        (AS_ANULADA, 'Anular'),
        (AS_RENUNCIA, 'Desistir'),
    )
    # ARCR Advisor Response - Committee Recommends
    ARCR_APROBAR = 'CAP'
    ARCR_NO_APROBAR = 'CNA'
    ARCR_RECOMENDAR = 'CRR'
    ARCR_NO_RECOMENDAR = 'CRN'
    ARCR_EN_ESPERA = 'CEE'
    ARCR_CHOICES = (
        (ARCR_APROBAR, 'Aprobar'),
        (ARCR_NO_APROBAR, 'No Aprobar'),
        (ARCR_RECOMENDAR, 'Recomendar'),
        (ARCR_NO_RECOMENDAR, 'No recomendar'),
        (ARCR_EN_ESPERA, 'En espera'),
    )

    DNI_TYPE_CEDULA_DE_CIUDADANIA = 'CC'
    DNI_TYPE_PASAPORTE = 'PS'
    DNI_TYPE_TARJETA_DE_IDENTIDAD = 'TI'
    DNI_TYPE_CEDULA_DE_EXTRANJERIA = 'CE'
    DNI_TYPE_OTRO = 'OT'
    DNI_TYPE_CHOICES = (
        (DNI_TYPE_OTRO, 'Otro'),
        (DNI_TYPE_PASAPORTE, 'Pasaporte'),
        (DNI_TYPE_CEDULA_DE_EXTRANJERIA, 'Cédula de extranjería'),
        (DNI_TYPE_CEDULA_DE_CIUDADANIA, 'Cédula de Ciudadanía colombiana'),
        (DNI_TYPE_TARJETA_DE_IDENTIDAD, 'Tarjeta de Identidad colombiana'),
    )
    # P Plan
    # I Ingenieria
    # E Especializacion
    # M Maestria
    # D Doctorado
    # BAP Bogota Asignaturas de Posgrado
    PI_CIVIL = '2542'
    PI_QUIMICA = '2549'
    PI_MECANICA = '2547'
    PI_AGRICOLA = '2541'
    PI_ELECTRICA = '2544'
    PI_INDUSTRIAL = '2546'
    PI_MECATRONICA = '2548'
    PI_ELECTRONICA = '2545'
    PM_BIOINFORMATICA = '2882'
    PE_GEOTECNIA = '2217'
    PE_TRANSPORTE = '2285'
    PE_ESTRUCTURAS = '2886'
    PMI_INDUSTRIAL = '2708'
    PMI_GEOTECNIA = '2700'
    PMI_TRANSPORTE = '2706'
    PMI_ESTRUCTURAS = '2699'
    PI_DE_SISTEMAS_Y_COMPUTACION = '2879'
    PE_RECURSOS_HIDRAULICOS = '2278'
    PE_GOBIERNO_ELECTRONICO = '2896'
    PEI_ELECTRICA = '2113'
    PE_CALIDAD_DE_LA_ENERGIA = '2064'
    PDI_CIVIL = '2887'
    PMI_TELECOMUNICACIONES = '2707'
    PE_AUTOMATIZACION_INDUSTRIAL = '2687'
    PMI_QUIMICA = '2704'
    PDI_QUIMICA = '2686'
    PMI_MECANICA = '2709'
    PMI_MATERIALES_Y_PROCESOS = '2710'
    PMI_AGRICOLA = '2701'
    PMI_RECURSOS_HIDRAULICOS = '2705'
    PMI_AMBIENTAL = '2562'
    PDI_ELECTRICA = '2685'
    PMI_ELECTRICA = '2703'
    PDI_SISTEMAS_Y_COMPUTACION = '2684'
    PE_ILUMINACION_PUBLICA_Y_PRIVADA = '2691'
    PMI_ELECTRONICA = '2865'
    PMI_AUTOMATIZACION_INDUSTRIAL = '2698'
    PDI_INDUSTRIA_Y_ORGANIZACIONES = '2838'
    PE_TRANSITO_DISEÑO_Y_SEGURIDAD_VIAL = '2696'
    PDI_CIENCIA_Y_TECNOLOGIA_DE_MATERIALES = '2682'
    PDI_MECANICA_Y_MECATRONICA = '2839'
    PMI_DE_SISTEMAS_Y_COMPUTACION = '2702'
    PDI_ESTUDIOS_AMBIENTALES = '2979'
    PMI_ELECTRICA_CONVENIO_SEDE_MANIZALES = '2794'
    PMI_DE_SISTEMAS_Y_COMPUTACION_CONV_UPC = '2856'
    PMI_DE_SISTEMAS_Y_COMPUTACION_CONV_UNILLANOS = '2928'
    BAP_ARTES = 'BAPA'
    BAP_CIENCIAS = 'BAPC'
    BAP_DERECHO = 'BAPD'
    BAP_ECONOMIA = 'BAPE'
    BAP_AGRONOMIA = 'BAPG'
    BAP_HUMANAS = 'BAPH'
    BAP_INGENIERIA = 'BAPI'
    BAP_MEDICINA = 'BAPM'
    BAP_ENFERMERIA = 'BAPN'
    BAP_ODONTOLOGIA = 'BAPO'
    PLAN_CHOICES = (
        (PI_CIVIL, 'Ingeniería Civil'),
        (PI_QUIMICA, 'Ingeniería Química'),
        (PI_MECANICA, 'Ingeniería Mecánica'),
        (PI_AGRICOLA, 'Ingeniería Agrícola'),
        (PI_ELECTRICA, 'Ingeniería Eléctrica'),
        (PI_INDUSTRIAL, 'Ingeniería Industrial'),
        (PI_MECATRONICA, 'Ingeniería Mecatrónica'),
        (PI_ELECTRONICA, 'Ingeniería Electrónica'),
        (PM_BIOINFORMATICA, 'Maestría en Bioinformática'),
        (PE_GEOTECNIA, 'Especialización en Geotecnia'),
        (PE_TRANSPORTE, 'Especialización en Transporte'),
        (PE_ESTRUCTURAS, 'Especialización en Estructuras'),
        (PMI_INDUSTRIAL, 'Maestría en Ingeniería Industrial'),
        (PMI_GEOTECNIA, 'Maestría en Ingeniería - Geotecnia'),
        (PMI_TRANSPORTE, 'Maestría en Ingeniería - Transporte'),
        (PMI_ESTRUCTURAS, 'Maestría en Ingeniería - Estructuras'),
        (PI_DE_SISTEMAS_Y_COMPUTACION, 'Ingeniería de Sistemas y Computación'),
        (PE_RECURSOS_HIDRAULICOS, 'Especialización en Recursos Hidráulicos'),
        (PE_GOBIERNO_ELECTRONICO, 'Especialización en Gobierno Electrónico'),
        (PEI_ELECTRICA, 'Especialización en Ingeniería Eléctrica'),
        (PE_CALIDAD_DE_LA_ENERGIA, 'Especialización en Calidad de la Energía'),
        (PDI_CIVIL, 'Doctorado en Ingeniería - Ingeniería Civil'),
        (PMI_TELECOMUNICACIONES,
         'Maestría en Ingeniería - Telecomunicaciones'),
        (PE_AUTOMATIZACION_INDUSTRIAL,
         'Especialización en Automatización Industrial'),
        (PMI_QUIMICA, 'Maestría en Ingeniería - Ingeniería Química'),
        (PDI_QUIMICA, 'Doctorado en Ingeniería - Ingeniería Química'),
        (PMI_MECANICA, 'Maestría en Ingeniería - Ingeniería Mecánica'),
        (PMI_MATERIALES_Y_PROCESOS,
         'Maestría en Ingeniería - Materiales y Procesos'),
        (PMI_AGRICOLA, 'Maestría en Ingeniería - Ingeniería Agrícola'),
        (PMI_RECURSOS_HIDRAULICOS,
         'Maestría en Ingeniería - Recursos Hidráulicos'),
        (PMI_AMBIENTAL, 'Maestría en Ingeniería - Ingeniería Ambiental'),
        (PDI_ELECTRICA, 'Doctorado en Ingeniería - Ingeniería Eléctrica'),
        (PMI_ELECTRICA, 'Maestría en Ingeniería - Ingeniería Eléctrica'),
        (PDI_SISTEMAS_Y_COMPUTACION,
         'Doctorado en Ingeniería - Sistemas y Computación'),
        (PE_ILUMINACION_PUBLICA_Y_PRIVADA,
         'Especialización en Iluminación Pública y Privada'),
        (PMI_ELECTRONICA, 'Maestría en Ingeniería - Ingeniería Electrónica'),
        (PMI_AUTOMATIZACION_INDUSTRIAL,
         'Maestría en Ingeniería - Automatización Industrial'),
        (PDI_INDUSTRIA_Y_ORGANIZACIONES,
         'Doctorado en Ingeniería - Industria y Organizaciones'),
        (PE_TRANSITO_DISEÑO_Y_SEGURIDAD_VIAL,
         'Especialización en Transito, Diseño y Seguridad Vial'),
        (PDI_CIENCIA_Y_TECNOLOGIA_DE_MATERIALES,
         'Doctorado en Ingeniería - Ciencia y Tecnología de Materiales'),
        (PDI_MECANICA_Y_MECATRONICA,
         'Doctorado en Ingeniería - Ingeniería Mecánica y Mecatrónica'),
        (PMI_DE_SISTEMAS_Y_COMPUTACION,
         'Maestría en Ingeniería - Ingeniería de Sistemas y Computación'),
        (PMI_ELECTRICA_CONVENIO_SEDE_MANIZALES,
         'Maestría en Ingeniería - Ingeniería Eléctrica Convenio Sede Manizales'
         ),
        (PMI_DE_SISTEMAS_Y_COMPUTACION_CONV_UPC,
         'Maestría en Ingeniería - Ingeniería de Sistemas y Computación - Conv UPC'
         ),
        (PMI_DE_SISTEMAS_Y_COMPUTACION_CONV_UNILLANOS,
         'Maestría en Ingeniería - Ingeniería de Sistemas y Computación - Conv Unillanos'
         ),
        (PDI_ESTUDIOS_AMBIENTALES, 'Doctorado en Estudios Ambientales'),
        (BAP_ARTES, 'Modalidad de Asignaturas de Posgrado Facultad de Artes'),
        (BAP_CIENCIAS,
         'Modalidad de Asignaturas de Posgrado Facultad de Ciencias'),
        (BAP_DERECHO,
         'Modalidad de Asignaturas de Posgrado Facultad de Derecho'),
        (BAP_ECONOMIA,
         'Modalidad de Asignaturas de Posgrado Facultad de Economía'),
        (BAP_AGRONOMIA,
         'Modalidad de Asignaturas de Posgrado Facultad de Agronomía'),
        (BAP_HUMANAS,
         'Modalidad de Asignaturas de Posgrado Facultad de Humanas'),
        (BAP_INGENIERIA,
         'Modalidad de Asignaturas de Posgrado Facultad de Ingeniería'),
        (BAP_MEDICINA,
         'Modalidad de Asignaturas de Posgrado Facultad de Medicina'),
        (BAP_ENFERMERIA,
         'Modalidad de Asignaturas de Posgrado Facultad de Enfermería'),
        (BAP_ODONTOLOGIA,
         'Modalidad de Asignaturas de Posgrado Facultad de Odontología'),
    )

    # DP Departamento
    DP_CIVIL_AGRICOLA = 'DCA'
    DP_ELECTRICA_ELECTRONICA = 'DEE'
    DP_MECANICA_MECATRONICA = 'DMM'
    DP_SISTEMAS_INDUSTRIAL = 'DSI'
    DP_QUIMICA_AMBIENTAL = 'DQA'
    DP_EXTERNO_FACULTAD = 'EFA'
    DP_EMPTY = ''
    DP_CHOICES = (
        (DP_CIVIL_AGRICOLA, 'Departamento de Ingeniería Civil y Agrícola'),
        (DP_ELECTRICA_ELECTRONICA,
         'Departamento de Ingeniería Eléctrica y Electrónica'),
        (DP_MECANICA_MECATRONICA,
         'Departamento de Ingeniería Mecánica y Mecatrónica'),
        (DP_SISTEMAS_INDUSTRIAL,
         'Departamento de Ingeniería de Sistemas e Industrial'),
        (DP_QUIMICA_AMBIENTAL,
         'Departamento de Ingeniería Química y Ambiental'),
        (DP_EXTERNO_FACULTAD, 'Externo a la Facultad de Ingeniería'),
        (DP_EMPTY, ''),
    )

    PROFILE_INVE = 'I'
    PROFILE_PROF = 'P'
    PROFILE_CHOICES = ((PROFILE_INVE, 'Investigación'), (PROFILE_PROF,
                                                         'Profundización'))

    GRADE_OPTION_TRABAJO_FINAL_MAESTRIA = 'TFM'
    GRADE_OPTION_TESIS_MAESTRIA = 'TSM'
    GRADE_OPTION_TESIS_DOCTORADO = 'TSD'
    GRADE_OPTION_CHOICES = ((GRADE_OPTION_TRABAJO_FINAL_MAESTRIA,
                             'Trabajo Final de Maestría'),
                            (GRADE_OPTION_TESIS_MAESTRIA, 'Tesis de Maestría'))

    PERIOD_CHOICES = get_period_choices()
    PERIOD_DEFAULT = PERIOD_CHOICES[1][0] if datetime.date.today(
    ).month <= 6 else PERIOD_CHOICES[0][0]

    _cls = StringField(required=True)
    _cls_display = StringField(default=full_name)
    date_stamp = DateTimeField(default=datetime.datetime.now)
    user = StringField(max_length=255, required=True)
    consecutive_minute = IntField(
        min_value=0,
        default=0,
        display='Número del Acta de Consejo de Facultad')
    consecutive_minute_ac = IntField(min_value=0,
                                     default=0,
                                     display='Número del Acta de Comité Asesor'
                                     )  # ac stands for advisory committe
    year = IntField(min_value=2000,
                    max_value=2100,
                    display='Año del Acta',
                    default=datetime.date.today().year)
    to_legal = BooleanField(
        default=False, display='Sugerir remitir caso a Comisión Delegataria')
    date = DateTimeField(default=datetime.date.today,
                         display='Fecha de radicación')
    academic_program = StringField(min_length=4,
                                   max_length=4,
                                   choices=PLAN_CHOICES,
                                   display='Programa Académico',
                                   default=PI_AGRICOLA)
    student_dni_type = StringField(min_length=2,
                                   choices=DNI_TYPE_CHOICES,
                                   default=DNI_TYPE_CEDULA_DE_CIUDADANIA,
                                   display='Tipo de Documento')
    student_dni = StringField(max_length=22, display='Documento', default='')
    student_name = StringField(max_length=512,
                               display='Nombre del Estudiante',
                               default='')
    academic_period = StringField(max_length=10,
                                  display='Periodo Académico Actual',
                                  choices=PERIOD_CHOICES,
                                  default=PERIOD_DEFAULT)
    approval_status = StringField(min_length=2,
                                  max_length=2,
                                  choices=AS_CHOICES,
                                  default=AS_EN_ESPERA,
                                  display='Estado de Aprobación')
    archive_note = StringField(max_length=200, default=None)
    advisor_response = StringField(min_length=3,
                                   max_length=3,
                                   choices=ARCR_CHOICES,
                                   default=ARCR_EN_ESPERA,
                                   display='Respuesta del Comité')
    council_decision = StringField(
        max_length=255,
        default='Justifica debidamente la solicitud.',
        display='Justificación del Consejo')
    student_justification = StringField(default='',
                                        display='Justificación del Estudiante')
    supports = StringField(default='', display='Soportes')
    extra_analysis = ListField(StringField(), display='Análisis Extra')
    received_date = DateTimeField(
    )  # Date when advisor recieves a case from secretary
    notes = StringField()

    regulations = {
        '008|2008|CSU':
        ('Acuerdo 008 de 2008 del Consejo Superior Universitario',
         'http://www.legal.unal.edu.co/rlunal/home/doc.jsp?d_i=34983'),
        '026|2012|CSU':
        ('Acuerdo 026 de 2012 del Consejo Superior Universitario',
         'http://www.legal.unal.edu.co/rlunal/home/doc.jsp?d_i=47025'),
        '032|2010|CSU':
        ('Acuerdo 032 de 2010 del Consejo Superior Universitario',
         'http://www.legal.unal.edu.co/rlunal/home/doc.jsp?d_i=39424'),
        '040|2017|CSU':
        ('Acuerdo 40 de 2012 del Consejo Superior Universitario',
         'http://www.legal.unal.edu.co/rlunal/home/doc.jsp?d_i=89183'),
        '051|2003|CSU':
        ('Resolución 051 de 2003 del Consejo Superior Universitario',
         'http://www.legal.unal.edu.co/rlunal/home/doc.jsp?d_i=35163'),
        '056|2012|CSU':
        ('Acuerdo 056 de 2012 del Consejo Superior Universitario',
         'http://www.legal.unal.edu.co/rlunal/home/doc.jsp?d_i=48208'),
        '102|2013|CSU':
        ('Acuerdo 102 de 2013 del Consejo Superior Universitario',
         'http://www.legal.unal.edu.co/rlunal/home/doc.jsp?d_i=56987'),
        '230|2016|CSU':
        ('Acuerdo 230 de 2016 del Consejo Superior Universitario',
         'http://www.legal.unal.edu.co/rlunal/home/doc.jsp?d_i=87737'),
        '014|2008|CAC':
        ('Acuerdo 014 de 2008 del Consejo Académico',
         'http://www.legal.unal.edu.co/rlunal/home/doc.jsp?d_i=34127'),
        '016|2011|CAC':
        ('Acuerdo 016 de 2011 del Consejo Academico',
         'http://www.legal.unal.edu.co/rlunal/home/doc.jsp?d_i=44965'),
        '070|2009|CAC':
        ('Acuerdo 070 de 2009 de Consejo Académico',
         'http://www.legal.unal.edu.co/rlunal/home/doc.jsp?d_i=35443'),
        '089|2014|CAC':
        ('Acuerdo 089 de 2014 del Consejo Académico',
         'http://www.legal.unal.edu.co/rlunal/home/doc.jsp?d_i=66330'),
        '002|2012|CFA':
        ('Acuerdo 002 de 2012 de Consejo de Facultad',
         'http://www.legal.unal.edu.co/rlunal/home/doc.jsp?d_i=50509'),
        '002|2011|CFA':
        ('Acuerdo 002 de 2011 de Consejo de Facultad',
         'http://www.legal.unal.edu.co/rlunal/home/doc.jsp?d_i=42724'),
        '040|2017|CFA':
        ('Acuerdo 40 de 2017 del Consejo de Facultad',
         'http://www.legal.unal.edu.co/rlunal/home/doc.jsp?d_i=89183'),
        '001|2016|VAC':
        ('Circular 01 de 2016 de la Vicerectoría Académica',
         'http://www.legal.unal.edu.co/rlunal/home/doc.jsp?d_i=86414#0'),
        '012|2014|VAC':
        ('Resolución 012 de 2014 de Vicerrectoría Académica',
         'http://www.legal.unal.edu.co/rlunal/home/doc.jsp?d_i=62849'),
        '035|2014|VAC':
        ('Resolución 035 de 2018 de La Vicerrectoría Académica',
         'http://www.legal.unal.edu.co/rlunal/home/doc.jsp?d_i=69990'),
        '239|2009|VAC':
        ('Resolución 239 de 2009 de Vicerrectoría Académica',
         'http://www.legal.unal.edu.co/rlunal/home/doc.jsp?d_i=34644'),
        '241|2009|VAC':
        ('Resolución 241 de 2009 de la Vicerrectoría Académica',
         'http://www.legal.unal.edu.co/rlunal/home/doc.jsp?d_i=34651'),
        '001|2019|VSB':
        ('Circular 001 de 2019 de Vicerrectoría de Sede Bogotá',
         'http://www.legal.unal.edu.co/rlunal/home/doc.jsp?d_i=92579'),
        '1416|2013|RE':
        ('Resolución 1416 de 2013 de Rectoría',
         'http://www.legal.unal.edu.co/rlunal/home/doc.jsp?d_i=60849'),
        '070|2012|CSU':
        ('Acuerdo 70 de 2018 del Consejo Superior Universitario',
         'http://www.legal.unal.edu.co/rlunal/home/doc.jsp?d_i=50105'),
        '155|2014|CSU':
        ('Acuerdo 155 de 2014 del Consejo Superior Universitario',
         'http://www.legal.unal.edu.co/rlunal/home/doc.jsp?d_i=69337'),
    }

    assertionerror = {'CHOICES': '{} is not in choices list.'}

    str_analysis = 'Análisis'
    str_answer = 'Concepto'
    str_council_header = 'El Consejo de Facultad'
    str_comittee_header = 'El Comité Asesor recomienda al Consejo de Facultad'

    def is_affirmative_response_approval_status(self):
        return self.approval_status in (self.AS_APRUEBA,
                                        self.AS_CONSEJO_RECOMIENDA)

    def is_waiting_response_advisor_response(self):
        return self.advisor_response in (self.ARCR_EN_ESPERA)

    def is_affirmative_response_advisor_response(self):
        return self.advisor_response in (self.ARCR_RECOMENDAR,
                                         self.ARCR_APROBAR)

    def is_pre(self):
        return self.academic_program in (self.PI_AGRICOLA, self.PI_CIVIL,
                                         self.PI_DE_SISTEMAS_Y_COMPUTACION,
                                         self.PI_INDUSTRIAL, self.PI_ELECTRICA,
                                         self.PI_MECANICA, self.PI_MECATRONICA,
                                         self.PI_ELECTRONICA, self.PI_QUIMICA)

    def safe_save(self):
        try:
            self.save()
        except ValidationError as e:
            raise ValueError(e.message)

    @staticmethod
    def get_cases_by_query(query):
        # pylint: disable=no-member

        ## Get all cases that follows the query
        cases = Request.objects(**query)
        ## Ignore "deleted" cases
        cases = cases.filter(
            approval_status__nin=[Request.AS_ANULADA, Request.AS_RENUNCIA])
        return cases.order_by('-date_stamp')

    @staticmethod
    def get_case_by_id(caseid):
        try:
            # pylint: disable=no-member
            return Request.objects.get(id=caseid)
        except ValidationError as e:
            raise ValueError(e.message)
        except DoesNotExist as e:
            raise KeyError('ID {} does not exist')

    @staticmethod
    def get_programs():
        return {'programs': sorted([plan[1] for plan in Request.PLAN_CHOICES])}

    @staticmethod
    def get_cases():
        cases = [{
            'code': type_case.__name__,
            'name': type_case.full_name
        } for type_case in Request.get_subclasses()]
        cases.sort(key=lambda case: case['name'])

        return {'cases': cases}

    @classmethod
    def translate(cls, data):
        to_del = []
        data_json = json.loads(data)
        for key in data_json:
            if data_json[key] is None or data_json[key] == 'None':
                to_del.append(key)
                continue
            try:
                # pylint: disable=no-member
                choices = cls._fields[key].choices
                if choices:
                    for item in choices:
                        if item[1] == data_json[key]:
                            data_json[key] = item[0]
                            break
                elif isinstance(cls._fields[key], EmbeddedDocumentListField):
                    _cls = cls._fields[key].field.document_type_obj
                    for field in _cls._fields:
                        choices = _cls._fields[field].choices
                        if choices:
                            _dict = dict((y, x) for x, y in choices)
                            for element in data_json[key]:
                                if element[field] in _dict:
                                    element[field] = _dict[element[field]]

                elif isinstance(cls._fields[key], ListField):
                    choices = cls._fields[key].field.choices
                    if choices:
                        _dict = dict((y, x) for x, y in choices)
                        for i, element in enumerate(data_json[key]):
                            if element in _dict:
                                data_json[key][i] = _dict[element]

            except KeyError:
                pass
        for key in to_del:
            del data_json[key]
        return json.dumps(data_json)

    @classmethod
    def get_entire_name(cls):
        parents = cls.mro()
        index = parents.index(Request)
        name = 'Request.'
        for _cls in reversed(parents[:index]):
            name += _cls.__name__ + '.'
        return name[:-1]

    @classmethod
    def get_subclasses(cls):
        subs = []
        for subclass in cls.__subclasses__():
            subs.append(subclass)
            subs += subclass.get_subclasses()
        return subs
Exemple #24
0
class IndicatorAccess(EmbeddedDocument, CritsDocumentFormatter, CommonAccess):
    """
    ACL for Indicators.
    """

    type_edit = BooleanField(default=False)
    threat_type_edit = BooleanField(default=False)
    attack_type_edit = BooleanField(default=False)
    confidence_edit = BooleanField(default=False)
    impact_edit = BooleanField(default=False)

    actions_read = BooleanField(default=False)
    actions_add = BooleanField(default=False)
    actions_edit = BooleanField(default=False)
    actions_delete = BooleanField(default=False)

    activity_read = BooleanField(default=False)
    activity_add = BooleanField(default=False)
    activity_edit = BooleanField(default=False)
    activity_delete = BooleanField(default=False)
Exemple #25
0
class User(Document):
  username = StringField()
  password = StringField()
  email_verified = BooleanField(default=False)
Exemple #26
0
class CPTE(Request):

    full_name = 'Cambio de proyecto de tesis de maestría'

    GO_TRABAJO_FINAL_MAESTRIA = 'TFM'
    GO_TESIS_MAESTRIA = 'TSM'
    GO_TESIS_DOCTORADO = 'TSD'
    GO_CHOICES = ((GO_TRABAJO_FINAL_MAESTRIA, 'Trabajo Final de Maestría'),
                  (GO_TESIS_MAESTRIA, 'Tesis de Maestría'),
                  (GO_TESIS_DOCTORADO, 'Tesis de Doctorado'))

    title = StringField(required=True,
                        display='Nuevo título de la tesis',
                        default='')
    grade_option = StringField(
        required=True,  # display='Tipo de tesis/trabajo final',
        choices=GO_CHOICES,
        default=GO_TESIS_MAESTRIA)
    new_advisor = StringField(required=True,
                              display='Nuevo director de tesis',
                              default='')
    old_advisor = StringField(display='Antiguo director de tesis', default='')
    new_co_advisor = StringField(display='Nuevo codirector de tesis',
                                 default='')
    old_co_advisor = StringField(display='Antiguo codirector de tesis',
                                 default='')
    inst_new_advisor = StringField(
        choices=Request.DP_CHOICES,
        display='Departamento de adscripción del nuevo director',
        default=Request.DP_EMPTY)
    inst_new_co_advisor = StringField(
        choices=Request.DP_CHOICES,
        display='Departamento de adscripción del nuevo codirector',
        default=Request.DP_EMPTY)
    inst_old_co_advisor = StringField(
        choices=Request.DP_CHOICES,
        display='Departamento de adscripción del antiguo codirector',
        default=Request.DP_EMPTY)
    inst_old_advisor = StringField(
        choices=Request.DP_CHOICES,
        display='Departamento de adscripción del antiguo director',
        default=Request.DP_EMPTY)
    enrolled_thesis = BooleanField(
        required=True,
        default=False,
        display='¿Tiene inscrita la asignatura tesis/trabajo final?')
    have_signature = BooleanField(
        required=True,
        default=False,
        display='¿Tiene la firma del (los) director(es)?')

    regulation_list = ['002|2011|CFA', '056|2012|CSU']  # List of regulations

    str_cm = [
        'cambiar el título de {} del programa {} a: ', '"{}"',
        'ratificar director', 'designar nuevo director', 'al profesor',
        'en reemplazo del profesor', 'Designar nuevo codirector',
        'ratificar director', ' del ', 'debido a que',
        'Ratificar nuevo codirector'
    ]

    list_analysis = [
        'Perfil de {}.', 'El estudiante {}tiene inscrita la asignatura {}.',
        'iene la firma de los directores de tesis/trabajo final: {}'
    ]

    def cm(self, docx):
        paragraph = docx.add_paragraph()
        paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY
        paragraph.paragraph_format.space_after = Pt(0)
        paragraph.add_run(self.str_council_header + ' ')
        self.cm_answer(paragraph)

    def cm_answer(self, paragraph):
        paragraph.add_run(
            # pylint: disable=no-member
            self.get_approval_status_display().upper() + ' ').font.bold = True
        # pylint: disable=no-member
        paragraph.add_run(self.str_cm[0].format(
            self.get_grade_option_display(),
            self.get_academic_program_display()))
        paragraph.add_run(self.str_cm[1].format(self.title)).font.italic = True
        if self.is_affirmative_response_approval_status():
            self.cm_af(paragraph)
        else:
            self.cm_ng(paragraph)

    def pcm(self, docx):
        self.pcm_analysis(docx)
        paragraph = docx.add_paragraph()
        paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY
        paragraph.paragraph_format.space_after = Pt(0)
        paragraph.add_run(self.str_answer + ': ').font.bold = True
        paragraph.add_run(self.str_comittee_header + ' ')
        self.pcm_answer(paragraph)

    def pcm_answer(self, paragraph):
        paragraph.add_run(
            # pylint: disable=no-member
            self.get_advisor_response_display().upper()).font.bold = True
        # pylint: disable=no-member
        paragraph.add_run(
            ' ' + self.str_cm[0].format(self.get_grade_option_display(),
                                        self.get_academic_program_display()))
        paragraph.add_run(self.str_cm[1].format(self.title)).font.italic = True
        if self.is_affirmative_response_approval_status():
            self.cm_af(paragraph)
        else:
            self.cm_ng(paragraph)

    def cm_af(self, paragraph):
        if self.old_advisor == self.new_advisor or self.old_advisor == '':
            paragraph.add_run(', ' + self.str_cm[2] + ' ' + self.str_cm[4] +
                              ' ')
            paragraph.add_run(self.new_advisor)
            if self.inst_new_advisor != self.DP_EXTERNO_FACULTAD and \
                    self.inst_new_advisor != '':
                # pylint: disable=no-member
                paragraph.add_run(self.str_cm[8] +
                                  self.get_inst_new_advisor_display())
        else:
            paragraph.add_run(', ' + self.str_cm[3] + ' ' + self.str_cm[4] +
                              ' ')
            paragraph.add_run(self.new_advisor)
            if self.inst_new_advisor != self.DP_EXTERNO_FACULTAD and \
                    self.inst_new_advisor != '':
                # pylint: disable=no-member
                paragraph.add_run(self.str_cm[8] +
                                  self.get_inst_new_advisor_display())
            paragraph.add_run(' ' + self.str_cm[5] + ' ' + self.old_advisor)
            # pylint: disable=no-member
            paragraph.add_run(self.str_cm[8] +
                              self.get_inst_old_advisor_display())
        paragraph.add_run('.')
        if self.new_co_advisor != '':
            if self.old_co_advisor == self.new_co_advisor or\
                    self.old_co_advisor == '':
                paragraph.add_run(' ' + self.str_cm[10] + ' ' +
                                  self.str_cm[4] + ' ')
                paragraph.add_run(self.new_co_advisor)
                if self.inst_new_co_advisor != self.DP_EXTERNO_FACULTAD and \
                        self.inst_new_co_advisor != '':
                    # pylint: disable=no-member
                    paragraph.add_run(self.str_cm[8] +
                                      self.get_inst_new_co_advisor_display())
            else:
                paragraph.add_run(' ' + self.str_cm[6] + ' ' + self.str_cm[4] +
                                  ' ')
                paragraph.add_run(self.new_co_advisor)
                if self.inst_new_co_advisor != self.DP_EXTERNO_FACULTAD and \
                        self.inst_new_co_advisor != '':
                    # pylint: disable=no-member
                    paragraph.add_run(self.str_cm[8] +
                                      self.get_inst_new_co_advisor_display())
                paragraph.add_run(' ' + self.str_cm[5] + ' ')
                paragraph.add_run(self.old_co_advisor)
                if self.inst_old_co_advisor != self.DP_EXTERNO_FACULTAD and \
                        self.inst_old_co_advisor != '':
                    # pylint: disable=no-member
                    paragraph.add_run(self.str_cm[8] +
                                      self.get_inst_old_co_advisor_display())
            paragraph.add_run('.')

    def cm_ng(self, paragraph):
        paragraph.add_run(' ' + self.str_cm[9] + ' ' + self.council_decision +
                          '.')

    def pcm_analysis(self, docx):
        if self.grade_option in [
                self.GO_TESIS_MAESTRIA, self.GO_TESIS_DOCTORADO
        ]:
            profile = 'investigación'
        else:
            profile = 'profundización'
        final_analysis = []
        final_analysis += [self.list_analysis[0].format(profile)]
        ets = '' if self.enrolled_thesis else 'no '
        # pylint: disable=no-member
        final_analysis += [
            self.list_analysis[1].format(ets, self.get_grade_option_display())
        ]
        hss = 'T' if self.have_signature else 'No t'
        final_analysis += [
            hss + self.list_analysis[2].format(self.new_advisor)
        ]
        for extra_a in self.extra_analysis:
            final_analysis += [extra_a]
        add_analysis_paragraph(docx, final_analysis)

    def resource_analysis(self, docx):
        last_paragraph = docx.paragraphs[-1]
        self.pcm_answer(last_paragraph)

    def resource_pre_answer(self, docx):
        last_paragraph = docx.paragraphs[-1]
        self.pcm_answer(last_paragraph)

    def resource_answer(self, docx):
        last_paragraph = docx.paragraphs[-1]
        self.cm_answer(last_paragraph)
Exemple #27
0
class MOTP(Request):

    full_name = 'Cambio de objetivos de tesis o trabajo final'
    decision_maker = Request.decision_makers[1]
    in_cm = False

    GO_TRABAJO_FINAL_MAESTRIA = 'TFM'
    GO_TESIS_MAESTRIA = 'TSM'
    GO_TESIS_DOCTORADO = 'TSD'
    GO_CHOICES = (
        (GO_TRABAJO_FINAL_MAESTRIA, 'Trabajo Final de Maestría'),
        (GO_TESIS_MAESTRIA, 'Tesis de Maestría'),
        (GO_TESIS_DOCTORADO, 'Tesis de Doctorado')
    )

    title = StringField(
        required=True, display='Título de la tesis/trabajo final', default=''),
    grade_option = StringField(
        required=True, display='Tipo de tesis/trabajo final',
        choices=GO_CHOICES, default=GO_TESIS_MAESTRIA)
    general_objetive = StringField(
        required=True, display='Objetivo general', default='')
    specific_objetives = ListField(StringField(),
                                   display='Objetivos específicos')
    enrolled_thesis = BooleanField(
        required=True, default=False,
        display='¿Tiene inscrita la asignatura tesis/trabajo final?')

    regulation_list = ['040|2017|CFA', '056|2012|CSU']  # List of regulations

    str_cm = ['cambiar los objetivos de ',
              '"{}"',
              'a:',
              'debido a que']

    list_analysis = ['Título:',
                     'Objetivo general:',
                     'Objetivos específicos:',
                     'Perfil de {}.',
                     'El estudiante {}tiene inscrita la asignatura {}.']

    def cm(self, docx):
        paragraph = docx.add_paragraph()
        paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY
        paragraph.paragraph_format.space_after = Pt(0)
        self.cm_answer(paragraph)
        self.cm_ob(docx)

    def cm_answer(self, paragraph):
        paragraph.add_run(self.str_council_header + ' ')
        # pylint: disable=no-member
        paragraph.add_run(
            self.get_approval_status_display().upper() + ' ').font.bold = True
        paragraph.add_run(
            self.str_cm[0] + self.get_grade_option_display() + ' ')
        paragraph.add_run(self.str_cm[1].format(self.title)).font.italic = True
        if self.is_affirmative_response_approval_status():
            self.cm_af(paragraph)
        else:
            self.cm_ng(paragraph)

    def pcm(self, docx):
        self.pcm_analysis(docx)
        self.pcm_answer(docx)
        self.cm_ob(docx)

    def pcm_answer(self, docx):
        paragraph = docx.add_paragraph()
        paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY
        paragraph.paragraph_format.space_after = Pt(0)
        paragraph.add_run(self.str_answer + ': ').font.bold = True
        paragraph.add_run(self.str_comittee_header + ' ')
        paragraph.add_run(
            # pylint: disable=no-member
            self.get_advisor_response_display().upper()).font.bold = True
        # pylint: disable=no-member
        paragraph.add_run(' ' + self.str_cm[0].format(
            self.get_grade_option_display(), self.get_academic_program_display()))
        paragraph.add_run(self.str_cm[1].format(self.title)).font.italic = True
        if self.is_affirmative_response_approval_status():
            self.cm_af(paragraph)
        else:
            self.cm_ng(paragraph)

    def cm_af(self, paragraph):
        paragraph.add_run(' ' + self.str_cm[2])

    def cm_ng(self, paragraph):
        paragraph.add_run(
            ' ' + self.str_cm[3] + ' ' + self.council_decision + '.')

    def cm_ob(self, docx):
        if not self.is_affirmative_response_approval_status():
            return
        paragraph = docx.add_paragraph()
        paragraph.style = 'List Bullet'
        paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY
        paragraph.paragraph_format.space_after = Pt(0)
        paragraph.add_run(self.list_analysis[1]).font.bold = True
        paragraph = docx.add_paragraph()
        paragraph.style = 'List Bullet 2'
        paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY
        paragraph.paragraph_format.space_after = Pt(0)
        paragraph.add_run(self.general_objetive + '.')
        paragraph = docx.add_paragraph()
        paragraph.style = 'List Bullet'
        paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY
        paragraph.paragraph_format.space_after = Pt(0)
        paragraph.add_run(self.list_analysis[2]).font.bold = True
        for spec in self.specific_objetives:
            paragraph = docx.add_paragraph()
            paragraph.style = 'List Bullet 2'
            paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY
            paragraph.paragraph_format.space_after = Pt(0)
            paragraph.add_run(spec + '.')

    def pcm_analysis(self, docx):
        if self.grade_option in [self.GO_TESIS_MAESTRIA, self.GO_TESIS_DOCTORADO]:
            profile = 'investigación'
        else:
            profile = 'profundización'
        final_analysis = []
        final_analysis += [self.list_analysis[3].format(profile)]
        ets = '' if self.enrolled_thesis else 'no '
        # pylint: disable=no-member
        final_analysis += [self.list_analysis[4].format(
            ets, self.get_grade_option_display())]
        for extra_a in self.extra_analysis:
            final_analysis += [extra_a]
        add_analysis_paragraph(docx, final_analysis)
        paragraph = docx.add_paragraph()
        paragraph.style = 'List Bullet'
        paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY
        paragraph.paragraph_format.space_after = Pt(0)
        paragraph.add_run(self.list_analysis[0] + ' ').font.bold = True
        paragraph.add_run(self.title + '.').font.italic = True
Exemple #28
0
class EMCA(Request):

    full_name = 'Exención de matrícula por consideración atípica'

    percentage = FloatField(
        min_value=0.0,
        max_value=100.0,
        required=True,
        display='Porcentaje de exención del valor de la matrícula',
        default=0.0)
    academic_period_exe = StringField(max_length=10,
                                      display='Periodo de exención',
                                      choices=Request.PERIOD_CHOICES,
                                      default=Request.PERIOD_DEFAULT)
    ha_active = BooleanField(default=True,
                             display='¿Tiene la historia académica activa?')

    regulation_list = ['070|2009|CAC']  # List of regulations

    str_cm = [
        ' otorgrar exención del pago de {}% del valor de la matrícula para el periodo '
        + 'académico {}, ', ' ({}).'
    ]

    str_analysis = ['iene la historia académica activa.']

    list_analysis = []

    def cm(self, docx):
        paragraph = docx.add_paragraph()
        paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY
        paragraph.paragraph_format.space_after = Pt(0)
        self.cm_answer(paragraph)

    def cm_answer(self, paragraph):
        # pylint: disable=no-member
        paragraph.add_run(self.str_council_header + ' ')
        paragraph.add_run(self.get_approval_status_display().upper() +
                          ' ').font.bold = True
        paragraph.add_run(self.str_cm[0].format(self.percentage,
                                                self.academic_period_exe))
        paragraph.add_run(self.council_decision)
        paragraph.add_run(self.str_cm[1].format(
            Request.regulations['070|2009|CAC'][0]))

    def pcm(self, docx):
        self.pcm_analysis(docx)
        self.pcm_answer(docx)

    def pcm_answer(self, docx):
        # pylint: disable=no-member
        paragraph = docx.add_paragraph()
        paragraph.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY
        paragraph.paragraph_format.space_after = Pt(0)
        paragraph.add_run(self.str_answer + ': ').font.bold = True
        paragraph.add_run(self.str_comittee_header + ' ')
        paragraph.add_run(
            self.get_advisor_response_display().upper()).font.bold = True
        paragraph.add_run(self.str_cm[0].format(self.percentage,
                                                self.academic_period_exe))
        paragraph.add_run(self.council_decision)
        paragraph.add_run(self.str_cm[1].format(
            Request.regulations['070|2009|CAC'][0]))

    def pcm_analysis(self, docx):
        final_analysis = []
        aux = 'T' if self.ha_active else 'No t'
        final_analysis += [aux + self.str_analysis[0]]
        for extra_a in self.extra_analysis:
            final_analysis += [extra_a]
        add_analysis_paragraph(docx, final_analysis)
Exemple #29
0
class CRITsUser(CritsDocument, CritsSchemaDocument, Document):
    """
    CRITs User object
    """

    meta = {
        "collection": settings.COL_USERS,
        'indexes': [
            {
                'fields': ['username'],
                'unique': True,
                'sparse': True,
            },
        ],
        "crits_type": 'User',
        "latest_schema_version": 3,
        "schema_doc": {
            'username':
            '******',
            'organization':
            'The name of the organization this user is from',
            'role':
            'The role this user has been granted from a CRITs Admin',
            'sources': ('List [] of source names this user has been granted'
                        ' access to view data from'),
            'subscriptions': {
                'Campaign': [{
                    'date': 'ISODate subscribed',
                    'id': 'ObjectId of the object subscribed to'
                }],
                'Domain': [{
                    'date': 'ISODate subscribed',
                    'id': 'ObjectId of the object subscribed to'
                }],
                'Email': [{
                    'date': 'ISODate subscribed',
                    'id': 'ObjectId of the object subscribed to'
                }],
                'Target': [{
                    'date': 'ISODate subscribed',
                    'id': 'ObjectId of the object subscribed to'
                }],
                'Event': [{
                    'date': 'ISODate subscribed',
                    'id': 'ObjectId of the object subscribed to'
                }],
                'IP': [{
                    'date': 'ISODate subscribed',
                    'id': 'ObjectId of the object subscribed to'
                }],
                'Indicator': [{
                    'date': 'ISODate subscribed',
                    'id': 'ObjectId of the object subscribed to'
                }],
                'PCAP': [{
                    'date': 'ISODate subscribed',
                    'id': 'ObjectId of the object subscribed to'
                }],
                'Sample': [{
                    'date': 'ISODate subscribed',
                    'id': 'ObjectId of the object subscribed to'
                }],
                'Source': [{
                    'date': 'ISODate subscribed',
                    'name': 'Name of the source subscribed to'
                }],
            },
            'favorites': {
                'Actor': [],
                'Backdoor': [],
                'Campaign': [],
                'Domain': [],
                'Email': [],
                'Target': [],
                'Event': [],
                'Exploit': [],
                'IP': [],
                'Indicator': [],
                'PCAP': [],
                'Sample': [],
            }
        },
    }

    username = StringField(
        max_length=30,
        required=True,
        verbose_name='username',
        help_text=
        "Required. 30 characters or fewer. Letters, numbers and @/./+/-/_ characters"
    )

    first_name = StringField(max_length=30, verbose_name='first name')

    last_name = StringField(max_length=30, verbose_name='last name')
    email = EmailField(verbose_name='e-mail address')
    password = StringField(
        max_length=128,
        verbose_name='password',
        help_text=
        "Use '[algo]$[iterations]$[salt]$[hexdigest]' or use the <a href=\"password/\">change password form</a>."
    )
    secret = StringField(verbose_name='TOTP Secret')
    is_staff = BooleanField(
        default=False,
        verbose_name='staff status',
        help_text="Designates whether the user can log into this admin site.")
    is_active = BooleanField(
        default=True,
        verbose_name='active',
        help_text=
        "Designates whether this user should be treated as active. Unselect this instead of deleting accounts."
    )
    is_superuser = BooleanField(
        default=False,
        verbose_name='superuser status',
        help_text=
        "Designates that this user has all permissions without explicitly assigning them."
    )
    last_login = DateTimeField(default=datetime_now, verbose_name='last login')
    date_joined = DateTimeField(default=datetime_now,
                                verbose_name='date joined')

    invalid_login_attempts = IntField(default=0)
    login_attempts = ListField(EmbeddedDocumentField(EmbeddedLoginAttempt))
    organization = StringField(default=settings.COMPANY_NAME)
    password_reset = EmbeddedDocumentField(EmbeddedPasswordReset,
                                           default=EmbeddedPasswordReset())
    role = StringField(default="Analyst")
    sources = ListField(StringField())
    subscriptions = EmbeddedDocumentField(EmbeddedSubscriptions,
                                          default=EmbeddedSubscriptions())
    favorites = EmbeddedDocumentField(EmbeddedFavorites,
                                      default=EmbeddedFavorites())
    prefs = EmbeddedDocumentField(PreferencesField, default=PreferencesField())
    totp = BooleanField(default=False)
    secret = StringField(default="")
    api_keys = ListField(EmbeddedDocumentField(EmbeddedAPIKey))
    USERNAME_FIELD = 'username'
    REQUIRED_FIELDS = ['email']

    defaultDashboard = ObjectIdField(required=False, default=None)

    def migrate(self):
        """
        Migrate to latest schema version.
        """

        migrate_user(self)

    def __setattr__(self, name, value):
        """
        Overrides our core __setattr__ because we have to allow for extra
        authentication attributes that would normally get moved to
        unsupported_attrs.
        """

        if (not self._dynamic and hasattr(self, 'unsupported_attrs')
                and not name in self._fields and not name.startswith('_')
                and not name.startswith('$') and not '.' in name
                and name not in ('backend')):
            if not self.unsupported_attrs:
                self.unsupported_attrs = UnsupportedAttrs()
            self.unsupported_attrs.__setattr__(name, value)
        else:
            super(CritsDocument, self).__setattr__(name, value)

    @property
    def pk(self):
        """
        Return the ObjectId as the primary key.
        """

        return self.id

    def __str__(self):
        """
        This is so request.user returns the username like Django expects,
        not the whole object.
        """

        if self.username:
            return self.username

    # the rest of this taken from the MongoEngine User class.

    def __unicode__(self):
        """
        This is so request.user returns the username like Django expects,
        not the whole object.
        """

        return self.username

    def get_full_name(self):
        """
        Returns the users first and last names, separated by a space.
        """

        full_name = u'%s %s' % (self.first_name or '', self.last_name or '')
        return full_name.strip()

    def is_anonymous(self):
        """
        We do not allow anonymous users.
        """

        return False

    def is_authenticated(self):
        """
        If we know about the user from the request, it means they've
        authenticated.
        """

        return True

    def mark_active(self, analyst=None):
        """
        Mark the user as active.
        """

        self.is_active = True
        self.save(username=analyst)
        return self

    def mark_inactive(self, analyst=None):
        """
        Deactivate the user.
        """

        self.is_active = False
        self.save(username=analyst)
        return self

    def is_password_complex(self, password):
        """
        Based on the CRITsConfig, is the password provided complex enough to be
        used?

        :param password: The password to check for complexity.
        :type password: str
        :returns: True, False
        """

        crits_config = CRITsConfig.objects().first()
        if crits_config:
            pw_regex = crits_config.password_complexity_regex
        else:
            pw_regex = settings.PASSWORD_COMPLEXITY_REGEX
        complex_regex = re.compile(pw_regex)
        if complex_regex.match(password):
            return True
        return False

    def set_password(self, raw_password, analyst=None):
        """
        Sets the user's password - always use this rather than directly
        assigning to :attr:`~mongoengine.django.auth.User.password` as the
        password is hashed before storage.

        :param raw_password: The password to hash and store.
        :type raw_password: str
        :returns: self, False
        """

        if self.is_password_complex(raw_password):
            self.password = make_password(raw_password)
            self.save(username=analyst)
            return self
        else:
            return False

    def set_reset_code(self, analyst):
        """
        Sets a reset code on the account for password reset validation.

        :returns: str
        """

        e = EmbeddedPasswordReset()
        char_set = string.ascii_uppercase + string.digits
        e.reset_code = ''.join(random.sample(char_set * 6, 6))
        e.date = datetime.datetime.now()
        self.password_reset = e
        self.save(username=analyst)
        return e.reset_code

    def reset_password(self, rcode, new_p, new_p_c, analyst):
        """
        Reset the user's password. Validate the reset code, ensure the two
        passwords are identical, and then set.

        :param rcode: Reset Code to validate.
        :type rcode: str
        :param new_p: New password.
        :type new_p: str
        :param new_p_c: New password confirmation.
        :type new_p_c: str
        :param analyst: The user.
        :type analyst: str
        :returns: dict with keys "success" (boolean) and "message" (str).
        """

        if self.validate_reset_code(rcode, analyst)['success']:
            if new_p == new_p_c:
                self.password_reset.reset_code = ""
                if self.set_password(new_p):
                    return {'success': True, 'message': 'Password reset.'}
                else:
                    crits_config = CRITsConfig.objects().first()
                    if crits_config:
                        pw_desc = crits_config.password_complexity_desc
                    else:
                        pw_desc = settings.PASSWORD_COMPLEXITY_DESC
                    message = 'Password not complex enough: %s' % pw_desc
                    return {'success': False, 'message': message}
            else:
                return {'success': False, 'message': 'Passwords do not match.'}
        else:
            self.password_reset.reset_code = ""
            self.save(username=analyst)
            return {'success': False, 'message': 'Reset Code Expired.'}

    def validate_reset_code(self, reset_code, analyst):
        """
        Validate the reset code. Also ensure that the reset code hasn't expired
        already since it is a limited-time use reset.

        :param reset_code: The reset code.
        :type reset_code: str
        :param analyst: The user.
        :type analyst: str
        :returns: dict with keys "success" (boolean) and "message" (str).
        """

        my_reset = self.password_reset.reset_code
        if len(reset_code) == 6 and len(
                my_reset) == 6 and my_reset == reset_code:
            date = datetime.datetime.now()
            diff = date - self.password_reset.date
            window = divmod(diff.days * 86400 + diff.seconds, 60)
            if window[0] < 5:
                self.password_reset.attempts = 0
                self.save(username=analyst)
                return {'success': True, 'message': 'Reset Code Validated.'}
            else:
                self.password_reset.attempts += 1
                self.password_reset.reset_code = ""
                self.save(username=analyst)
                return {'success': False, 'message': 'Reset Code Expired.'}
        self.password_reset.attempts += 1
        if self.password_reset.attempts > 2:
            self.password_reset.date = self.password_reset.date + datetime.timedelta(
                minutes=-5)
            self.save(username=analyst)
            return {'success': False, 'message': 'Reset Code Expired.'}
        self.save(username=analyst)
        return {'success': False, 'message': 'Reset Code Invalid.'}

    def check_password(self, raw_password):
        """
        Checks the user's password against a provided password - always use
        this rather than directly comparing to
        :attr:`~mongoengine.django.auth.User.password` as the password is
        hashed before storage.
        """

        return check_password(raw_password, self.password)

    def create_api_key(self, name, analyst, default=False):
        """
        Generate an API key for the user. It will require a name as we allow for
        unlimited API keys and users need a way to reference them.

        :param name: The name for the API key.
        :type name: str
        :param analyst: The user.
        :type analyst: str
        :param default: Use as default API key.
        :type default: boolean
        :returns: dict with keys "success" (boolean) and "message" (str).
        """

        if not name:
            return {'success': False, 'message': 'Need a name'}
        new_uuid = uuid.uuid4()
        key = hmac.new(new_uuid.bytes, digestmod=sha1).hexdigest()
        ea = EmbeddedAPIKey(name=name, api_key=key, default=default)
        if len(self.api_keys) < 1:
            ea.default = True
        self.api_keys.append(ea)
        self.save(username=analyst)
        return {
            'success': True,
            'message': {
                'name': name,
                'key': key,
                'date': str(ea.date)
            }
        }

    def default_api_key(self, name, analyst):
        """
        Make an API key the default key for a user. The default key is used for
        situations where the user is not or cannot be asked which API key to
        use.

        :param name: The name of the API key.
        :type name: str
        :param analyst: The user.
        :type analyst: str
        :returns: dict with keys "success" (boolean) and "message" (str).
        """

        c = 0
        for key in self.api_keys:
            if key.name == name:
                self.api_keys[c].default = True
            else:
                self.api_keys[c].default = False
            c += 1
        self.save(username=analyst)
        return {'success': True}

    def revoke_api_key(self, name, analyst):
        """
        Revoke an API key so it can no longer be used.

        :param name: The name of the API key.
        :type name: str
        :param analyst: The user.
        :type analyst: str
        :returns: dict with keys "success" (boolean) and "message" (str).
        """

        keys = self.api_keys
        keyslen = len(keys)
        self.api_keys = [k for k in keys if k.name != name]
        if keyslen > len(self.api_keys):
            self.save(username=analyst)
            return {'success': True}
        else:
            return {'success': False, 'message': 'Key not found.'}

    def get_api_key(self, name):
        """
        Get the API key.

        :param name: The name of the API key.
        :type name: str
        :returns: str, None
        """

        for key in self.api_keys:
            if key.name == name:
                return key.api_key
        return None

    def validate_api_key(self, key):
        """
        Validate that the API key exists for this user.

        :param key: The API key.
        :type key: str
        :returns: True, False
        """

        for keys in self.api_keys:
            if keys.api_key == key:
                return True
        return False

    @classmethod
    def create_user(cls, username, password, email=None, analyst=None):
        """
        Create (and save) a new user with the given username, password and
        email address.
        """

        now = datetime_now()

        # Normalize the address by lowercasing the domain part of the email
        # address.
        if email is not None:
            try:
                email_name, domain_part = email.strip().split('@', 1)
            except ValueError:
                pass
            else:
                email = '@'.join([email_name, domain_part.lower()])

        user = cls(username=username, email=email, date_joined=now)
        user.create_api_key("default", analyst, default=True)
        if password and user.set_password(password):
            user.save(username=analyst)
            return user
        elif CRITsConfig.remote_user:
            user.save(username="******")
            return user
        else:
            return None

    def get_group_permissions(self, obj=None):
        """
        Returns a list of permission strings that this user has through his/her
        groups. This method queries all available auth backends. If an object
        is passed in, only permissions matching this object are returned.
        """
        permissions = set()
        for backend in auth.get_backends():
            if hasattr(backend, "get_group_permissions"):
                permissions.update(backend.get_group_permissions(self, obj))
        return permissions

    def get_all_permissions(self, obj=None):
        return _user_get_all_permissions(self, obj)

    def has_perm(self, perm, obj=None):
        """
        Returns True if the user has the specified permission. This method
        queries all available auth backends, but returns immediately if any
        backend returns True. Thus, a user who has permission from a single
        auth backend is assumed to have permission in general. If an object is
        provided, permissions for this specific object are checked.
        """

        # Active superusers have all permissions.
        if self.is_active and self.is_superuser:
            return True

        # Otherwise we need to check the backends.
        return _user_has_perm(self, perm, obj)

    def has_module_perms(self, app_label):
        """
        Returns True if the user has any permissions in the given app label.
        Uses pretty much the same logic as has_perm, above.
        """
        # Active superusers have all permissions.
        if self.is_active and self.is_superuser:
            return True

        return _user_has_module_perms(self, app_label)

    def email_user(self, subject, message, from_email=None):
        """
        Sends an e-mail to this User.
        """

        from django.core.mail import send_mail
        if not from_email:
            crits_config = CRITsConfig.objects().first()
            if crits_config:
                from_email = crits_config.crits_email
        send_mail(subject, message, from_email, [self.email])

    def get_username(self):
        return self.username

    '''
    def get_profile(self):
        """
        Returns site-specific profile for this user. Raises
        SiteProfileNotAvailable if this site does not allow profiles.
        """
        if not hasattr(self, '_profile_cache'):
            from django.conf import settings
            if not getattr(settings, 'AUTH_PROFILE_MODULE', False):
                raise SiteProfileNotAvailable('You need to set AUTH_PROFILE_MO'
                                              'DULE in your project settings')
            try:
                app_label, model_name = settings.AUTH_PROFILE_MODULE.split('.')
            except ValueError:
                raise SiteProfileNotAvailable('app_label and model_name should'
                        ' be separated by a dot in the AUTH_PROFILE_MODULE set'
                        'ting')

            try:
                model = models.get_model(app_label, model_name)
                if model is None:
                    raise SiteProfileNotAvailable('Unable to load the profile '
                        'model, check AUTH_PROFILE_MODULE in your project sett'
                        'ings')
                self._profile_cache = model._default_manager.using(self._state.db).get(user__id__exact=self.id)
                self._profile_cache.user = self
            except (ImportError, ImproperlyConfigured):
                raise SiteProfileNotAvailable
        return self._profile_cache
    '''

    def get_preference(self, section, setting, default=None):
        """
        Get a user preference setting out of the deep dynamic dictionary
        'section' is the preferences 'section' e.g. 'ui'
        'setting' is the dot separated preference setting  e.g. 'foo.bar.enabled'

        :param section: A specific section of preferences you want.
        :type section: str
        :param setting: The setting you want to get.
        :type setting: str
        :returns: None, str, dict
        """

        if not section in self.prefs:
            return default

        # Split the preference option into subtrees on '.'
        otree = setting.split(".")
        param = otree.pop()
        opt = self.prefs[section]

        if len(otree):
            for subsect in otree:
                if subsect in opt:
                    opt = opt[subsect]
                else:
                    return default

        if not param in opt:
            return default

        return opt[param]

    def update_from_ldap(self, analyst, config=None, passw=''):
        """
        Set First Name, Last Name, and Email from LDAP if we can get the data.
        """

        info = self.info_from_ldap(config, passw)
        if info['result'] == "OK":
            self.first_name = info['first_name']
            self.last_name = info['last_name']
            self.email = info['email']
            self.save(username=analyst)

    def info_from_ldap(self, config=None, password=''):
        """
        Get information about this user from LDAP.
        """

        import ldap, ldapurl
        resp = {"result": "ERROR"}
        if not config:
            config = CRITsConfig.objects().first()
        # Make sure we have the rquired settings, else return failure
        if not config.ldap_server or not config.ldap_userdn:
            return resp
        ldap_server = config.ldap_server.split(':')
        scheme = "ldap"
        if config.ldap_tls:
            scheme = "ldaps"
        url = ldapurl.LDAPUrl('%s://%s' % (scheme, ldap_server[0]))
        if len(ldap_server) == 2:
            l = ldap.initialize('%s:%s' % (url.unparse(), ldap_server[1]))
        else:
            l = ldap.initialize(url.unparse())
        l.protocol_version = 3
        l.set_option(ldap.OPT_REFERRALS, 0)
        l.set_option(ldap.OPT_TIMEOUT, 10)
        # setup auth for custom cn's
        cn = "cn="
        if config.ldap_usercn:
            cn = config.ldap_usercn
        # setup auth for custom cn's
        if len(config.ldap_usercn) > 0:
            un = "%s%s,%s" % (config.ldap_usercn, self.username,
                              config.ldap_userdn)
        elif "@" in config.ldap_userdn:
            un = "%s%s" % (self.username, config.ldap_userdn)
        else:
            un = self.username
        try:
            # Try auth bind first
            l.simple_bind_s(un, password)
            logger.info("Bound to LDAP for: %s" % self.username)
        except Exception, e:
            logger.error("Error binding to LDAP for: %s" % self.username)
            logger.error("ERR: %s" % e)
        try:
            uatr = None
            uatr = l.search_s(config.ldap_userdn, ldap.SCOPE_SUBTREE,
                              "(%s%s)" % (cn, self.username))[0][1]
            resp['first_name'] = uatr['givenName'][0]
            resp['last_name'] = uatr['sn'][0]
            resp['email'] = uatr['mail'][0]
            resp['result'] = "OK"
            logger.info("Retrieved LDAP info for: %s" % self.username)
        except Exception, e:
            logger.error("Error retrieving LDAP info for: %s" % self.username)
            logger.error("ERR: %s" % e)
class TestMe(Document):
    name = StringField(required=True)
    address = StringField(required=True)
    is_active = BooleanField(default=False)