예제 #1
0
    def test_typeutil(self):
        # Tester la conversion de chaîne à un autre type
        self.assertEqual(str_to("c", int), 0)
        self.assertEqual(str_to("9", int), 9)

        # Tester make_iterable
        self.assertEqual(make_iterable(None), [])
        self.assertEqual(make_iterable([1, 2, 3], tuple), (1, 2, 3))

        # Tester les noms de couleur
        self.assertIn(closest_color((0, 255, 255)), ('aqua', 'cyan'))
예제 #2
0
def check_file_extension(filename, resource_path, extensions):
    """
    Renvoyer le nom d'un fichier avec l'extension correspondant à son type MIME

    :param extensions: extensions autorisées pour le renommage
    :param filename: nom de fichier
    :param resource_path: chemin du fichier de données à analyser
    """
    if os.path.exists(resource_path) and filename:
        # Réparer l'extension de fichier
        extension_add = True
        extensions = make_iterable(extensions)
        for extension in extensions:
            if filename.lower().endswith(extension.lower()):
                extension_add = False
        if extension_add:
            # Trouver le type MIME
            mime = Magic(mime=True, keep_going=True)
            mimetype = mime.from_file(resource_path)
            new_extension = guess_extension(mimetype)
            if filename and new_extension:
                filename = "{}{}".format(filename, new_extension)
                if new_extension.lower() in extensions:
                    return filename
            else:
                return None
        else:
            return filename
    return filename
예제 #3
0
파일: mailevent.py 프로젝트: artscoop/scoop
    def queue(self, recipient, typename, data=None, forced=False):
        """
        Mettre en file un événement mail

        :param recipient: utilisateur ou email
        :param typename: type d'email enregistré (voir MailType) ex. 'messaging.message.staff'
        :param data: données à attacher au mail. Les données sont agrégées si possible au données en file.
        :param forced: indique si le mail fait partie des contenus prioritaires
        :type data: dict
        :type forced: bool
        :type recipient: str | User
        :type typename: str
        """
        from scoop.messaging.models.mailtype import MailType
        # Convertir les éléments du dictionnaire passé en listes
        data = dict() if data is None else data
        mail_data = {item: make_iterable(data[item]) for item in data}
        # Créer ou récupérer un événement mail
        mail_type = MailType.objects.get_named(typename)
        kwargs = {'sent_email': recipient} if isinstance(recipient, str) else {'recipient': recipient, 'sent_email': recipient.email}
        mail, created = self.get_or_create(sent=False, forced=forced, type=mail_type, **kwargs)
        # Ajouter des données au mail en file
        for item in mail_data:
            mail.set_data(item, mail_data[item] if mail.get_data(item) is None else mail.get_data(item) + mail_data[item])
        if created is True:
            mail.minimum_time = timezone.now() + datetime.timedelta(minutes=mail.type.interval)
        mail.save()
예제 #4
0
    def post(self, authors, category, title, body, visible=True, **kwargs):
        """
        Créer un nouveau contenu

        :param authors: auteur ou liste des utilisateurs auteurs
        :param category: nom de catégorie du nouveau contenu
        :param title: titre du contenu
        :param body: texte du contenu
        :param visible: définir si le contenu est visible du public
        """
        try:
            [
                kwargs.pop(name, None) for name in
                ['authors', 'category', 'title', 'body', 'visible']
            ]
            category_instance = Category.objects.get_by_name(category)
            content, _ = self.get_or_create(category=category_instance,
                                            title=title,
                                            body=body,
                                            published=visible,
                                            **kwargs)
            authors = make_iterable(authors, list)
            content.authors.add(*authors)
            return content
        except AttributeError as e:
            print_exc(e)
            return None
예제 #5
0
파일: comment.py 프로젝트: artscoop/scoop
    def hide_from_author(self, author=None):
        """
        Rendre invisible les contenus d'un auteur

        :param author: utilisateur ou liste d'utilisateurs
        """
        if author:
            author = make_iterable(author)
            return self.filter(author__in=author).update(visible=False)
예제 #6
0
 def create_with(self, name, pictures, **kwargs):
     """ Créer un album et y intégrer une liste d'images """
     pictures = make_iterable(pictures)
     description = kwargs.get('description', '')
     author = kwargs.get('author', None)
     album = Album(name=name, description=description, author=author)
     album.save()
     album.add(pictures)
     return album
예제 #7
0
def message_on_invalid(forms, request, message, level=None, extra_tags=None):
    """ Afficher un message à l'utilisateur si un formulaire n'est pas valide """
    forms = make_iterable(forms)
    for item in forms:
        if not item.is_valid():
            messages.add_message(request,
                                 level or messages.SUCCESS,
                                 message.format(errors=error_labels(forms)),
                                 extra_tags=extra_tags)
예제 #8
0
파일: thread.py 프로젝트: artscoop/scoop
 def get_users(self, exclude=None, only_active=True):
     """ Renvoyer les utilisateurs participant au fil """
     criteria = {'user_recipients__active': True} if only_active else {}
     exclusion = {
         'id__in': map(lambda i: i.id, make_iterable(exclude))
     } if exclude else {}
     users = get_user_model().objects.filter(
         user_recipients__thread=self,
         **criteria).exclude(**exclusion).distinct()
     return users
예제 #9
0
파일: thread.py 프로젝트: artscoop/scoop
 def get_recipients(self, exclude=None, only_active=True):
     """ Renvoyer les objets Recipient du fil """
     criteria = {'active': True} if only_active else {}
     exclusion = {
         'id__in': map(lambda i: i.id, make_iterable(exclude))
     } if exclude else {}
     recipients = self.recipients.select_related(
         'user',
         'user__profile__picture').filter(**criteria).exclude(**exclusion)
     return recipients
예제 #10
0
파일: mailevent.py 프로젝트: artscoop/scoop
 def _send_mail(self, sender, to, title, text, html=None):
     """ Envoyer immédiatement un courrier """
     message = EmailMultiRelated(title, text, sender, make_iterable(to))
     if html is not None:
         message.attach_alternative(html, "text/html")
     try:
         message.send()
         return True
     except (SMTPException, SMTPResponseException):
         return False
예제 #11
0
def find_files_in_folder(path, extensions):
    """ Renvoyer tous les fichiers d'un répertoire correspondant à une ou plusieurs extensions """
    files = []
    extensions = make_iterable(extensions)
    for folder, _directories, filenames in os.walk(path):
        for filename in filenames:
            for extension in extensions:
                if filename.lower().endswith(extension):
                    files.append(join(folder, filename))
    return files
예제 #12
0
 def acknowledge(self, user=None, threads=None):
     """ Prendre connaissance de l'existence d'un fil """
     queryset = self
     if user is not None:
         queryset = queryset.filter(user=user)
     if threads is not None:
         threads = make_iterable(threads)
         queryset = queryset.filter(thread__in=threads)
     updated = self.update(acknowledged=True)
     return updated
예제 #13
0
def error_labels(forms):
    """ Renvoyer la liste des étiquettes de champs pour les erreurs d'un formulaire """
    forms = make_iterable(forms)
    labels = []
    for item in forms:
        if item.errors:
            labels += [field.label for field in item if field.errors]
    if labels:
        return humanize_join(labels, 10, "field;fields")
    else:
        return None
예제 #14
0
    def by_tags(self, tags, **kwargs):
        """
        Renvoyer les contenus ayant des étiquettes précises

        :param tags: liste de noms de tags ou liste de tags
        :param kwargs: options de filtrage supplémentaires
        """
        assert isinstance(self, (models.QuerySet, models.Manager))
        tags = make_iterable(tags, list)
        ttype = type(tags[0])
        return self.filter(tags__short_name__in=tags, **kwargs) if issubclass(
            ttype, str) else self.filter(terms__in=tags, **kwargs)
예제 #15
0
파일: thread.py 프로젝트: artscoop/scoop
 def remove_recipient(self, user):
     """ Supprimer un ou plusieurs destinataires du fil """
     for recipient in self.recipients.filter(user__in=make_iterable(user),
                                             thread=self):
         recipient.disable()
     # Fermer ou supprimer si plus assez de participants
     count = self.get_recipient_count()
     actions = {
         0: (lambda t: t.delete()),
         1: (lambda t: t.toggle(force_close=True))
     }
     actions.get(count, lambda t: t)(self)
예제 #16
0
파일: flag.py 프로젝트: artscoop/scoop
def ban_users(request, users, mail=True):
    """ Bannir les profils et alterter les utilisateurs qui ont été en contact """
    users = make_iterable(users)
    banned = []
    for user in users:
        if user.profile.ban() is True:
            Alert.objects.alert_related(user, 'user.profile.fake', 'security', {'profile': user.profile}, as_mail=mail)
            banned.append(user)
    if banned:
        messages.success(request, humanize_join(banned, 3, _("user has been banned;users have been banned")))
        return True
    else:
        messages.info(request, _("No user has been banned."))
        return False
예제 #17
0
    def is_safe(self, code2):
        """
        Renvoyer si un pays portant un code est considéré sain

        :param code2: code pays ou liste de codes pays
        :type code2: str | list | set | tuple
        """
        codes = make_iterable(code2, set)
        codes = (code.lower().strip() for code in codes)
        # Si un des pays est non safe
        if codes and codes != {""}:
            if self.filter(safe=False, code2__in=codes).exists():
                return False
        return True
예제 #18
0
    def by_category(self, categories, attribute='short_name', **kwargs):
        """
        Renvoyer les contenus correspondant à des catégories précises

        :param categories: liste de catégories ou liste de noms de catégories
        :param attribute: sur quel attribut de la classe catégorie effectuer la recherche
        """
        assert isinstance(self, (models.QuerySet, models.Manager))
        categories = make_iterable(categories, list)
        ctype = type(categories[0])
        kwargs.update({
            ('category__{}__in' if issubclass(ctype, str) else 'category__in').format(attribute):
            categories
        })
        return self.filter(**kwargs)
예제 #19
0
def has_post(request, action=None):
    """
    Renvoyer si l'objet HttpRequest contient des données POST

    :param request: requête
    :param action: nom de la donnée POST à chercher, ou liste de noms POST.
    Si action est une liste, vérifier qu'au moins une donnée est présente.
    Si action est None ou vide, vérifier uniquement que method == POST
    :rtype: bool
    """
    posted = (request.method == 'POST')
    action = make_iterable(action)
    if posted and action:
        return posted and any(name in request.POST for name in action)
    return posted
예제 #20
0
파일: thread.py 프로젝트: artscoop/scoop
 def add_recipients(self, recipients):
     """ Ajouter des destinataires au fil """
     from scoop.rogue.models import Blocklist
     # Vérifier la possibilité d'ajouter chaque destinataire
     recipients = make_iterable(recipients, set)
     for recipient in recipients:
         if Blocklist.objects.is_safe(self.author, recipient):
             recipient, created = self.recipients.get_or_create(
                 thread=self, user=recipient)
             if not created:
                 if not recipient.active:
                     recipient.enable()
             else:
                 self.population += 1
     self.save()
예제 #21
0
파일: flag.py 프로젝트: artscoop/scoop
    def flag_by_lookup(self, model_name, identifier, *args, **kwargs):
        """
        Signaler un objet via app_label.model et id

        :param model_name: nom de modèle Django
        :param identifier: identifiant de l'objet, ou identifiants
        :type identifier: int | list
        """
        identifiers = make_iterable(identifier)
        for identifier in identifiers:
            try:
                item = ContentType.get_object_for_this_type(model=model_name, pk=identifier)
                self.flag(item, **kwargs)
                return True
            except ContentType.DoesNotExist:
                return False
예제 #22
0
def default_pre_thread(sender, author, recipients, request, unique, force, **kwargs):
    """ Traiter la pré-création d'un thread """
    errors = set()
    recipients = make_iterable(recipients)
    # Ne rien faire si le quota de sujets pour user est atteint
    if Quota.objects.exceeded_threads_for(author) and not force:
        errors.add(_("You have started discussions with too much people today."))
    # Ne rien faire s'il n'y a aucun participant ou juste author
    if recipients == {author} or not recipients:
        if not force:
            errors.add(_("Cannot send a new message to nobody."))
    # Vérifier que l'expéditeur n'est pas bloqué par un destinataire
    if getattr(settings, 'MESSAGING_BLACKLIST_ENABLE', False) is True:
        for recipient in recipients:
            if not Blocklist.objects.is_safe(recipient, author):  # or recipient.rule.is_blocked(author):
                errors.add(_("User policy prevents you from talking to at least one recipient."))
    return {'messages': errors} if errors else True
예제 #23
0
파일: mail.py 프로젝트: artscoop/scoop
def default_mail_send(sender, mailtype, recipient, data, **kwargs):
    """
    Traiter la mise en file d'un nouvel événement mail

    Certains mails peuvent ne pas être envoyés dans les cas suivants :
    - L'utilisateur est en ligne et le mail est spécifique au hors-ligne
    Certains mails sont toujours envoyés :
    - Les mails avec un type dit forcé (avec une catégorie "important")
    :param recipient: L'adresse email ou l'utilisateur cible
    :type mailtype: str | MailType
    :type recipient: str | User | list
    :param data: données à joindre au mail
    """
    category_option = {
        'message': 'email_on_message',
        'staff': 'email_on_staff',
        'subscription': 'email_on_subscription'
    }

    recipients = make_iterable(recipient)
    # Récupérer l'obet MailType correspondant au mailtype passé
    mailtype = MailType.objects.get_named(mailtype) if isinstance(
        mailtype, str) else mailtype
    categories = mailtype.get_categories()
    # Recenser les cas où le mail peut, doit ou ne peut pas être envoyé
    for recipient in recipients:
        chose_to_receive = any([
            ConfigurationForm.get_option_for(recipient,
                                             category_option[category])
            for category in categories if category in category_option
        ])
        can_receive = all([
            category not in category_option for category in categories
        ])  # Si aucune catégorie correspond à une option autoriser par défaut
        must_receive = mailtype.has_category('important')
        restrict_online = False
        if not isinstance(recipient, str):
            restrict_online = recipient.is_active and recipient.is_online(
                600) and not mailtype.has_category('online')
        # Si le mail doit, ou peut être envoyé, ajouter en file
        if must_receive or ((chose_to_receive or can_receive)
                            and not restrict_online):
            MailEvent.objects.queue(recipient,
                                    mailtype.short_name,
                                    data,
                                    forced=must_receive)
예제 #24
0
파일: flag.py 프로젝트: artscoop/scoop
def remove_pictures(request, users):
    """ Retirer toutes les images d'un profil """
    users = make_iterable(users)
    destroyed = []
    for user in users:
        pictures = user.profile.get_pictures()
        count = pictures.count()
        if count > 0:
            Alert.objects.alert(user, 'user.profile.picture.invalid', 'notification', {'count': count, 'pictures': pictures})
            record.send(get_user_model(), request.user, 'content.delete.picture', user)
            pictures.delete()
            destroyed.append(user)
    if destroyed:
        messages.success(request, humanize_join(destroyed, 3, _("user has images removed;users have images removed")))
        return True
    else:
        messages.info(request, _("No picture has to be deleted."))
        return False
예제 #25
0
파일: alert.py 프로젝트: artscoop/scoop
    def alert(self,
              recipients,
              mailtype_name,
              data,
              level=0,
              as_mail=None,
              **kwargs):
        """
        Envoyer une alerte à un ou plusieurs utilisateurs

        :param recipients: utilisateurs destinataires
        :param mailtype_name: nom de code du type de courrier/alerte à envoyer, :see: messaging.models.MailType
        :param data: dictionnaire d'infos pour le rendu de l'alerte/courrier
        :param level: niveau d'urgence de l'alerte
        :param as_mail: indique si un mail récapitulatif doit être envoyé. Par défaut None=n'envoie que les alertes de sécurité
        :returns: la liste des alertes effectivement envoyées
        :rtype: list<Alert>
        """
        from scoop.messaging.models.mailtype import MailType
        # Maximum de 1000 membres à qui envoyer l'alerte
        recipients = make_iterable(recipients)[0:1000]
        context = default_context()
        mailtype = MailType.objects.get_named(mailtype_name)
        template = 'messaging/alert/{name}.html'.format(name=mailtype.template)
        title, html = [
            render_block_to_string(template, label, data, context=context)
            for label in ['title', 'html']
        ]
        as_mail = level == Alert.SECURITY if as_mail is None else as_mail
        alerts = []
        # Créer une alerte pour chacun des destinataires
        for recipient in recipients:
            new_alert = self.create(user=recipient,
                                    title=one_line(title),
                                    text=html,
                                    level=level)
            alerts.append(new_alert)
            if as_mail is True:
                mailable_event.send(sender=None,
                                    mailtype=mailtype_name,
                                    recipient=recipient,
                                    data=data)
        return alerts
예제 #26
0
def form(request, config, initial=None):
    """
    Créer un formulaire initialisé selon l'état de la requête.

    Si request contient des données POST, créer le formulaire avec ces données.
    Exemple :
    >> a, b, c = form(request, ((A, None), (B, {'instance': y}), (C, {'instance': z})), initial=None)
    >> [a] = form(request, {A: {'instance': x}})
    
    :param request: requête HTTP
    :param config: Configuration des formulaires
    :type config: Form or list[Form] or collections.OrderedDict or tuple[tuple] or dict(len=1) or list[list]
    :param initial: Valeurs des champs par défaut en l'absence de POST
    :returns: une liste de formulaires ou None
    :rtype: list
    """
    forms = list()
    config = make_iterable(config, list)
    if is_iterable(config) and not is_multi_dimensional(config):
        config = OrderedDict(((item, None) for item in config))
    else:
        config = OrderedDict(config)
    for form_class in config.keys():
        args, kwargs = list(), dict()
        # Réunir les arguments d'initialisation du formulaire
        if request and request.has_post():
            args.append(request.POST)
            args.append(request.FILES)
        elif initial is not None:
            if isinstance(initial, QueryDict):  # Charger des données POST
                args.append(initial.dict())
            else:
                kwargs['initial'] = _normalize_initial(initial, form_class)
        if isclass(form_class) and issubclass(
                form_class, ModelForm) and config[form_class] is not None:
            kwargs['instance'] = config[form_class]
        # Vérifier que le formulaire fonctionne avec initial
        temp_form = form_class(*args, **kwargs)
        temp_form.request = request
        forms.append(temp_form)
    # Renvoyer les formulaires
    return forms if forms else None
예제 #27
0
파일: label.py 프로젝트: artscoop/scoop
    def get_item_count(self, model_list, per_class=False):
        """
        Renvoyer le nombre d'instances d'un ou plusieurs modèles avec cette étiquette

        :param per_class: renvoyer un dictionnaire avec le nombre d'instances par classe
        :type per_class: bool
        :param model_list: classe(s) de modèles avec étiquette à recenser
        :type model_list: list | models.Model
        :returns: un dictionnaire {Model:int} ou int
        """
        count = {} if per_class else 0
        model_list = make_iterable(model_list)
        for model in model_list:
            if issubclass(model, LabelableModel):
                total = model.objects.filter(labels=self).count()
                if per_class is True:
                    count[model] = total
                else:
                    count = count + total
        return count
예제 #28
0
def batch_execute(path, extensions, command):
    """
    Exécuter une commande shell sur tous les fichers de <path> correspondant aux

    extensions passées en paramètre (liste ou simple chaîne)
    :param command: chaîne contenant la commande à exécuter sur chaque fichier.
    Autorise l'utilisation du placeholder {file} pour indiquer le nom de fichier
    """
    total_processed = 0
    for root, _dummy, files in os.walk(path):
        for f in files:
            for extension in make_iterable(extensions):
                if f.lower().endswith(extension.lower()):
                    for i, _dummyx in enumerate(command):
                        command[i] = command[i].format(
                            file=os.path.join(path, root, f))
                    subprocess.call(command)
                    total_processed += 1
    logger.info("Batch executed successfully on {count} files.".format(
        count=total_processed))
예제 #29
0
    def block_ips(self, ips, harm=3, category=0, description=None):
        """
        Bloquer une ou plusieurs adresse IP

        :param ips: id ou instance d'IP ou chaîne au format A.B.C.D
        :type ips: list | tuple | set | IP | str | int
        :returns: les nouveaux blocages d'IP
        :param harm: niveau de danger de la plage, entre 0 et 3
        :param category: type de blocage, voir IPBlock
        :param description: description et raison du blocage
        """
        from scoop.user.access.models.ip import IP
        ips = make_iterable(ips)
        new_blocks = []
        for ip in ips:
            try:
                # Convertir en  une instance d'IP
                if isinstance(ip, str):
                    ip = IP.objects.get_by_ip(ip)
                elif isinstance(ip, int):
                    ip = IP.objects.get(id=ip)
                elif isinstance(ip, IP):
                    ip = ip
                else:
                    raise TypeError("IPs must be strings, ints or IPs.")
                if not ip.is_protected():
                    block, created = self.get_or_create(type=IPBlock.SINGLE,
                                                        ip1=ip.ip,
                                                        isp=ip.isp,
                                                        harm=harm,
                                                        category=category,
                                                        description=description
                                                        or "")
                    if created is False:
                        block.active = True
                        block.save()
                    else:
                        new_blocks.append(block)
            except TypeError:
                pass
            return new_blocks
예제 #30
0
 def add(self, pictures):
     """ Insérer une image dans l'album """
     pictures = make_iterable(pictures)
     for picture in pictures:
         AlbumPicture.objects.get_or_create(album=self, picture=picture)
     self.save()  # Mettre à jour l'état pictured