<commit_before>from myuw.views.decorators import admin_required
from myuw.views import set_admin_wrapper_template
from myuw.dao.messages import clean_html
from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
import logging
from myuw.models.myuw_notice import MyuwNotice
from datetime import datetime
from myuw.dao.term import get_comparison_datetime

logger = logging.getLogger(__name__)

@login_required
@admin_required('MYUW_ADMIN_GROUP')
def create_notice(request):
    context = {}
    if request.POST:
        if _save_notice(request, context):
            return redirect('myuw_manage_notices')
    set_admin_wrapper_template(context)
    context['action'] = "save"
    return render(request, "admin/notice_edit.html", context)

@login_required
@admin_required('MYUW_ADMIN_GROUP')
def edit_notice(request, notice_id):
    context = {}
    set_admin_wrapper_template(context)
    if request.POST:
        if request.POST.get('action') == "delete":
            MyuwNotice.objects.get(id=notice_id).delete()
            return redirect("myuw_manage_notices")
        else:
            _save_notice(request, context, notice_id)
    notice = _get_notice_by_id(notice_id)
    context['notice'] = notice
    context['action'] = "edit"
    return render(request, "admin/notice_edit.html", context)

@login_required
@admin_required('MYUW_ADMIN_GROUP')
def list_notices(request):
    context = {}
    set_admin_wrapper_template(context)
    now = get_comparison_datetime(request)
    notices = MyuwNotice.objects.filter(end__gte=now).order_by('start', 'end')
    context['notices'] = notices
    return render(request, "admin/notice_list.html", context)

def _get_notice_by_id(notice_id):
    notice = MyuwNotice.objects.get(id=notice_id)
    return notice

def _get_notice_data(request, context):
    pass

def _edit_notice(request, context):
    pass

def _save_notice(request, context, notice_id=None):
    form_action = request.POST.get('action')

    has_error = False

    start_date = None
    end_date = None
    try:
        start_date = _get_datetime(request.POST.get('start_date'))
    except TypeError:
        has_error = True
        context['start_error'] = True
    if start_date is None:
        has_error = True
        context['start_error'] = True

    try:
        end_date = _get_datetime(request.POST.get('end_date'))
    except TypeError:
        has_error = True

    try:
        if end_date < start_date:
            has_error = True
            context['date_error'] = True
    except TypeError:
        pass

    notice_type = request.POST.get('notice_type')
    notice_category = request.POST.get('notice_category')
    if notice_type is None:
        has_error = True
        context['type_error'] = True
    if notice_category is None:
        has_error = True
        context['category_error'] = True

    title = None
    content = None
    try:
        title = clean_html(request.POST.get('title'))
    except TypeError:
        has_error = True
        context['title_error'] = True
    if title is not None and len(title) == 0:
        has_error = True
        context['title_error'] = True
    try:
        content = clean_html(request.POST.get('content'))
    except TypeError:
        has_error = True
        context['content_error'] = True
    if content is not None and len(content) == 0:
        has_error = True
        context['content_error'] = True

    campus_list = request.POST.getlist('campus')
    affil_list = request.POST.getlist('affil')
    if not has_error:
        if form_action == "save":
            notice = MyuwNotice(title=title,
                                content=content,
                                notice_type=notice_type,
                                notice_category=notice_category,
                                start=start_date,
                                end=end_date)
            for campus in campus_list:
                setattr(notice, campus, True)

            for affil in affil_list:
                setattr(notice, affil, True)
            notice.save()
        elif form_action == "edit":
            notice = MyuwNotice.objects.get(id=notice_id)
            notice.title = title
            notice.content = content
            notice.notice_type = notice_type
            notice.notice_category = notice_category
            notice.start = start_date
            notice.end = end_date

            # reset filters
            fields = MyuwNotice._meta.get_fields()
            for field in fields:
                if "is_" in field.name:
                    setattr(notice, field.name, False)

            for campus in campus_list:
                setattr(notice, campus, True)

            for affil in affil_list:
                setattr(notice, affil, True)
            notice.save()

        return True
    else:
        context['has_error'] = has_error
        return False

def _get_datetime(dt_string):
    try:
        dt = datetime.strptime(dt_string, "%Y-%m-%d %H:%M")
    except ValueError:
        dt = None
    return dt
<commit_msg>remove end date filtering on admin page<commit_after>from myuw.views.decorators import admin_required
from myuw.views import set_admin_wrapper_template
from myuw.dao.messages import clean_html
from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
import logging
from myuw.models.myuw_notice import MyuwNotice
from datetime import datetime
from myuw.dao.term import get_comparison_datetime

logger = logging.getLogger(__name__)

@login_required
@admin_required('MYUW_ADMIN_GROUP')
def create_notice(request):
    context = {}
    if request.POST:
        if _save_notice(request, context):
            return redirect('myuw_manage_notices')
    set_admin_wrapper_template(context)
    context['action'] = "save"
    return render(request, "admin/notice_edit.html", context)

@login_required
@admin_required('MYUW_ADMIN_GROUP')
def edit_notice(request, notice_id):
    context = {}
    set_admin_wrapper_template(context)
    if request.POST:
        if request.POST.get('action') == "delete":
            MyuwNotice.objects.get(id=notice_id).delete()
            return redirect("myuw_manage_notices")
        else:
            _save_notice(request, context, notice_id)
    notice = _get_notice_by_id(notice_id)
    context['notice'] = notice
    context['action'] = "edit"
    return render(request, "admin/notice_edit.html", context)

@login_required
@admin_required('MYUW_ADMIN_GROUP')
def list_notices(request):
    context = {}
    set_admin_wrapper_template(context)
    notices = MyuwNotice.objects.order_by('start', 'end')
    context['notices'] = notices
    return render(request, "admin/notice_list.html", context)

def _get_notice_by_id(notice_id):
    notice = MyuwNotice.objects.get(id=notice_id)
    return notice

def _get_notice_data(request, context):
    pass

def _edit_notice(request, context):
    pass

def _save_notice(request, context, notice_id=None):
    form_action = request.POST.get('action')

    has_error = False

    start_date = None
    end_date = None
    try:
        start_date = _get_datetime(request.POST.get('start_date'))
    except TypeError:
        has_error = True
        context['start_error'] = True
    if start_date is None:
        has_error = True
        context['start_error'] = True

    try:
        end_date = _get_datetime(request.POST.get('end_date'))
    except TypeError:
        has_error = True

    try:
        if end_date < start_date:
            has_error = True
            context['date_error'] = True
    except TypeError:
        pass

    notice_type = request.POST.get('notice_type')
    notice_category = request.POST.get('notice_category')
    if notice_type is None:
        has_error = True
        context['type_error'] = True
    if notice_category is None:
        has_error = True
        context['category_error'] = True

    title = None
    content = None
    try:
        title = clean_html(request.POST.get('title'))
    except TypeError:
        has_error = True
        context['title_error'] = True
    if title is not None and len(title) == 0:
        has_error = True
        context['title_error'] = True
    try:
        content = clean_html(request.POST.get('content'))
    except TypeError:
        has_error = True
        context['content_error'] = True
    if content is not None and len(content) == 0:
        has_error = True
        context['content_error'] = True

    campus_list = request.POST.getlist('campus')
    affil_list = request.POST.getlist('affil')
    if not has_error:
        if form_action == "save":
            notice = MyuwNotice(title=title,
                                content=content,
                                notice_type=notice_type,
                                notice_category=notice_category,
                                start=start_date,
                                end=end_date)
            for campus in campus_list:
                setattr(notice, campus, True)

            for affil in affil_list:
                setattr(notice, affil, True)
            notice.save()
        elif form_action == "edit":
            notice = MyuwNotice.objects.get(id=notice_id)
            notice.title = title
            notice.content = content
            notice.notice_type = notice_type
            notice.notice_category = notice_category
            notice.start = start_date
            notice.end = end_date

            # reset filters
            fields = MyuwNotice._meta.get_fields()
            for field in fields:
                if "is_" in field.name:
                    setattr(notice, field.name, False)

            for campus in campus_list:
                setattr(notice, campus, True)

            for affil in affil_list:
                setattr(notice, affil, True)
            notice.save()

        return True
    else:
        context['has_error'] = has_error
        return False

def _get_datetime(dt_string):
    try:
        dt = datetime.strptime(dt_string, "%Y-%m-%d %H:%M")
    except ValueError:
        dt = None
    return dt
<|endoftext|>


<commit_before>from django import forms
# from django.core.exceptions import ValidationError

import geral.queries
from base.forms import O2BaseForm, O2FieldRefForm, O2FieldModeloForm

class PorDepositoForm(forms.Form):
    nivel = forms.IntegerField(
        label='Nível', required=False,
        widget=forms.TextInput(attrs={'type': 'number',
                               'autofocus': 'autofocus'}))

    ref = forms.CharField(
        label='Referência ou modelo',
        required=True, min_length=1, max_length=5,
        widget=forms.TextInput(attrs={'type': 'string'}))

    tam = forms.CharField(
        label='Tamanho', required=False, min_length=1, max_length=3,
        widget=forms.TextInput(attrs={'type': 'string'}))

    cor = forms.CharField(
        label='Cor', required=False, max_length=6,
        widget=forms.TextInput(attrs={'type': 'string'}))

    CHOICES = [
        ('999', '--Todos--'),
        ('A00', '231, 101 e 102 - '
                'MAT PRIMA + PA ATACADO E VAREJO 1ª QUALI.'),
    ]
    depositos = geral.queries.deposito()
    for deposito in depositos:
        if deposito['COD'] > 1:
            CHOICES.append((
                deposito['COD'],
                '{} - {}'.format(deposito['COD'], deposito['DESCR'])
            ))
    deposito = forms.ChoiceField(
        label='Depósito', choices=CHOICES, initial='999')

    CHOICES = [
        ('rct', 'Referência/Tamanho/Cor/Depósito'),
        ('r', 'Referência/Depósito'),
        ('tc', 'Tamanho/Cor'),
        ('d', 'Depósito'),
    ]
    agrupamento = forms.ChoiceField(
        choices=CHOICES, initial='rct')

    CHOICES = [('t', 'Todos'),
               ('a', 'PA'),
               ('g', 'PG'),
               ('b', 'PB'),
               ('p', 'PG/PB'),
               ('v', 'PA/PG/PB'),
               ('m', 'MD'),
               ]
    tipo = forms.ChoiceField(
        choices=CHOICES, initial='t')

    def upper_clean(self, field_name):
        field = self.cleaned_data[field_name].upper()
        data = self.data.copy()
        data[field_name] = field
        self.data = data
        return field

    def clean_ref(self):
        return self.upper_clean('ref')

    def clean_tam(self):
        return self.upper_clean('tam')

    def clean_cor(self):
        return self.upper_clean('cor')

# def validate_nivel_mp(value):
#     if value != 2 and value != 9:
#         raise ValidationError(
#             '%(value)s não é nível de MP',
#             params={'value': value},
#         )

class ValorForm(forms.Form):
    # nivel = forms.IntegerField(
    #     label='Nível', required=False,
    #     help_text='2=Tecidos/malhas, 9=Demais materiais',
    #     validators=[validate_nivel_mp],
    #     widget=forms.TextInput(attrs={'type': 'number',
    #                            'autofocus': 'autofocus'}))
    CHOICES = [
        ('2', '2 - Tecidos/malhas'),
        ('9', '9 - Demais materiais'),
    ]
    nivel = forms.ChoiceField(
        label='Nível',
        choices=CHOICES, initial='a')

    CHOICES = [('s', 'Sim'),
               ('n', 'Não'),
               ]
    positivos = forms.ChoiceField(
        label='Quantidade positiva',
        choices=CHOICES, initial='s')

    zerados = forms.ChoiceField(
        label='Quantidade zerada',
        choices=CHOICES, initial='n')

    negativos = forms.ChoiceField(
        label='Quantidade negativa',
        choices=CHOICES, initial='n')

    preco_zerado = forms.ChoiceField(
        label='Preço zerado',
        choices=CHOICES, initial='n')

    CHOICES = [
        ('a', 'Apenas os depósitos indicados pelo Compras'),
        ('t', 'Todos os depósitos'),
    ]
    deposito_compras = forms.ChoiceField(
        label='Quanto aos depósitos',
        choices=CHOICES, initial='a')

class InventarioExpedicaoForm(forms.Form):
    data_ini = forms.DateField(
        label='Referências com movimento a partir da data:',
        widget=forms.DateInput(attrs={'type': 'date',
                               'autofocus': 'autofocus'}))

class ReferenciasEstoqueForm(
        O2BaseForm,
        O2FieldModeloForm):

    CHOICES = [
        ('-', 'TODOS (101, 102, 231)'),
        ('101', '101-PA ATACADO PRIMEIRA QUALIDADE'),
        ('102', '102-PA VAREJO PRIMEIRA QUALIDADE'),
        ('231', '231-MAT PRIMA ESTOQUE'),
    ]
    deposito = forms.ChoiceField(
        label='Depósito',
        choices=CHOICES, initial='-')

    class Meta:
        order_fields = ['deposito', 'modelo']
        autofocus_field = 'modelo'

class EditaEstoqueForm(forms.Form):
    qtd = forms.CharField(
        label='Quantidade inventariada', max_length=6, min_length=1,
        widget=forms.TextInput(attrs={'type': 'number',
                               'autofocus': 'autofocus'}))
    data = forms.DateField(
        label='Data do inventário', required=False,
        widget=forms.DateInput(attrs={'type': 'date'}, format='%Y-%m-%d'))
    hora = forms.TimeField(
        label='Hora do inventário', required=False,
        help_text='Padrão: início do dia',
        widget=forms.TimeInput(attrs={'type': 'time'}))

class MostraEstoqueForm(forms.Form):
    qtd = forms.CharField(
        label='Quantidade inventariada',
        max_length=6, min_length=1, required=False,
        widget=forms.TextInput(attrs={'type': 'number',
                               'autofocus': 'autofocus'}))
    data = forms.DateField(
        label='Data do inventário', required=False,
        widget=forms.DateInput(attrs={'type': 'date'}, format='%Y-%m-%d'))
    hora = forms.TimeField(
        label='Hora do inventário', required=False,
        help_text='Padrão: início do dia',
        widget=forms.TimeInput(attrs={'type': 'time'}))

class RecalculaEstoqueForm(forms.Form):
    ref = forms.CharField(
        label='Referência ou modelo',
        required=False, min_length=1, max_length=5,
        widget=forms.TextInput(attrs={'type': 'string',
                               'autofocus': 'autofocus'}))

    tam = forms.CharField(
        label='Tamanho', required=False, min_length=1, max_length=3,
        widget=forms.TextInput(attrs={'type': 'string'}))

    cor = forms.CharField(
        label='Cor', required=False, max_length=6,
        widget=forms.TextInput(attrs={'type': 'string'}))

    CHOICES = [
        ('101', '101-PA ATACADO PRIMEIRA QUALIDADE'),
        ('102', '102-PA VAREJO PRIMEIRA QUALIDADE'),
        ('231', '231-MAT PRIMA ESTOQUE'),
    ]
    deposito = forms.ChoiceField(
        label='Depósito', required=True,
        choices=CHOICES, initial='')

    def upper_clean(self, field_name):
        field = self.cleaned_data[field_name].upper()
        data = self.data.copy()
        data[field_name] = field
        self.data = data
        return field

    def clean_ref(self):
        return self.upper_clean('ref')

    def clean_tam(self):
        return self.upper_clean('tam')

    def clean_cor(self):
        return self.upper_clean('cor')

class EstoqueNaDataForm(forms.Form):
    data = forms.DateField(
        label='Data', required=True,
        widget=forms.DateInput(
            format='%Y-%m-%d',
            attrs={'type': 'date', 'autofocus': 'autofocus'}))

    hora = forms.TimeField(
        label='Hora', required=False,
        help_text='Padrão: início do dia',
        widget=forms.TimeInput(attrs={'type': 'time'}))

    CHOICES = [
        ('101', '101-PA ATACADO PRIMEIRA QUALIDADE'),
        ('102', '102-PA VAREJO PRIMEIRA QUALIDADE'),
        ('231', '231-MAT PRIMA ESTOQUE'),
    ]
    deposito = forms.ChoiceField(
        label='Depósito', required=True,
        choices=CHOICES, initial='')
<commit_msg>EstoqueNaDataForm: adicionado ref/co/rtam<commit_after>from django import forms
# from django.core.exceptions import ValidationError

import geral.queries
from base.forms import O2BaseForm, O2FieldRefForm, O2FieldModeloForm

class PorDepositoForm(forms.Form):
    nivel = forms.IntegerField(
        label='Nível', required=False,
        widget=forms.TextInput(attrs={'type': 'number',
                               'autofocus': 'autofocus'}))

    ref = forms.CharField(
        label='Referência ou modelo',
        required=True, min_length=1, max_length=5,
        widget=forms.TextInput(attrs={'type': 'string'}))

    tam = forms.CharField(
        label='Tamanho', required=False, min_length=1, max_length=3,
        widget=forms.TextInput(attrs={'type': 'string'}))

    cor = forms.CharField(
        label='Cor', required=False, max_length=6,
        widget=forms.TextInput(attrs={'type': 'string'}))

    CHOICES = [
        ('999', '--Todos--'),
        ('A00', '231, 101 e 102 - '
                'MAT PRIMA + PA ATACADO E VAREJO 1ª QUALI.'),
    ]
    depositos = geral.queries.deposito()
    for deposito in depositos:
        if deposito['COD'] > 1:
            CHOICES.append((
                deposito['COD'],
                '{} - {}'.format(deposito['COD'], deposito['DESCR'])
            ))
    deposito = forms.ChoiceField(
        label='Depósito', choices=CHOICES, initial='999')

    CHOICES = [
        ('rct', 'Referência/Tamanho/Cor/Depósito'),
        ('r', 'Referência/Depósito'),
        ('tc', 'Tamanho/Cor'),
        ('d', 'Depósito'),
    ]
    agrupamento = forms.ChoiceField(
        choices=CHOICES, initial='rct')

    CHOICES = [('t', 'Todos'),
               ('a', 'PA'),
               ('g', 'PG'),
               ('b', 'PB'),
               ('p', 'PG/PB'),
               ('v', 'PA/PG/PB'),
               ('m', 'MD'),
               ]
    tipo = forms.ChoiceField(
        choices=CHOICES, initial='t')

    def upper_clean(self, field_name):
        field = self.cleaned_data[field_name].upper()
        data = self.data.copy()
        data[field_name] = field
        self.data = data
        return field

    def clean_ref(self):
        return self.upper_clean('ref')

    def clean_tam(self):
        return self.upper_clean('tam')

    def clean_cor(self):
        return self.upper_clean('cor')

# def validate_nivel_mp(value):
#     if value != 2 and value != 9:
#         raise ValidationError(
#             '%(value)s não é nível de MP',
#             params={'value': value},
#         )

class ValorForm(forms.Form):
    # nivel = forms.IntegerField(
    #     label='Nível', required=False,
    #     help_text='2=Tecidos/malhas, 9=Demais materiais',
    #     validators=[validate_nivel_mp],
    #     widget=forms.TextInput(attrs={'type': 'number',
    #                            'autofocus': 'autofocus'}))
    CHOICES = [
        ('2', '2 - Tecidos/malhas'),
        ('9', '9 - Demais materiais'),
    ]
    nivel = forms.ChoiceField(
        label='Nível',
        choices=CHOICES, initial='a')

    CHOICES = [('s', 'Sim'),
               ('n', 'Não'),
               ]
    positivos = forms.ChoiceField(
        label='Quantidade positiva',
        choices=CHOICES, initial='s')

    zerados = forms.ChoiceField(
        label='Quantidade zerada',
        choices=CHOICES, initial='n')

    negativos = forms.ChoiceField(
        label='Quantidade negativa',
        choices=CHOICES, initial='n')

    preco_zerado = forms.ChoiceField(
        label='Preço zerado',
        choices=CHOICES, initial='n')

    CHOICES = [
        ('a', 'Apenas os depósitos indicados pelo Compras'),
        ('t', 'Todos os depósitos'),
    ]
    deposito_compras = forms.ChoiceField(
        label='Quanto aos depósitos',
        choices=CHOICES, initial='a')

class InventarioExpedicaoForm(forms.Form):
    data_ini = forms.DateField(
        label='Referências com movimento a partir da data:',
        widget=forms.DateInput(attrs={'type': 'date',
                               'autofocus': 'autofocus'}))

class ReferenciasEstoqueForm(
        O2BaseForm,
        O2FieldModeloForm):

    CHOICES = [
        ('-', 'TODOS (101, 102, 231)'),
        ('101', '101-PA ATACADO PRIMEIRA QUALIDADE'),
        ('102', '102-PA VAREJO PRIMEIRA QUALIDADE'),
        ('231', '231-MAT PRIMA ESTOQUE'),
    ]
    deposito = forms.ChoiceField(
        label='Depósito',
        choices=CHOICES, initial='-')

    class Meta:
        order_fields = ['deposito', 'modelo']
        autofocus_field = 'modelo'

class EditaEstoqueForm(forms.Form):
    qtd = forms.CharField(
        label='Quantidade inventariada', max_length=6, min_length=1,
        widget=forms.TextInput(attrs={'type': 'number',
                               'autofocus': 'autofocus'}))
    data = forms.DateField(
        label='Data do inventário', required=False,
        widget=forms.DateInput(attrs={'type': 'date'}, format='%Y-%m-%d'))
    hora = forms.TimeField(
        label='Hora do inventário', required=False,
        help_text='Padrão: início do dia',
        widget=forms.TimeInput(attrs={'type': 'time'}))

class MostraEstoqueForm(forms.Form):
    qtd = forms.CharField(
        label='Quantidade inventariada',
        max_length=6, min_length=1, required=False,
        widget=forms.TextInput(attrs={'type': 'number',
                               'autofocus': 'autofocus'}))
    data = forms.DateField(
        label='Data do inventário', required=False,
        widget=forms.DateInput(attrs={'type': 'date'}, format='%Y-%m-%d'))
    hora = forms.TimeField(
        label='Hora do inventário', required=False,
        help_text='Padrão: início do dia',
        widget=forms.TimeInput(attrs={'type': 'time'}))

class RecalculaEstoqueForm(forms.Form):
    ref = forms.CharField(
        label='Referência ou modelo',
        required=False, min_length=1, max_length=5,
        widget=forms.TextInput(attrs={'type': 'string',
                               'autofocus': 'autofocus'}))

    tam = forms.CharField(
        label='Tamanho', required=False, min_length=1, max_length=3,
        widget=forms.TextInput(attrs={'type': 'string'}))

    cor = forms.CharField(
        label='Cor', required=False, max_length=6,
        widget=forms.TextInput(attrs={'type': 'string'}))

    CHOICES = [
        ('101', '101-PA ATACADO PRIMEIRA QUALIDADE'),
        ('102', '102-PA VAREJO PRIMEIRA QUALIDADE'),
        ('231', '231-MAT PRIMA ESTOQUE'),
    ]
    deposito = forms.ChoiceField(
        label='Depósito', required=True,
        choices=CHOICES, initial='')

    def upper_clean(self, field_name):
        field = self.cleaned_data[field_name].upper()
        data = self.data.copy()
        data[field_name] = field
        self.data = data
        return field

    def clean_ref(self):
        return self.upper_clean('ref')

    def clean_tam(self):
        return self.upper_clean('tam')

    def clean_cor(self):
        return self.upper_clean('cor')

class EstoqueNaDataForm(forms.Form):
    ref = forms.CharField(
        label='Referência ou modelo',
        required=True, min_length=1, max_length=5,
        widget=forms.TextInput(
            attrs={'type': 'string', 'autofocus': 'autofocus'}))

    tam = forms.CharField(
        label='Tamanho', required=False, min_length=1, max_length=3,
        widget=forms.TextInput(attrs={'type': 'string'}))

    cor = forms.CharField(
        label='Cor', required=False, max_length=6,
        widget=forms.TextInput(attrs={'type': 'string'}))

    data = forms.DateField(
        label='Data', required=True,
        widget=forms.DateInput(
            format='%Y-%m-%d',
            attrs={'type': 'date'}))

    hora = forms.TimeField(
        label='Hora', required=False,
        help_text='Padrão: início do dia',
        widget=forms.TimeInput(attrs={'type': 'time'}))

    CHOICES = [
        ('101', '101-PA ATACADO PRIMEIRA QUALIDADE'),
        ('102', '102-PA VAREJO PRIMEIRA QUALIDADE'),
        ('231', '231-MAT PRIMA ESTOQUE'),
    ]
    deposito = forms.ChoiceField(
        label='Depósito', required=True,
        choices=CHOICES, initial='')

    def upper_clean(self, field_name):
        field = self.cleaned_data[field_name].upper()
        data = self.data.copy()
        data[field_name] = field
        self.data = data
        return field

    def clean_ref(self):
        return self.upper_clean('ref')

    def clean_tam(self):
        return self.upper_clean('tam')

    def clean_cor(self):
        return self.upper_clean('cor')
<|endoftext|>


<commit_before>from django.contrib.auth import get_user_model
from rest_framework import generics, parsers, response
from rest_framework.permissions import IsAuthenticated
from rest_framework.settings import api_settings
from rest_framework.status import HTTP_204_NO_CONTENT

from . import serializers
from user_management.api import authentication, permissions

User = get_user_model()

class ProfileAvatar(generics.RetrieveUpdateAPIView):
    """
    Retrieve, update & delete the authenticated user's avatar. Pass get
    parameters to retrieve a thumbnail of the avatar.

    We don't inherit from `generics.RetrieveUpdateDestroyAPIView because we
    need a custom `delete` method with no common functionality.

    Thumbnail options are specified as get parameters. Options are:
        width: Specify the width (in pixels) to resize / crop to.
        height: Specify the height (in pixels) to resize / crop to.
        crop: Whether to crop or not [1,0]
        anchor: Where to anchor the crop [t,r,b,l]
        upscale: Whether to upscale or not [1,0]

    If no options are specified the users avatar is returned.

    To crop avatar to 100x100 anchored to the top right:
        avatar?width=100&height=100&crop=1&anchor=tr
    """
    model = User
    permission_classes = (IsAuthenticated,)
    serializer_class = serializers.AvatarSerializer
    parser_classes = (parsers.MultiPartParser,)
    authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES + [
        authentication.FormTokenAuthentication,
    ]

    def get_object(self):
        return self.request.user

    def post(self, *args, **kwargs):
        """
        Browsers like to do POST with multipart forms.

        As this is a fallback, we need to allow for that.
        """
        return self.put(*args, **kwargs)

    def delete(self, request, *args, **kwargs):
        """
        Delete the user's avatar.

        We set `user.avatar = None` instead of calling `user.avatar.delete()`
        to avoid test errors with `django.inmemorystorage`.
        """
        user = self.get_object()
        user.avatar = None
        user.save()
        return response.Response(status=HTTP_204_NO_CONTENT)

class UserAvatar(generics.RetrieveUpdateAPIView):
    """
    Retrieve and update the user's avatar. Pass get parameters to
    retrieve a thumbnail of the avatar.

    Thumbnail options are specified as get parameters. Options are:
        width: Specify the width (in pixels) to resize / crop to.
        height: Specify the height (in pixels) to resize / crop to.
        crop: Whether to crop or not [1,0]
        anchor: Where to anchor the crop [t,r,b,l]
        upscale: Whether to upscale or not [1,0]

    If no options are specified the users avatar is returned.

    To crop avatar to 100x100 anchored to the top right:
        avatar?width=100&height=100&crop=1&anchor=tr
    """
    authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES + [
        authentication.FormTokenAuthentication,
    ]
    model = User
    permission_classes = (IsAuthenticated, permissions.IsAdminOrReadOnly)
    parser_classes = (parsers.MultiPartParser,)
    serializer_class = serializers.AvatarSerializer

    def post(self, *args, **kwargs):
        """
        Browsers like to do POST with multipart forms.

        As this is a fallback, we need to allow for that.
        """
        return self.put(*args, **kwargs)
<commit_msg>DRY out avatar views<commit_after>from django.contrib.auth import get_user_model
from rest_framework import generics, parsers, response
from rest_framework.permissions import IsAuthenticated
from rest_framework.settings import api_settings
from rest_framework.status import HTTP_204_NO_CONTENT

from . import serializers
from user_management.api import authentication, permissions

User = get_user_model()

class AvatarAPIViewBase(generics.RetrieveUpdateAPIView):
    """
    Base class for avatar views. Probably shouldn't be used directly.

    Instead, subclass, and at least define the `permission_classes`.

    Can retrieve, update & delete the authenticated user's avatar. Pass GET
    parameters to retrieve a thumbnail of the avatar.

    Thumbnail options are specified as get parameters. Options are:
        width: Specify the width (in pixels) to resize / crop to.
        height: Specify the height (in pixels) to resize / crop to.
        crop: Whether to crop or not [1,0]
        anchor: Where to anchor the crop [t,r,b,l]
        upscale: Whether to upscale or not [1,0]

    To crop avatar to 100x100 anchored to the top right:
        avatar?width=100&height=100&crop=1&anchor=tr

    If no options are specified the users avatar is returned.
    """
    authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES + [
        authentication.FormTokenAuthentication,
    ]
    model = User
    parser_classes = (parsers.MultiPartParser,)
    serializer_class = serializers.AvatarSerializer

    def post(self, *args, **kwargs):
        """
        Browsers like to do POST with multipart forms.

        As this is a fallback, we need to allow for that.
        """
        return self.put(*args, **kwargs)

class ProfileAvatar(AvatarAPIViewBase):
    """
    Retrieve and update the authenticated user's avatar.

    We don't inherit from `rest_framework.mixins.DestroyModelMixin` because we
    need a custom DELETE with no common functionality.
    """
    permission_classes = (IsAuthenticated,)

    def get_object(self):
        return self.request.user

    def delete(self, request, *args, **kwargs):
        """
        Delete the user's avatar.

        We set `user.avatar = None` instead of calling `user.avatar.delete()`
        to avoid test errors with `django.inmemorystorage`.
        """
        user = self.get_object()
        user.avatar = None
        user.save()
        return response.Response(status=HTTP_204_NO_CONTENT)

class UserAvatar(AvatarAPIViewBase):
    """
    Retrieve and update the user's avatar based upon `pk` in the url.

    Allow all users access to "safe" HTTP methods, but limit access to "unsafe"
    methods to users with the `is_staff` flag set.
    """
    permission_classes = (IsAuthenticated, permissions.IsAdminOrReadOnly)
<|endoftext|>


<commit_before># Copyright (C) 2010-2015 Cuckoo Foundation.
# This file is part of Cuckoo Sandbox - http://www.cuckoosandbox.org
# See the file 'docs/LICENSE' for copying permission.

import logging
import datetime

from lib.cuckoo.common.abstracts import BehaviorHandler
from lib.cuckoo.common.netlog import BsonParser

log = logging.getLogger(__name__)

class MonitorProcessLog(list):
    def __init__(self, eventstream):
        self.eventstream = eventstream
        self.first_seen = None
        self.has_apicalls = False

    def __iter__(self):
        # call_id = 0
        for event in self.eventstream:
            if event["type"] == "process":
                self.first_seen = event["first_seen"]
            elif event["type"] == "apicall":
                self.has_apicalls = True

                event["time"] = self.first_seen + datetime.timedelta(0, 0, event["time"] * 1000)

                # backwards compat with previous reports, remove if not necessary
                # event["repeated"] = 0
                # event["timestamp"] = logtime(event.pop("time"))
                # event["arguments"] = [dict(name=i, value=j) for i,j in event["arguments"].iteritems()]
                # event["return"] = convert_to_printable(cleanup_value(event.pop("return_value")))

                # event["is_success"] = bool(int(event.pop("status")))
                # event["id"] = call_id
                # call_id += 1

                # remove the type for reporting output
                del event["type"]

                # also get rid of the pid (we're below the pid in the structure)
                del event["pid"]

                yield event

    def __nonzero__(self):
        """Required for the JSON reporting module as otherwise the on-demand
        generated list of API calls would be seen as empty."""
        return self.has_apicalls

class WindowsMonitor(BehaviorHandler):
    """Parses monitor generated logs."""
    key = "processes"

    def __init__(self, *args, **kwargs):
        super(WindowsMonitor, self).__init__(*args, **kwargs)
        self.processes = []
        self.reconstructors = {}
        self.matched = False

    def handles_path(self, path):
        if path.endswith(".bson"):
            self.matched = True
            return True

    def parse(self, path):
        # Invoke parsing of current log file.
        parser = BsonParser(open(path, "rb"))

        for event in parser:
            if event["type"] == "process":
                process = dict(event)
                process["calls"] = MonitorProcessLog(parser)
                self.processes.append(process)

                self.reconstructors[process["pid"]] = BehaviorReconstructor()

            # create generic events out of the windows calls
            elif event["type"] == "apicall":
                reconstructor = self.reconstructors[event["pid"]]
                res = reconstructor.process_apicall(event)

                if res and isinstance(res, tuple):
                    res = [res]

                if res:
                    for category, arg in res:
                        yield {
                            "type": "generic",
                            "pid": event["pid"],
                            "category": category,
                            "value": arg,
                        }

            yield event

    def run(self):
        if not self.matched:
            return

        self.processes.sort(key=lambda process: process["first_seen"])
        return self.processes

def NT_SUCCESS(value):
    return value % 2**32 < 0x80000000

class BehaviorReconstructor(object):
    """Reconstructs the behavior of behavioral API logs."""
    def __init__(self):
        self.files = {}

    def process_apicall(self, event):
        fn = getattr(self, "_api_%s" % event["api"], None)
        if fn is not None:
            return fn(event["return_value"], event["arguments"])

    # Generic file & directory stuff.

    def _api_CreateDirectoryW(self, return_value, arguments):
        return ("directory_created", arguments["dirpath"])

    _api_CreateDirectoryExW = _api_CreateDirectoryW

    def _api_RemoveDirectoryA(self, return_value, arguments):
        return ("directory_removed", arguments["dirpath"])

    _api_RemoveDirectoryW = _api_RemoveDirectoryA

    def _api_MoveFileWithProgressW(self, return_value, arguments):
        return ("file_moved", dict(src=arguments["oldfilepath"],
                                   dst=arguments["newfilepath"]))

    def _api_CopyFileA(self, return_value, arguments):
        return ("file_copied", dict(src=arguments["oldfilepath"],
                                    dst=arguments["newfilepath"]))

    _api_CopyFileW = _api_CopyFileA
    _api_CopyFileExW = _api_CopyFileA

    def _api_DeleteFileA(self, return_value, arguments):
        return ("file_deleted", arguments["filepath"])

    _api_DeleteFileW = _api_DeleteFileA
    _api_NtDeleteFile = _api_DeleteFileA

    def _api_FindFirstFileExA(self, return_value, arguments):
        return ("directory_enumerated", arguments["filepath"])

    _api_FindFirstFileExW = _api_FindFirstFileExA

    # File stuff.

    def _api_NtCreateFile(self, return_value, arguments):
        if NT_SUCCESS(return_value):
            self.files[arguments["file_handle"]] = arguments["filepath"]
            return ("file_opened", arguments["filepath"])

    _api_NtOpenFile = _api_NtCreateFile

    def _api_NtReadFile(self, return_value, arguments):
        h = arguments["file_handle"]
        if NT_SUCCESS(return_value) and h in self.files:
            return ("file_read", self.files[h])

    def _api_NtWriteFile(self, return_value, arguments):
        h = arguments["file_handle"]
        if NT_SUCCESS(return_value) and h in self.files:
            return ("file_written", self.files[h])

    # Registry stuff.

    def _api_RegOpenKeyExA(self, return_value, arguments):
        return ("regkey_opened", arguments["regkey"])

    _api_RegOpenKeyExW = _api_RegOpenKeyExA
    _api_RegCreateKeyExA = _api_RegOpenKeyExA
    _api_RegCreateKeyExW = _api_RegOpenKeyExA

    def _api_RegDeleteKeyA(self, return_value, arguments):
        return ("regkey_deleted", arguments["regkey"])

    _api_RegDeleteKeyW = _api_RegDeleteKeyA
    _api_RegDeleteValueA = _api_RegDeleteKeyA
    _api_RegDeleteValueW = _api_RegDeleteKeyA
    _api_NtDeleteValueKey = _api_RegDeleteKeyA

    def _api_RegQueryValueExA(self, return_value, arguments):
        return ("regkey_read", arguments["regkey"])

    _api_RegQueryValueExW = _api_RegQueryValueExA
    _api_NtQueryValueKey = _api_RegQueryValueExA

    def _api_RegSetValueExA(self, return_value, arguments):
        return ("regkey_written", arguments["regkey"])

    _api_RegSetValueExW = _api_RegSetValueExA
    _api_NtSetValueKey = _api_RegSetValueExA

    def _api_NtClose(self, return_value, arguments):
        self.files.pop(arguments["handle"], None)

    # Network stuff.

    def _api_URLDownloadToFileW(self, return_value, arguments):
        return [
            ("downloads_file", arguments["url"]),
            ("file_opened", arguments["filepath"])
            ("file_written", arguments["filepath"])
        ]

    def _api_InternetConnectA(self, return_value, arguments):
        return ("connects_host", arguments["hostname"])

    _api_InternetConnectW = _api_InternetConnectA

    def _api_InternetOpenUrlA(self, return_value, arguments):
        return ("fetches_url", arguments["url"])

    _api_InternetOpenUrlW = _api_InternetOpenUrlA

    def _api_DnsQuery_A(self, return_value, arguments):
        if arguments["hostname"]:
            return ("resolves_host", arguments["hostname"])

    _api_DnsQuery_W = _api_DnsQuery_A
    _api_DnsQuery_UTF8 = _api_DnsQuery_A
    _api_getaddrinfo = _api_DnsQuery_A
    _api_GetAddrInfoW = _api_DnsQuery_A
    _api_gethostbyname = _api_DnsQuery_A

    def _api_connect(self, return_value, arguments):
        return ("connects_ip", arguments["ip_address"])

    # Mutex stuff

    def _api_NtCreateMutant(self, return_value, arguments):
        return ("mutex", arguments["mutant_name"])

    _api_ConnectEx = _api_connect
<commit_msg>document has-apicalls functionality<commit_after># Copyright (C) 2010-2015 Cuckoo Foundation.
# This file is part of Cuckoo Sandbox - http://www.cuckoosandbox.org
# See the file 'docs/LICENSE' for copying permission.

import logging
import datetime

from lib.cuckoo.common.abstracts import BehaviorHandler
from lib.cuckoo.common.netlog import BsonParser

log = logging.getLogger(__name__)

class MonitorProcessLog(list):
    def __init__(self, eventstream):
        self.eventstream = eventstream
        self.first_seen = None
        self.has_apicalls = False

    def __iter__(self):
        # call_id = 0
        for event in self.eventstream:
            if event["type"] == "process":
                self.first_seen = event["first_seen"]
            elif event["type"] == "apicall":
                self.has_apicalls = True

                event["time"] = self.first_seen + datetime.timedelta(0, 0, event["time"] * 1000)

                # backwards compat with previous reports, remove if not necessary
                # event["repeated"] = 0
                # event["timestamp"] = logtime(event.pop("time"))
                # event["arguments"] = [dict(name=i, value=j) for i,j in event["arguments"].iteritems()]
                # event["return"] = convert_to_printable(cleanup_value(event.pop("return_value")))

                # event["is_success"] = bool(int(event.pop("status")))
                # event["id"] = call_id
                # call_id += 1

                # remove the type for reporting output
                del event["type"]

                # also get rid of the pid (we're below the pid in the structure)
                del event["pid"]

                yield event

    def __nonzero__(self):
        """Required for the JSON reporting module as otherwise the on-demand
        generated list of API calls would be seen as empty.

        Note that the result structure is kept between processing and
        reporting time which means that at reporting time, where this
        functionality is actually needed, the has_apicalls will already have
        been set by an earlier iteration over the MonitorProcessLog. We use
        this knowledge to pass along whether or not this log actually has API
        call events and thus whether it's "nonzero" or not.
        """
        return self.has_apicalls

class WindowsMonitor(BehaviorHandler):
    """Parses monitor generated logs."""
    key = "processes"

    def __init__(self, *args, **kwargs):
        super(WindowsMonitor, self).__init__(*args, **kwargs)
        self.processes = []
        self.reconstructors = {}
        self.matched = False

    def handles_path(self, path):
        if path.endswith(".bson"):
            self.matched = True
            return True

    def parse(self, path):
        # Invoke parsing of current log file.
        parser = BsonParser(open(path, "rb"))

        for event in parser:
            if event["type"] == "process":
                process = dict(event)
                process["calls"] = MonitorProcessLog(parser)
                self.processes.append(process)

                self.reconstructors[process["pid"]] = BehaviorReconstructor()

            # Create generic events out of the windows calls.
            elif event["type"] == "apicall":
                reconstructor = self.reconstructors[event["pid"]]
                res = reconstructor.process_apicall(event)

                if res and isinstance(res, tuple):
                    res = [res]

                if res:
                    for category, arg in res:
                        yield {
                            "type": "generic",
                            "pid": event["pid"],
                            "category": category,
                            "value": arg,
                        }

            yield event

    def run(self):
        if not self.matched:
            return

        self.processes.sort(key=lambda process: process["first_seen"])
        return self.processes

def NT_SUCCESS(value):
    return value % 2**32 < 0x80000000

class BehaviorReconstructor(object):
    """Reconstructs the behavior of behavioral API logs."""
    def __init__(self):
        self.files = {}

    def process_apicall(self, event):
        fn = getattr(self, "_api_%s" % event["api"], None)
        if fn is not None:
            return fn(event["return_value"], event["arguments"])

    # Generic file & directory stuff.

    def _api_CreateDirectoryW(self, return_value, arguments):
        return ("directory_created", arguments["dirpath"])

    _api_CreateDirectoryExW = _api_CreateDirectoryW

    def _api_RemoveDirectoryA(self, return_value, arguments):
        return ("directory_removed", arguments["dirpath"])

    _api_RemoveDirectoryW = _api_RemoveDirectoryA

    def _api_MoveFileWithProgressW(self, return_value, arguments):
        return ("file_moved", dict(src=arguments["oldfilepath"],
                                   dst=arguments["newfilepath"]))

    def _api_CopyFileA(self, return_value, arguments):
        return ("file_copied", dict(src=arguments["oldfilepath"],
                                    dst=arguments["newfilepath"]))

    _api_CopyFileW = _api_CopyFileA
    _api_CopyFileExW = _api_CopyFileA

    def _api_DeleteFileA(self, return_value, arguments):
        return ("file_deleted", arguments["filepath"])

    _api_DeleteFileW = _api_DeleteFileA
    _api_NtDeleteFile = _api_DeleteFileA

    def _api_FindFirstFileExA(self, return_value, arguments):
        return ("directory_enumerated", arguments["filepath"])

    _api_FindFirstFileExW = _api_FindFirstFileExA

    # File stuff.

    def _api_NtCreateFile(self, return_value, arguments):
        if NT_SUCCESS(return_value):
            self.files[arguments["file_handle"]] = arguments["filepath"]
            return ("file_opened", arguments["filepath"])

    _api_NtOpenFile = _api_NtCreateFile

    def _api_NtReadFile(self, return_value, arguments):
        h = arguments["file_handle"]
        if NT_SUCCESS(return_value) and h in self.files:
            return ("file_read", self.files[h])

    def _api_NtWriteFile(self, return_value, arguments):
        h = arguments["file_handle"]
        if NT_SUCCESS(return_value) and h in self.files:
            return ("file_written", self.files[h])

    # Registry stuff.

    def _api_RegOpenKeyExA(self, return_value, arguments):
        return ("regkey_opened", arguments["regkey"])

    _api_RegOpenKeyExW = _api_RegOpenKeyExA
    _api_RegCreateKeyExA = _api_RegOpenKeyExA
    _api_RegCreateKeyExW = _api_RegOpenKeyExA

    def _api_RegDeleteKeyA(self, return_value, arguments):
        return ("regkey_deleted", arguments["regkey"])

    _api_RegDeleteKeyW = _api_RegDeleteKeyA
    _api_RegDeleteValueA = _api_RegDeleteKeyA
    _api_RegDeleteValueW = _api_RegDeleteKeyA
    _api_NtDeleteValueKey = _api_RegDeleteKeyA

    def _api_RegQueryValueExA(self, return_value, arguments):
        return ("regkey_read", arguments["regkey"])

    _api_RegQueryValueExW = _api_RegQueryValueExA
    _api_NtQueryValueKey = _api_RegQueryValueExA

    def _api_RegSetValueExA(self, return_value, arguments):
        return ("regkey_written", arguments["regkey"])

    _api_RegSetValueExW = _api_RegSetValueExA
    _api_NtSetValueKey = _api_RegSetValueExA

    def _api_NtClose(self, return_value, arguments):
        self.files.pop(arguments["handle"], None)

    # Network stuff.

    def _api_URLDownloadToFileW(self, return_value, arguments):
        return [
            ("downloads_file", arguments["url"]),
            ("file_opened", arguments["filepath"])
            ("file_written", arguments["filepath"])
        ]

    def _api_InternetConnectA(self, return_value, arguments):
        return ("connects_host", arguments["hostname"])

    _api_InternetConnectW = _api_InternetConnectA

    def _api_InternetOpenUrlA(self, return_value, arguments):
        return ("fetches_url", arguments["url"])

    _api_InternetOpenUrlW = _api_InternetOpenUrlA

    def _api_DnsQuery_A(self, return_value, arguments):
        if arguments["hostname"]:
            return ("resolves_host", arguments["hostname"])

    _api_DnsQuery_W = _api_DnsQuery_A
    _api_DnsQuery_UTF8 = _api_DnsQuery_A
    _api_getaddrinfo = _api_DnsQuery_A
    _api_GetAddrInfoW = _api_DnsQuery_A
    _api_gethostbyname = _api_DnsQuery_A

    def _api_connect(self, return_value, arguments):
        return ("connects_ip", arguments["ip_address"])

    # Mutex stuff

    def _api_NtCreateMutant(self, return_value, arguments):
        return ("mutex", arguments["mutant_name"])

    _api_ConnectEx = _api_connect
<|endoftext|>


<commit_before>#
# linter.py
# Part of SublimeLinter3, a code checking framework for Sublime Text 3
#
# Written by Ryan Hileman and Aparajita Fishman
#
# Project: https://github.com/SublimeLinter/SublimeLinter3
# License: MIT
#

import re
import shlex
import sublime

from . import highlight as hilite
from . import persist
from . import util

SYNTAX_RE = re.compile(r'/([^/]+)\.tmLanguage$')
WARNING_RE = re.compile(r'^w(?:arn(?:ing)?)?$', re.IGNORECASE)

class Registrar(type):
    '''This metaclass registers the linter when the class is declared.'''
    def __init__(cls, name, bases, attrs):
        if bases:
            persist.register_linter(cls, name, attrs)

class Linter(metaclass=Registrar):
    '''
    The base class for linters. Subclasses must at a minimum define
    the attributes language, cmd, and regex.
    '''

    #
    # Public attributes
    #

    # The name of the linter's language for display purposes.
    # By convention this is all lowercase.
    language = ''

    # A string, tuple or callable that returns a string or tuple, containing the
    # command line arguments used to lint.
    cmd = ''

    # If the name of the executable cannot be determined by the first element of cmd
    # (for example when cmd is a method that dynamically generates the command line arguments),
    # this can be set to the name of the executable used to do linting.
    #
    # Once the executable's name is determined, its existence is checked in the user's path.
    # If it is not available, the linter is disabled.
    executable = None

    # If the executable is available, this is set to the full path of the executable.
    # If the executable is not available, it is set an empty string.
    # Subclasses should consider this read only.
    executable_path = None

    # A regex pattern used to extract information from the linter's executable output.
    regex = ''

    # Set to True if the linter outputs multiple errors or multiline errors. When True,
    # regex will be created with the re.MULTILINE flag.
    multiline = False

    # If you want to set flags on the regex other than re.MULTILINE, set this.
    re_flags = 0

    # If the linter executable cannot receive from stdin and requires a temp file,
    # set this attribute to the suffix of the temp file (including leading '.').
    tempfile_suffix = None

    # Tab width
    tab_width = 1

    # If you want to limit the linter to specific portions of the source
    # based on a scope selector, set this attribute to the selector. For example,
    # in an html file with embedded php, you would set the selector for a php
    # linter to 'source.php'.
    selector = None

    # If you want to provide default settings for the linter, set this attribute.
    defaults = None

    #
    # Internal class storage, do not set
    #
    errors = None
    highlight = None
    lint_settings = None

    def __init__(self, view, syntax, filename=None):
        self.view = view
        self.syntax = syntax
        self.filename = filename

        if self.regex:
            if self.multiline:
                self.re_flags |= re.MULTILINE

            try:
                self.regex = re.compile(self.regex, self.re_flags)
            except:
                persist.debug('error compiling regex for {}'.format(self.language))

        self.highlight = hilite.Highlight()

    @classmethod
    def get_settings(cls):
        '''Return the default settings for this linter, merged with the user settings.'''
        linters = persist.settings.get('linters', {})
        settings = cls.defaults or {}
        settings.update(linters.get(cls.__name__, {}))
        return settings

    @property
    def settings(self):
        return self.get_settings()

    @classmethod
    def assign(cls, view, reassign=False):
        '''
        Assign a view to an instance of a linter.
        Find a linter for a specified view if possible, then add it to our view <--> lint class map and return it.
        Each view has its own linter so that linters can store persistent data about a view.
        '''
        vid = view.id()
        persist.views[vid] = view

        settings = view.settings()
        syntax = settings.get('syntax')

        if not syntax:
            cls.remove(vid)
            return

        match = SYNTAX_RE.search(syntax)

        if match:
            syntax = match.group(1)
        else:
            syntax = ''

        if syntax:
            if vid in persist.linters and persist.linters[vid] and not reassign:
                # If a linter in the set of linters for the given view
                # already handles the view's syntax, we have nothing more to do.
                for linter in tuple(persist.linters[vid]):
                    if linter.syntax == syntax:
                        return

            linters = set()

            for name, linter_class in persist.languages.items():
                if linter_class.can_lint(syntax):
                    linter = linter_class(view, syntax, view.file_name())
                    linters.add(linter)

            persist.linters[vid] = linters
            return linters

        cls.remove(vid)

    @classmethod
    def remove(cls, vid):
        '''Remove a the mapping between a view and its set of linters.'''
        if vid in persist.linters:
            for linters in persist.linters[vid]:
                linters.clear()

            del persist.linters[vid]

    @classmethod
    def reload(cls, mod=None):
        '''Reload all linters, optionally filtering by module.'''

        # Merge linter default settings with user settings
        linter_settings = persist.settings.get('linters', {})

        for name, linter in persist.languages.items():
            settings = linter_settings.get(name, {})
            defaults = (linter.defaults or {}).copy()
            defaults.update(settings)
            linter.lint_settings = defaults

        for vid, linters in persist.linters.items():
            for linter in linters:
                if mod and linter.__module__ != mod:
                    continue

                linter.clear()
                persist.linters[vid].remove(linter)
                linter = persist.languages[linter.name](linter.view, linter.syntax, linter.filename)
                persist.linters[vid].add(linter)
                linter.draw()

    @classmethod
    def text(cls, view):
        '''Returns the entire text of a view.'''
        return view.substr(sublime.Region(0, view.size()))

    @classmethod
    def get_view(cls, vid):
        '''Returns the view object with the given id.'''
        return persist.views.get(vid)

    @classmethod
    def get_linters(cls, vid):
        '''Returns a tuple of linters for the view with the given id.'''
        if vid in persist.linters:
            return tuple(persist.linters[vid])

        return ()

    @classmethod
    def get_selectors(cls, vid):
        '''Returns a list of scope selectors for all linters for the view with the given id.'''
        return [
            (linter.selector, linter)
            for linter in cls.get_linters(vid)
            if linter.selector
        ]

    @classmethod
    def lint_view(cls, vid, filename, code, sections, hit_time, callback):
        if not code or vid not in persist.linters:
            return

        linters = list(persist.linters.get(vid))

        if not linters:
            return

        filename = filename or 'untitled'

        for linter in linters:
            if linter.settings.get('disable'):
                continue

            if not linter.selector:
                linter.reset(code, filename=filename)
                linter.lint()

        selectors = Linter.get_selectors(vid)

        for sel, linter in selectors:
            linters.append(linter)

            if sel in sections:
                linter.reset(code, filename=filename)
                errors = {}

                for line_offset, left, right in sections[sel]:
                    linter.hilite.move_to(line_offset, left)
                    linter.code = code[left:right]
                    linter.errors = {}
                    linter.lint()

                    for line, error in linter.errors.items():
                        errors[line + line_offset] = error

                linter.errors = errors

        # Merge our result back to the main thread
        callback(cls.get_view(vid), linters, hit_time)

    def reset(self, code, filename=None, highlight=None):
        self.errors = {}
        self.code = code
        self.filename = filename or self.filename
        self.highlight = highlight or hilite.Highlight(self.code)

    def get_cmd(self):
        if callable(self.cmd):
            cmd = self.cmd()
        else:
            cmd = self.cmd

        if not cmd:
            return

        if isinstance(cmd, str):
            cmd = shlex.split(cmd)

        return tuple(cmd)

    def lint(self):
        if not (self.language and self.cmd and self.regex):
            raise NotImplementedError

        cmd = self.get_cmd()

        if not cmd:
            return

        output = self.run(cmd, self.code)

        if not output:
            return

        persist.debug('{} output:\n{}'.format(self.__class__.__name__, output.strip()))

        for match, row, col, length, error_type, message, near in self.find_errors(output):
            if match and row is not None:
                if error_type and WARNING_RE.match(error_type) is not None:
                    error_type = hilite.WARNING
                else:
                    error_type = hilite.ERROR

                if col is not None:
                    # Adjust column numbers to match the linter's tabs if necessary
                    if self.tab_width > 1:
                        start, end = self.highlight.full_line(row)
                        code_line = self.code[start:end]
                        diff = 0

                        for i in range(len(code_line)):
                            if code_line[i] == '\t':
                                diff += (self.tab_width - 1)

                            if col - diff <= i:
                                col = i
                                break

                    if length is None:
                        self.highlight.range(row, col, error_type=error_type)
                    else:
                        self.highlight.range(row, col, length=length, error_type=error_type)
                elif near:
                    self.highlight.near(row, near, error_type)
                else:
                    self.highlight.range(row, 0, length=0, error_type=error_type)

                self.error(row, col, message, error_type)

    def draw(self):
        self.highlight.draw(self.view)

    def clear(self):
        self.highlight.clear(self.view)

    # Helper methods

    @classmethod
    def can_lint(cls, language):
        '''
        Determines if a linter can lint a given language. Subclasses may override this
        if the built in mechanism is not sufficient, but should call super().can_list(cls, language)
        first and continue checking only if that returns True.
        '''
        can = False
        language = language.lower()

        if cls.language:
            if language == cls.language:
                can = True
            elif isinstance(cls.language, (tuple, list)) and language in cls.language:
                can = True

        if can and cls.executable_path is None:
            executable = ''

            if not callable(cls.cmd):
                if isinstance(cls.cmd, (tuple, list)):
                    executable = (cls.cmd or [''])[0]
                else:
                    executable = cls.cmd

            if not executable and cls.executable:
                executable = cls.executable

            if executable:
                cls.executable_path = util.which(executable) or ''
            else:
                cls.executable_path = ''

            can = cls.executable_path != ''
            persist.printf('{} {}'.format(
                cls.__name__,
                'enabled ({})'.format(cls.executable_path) if can
                else 'disabled, cannot locate \'{}\''.format(executable)
            ))

        return can

    def error(self, line, col, error, error_type):
        self.highlight.line(line, error_type)
        error = ((col or 0), str(error).rstrip(' .'))

        if line in self.errors:
            self.errors[line].append(error)
        else:
            self.errors[line] = [error]

    def find_errors(self, output):
        if self.multiline:
            errors = self.regex.finditer(output)

            if errors:
                for error in errors:
                    yield self.split_match(error)
            else:
                yield self.split_match(None)
        else:
            for line in output.splitlines():
                yield self.match_error(self.regex, line.strip())

    def split_match(self, match):
        if match:
            items = {'line': None, 'col': None, 'length': None, 'type': None, 'error': '', 'near': None}
            items.update(match.groupdict())
            row, col, length, error_type, error, near = [items[k] for k in ('line', 'col', 'length', 'type', 'error', 'near')]

            if row is not None:
                row = int(row) - 1

            if col is not None:
                col = int(col) - 1

            return match, row, col, length, error_type, error, near
        else:
            return match, None, None, None, None, '', None

    def match_error(self, r, line):
        return self.split_match(r.match(line))

    # Subclasses may need to override this in complex cases
    def run(self, cmd, code):
        if self.tempfile_suffix:
            return self.tmpfile(cmd, suffix=self.tempfile_suffix)
        else:
            return self.communicate(cmd, code)

    # popen wrappers
    def communicate(self, cmd, code):
        return util.communicate(cmd, code)

    def tmpfile(self, cmd, code, suffix=''):
        return util.tmpfile(cmd, code, suffix or self.tempfile_suffix)

    def tmpdir(self, cmd, files, code):
        return util.tmpdir(cmd, files, self.filename, code)

    def popen(self, cmd, env=None):
        return util.popen(cmd, env)
<commit_msg>Oops, missed an argument<commit_after>#
# linter.py
# Part of SublimeLinter3, a code checking framework for Sublime Text 3
#
# Written by Ryan Hileman and Aparajita Fishman
#
# Project: https://github.com/SublimeLinter/SublimeLinter3
# License: MIT
#

import re
import shlex
import sublime

from . import highlight as hilite
from . import persist
from . import util

SYNTAX_RE = re.compile(r'/([^/]+)\.tmLanguage$')
WARNING_RE = re.compile(r'^w(?:arn(?:ing)?)?$', re.IGNORECASE)

class Registrar(type):
    '''This metaclass registers the linter when the class is declared.'''
    def __init__(cls, name, bases, attrs):
        if bases:
            persist.register_linter(cls, name, attrs)

class Linter(metaclass=Registrar):
    '''
    The base class for linters. Subclasses must at a minimum define
    the attributes language, cmd, and regex.
    '''

    #
    # Public attributes
    #

    # The name of the linter's language for display purposes.
    # By convention this is all lowercase.
    language = ''

    # A string, tuple or callable that returns a string or tuple, containing the
    # command line arguments used to lint.
    cmd = ''

    # If the name of the executable cannot be determined by the first element of cmd
    # (for example when cmd is a method that dynamically generates the command line arguments),
    # this can be set to the name of the executable used to do linting.
    #
    # Once the executable's name is determined, its existence is checked in the user's path.
    # If it is not available, the linter is disabled.
    executable = None

    # If the executable is available, this is set to the full path of the executable.
    # If the executable is not available, it is set an empty string.
    # Subclasses should consider this read only.
    executable_path = None

    # A regex pattern used to extract information from the linter's executable output.
    regex = ''

    # Set to True if the linter outputs multiple errors or multiline errors. When True,
    # regex will be created with the re.MULTILINE flag.
    multiline = False

    # If you want to set flags on the regex other than re.MULTILINE, set this.
    re_flags = 0

    # If the linter executable cannot receive from stdin and requires a temp file,
    # set this attribute to the suffix of the temp file (including leading '.').
    tempfile_suffix = None

    # Tab width
    tab_width = 1

    # If you want to limit the linter to specific portions of the source
    # based on a scope selector, set this attribute to the selector. For example,
    # in an html file with embedded php, you would set the selector for a php
    # linter to 'source.php'.
    selector = None

    # If you want to provide default settings for the linter, set this attribute.
    defaults = None

    #
    # Internal class storage, do not set
    #
    errors = None
    highlight = None
    lint_settings = None

    def __init__(self, view, syntax, filename=None):
        self.view = view
        self.syntax = syntax
        self.filename = filename

        if self.regex:
            if self.multiline:
                self.re_flags |= re.MULTILINE

            try:
                self.regex = re.compile(self.regex, self.re_flags)
            except:
                persist.debug('error compiling regex for {}'.format(self.language))

        self.highlight = hilite.Highlight()

    @classmethod
    def get_settings(cls):
        '''Return the default settings for this linter, merged with the user settings.'''
        linters = persist.settings.get('linters', {})
        settings = cls.defaults or {}
        settings.update(linters.get(cls.__name__, {}))
        return settings

    @property
    def settings(self):
        return self.get_settings()

    @classmethod
    def assign(cls, view, reassign=False):
        '''
        Assign a view to an instance of a linter.
        Find a linter for a specified view if possible, then add it to our view <--> lint class map and return it.
        Each view has its own linter so that linters can store persistent data about a view.
        '''
        vid = view.id()
        persist.views[vid] = view

        settings = view.settings()
        syntax = settings.get('syntax')

        if not syntax:
            cls.remove(vid)
            return

        match = SYNTAX_RE.search(syntax)

        if match:
            syntax = match.group(1)
        else:
            syntax = ''

        if syntax:
            if vid in persist.linters and persist.linters[vid] and not reassign:
                # If a linter in the set of linters for the given view
                # already handles the view's syntax, we have nothing more to do.
                for linter in tuple(persist.linters[vid]):
                    if linter.syntax == syntax:
                        return

            linters = set()

            for name, linter_class in persist.languages.items():
                if linter_class.can_lint(syntax):
                    linter = linter_class(view, syntax, view.file_name())
                    linters.add(linter)

            persist.linters[vid] = linters
            return linters

        cls.remove(vid)

    @classmethod
    def remove(cls, vid):
        '''Remove a the mapping between a view and its set of linters.'''
        if vid in persist.linters:
            for linters in persist.linters[vid]:
                linters.clear()

            del persist.linters[vid]

    @classmethod
    def reload(cls, mod=None):
        '''Reload all linters, optionally filtering by module.'''

        # Merge linter default settings with user settings
        linter_settings = persist.settings.get('linters', {})

        for name, linter in persist.languages.items():
            settings = linter_settings.get(name, {})
            defaults = (linter.defaults or {}).copy()
            defaults.update(settings)
            linter.lint_settings = defaults

        for vid, linters in persist.linters.items():
            for linter in linters:
                if mod and linter.__module__ != mod:
                    continue

                linter.clear()
                persist.linters[vid].remove(linter)
                linter = persist.languages[linter.name](linter.view, linter.syntax, linter.filename)
                persist.linters[vid].add(linter)
                linter.draw()

    @classmethod
    def text(cls, view):
        '''Returns the entire text of a view.'''
        return view.substr(sublime.Region(0, view.size()))

    @classmethod
    def get_view(cls, vid):
        '''Returns the view object with the given id.'''
        return persist.views.get(vid)

    @classmethod
    def get_linters(cls, vid):
        '''Returns a tuple of linters for the view with the given id.'''
        if vid in persist.linters:
            return tuple(persist.linters[vid])

        return ()

    @classmethod
    def get_selectors(cls, vid):
        '''Returns a list of scope selectors for all linters for the view with the given id.'''
        return [
            (linter.selector, linter)
            for linter in cls.get_linters(vid)
            if linter.selector
        ]

    @classmethod
    def lint_view(cls, vid, filename, code, sections, hit_time, callback):
        if not code or vid not in persist.linters:
            return

        linters = list(persist.linters.get(vid))

        if not linters:
            return

        filename = filename or 'untitled'

        for linter in linters:
            if linter.settings.get('disable'):
                continue

            if not linter.selector:
                linter.reset(code, filename=filename)
                linter.lint()

        selectors = Linter.get_selectors(vid)

        for sel, linter in selectors:
            linters.append(linter)

            if sel in sections:
                linter.reset(code, filename=filename)
                errors = {}

                for line_offset, left, right in sections[sel]:
                    linter.hilite.move_to(line_offset, left)
                    linter.code = code[left:right]
                    linter.errors = {}
                    linter.lint()

                    for line, error in linter.errors.items():
                        errors[line + line_offset] = error

                linter.errors = errors

        # Merge our result back to the main thread
        callback(cls.get_view(vid), linters, hit_time)

    def reset(self, code, filename=None, highlight=None):
        self.errors = {}
        self.code = code
        self.filename = filename or self.filename
        self.highlight = highlight or hilite.Highlight(self.code)

    def get_cmd(self):
        if callable(self.cmd):
            cmd = self.cmd()
        else:
            cmd = self.cmd

        if not cmd:
            return

        if isinstance(cmd, str):
            cmd = shlex.split(cmd)

        return tuple(cmd)

    def lint(self):
        if not (self.language and self.cmd and self.regex):
            raise NotImplementedError

        cmd = self.get_cmd()

        if not cmd:
            return

        output = self.run(cmd, self.code)

        if not output:
            return

        persist.debug('{} output:\n{}'.format(self.__class__.__name__, output.strip()))

        for match, row, col, length, error_type, message, near in self.find_errors(output):
            if match and row is not None:
                if error_type and WARNING_RE.match(error_type) is not None:
                    error_type = hilite.WARNING
                else:
                    error_type = hilite.ERROR

                if col is not None:
                    # Adjust column numbers to match the linter's tabs if necessary
                    if self.tab_width > 1:
                        start, end = self.highlight.full_line(row)
                        code_line = self.code[start:end]
                        diff = 0

                        for i in range(len(code_line)):
                            if code_line[i] == '\t':
                                diff += (self.tab_width - 1)

                            if col - diff <= i:
                                col = i
                                break

                    if length is None:
                        self.highlight.range(row, col, error_type=error_type)
                    else:
                        self.highlight.range(row, col, length=length, error_type=error_type)
                elif near:
                    self.highlight.near(row, near, error_type)
                else:
                    self.highlight.range(row, 0, length=0, error_type=error_type)

                self.error(row, col, message, error_type)

    def draw(self):
        self.highlight.draw(self.view)

    def clear(self):
        self.highlight.clear(self.view)

    # Helper methods

    @classmethod
    def can_lint(cls, language):
        '''
        Determines if a linter can lint a given language. Subclasses may override this
        if the built in mechanism is not sufficient, but should call super().can_list(cls, language)
        first and continue checking only if that returns True.
        '''
        can = False
        language = language.lower()

        if cls.language:
            if language == cls.language:
                can = True
            elif isinstance(cls.language, (tuple, list)) and language in cls.language:
                can = True

        if can and cls.executable_path is None:
            executable = ''

            if not callable(cls.cmd):
                if isinstance(cls.cmd, (tuple, list)):
                    executable = (cls.cmd or [''])[0]
                else:
                    executable = cls.cmd

            if not executable and cls.executable:
                executable = cls.executable

            if executable:
                cls.executable_path = util.which(executable) or ''
            else:
                cls.executable_path = ''

            can = cls.executable_path != ''
            persist.printf('{} {}'.format(
                cls.__name__,
                'enabled ({})'.format(cls.executable_path) if can
                else 'disabled, cannot locate \'{}\''.format(executable)
            ))

        return can

    def error(self, line, col, error, error_type):
        self.highlight.line(line, error_type)
        error = ((col or 0), str(error).rstrip(' .'))

        if line in self.errors:
            self.errors[line].append(error)
        else:
            self.errors[line] = [error]

    def find_errors(self, output):
        if self.multiline:
            errors = self.regex.finditer(output)

            if errors:
                for error in errors:
                    yield self.split_match(error)
            else:
                yield self.split_match(None)
        else:
            for line in output.splitlines():
                yield self.match_error(self.regex, line.strip())

    def split_match(self, match):
        if match:
            items = {'line': None, 'col': None, 'length': None, 'type': None, 'error': '', 'near': None}
            items.update(match.groupdict())
            row, col, length, error_type, error, near = [items[k] for k in ('line', 'col', 'length', 'type', 'error', 'near')]

            if row is not None:
                row = int(row) - 1

            if col is not None:
                col = int(col) - 1

            return match, row, col, length, error_type, error, near
        else:
            return match, None, None, None, None, '', None

    def match_error(self, r, line):
        return self.split_match(r.match(line))

    # Subclasses may need to override this in complex cases
    def run(self, cmd, code):
        if self.tempfile_suffix:
            return self.tmpfile(cmd, code, suffix=self.tempfile_suffix)
        else:
            return self.communicate(cmd, code)

    # popen wrappers
    def communicate(self, cmd, code):
        return util.communicate(cmd, code)

    def tmpfile(self, cmd, code, suffix=''):
        return util.tmpfile(cmd, code, suffix or self.tempfile_suffix)

    def tmpdir(self, cmd, files, code):
        return util.tmpdir(cmd, files, self.filename, code)

    def popen(self, cmd, env=None):
        return util.popen(cmd, env)
<|endoftext|>


<commit_before>import logging
from datetime import datetime
from logging import Handler, LogRecord
from pathlib import Path

from rich._log_render import LogRender
from rich.console import Console
from rich.highlighter import ReprHighlighter
from rich.markup import render
from rich.text import Text

class RichHandler(Handler):
    """A logging handler that renders output with Rich. The time / level / message and file are displayed in columns.
    The level is color coded, and the message is syntax highlighted.

    Args:
        level (int, optional): Log level. Defaults to logging.NOTSET.
        console (:class:`~rich.console.Console`, optional). Optional console instance to write logs.
            Default will create a new console writing to stderr.

    """

    KEYWORDS = ["GET", "POST", "HEAD", "PUT", "DELETE", "OPTIONS", "TRACE", "PATCH"]

    def __init__(self, level: int = logging.NOTSET, console: Console = None) -> None:
        super().__init__(level=level)
        self.console = Console() if console is None else console
        self.highlighter = ReprHighlighter()
        self._log_render = LogRender(show_level=True)

    def emit(self, record: LogRecord) -> None:
        """Invoked by logging."""
        path = Path(record.pathname).name
        log_style = f"logging.level.{record.levelname.lower()}"
        message = self.format(record)
        time_format = None if self.formatter is None else self.formatter.datefmt
        log_time = datetime.fromtimestamp(record.created)

        level = Text()
        level.append(record.levelname, log_style)
        message_text = Text(message)
        message_text.highlight_words(self.KEYWORDS, "logging.keyword")
        message_text = self.highlighter(message_text)

        self.console.print(
            self._log_render(
                self.console,
                [message_text],
                log_time=log_time,
                time_format=time_format,
                level=level,
                path=path,
                line_no=record.lineno,
            )
        )

if __name__ == "__main__":  # pragma: no cover
    from time import sleep

    FORMAT = "%(message)s"
    # FORMAT = "%(asctime)-15s - %(level) - %(message)s"
    logging.basicConfig(
        level="NOTSET", format=FORMAT, datefmt="[%X] ", handlers=[RichHandler()]
    )
    log = logging.getLogger("rich")

    log.info("Server starting...")
    log.info("Listening on http://127.0.0.1:8080")
    sleep(1)

    log.info("GET /index.html 200 1298")
    log.info("GET /imgs/backgrounds/back1.jpg 200 54386")
    log.info("GET /css/styles.css 200 54386")
    log.warning("GET /favicon.ico 404 242")
    sleep(1)

    log.debug(
        "JSONRPC request\n--> %r\n<-- %r",
        {
            "version": "1.1",
            "method": "confirmFruitPurchase",
            "params": [["apple", "orange", "mangoes", "pomelo"], 1.123],
            "id": "194521489",
        },
        {"version": "1.1", "result": True, "error": None, "id": "194521489"},
    )
    log.error("Unable to find 'pomelo' in database!")
    log.info("POST /jsonrpc/ 200 65532")
    log.info("POST /admin/ 401 42234")
    log.warning("password was rejected for admin site.")
    try:
        1 / 0
    except:
        log.exception("An error of some kind occurred!")
    sleep(1)
    log.critical("Out of memory!")
    log.info("Server exited with code=-1")
<commit_msg>missing colon<commit_after>import logging
from datetime import datetime
from logging import Handler, LogRecord
from pathlib import Path

from rich._log_render import LogRender
from rich.console import Console
from rich.highlighter import ReprHighlighter
from rich.markup import render
from rich.text import Text

class RichHandler(Handler):
    """A logging handler that renders output with Rich. The time / level / message and file are displayed in columns.
    The level is color coded, and the message is syntax highlighted.

    Args:
        level (int, optional): Log level. Defaults to logging.NOTSET.
        console (:class:`~rich.console.Console`, optional): Optional console instance to write logs.
            Default will create a new console writing to stderr.

    """

    KEYWORDS = ["GET", "POST", "HEAD", "PUT", "DELETE", "OPTIONS", "TRACE", "PATCH"]

    def __init__(self, level: int = logging.NOTSET, console: Console = None) -> None:
        super().__init__(level=level)
        self.console = Console() if console is None else console
        self.highlighter = ReprHighlighter()
        self._log_render = LogRender(show_level=True)

    def emit(self, record: LogRecord) -> None:
        """Invoked by logging."""
        path = Path(record.pathname).name
        log_style = f"logging.level.{record.levelname.lower()}"
        message = self.format(record)
        time_format = None if self.formatter is None else self.formatter.datefmt
        log_time = datetime.fromtimestamp(record.created)

        level = Text()
        level.append(record.levelname, log_style)
        message_text = Text(message)
        message_text.highlight_words(self.KEYWORDS, "logging.keyword")
        message_text = self.highlighter(message_text)

        self.console.print(
            self._log_render(
                self.console,
                [message_text],
                log_time=log_time,
                time_format=time_format,
                level=level,
                path=path,
                line_no=record.lineno,
            )
        )

if __name__ == "__main__":  # pragma: no cover
    from time import sleep

    FORMAT = "%(message)s"
    # FORMAT = "%(asctime)-15s - %(level) - %(message)s"
    logging.basicConfig(
        level="NOTSET", format=FORMAT, datefmt="[%X] ", handlers=[RichHandler()]
    )
    log = logging.getLogger("rich")

    log.info("Server starting...")
    log.info("Listening on http://127.0.0.1:8080")
    sleep(1)

    log.info("GET /index.html 200 1298")
    log.info("GET /imgs/backgrounds/back1.jpg 200 54386")
    log.info("GET /css/styles.css 200 54386")
    log.warning("GET /favicon.ico 404 242")
    sleep(1)

    log.debug(
        "JSONRPC request\n--> %r\n<-- %r",
        {
            "version": "1.1",
            "method": "confirmFruitPurchase",
            "params": [["apple", "orange", "mangoes", "pomelo"], 1.123],
            "id": "194521489",
        },
        {"version": "1.1", "result": True, "error": None, "id": "194521489"},
    )
    log.error("Unable to find 'pomelo' in database!")
    log.info("POST /jsonrpc/ 200 65532")
    log.info("POST /admin/ 401 42234")
    log.warning("password was rejected for admin site.")
    try:
        1 / 0
    except:
        log.exception("An error of some kind occurred!")
    sleep(1)
    log.critical("Out of memory!")
    log.info("Server exited with code=-1")
<|endoftext|>