<commit_before>#!/usr/bin/python3
# -*- encoding: utf-8 -*-
# PKGBUILDer v3.0.0
# An AUR helper (and library) in Python 3.
# Copyright © 2011-2013, Kwpolska.
# See /LICENSE for licensing information.

"""
    pkgbuilder.upgrade
    ~~~~~~~~~~~~~~~~~~

    Tools for performing upgrades of AUR packages.

    :Copyright: © 2011-2013, Kwpolska.
    :License: BSD (see /LICENSE).
"""

from . import DS, _
from pkgbuilder.exceptions import SanityError
import pkgbuilder.build
import pkgbuilder.utils
import pyalpm
import datetime
import subprocess
import textwrap

__all__ = ['gather_foreign_pkgs', 'list_upgradable', 'auto_upgrade']

def gather_foreign_pkgs():
    """Gathers a list of all foreign packages."""
    localdb = DS.pyc.get_localdb()
    # Based on paconky.py.
    installed = [p for p in localdb.pkgcache]
    repo = []
    aur = []
    syncdbs = DS.pyc.get_syncdbs()
    for sdb in syncdbs:
        for ipkg in installed:
            if sdb.get_pkg(ipkg.name):
                repo.append(ipkg)

    aur = set(set(installed) - set(repo))
    # Return foreign packages.
    return dict([(p.name, p) for p in aur])

def list_upgradable(pkglist, vcsup=False, aurcache=None):
    """Compares package versions and returns upgradable ones."""
    localdb = DS.pyc.get_localdb()
    if aurcache:
        aurlist = aurcache
    else:
        aurlist = pkgbuilder.utils.info(pkglist)
        # It’s THAT easy.  Oh, and by the way: it is much, MUCH faster
        # than others.  It makes ONE multiinfo request rather than
        # len(installed_packages) info requests.

    upgradable = []
    downgradable = []

    for rpkg in aurlist:
        lpkg = localdb.get_pkg(rpkg.name)
        if lpkg is not None:
            vc = pyalpm.vercmp(rpkg.version, lpkg.version)
            if vc > 0:
                upgradable.append([rpkg.name, lpkg.version, rpkg.version])
            elif vc < 0:
                # If the package version is a date or the name ends in
                # -{git,hg,bzr,svn,cvs,darcs}, do not mark it as downgradable.
                # BTW: the above is yours truly’s list of VCS preference, if
                # you added big a gap between git and hg and then HUGE gaps
                # between everything else.

                try:
                    # For epoch packages.  Also, cheating here.
                    v = rpkg.version.split(':')[1]
                except IndexError:
                    v = rpkg.version

                try:
                    datetime.datetime.strptime(v.split('-')[0], '%Y%m%d')
                    datever = True
                except:
                    datever = False

                dt = datetime.date.today().strftime('%Y%m%d')

                if (rpkg.name.endswith(('git', 'hg', 'bzr', 'svn', 'cvs',
                                        'darcs'))):
                    if vcsup:
                        upgradable.append([rpkg.name, lpkg.version, dt])
                    else:
                        DS.log.warning('{0} is -[vcs], ignored for '
                                       'downgrade.'.format(rpkg.name))
                elif datever:
                    if vcsup:
                        upgradable.append([rpkg.name, lpkg.version, dt])
                    else:
                        DS.log.warning('{0} version is a date, ignored '
                                       'for downgrade.'.format(rpkg.name))
                else:
                    downgradable.append([rpkg.name, lpkg.version,
                                         rpkg.version])
    return [upgradable, downgradable]

def auto_upgrade(downgrade=False, vcsup=False):
    """
    Human friendly upgrade question and output.

    Returns packages — should be passed over to builder functions.
    """
    DS.log.info('Ran auto_upgrade.')
    if DS.pacman:
        print(':: ' + _('Synchronizing package databases...'))
    else:
        DS.fancy_msg(_('Synchronizing package databases...'))

    foreign = gather_foreign_pkgs()
    gradable = list_upgradable(foreign.keys(), vcsup)
    upgradable = gradable[0]
    downgradable = gradable[1]
    upglen = len(upgradable)
    downlen = len(downgradable)

    if DS.pacman:
        print(':: ' + _('Starting full system upgrade...'))
    else:
        DS.fancy_msg(_('Starting full system upgrade...'))

    if downlen > 0:
        for i in downgradable:
            if DS.pacman:
                print(_('{0}: local ({1}) is newer than aur '
                        '({2})').format(*i))
            else:
                DS.fancy_warning(_('{0}: local ({1}) is newer than aur '
                                   '({2})').format(*i))

        if downgrade:
            upglen = upglen + downlen
            upgradable = upgradable + downgradable

    if upglen == 0:
        if DS.pacman:
            print(' ' + _('there is nothing to do'))
        else:
            DS.fancy_msg2(_('there is nothing to do'))

        return []

    upgnames = [i[0] for i in upgradable]
    upgstrings = [i[0] + '-' + i[2] for i in upgradable]

    verbosepkglists = False
    with open('/etc/pacman.conf') as fh:
        for i in fh.read().split('\n'):
            if i.strip() == 'VerbosePkgLists':
                verbosepkglists = True
                break

    if upglen > 0:
        if 'pkgbuilder' in upgnames or 'pkgbuilder-git' in upgnames:
            if 'pkgbuilder' in upgnames:
                pkgbname = 'pkgbuilder'
            elif 'pkgbuilder-git' in upgnames:
                pkgbname = 'pkgbuilder-git'
            else:
                raise SanityError('if goes apeshit', 'syu-safeupgrade')

            if DS.pacman:
                print(':: ' + _('The following packages should be upgraded '
                               'first:'))
                print('    {0}'.format(pkgbname))
                print(':: ' + _('Do you want to cancel the current operation'))
                query = ':: ' + _('and upgrade these packages now? [Y/n] ')
            else:
                DS.fancy_warning(_('The following packages should be upgraded '
                                   'first:'))
                DS.fancy_msg2(pkgbname)
                query = (DS.colors['green'] + '==>' + DS.colors['all_off'] +
                         DS.colors['bold'] + ' ' +
                         _('Do you want to cancel the current operation and '
                           'upgrade these packages now? [Y/n] ') +
                         DS.colors['all_off'])

            yesno = input(query)

            if yesno.lower().strip().startswith('y') or yesno.strip() == '':
                pkgbuilder.build.safeupgrade(pkgbname)
                # The return causes PKGBUILDer.main() to quit and do nothing.
                # The else is unnecessary, as we drop to a regular upgrade
                # if the luser says “no”.
                return []

        if DS.pacman:
            targetstring = _('Targets ({0}): ').format(upglen)

            size = subprocess.check_output(['stty', 'size'])
            try:
                termwidth = int(size.split()[1])
            except IndexError:
                if verbosepkglists:
                    # Pacman doesn’t allow tables if the terminal is too small.
                    # And since we don’t know the size, better safe than sorry.
                    verbosepkglists = False
                    DS.log.warning('VerbosePkgLists disabled, cannot '
                                   'determine terminal width')
                else:
                    termwidth = 9001  # Auto-wrap by terminal.
            if verbosepkglists:
                headers = [_('Name'), _('Old Version'), _('New Version')]
                items = upgradable  # Magical.

                sizes = [len(i) for i in headers]

                for n, ov, nv in items:
                    if len(n) > sizes[0]:
                        sizes[0] = len(n)

                    if len(ov) > sizes[1]:
                        sizes[1] = len(ov)

                    if len(nv) > sizes[2]:
                        sizes[2] = len(nv)

                fstring = ('{{i[0]:<{s[0]}}}  {{i[1]:<{s[1]}}}  '
                           '{{i[2]:<{s[2]}}}').format(s=sizes)

                if len(fstring.format(i=4 * ['n'])) > termwidth:
                    verbosepkglists = False
                    DS.log.warning('VerbosePkgLists disabled, terminal is '
                                   'not wide enough')
                else:
                    print('\n{0}\n'.format(targetstring.strip()))
                    print(fstring.format(i=headers))
                    print()

                    for i in items:
                        print(fstring.format(i=i))

            # Not using else because there is a fallback if the terminal
            # is too small.
            if not verbosepkglists:
                nowrap = targetstring + '  '.join(upgstrings)
                wrapv = textwrap.wrap(nowrap, termwidth,
                                      break_on_hyphens=False)
                wrap0 = wrapv[0]
                wraprest = textwrap.wrap('\n'.join(wrapv[1:]), termwidth -
                                         len(targetstring),
                                         break_on_hyphens=False)
                wraprest = [i.replace('  ', ' ').replace(' ', '  ') for i
                            in wraprest]
                print(wrap0)
                for i in wraprest:
                    print(len(targetstring) * ' ' + i)

            print()
            query = ':: ' + _('Proceed with installation? [Y/n] ')
        else:
            DS.fancy_msg(_('Targets ({0}): ').format(upglen))
            DS.fancy_msg2('  '.join(upgstrings))
            query = (DS.colors['green'] + '==>' + DS.colors['all_off'] +
                     DS.colors['bold'] + ' ' +
                     _('Proceed with installation? [Y/n] ') +
                     DS.colors['all_off'])

        yesno = input(query)

        if yesno.lower().strip().startswith('y') or yesno.strip() == '':
            return upgnames
        else:
            return []
<commit_msg>typo<commit_after>#!/usr/bin/python3
# -*- encoding: utf-8 -*-
# PKGBUILDer v3.0.0
# An AUR helper (and library) in Python 3.
# Copyright © 2011-2013, Kwpolska.
# See /LICENSE for licensing information.

"""
    pkgbuilder.upgrade
    ~~~~~~~~~~~~~~~~~~

    Tools for performing upgrades of AUR packages.

    :Copyright: © 2011-2013, Kwpolska.
    :License: BSD (see /LICENSE).
"""

from . import DS, _
from pkgbuilder.exceptions import SanityError
import pkgbuilder.build
import pkgbuilder.utils
import pyalpm
import datetime
import subprocess
import textwrap

__all__ = ['gather_foreign_pkgs', 'list_upgradable', 'auto_upgrade']

def gather_foreign_pkgs():
    """Gathers a list of all foreign packages."""
    localdb = DS.pyc.get_localdb()
    # Based on paconky.py.
    installed = [p for p in localdb.pkgcache]
    repo = []
    aur = []
    syncdbs = DS.pyc.get_syncdbs()
    for sdb in syncdbs:
        for ipkg in installed:
            if sdb.get_pkg(ipkg.name):
                repo.append(ipkg)

    aur = set(set(installed) - set(repo))
    # Return foreign packages.
    return dict([(p.name, p) for p in aur])

def list_upgradable(pkglist, vcsup=False, aurcache=None):
    """Compares package versions and returns upgradable ones."""
    localdb = DS.pyc.get_localdb()
    if aurcache:
        aurlist = aurcache
    else:
        aurlist = pkgbuilder.utils.info(pkglist)
        # It’s THAT easy.  Oh, and by the way: it is much, MUCH faster
        # than others.  It makes ONE multiinfo request rather than
        # len(installed_packages) info requests.

    upgradable = []
    downgradable = []

    for rpkg in aurlist:
        lpkg = localdb.get_pkg(rpkg.name)
        if lpkg is not None:
            vc = pyalpm.vercmp(rpkg.version, lpkg.version)
            if vc > 0:
                upgradable.append([rpkg.name, lpkg.version, rpkg.version])
            elif vc < 0:
                # If the package version is a date or the name ends in
                # -{git,hg,bzr,svn,cvs,darcs}, do not mark it as downgradable.
                # BTW: the above is yours truly’s list of VCS preference, if
                # you added big a gap between git and hg and then HUGE gaps
                # between everything else.

                try:
                    # For epoch packages.  Also, cheating here.
                    v = rpkg.version.split(':')[1]
                except IndexError:
                    v = rpkg.version

                try:
                    datetime.datetime.strptime(v.split('-')[0], '%Y%m%d')
                    datever = True
                except:
                    datever = False

                dt = datetime.date.today().strftime('%Y%m%d-1')

                if (rpkg.name.endswith(('git', 'hg', 'bzr', 'svn', 'cvs',
                                        'darcs'))):
                    if vcsup:
                        upgradable.append([rpkg.name, lpkg.version, dt])
                    else:
                        DS.log.warning('{0} is -[vcs], ignored for '
                                       'downgrade.'.format(rpkg.name))
                elif datever:
                    if vcsup:
                        upgradable.append([rpkg.name, lpkg.version, dt])
                    else:
                        DS.log.warning('{0} version is a date, ignored '
                                       'for downgrade.'.format(rpkg.name))
                else:
                    downgradable.append([rpkg.name, lpkg.version,
                                         rpkg.version])
    return [upgradable, downgradable]

def auto_upgrade(downgrade=False, vcsup=False):
    """
    Human friendly upgrade question and output.

    Returns packages — should be passed over to builder functions.
    """
    DS.log.info('Ran auto_upgrade.')
    if DS.pacman:
        print(':: ' + _('Synchronizing package databases...'))
    else:
        DS.fancy_msg(_('Synchronizing package databases...'))

    foreign = gather_foreign_pkgs()
    gradable = list_upgradable(foreign.keys(), vcsup)
    upgradable = gradable[0]
    downgradable = gradable[1]
    upglen = len(upgradable)
    downlen = len(downgradable)

    if DS.pacman:
        print(':: ' + _('Starting full system upgrade...'))
    else:
        DS.fancy_msg(_('Starting full system upgrade...'))

    if downlen > 0:
        for i in downgradable:
            if DS.pacman:
                print(_('{0}: local ({1}) is newer than aur '
                        '({2})').format(*i))
            else:
                DS.fancy_warning(_('{0}: local ({1}) is newer than aur '
                                   '({2})').format(*i))

        if downgrade:
            upglen = upglen + downlen
            upgradable = upgradable + downgradable

    if upglen == 0:
        if DS.pacman:
            print(' ' + _('there is nothing to do'))
        else:
            DS.fancy_msg2(_('there is nothing to do'))

        return []

    upgnames = [i[0] for i in upgradable]
    upgstrings = [i[0] + '-' + i[2] for i in upgradable]

    verbosepkglists = False
    with open('/etc/pacman.conf') as fh:
        for i in fh.read().split('\n'):
            if i.strip() == 'VerbosePkgLists':
                verbosepkglists = True
                break

    if upglen > 0:
        if 'pkgbuilder' in upgnames or 'pkgbuilder-git' in upgnames:
            if 'pkgbuilder' in upgnames:
                pkgbname = 'pkgbuilder'
            elif 'pkgbuilder-git' in upgnames:
                pkgbname = 'pkgbuilder-git'
            else:
                raise SanityError('if goes apeshit', 'syu-safeupgrade')

            if DS.pacman:
                print(':: ' + _('The following packages should be upgraded '
                               'first:'))
                print('    {0}'.format(pkgbname))
                print(':: ' + _('Do you want to cancel the current operation'))
                query = ':: ' + _('and upgrade these packages now? [Y/n] ')
            else:
                DS.fancy_warning(_('The following packages should be upgraded '
                                   'first:'))
                DS.fancy_msg2(pkgbname)
                query = (DS.colors['green'] + '==>' + DS.colors['all_off'] +
                         DS.colors['bold'] + ' ' +
                         _('Do you want to cancel the current operation and '
                           'upgrade these packages now? [Y/n] ') +
                         DS.colors['all_off'])

            yesno = input(query)

            if yesno.lower().strip().startswith('y') or yesno.strip() == '':
                pkgbuilder.build.safeupgrade(pkgbname)
                # The return causes PKGBUILDer.main() to quit and do nothing.
                # The else is unnecessary, as we drop to a regular upgrade
                # if the luser says “no”.
                return []

        if DS.pacman:
            targetstring = _('Targets ({0}): ').format(upglen)

            size = subprocess.check_output(['stty', 'size'])
            try:
                termwidth = int(size.split()[1])
            except IndexError:
                if verbosepkglists:
                    # Pacman doesn’t allow tables if the terminal is too small.
                    # And since we don’t know the size, better safe than sorry.
                    verbosepkglists = False
                    DS.log.warning('VerbosePkgLists disabled, cannot '
                                   'determine terminal width')
                else:
                    termwidth = 9001  # Auto-wrap by terminal.
            if verbosepkglists:
                headers = [_('Name'), _('Old Version'), _('New Version')]
                items = upgradable  # Magical.

                sizes = [len(i) for i in headers]

                for n, ov, nv in items:
                    if len(n) > sizes[0]:
                        sizes[0] = len(n)

                    if len(ov) > sizes[1]:
                        sizes[1] = len(ov)

                    if len(nv) > sizes[2]:
                        sizes[2] = len(nv)

                fstring = ('{{i[0]:<{s[0]}}}  {{i[1]:<{s[1]}}}  '
                           '{{i[2]:<{s[2]}}}').format(s=sizes)

                if len(fstring.format(i=4 * ['n'])) > termwidth:
                    verbosepkglists = False
                    DS.log.warning('VerbosePkgLists disabled, terminal is '
                                   'not wide enough')
                else:
                    print('\n{0}\n'.format(targetstring.strip()))
                    print(fstring.format(i=headers))
                    print()

                    for i in items:
                        print(fstring.format(i=i))

            # Not using else because there is a fallback if the terminal
            # is too small.
            if not verbosepkglists:
                nowrap = targetstring + '  '.join(upgstrings)
                wrapv = textwrap.wrap(nowrap, termwidth,
                                      break_on_hyphens=False)
                wrap0 = wrapv[0]
                wraprest = textwrap.wrap('\n'.join(wrapv[1:]), termwidth -
                                         len(targetstring),
                                         break_on_hyphens=False)
                wraprest = [i.replace('  ', ' ').replace(' ', '  ') for i
                            in wraprest]
                print(wrap0)
                for i in wraprest:
                    print(len(targetstring) * ' ' + i)

            print()
            query = ':: ' + _('Proceed with installation? [Y/n] ')
        else:
            DS.fancy_msg(_('Targets ({0}): ').format(upglen))
            DS.fancy_msg2('  '.join(upgstrings))
            query = (DS.colors['green'] + '==>' + DS.colors['all_off'] +
                     DS.colors['bold'] + ' ' +
                     _('Proceed with installation? [Y/n] ') +
                     DS.colors['all_off'])

        yesno = input(query)

        if yesno.lower().strip().startswith('y') or yesno.strip() == '':
            return upgnames
        else:
            return []
<|endoftext|>


<commit_before>#
# Copyright (c) 2015 Red Hat
# Licensed under The MIT License (MIT)
# http://opensource.org/licenses/MIT
#
from django.conf import settings
from django.core.exceptions import ValidationError
from django.views.generic import ListView, DetailView

from rest_framework import viewsets, status
from rest_framework.response import Response

from pdc.apps.common.viewsets import StrictQueryParamMixin
from . import models
from .filters import ChangesetFilterSet
from .serializers import ChangesetSerializer

class ChangesetListView(ListView):
    queryset = models.Changeset.objects.all().order_by('-committed_on')
    allow_empty = True
    template_name = 'changeset_list.html'
    context_object_name = 'changeset_list'
    paginate_by = settings.ITEMS_PER_PAGE

class ChangesetDetailView(DetailView):
    model = models.Changeset
    pk_url_kwarg = "id"
    template_name = "changeset_detail.html"

class ChangesetViewSet(StrictQueryParamMixin,
                       viewsets.ReadOnlyModelViewSet):
    """
    ##Overview##

    This page shows the usage of the **Changeset API**, please see the
    following for more details.
    """

    def list(self, request, *args, **kwargs):
        """
        ### LIST

        __Method__:
        GET

        __URL__: $LINK:changeset-list$

        __Query Params__:

        %(FILTERS)s

        The dates for `changed_since` and `changed_until` should have one these
        formats:

            Format               | Example
            ---------------------+---------------------------
            %%Y-%%m-%%d %%H:%%M:%%S    | 2006-10-25 14:30:59
            %%Y-%%m-%%d %%H:%%M:%%S.%%f | 2006-10-25 14:30:59.000200
            %%Y-%%m-%%d %%H:%%M       | 2006-10-25 14:30
            %%Y-%%m-%%d             | 2006-10-25

        Resource names for `resource` should be specified in all lower case.

        __Response__: a paged list of following objects

        %(SERIALIZER)s

        The unit for duration is second.

        __Example__:

            curl -H "Content-Type: application/json"  -X GET $URL:changeset-list$
            # output
            {
                "count": 84,
                "next": "$URL:changeset-list$?page=2",
                "previous": null,
                "results": [
                    {
                        {
                            "author": "xxx",
                            "requested_on": "2015-02-03T05:50:49.387Z",
                            "committed_on": "2015-02-03T05:51:17.262Z",
                            "duration": "27.875",
                            "changes": [
                                {
                                    "id": 1
                                    "resource": "person",
                                    "resource_id": "2",
                                    "old_value": "old",
                                    "new_value": "new"
                                }
                            ],
                            "comment": "xxx"
                        }
                    },
                    ...
                ]
            }

        With query params:

            curl -H "Content-Type: application/json"  -G $URL:changeset-list$ --data-urlencode "resource=test"
            # output
            {
                "count": 1,
                "next": null,
                "previous": null,
                "results": [
                        {
                            "id": 1
                            "author": "xxx",
                            "requested_on": "2015-02-03T05:50:49.387Z",
                            "committed_on": "2015-02-03T05:51:17.262Z",
                            "duration": "27.875",
                            "changes": [
                                {
                                    "resource": "person",
                                    "resource_id": "2",
                                    "old_value": "old",
                                    "new_value": "new"
                                }
                            ],
                            "comment": "xxx"
                        }
                ]
            }
        """
        try:
            return super(ChangesetViewSet, self).list(request, *args, **kwargs)
        except ValidationError as exc:
            msg = exc.messages if hasattr(exc, 'messages') else str(exc)
            return Response({'detail': msg},
                            status=status.HTTP_400_BAD_REQUEST)

    def retrieve(self, request, *args, **kwargs):
        """
        ### RETRIEVE

        __Method__:
        GET

        __URL__: $LINK:changeset-detail:instance_pk$

        __Response__:

        %(SERIALIZER)s

        The unit for duration is second.

        __Example__:

            curl -H "Content-Type: application/json" $URL:changeset-detail:1$
            # output
            {
                "id": 1,
                "author": "xxx",
                "requested_on": "2015-02-03T05:50:49.387Z",
                "committed_on": "2015-02-03T05:51:17.262Z",
                "duration": "27.875",
                "changes": [
                   {
                       "resource": "person",
                       "resource_id": "2",
                       "old_value": "old",
                       "new_value": "new"
                   }
                ],
                "comment": "xxx"
            }
        """
        return super(ChangesetViewSet, self).retrieve(request, *args, **kwargs)

    serializer_class = ChangesetSerializer
    queryset = models.Changeset.objects.all().order_by('-committed_on')
    filter_class = ChangesetFilterSet
<commit_msg>Improve documentation of changeset resource<commit_after>#
# Copyright (c) 2015 Red Hat
# Licensed under The MIT License (MIT)
# http://opensource.org/licenses/MIT
#
from django.conf import settings
from django.core.exceptions import ValidationError
from django.views.generic import ListView, DetailView

from rest_framework import viewsets, status
from rest_framework.response import Response

from pdc.apps.common.viewsets import StrictQueryParamMixin
from . import models
from .filters import ChangesetFilterSet
from .serializers import ChangesetSerializer

class ChangesetListView(ListView):
    queryset = models.Changeset.objects.all().order_by('-committed_on')
    allow_empty = True
    template_name = 'changeset_list.html'
    context_object_name = 'changeset_list'
    paginate_by = settings.ITEMS_PER_PAGE

class ChangesetDetailView(DetailView):
    model = models.Changeset
    pk_url_kwarg = "id"
    template_name = "changeset_detail.html"

class ChangesetViewSet(StrictQueryParamMixin,
                       viewsets.ReadOnlyModelViewSet):
    """
    PDC tracks every modification that was made through any of the API
    end-points. This provides an auditable trail of who changed what and when.

    Each request to the API creates one `Changeset`, which contains one or more
    `Change`s.

    Each `ChangeSet` carries metadata about author and date. Optionally, there
    can also be a comment, which is an arbitrary string. It is extracted from
    the `PDC-Change-Comment` HTTP header in the request.

    A `Change` has information about which database model was changed, its
    primary key and old and new value (provided as a JSON). If both the values
    are provided, the `Change` represents an update in some of the fields. If
    only new value is provided, the `Change` represents creation of new entity.
    If only old value is non-null, an entity was deleted.

    This page shows the usage of the **Changeset API**, please see the
    following for more details. The access to this data is read-only. It is
    possible to either request all changesets satisfying given criteria, or
    view detail of a particular changeset.
    """

    def list(self, request, *args, **kwargs):
        """
        __Method__:
        GET

        __URL__: $LINK:changeset-list$

        __Query Params__:

        %(FILTERS)s

        The dates for `changed_since` and `changed_until` should have one these
        formats:

            Format               | Example
            ---------------------+---------------------------
            %%Y-%%m-%%d %%H:%%M:%%S    | 2006-10-25 14:30:59
            %%Y-%%m-%%d %%H:%%M:%%S.%%f | 2006-10-25 14:30:59.000200
            %%Y-%%m-%%d %%H:%%M       | 2006-10-25 14:30
            %%Y-%%m-%%d             | 2006-10-25

        Resource names for `resource` should be specified in all lower case.

        __Response__: a paged list of following objects

        %(SERIALIZER)s

        The unit for duration is second.

        __Example__:

            curl -H "Content-Type: application/json"  -X GET $URL:changeset-list$
            # output
            {
                "count": 84,
                "next": "$URL:changeset-list$?page=2",
                "previous": null,
                "results": [
                    {
                        {
                            "author": "xxx",
                            "requested_on": "2015-02-03T05:50:49.387Z",
                            "committed_on": "2015-02-03T05:51:17.262Z",
                            "duration": "27.875",
                            "changes": [
                                {
                                    "id": 1
                                    "resource": "person",
                                    "resource_id": "2",
                                    "old_value": "old",
                                    "new_value": "new"
                                }
                            ],
                            "comment": "xxx"
                        }
                    },
                    ...
                ]
            }

        With query params:

            curl -H "Content-Type: application/json"  -G $URL:changeset-list$ --data-urlencode "resource=test"
            # output
            {
                "count": 1,
                "next": null,
                "previous": null,
                "results": [
                        {
                            "id": 1
                            "author": "xxx",
                            "requested_on": "2015-02-03T05:50:49.387Z",
                            "committed_on": "2015-02-03T05:51:17.262Z",
                            "duration": "27.875",
                            "changes": [
                                {
                                    "resource": "person",
                                    "resource_id": "2",
                                    "old_value": "old",
                                    "new_value": "new"
                                }
                            ],
                            "comment": "xxx"
                        }
                ]
            }
        """
        try:
            return super(ChangesetViewSet, self).list(request, *args, **kwargs)
        except ValidationError as exc:
            msg = exc.messages if hasattr(exc, 'messages') else str(exc)
            return Response({'detail': msg},
                            status=status.HTTP_400_BAD_REQUEST)

    def retrieve(self, request, *args, **kwargs):
        """
        __Method__:
        GET

        __URL__: $LINK:changeset-detail:instance_pk$

        __Response__:

        %(SERIALIZER)s

        The unit for duration is second.

        __Example__:

            curl -H "Content-Type: application/json" $URL:changeset-detail:1$
            # output
            {
                "id": 1,
                "author": "xxx",
                "requested_on": "2015-02-03T05:50:49.387Z",
                "committed_on": "2015-02-03T05:51:17.262Z",
                "duration": "27.875",
                "changes": [
                   {
                       "resource": "person",
                       "resource_id": "2",
                       "old_value": "old",
                       "new_value": "new"
                   }
                ],
                "comment": "xxx"
            }
        """
        return super(ChangesetViewSet, self).retrieve(request, *args, **kwargs)

    serializer_class = ChangesetSerializer
    queryset = models.Changeset.objects.all().order_by('-committed_on')
    filter_class = ChangesetFilterSet
<|endoftext|>


<commit_before>#!/usr/bin/python
# -*- coding: utf-8 -*-
##############################################################################
#
#   Copyright (C) 2010-2012 Associazione OpenERP Italia
#   (<http://www.openerp-italia.org>).
#   Copyright(c)2008-2010 SIA "KN dati".(http://kndati.lv) All Rights Reserved.
#                   General contacts <info@kndati.lv>
#
#   This program is free software: you can redistribute it and/or modify
#   it under the terms of the GNU Affero General Public License as published by
#   the Free Software Foundation, either version 3 of the License, or
#   (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU Affero General Public License
#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################

import os
import sys
import logging
import openerp
import xlsxwriter # XLSX export
import openerp.netsvc as netsvc
import openerp.addons.decimal_precision as dp
from openerp.report import report_sxw
from openerp.report.report_sxw import rml_parse
from openerp.osv import fields, osv, expression, orm
from datetime import datetime, timedelta
from dateutil.relativedelta import relativedelta
from openerp import SUPERUSER_ID, api
from openerp import tools
from openerp.tools.translate import _
from openerp.tools.float_utils import float_round as round
from openerp.tools import (DEFAULT_SERVER_DATE_FORMAT,
    DEFAULT_SERVER_DATETIME_FORMAT,
    DATETIME_FORMATS_MAP,
    float_compare)

_logger = logging.getLogger(__name__)

class CampaignCampaign(orm.Model):
    """ Model name: CampaignCampaign
    """
    _inherit = 'campaign.campaign'

    # -------------------------------------------------------------------------
    # Button event:
    # -------------------------------------------------------------------------
    def export_report_as_xlsx(self, cr, uid, ids, context=None):
        ''' Export report in XLSX file
        '''
        def get_image(path, code, extension):
            ''' Generate image name
            '''
            name = '%s.%s' % (
                os.path.join(path, line[0]),
                extension,
                )
            # Test if file exists:
            if os.path.isfile(name):
                return name
            else:
                return False

        # ---------------------------------------------------------------------
        # Parameters:
        # ---------------------------------------------------------------------
        path = '/home/administrator/photo/xls/campaign'
        objects = self.browse(cr, uid, ids, context=context)
        filename = 'export.xlsx' #'%s.xlsx' % campaign_proxy.code
        fullname = os.path.join(path, filename)
        data = {} # Not from wizard

        # ---------------------------------------------------------------------
        # Create and open Workbook:
        # ---------------------------------------------------------------------
        WB = xlsxwriter.Workbook(fullname)
        WS = WB.add_worksheet()#campaign_proxy.code)

        # ---------------------------------------------------------------------
        # Format elements:
        # ---------------------------------------------------------------------
        format_header = WB.add_format({
            'bold': True,
            'font_name': 'Arial',
            'font_size': 11,
            })

        format_title = WB.add_format({
            'bold': True,
            'font_color': 'black',
            'font_name': 'Arial',
            'font_size': 10,
            'align': 'center',
            'valign': 'center',
            'bg_color': 'gray',
            'border': 1,
            })

        format_hidden = WB.add_format({
            'font_color': 'white',
            'font_name': 'Arial',
            'font_size': 8,
            })

        format_data = WB.add_format({
            'font_name': 'Arial',
            'font_size': 10,
            })

        # ---------------------------------------------------------------------
        # Export
        # ---------------------------------------------------------------------
        # Init setup:
        self.get_total_pack_block(cr, uid, objects, context=context) # no data

        # Column dimension:
        WS.set_column ('A:A', 0, None, {'hidden': 1}) # ID column
        WS.set_column ('B:B', 30) # Image colums

        row = 1
        for o in objects: # NOTE: only one from button
            path = os.path.expanduser(o.thumb_album_id.path)
            extension = o.thumb_album_id.extension_image

            # -----------------------------------------------------------------
            # Header:
            # -----------------------------------------------------------------
            WS.write(row, 1, 'CAMPAGNA', format_header)
            WS.write(row, 2, o.name, format_header)
            WS.write(row, 4, 'Cliente:', format_header)
            WS.write(row, 5, o.partner_id.name, format_header)
            row += 1

            # -----------------------------------------------------------------
            # Body:
            # -----------------------------------------------------------------
            for mode, line in self.get_product_pack(
                    cr, uid, o.product_ids, data):
                row += 1
                # -------------------------------------------------------------
                # Body mode:
                # -------------------------------------------------------------
                # Title:
                WS.set_row(row, 30)
                if mode == 'HEADER':
                    WS.write(row, 1, _('Immagine'), format_title)
                    col = 1
                    for field in line:
                        col += 1
                        WS.set_column (col, col, 20) # Col large
                        WS.write(row, col, field, format_title)

                    # Add 2 extra col:
                    WS.write(row, col + 1, _('Campagna'), format_title)
                    WS.write(row, col + 2, _('Ordine'), format_title)

                # Hidden:
                elif mode == 'HIDDEN':
                    WS.set_row(row, 0)
                    WS.write(row, 0, 'id', format_hidden)
                    col = 2 + len(line)
                    WS.write(row, col, 'qty', format_hidden)
                    WS.write(row, col + 1, 'qty_ordered', format_hidden)

                # Body:
                else: # Product line
                    WS.set_row(row, 50)
                    WS.write(row, 0, mode, format_hidden)
                    image = get_image(path, line[0], extension)
                    if image:
                        WS.insert_image(row, 1, image, {
                            'x_scale': 1, 'y_scale': 1,
                            'x_offset': 2, 'y_offset': 2,
                            })
                    else:
                        WS.write(row, 1, 'Nessuna immagine', format_data)
                    col = 1
                    for field in line:
                        col += 1
                        WS.write(row, col, field, format_data)
        WB.close()
        return True

    # -------------------------------------------------------------------------
    # Report functions:
    # -------------------------------------------------------------------------
    def _get_active_objects(self, cr, uid, data=None, context=None):
        ''' Return active campaign
        '''
        if data is None:
            data = {} # TODO manage filter confirmed draft

        campaign_pool = self.pool.get('campaign.campaign')

        if data.get('mode', False) == 'draft':
            domain = [('state', 'in', ('draft', 'confirmed'))]
        else: # only confirmed
            domain = [('state', '=', 'confirmed')]

        campaign_ids = campaign_pool.search(cr, uid, domain, context=context)
        if not campaign_ids:
            raise osv.except_osv(
                _('Report error!'),
                _('No data, change filter'),
                )

        return campaign_pool.browse(cr, uid, campaign_ids, context=context)

    def get_total_pack_block(self, cr, uid, objects, data=None, context=None):
        ''' Read all package objects for decide how much colums
        '''
        if data is not None:
            objects = self._get_active_objects(
                cr, uid, data=data, context=context)

        self.pack_max = 1
        for campaign in objects:
            for line in campaign.product_ids:
                product = line.product_id
                if product.has_multipackage:
                    tot = sum([item.number for item in product.multi_pack_ids])
                else:
                    tot = 1
                if tot > self.pack_max:
                    self.pack_max = tot
        return ''

    def get_product_pack(self, cr, uid, relations, data=None, context=None):
        ''' Create a list for all package in product
            [(l, h, p, w)]
            fill extra element till pack_max
        '''
        if data is None:
            data = {}
            from_wizard = False
        else:
            from_wizard = True

        res = []
        empty = ['', '', '', ''] # XXX loop block if empty

        # ---------------------------------------------------------------------
        #                               Header block:
        # ---------------------------------------------------------------------
        header_data = [
            _('Codice prodotto'),
            _('Nome prodotto'),
            _('Quantità riservata'),
            _('Prezzo listino (IVA inclusa)'),
            _('Prezzo cessione (IVA esclusa)'),
            _('Altezza seduta'),
            _('Commenti Aggiuntivi'),
            _('Altezza'),
            _('Larghezza'),
            _('Lunghezza'),
            _('Peso Prodotto'),
            _('Arriva Montato'),
            _('Unità Imballo'),
            _('Ean'),
            _('Materiali (struttura, rivestimenti, imbottiture, piani ecc.)'),
            _('Colore/i (indicare tutti i colori presenti)'),
            _('Informazioni lavaggio'),
            _('Rivestimento sfoderabile'),
            ]
        if from_wizard:
            header_data.append(_('Disponibilità'))

        for i in range(0, self.pack_max):
            header_data.extend([
                _('Lunghezza # %s') % (i + 1),
                _('Altezza # %s') % (i + 1),
                _('Profondità # %s') % (i + 1),
                _('Peso # %s') % (i + 1),
                ])
        res.append(('HEADER', header_data))

        # ---------------------------------------------------------------------
        #                               Hidden block:
        # ---------------------------------------------------------------------
        # Static data list:
        hidden_data = [
            'id', 'default_code', '', '', '', '', '', '', '', '', ''] #, '']
        if from_wizard:
            hidden_data.append('')

        # Dynamic part:
        for i in range(0, self.pack_max):
            hidden_data.extend(empty)

        res.append(('HIDDEN', hidden_data))

        # ---------------------------------------------------------------------
        #                            Data block:
        # ---------------------------------------------------------------------
        for relation in relations:
            product = relation.product_id # readability

            # Ean part:
            ean = product.ean13 or '' # normal
            if relation.packaging_id:
                if relation.packaging_id.ean:
                    ean = relation.packaging_id.ean # normal different pack
                else:
                    if ean: # warning:
                        ean = '%s (prod.)' % ean

            # ------------
            # Common part:
            # ------------
            data = [
                # Product:
                product.default_code,

                # Relation:
                '%s %s' % (
                    relation.description or product.name or '?',
                    product.colour or ''),
                int(relation.qty),
                #relation.price,
                relation.price * 1.22, # TODO parametrize
                relation.campaign_price,
                product.seat_height,
                product.campaign_comment,
                product.height,
                product.width,
                product.length,
                product.weight,
                _('Sì') if product.campaign_mounted else _('No'),
                int(relation.q_x_pack),
                # Product:
                ean,
                product.campaign_material or '',
                product.campaign_color or '',
                product.campaign_wash or '',
                _('Sì') if product.campaign_cover else _('No'),

                #0.0, #TODO what data?!?!? int(product.qty),
                ]

            if from_wizard:
                data.append(int(product.mx_lord_qty or 0.0))

            if product.has_multipackage:
                # -------------------------------------------------------------
                #                   Multipackage product:
                # -------------------------------------------------------------
                i = 0

                for pack in product.multi_pack_ids: # Loop on all elements
                    i += pack.number or 1
                    for item in range(0, pack.number or 1):
                        data.extend([ # pack
                            pack.height,
                            pack.width,
                            pack.length,
                            pack.weight,
                            ])

            elif relation.packaging_id: # extra pack setted
                # -------------------------------------------------------------
                #                  Extra package selected:
                # -------------------------------------------------------------
                i = 1 # only one

                data.extend([ # extra pack selected
                    relation.packaging_id.pack_h,
                    relation.packaging_id.pack_l,
                    relation.packaging_id.pack_p,
                    relation.packaging_id.weight,
                    ])
            else:
                i = 1 # only one
                # -------------------------------------------------------------
                #                    Default package:
                # -------------------------------------------------------------
                data.extend([ # extra pack selected
                    product.pack_h,
                    product.pack_l,
                    product.pack_p,
                    product.weight,
                    ])

            # -----------------------
            # Add empty extra fields:
            # -----------------------
            for item in range(0, self.pack_max - i):
                data.extend(empty)

            res.append((relation.id, data))
        return res

class Parser(report_sxw.rml_parse):
    counters = {}
    context = False

    def __init__(self, cr, uid, name, context):
        self.context = context
        super(Parser, self).__init__(cr, uid, name, context)
        self.localcontext.update({
            'get_objects': self.get_objects,
            'load_context_image': self.load_context_image,
            'get_total_pack_block': self.get_total_pack_block,
            'get_product_pack': self.get_product_pack,
        })

    def get_objects(self, objects, data=None):
        ''' Return active campaign
        '''
        # Readability:
        cr = self.cr
        uid = self.uid
        context = {}

        return self.pool.get('campaign.campaign')._get_active_objects(
            cr, uid, data=data, context=context)

    def load_context_image(self, album_id, product_id):
        ''' Load image from album (used in ODT document, not in ODS)
        '''
        # Readability:
        cr = self.cr
        uid = self.uid
        context = {'album_id': album_id}

        product_pool = self.pool.get('product.product')
        product_proxy = product_pool.browse(cr, uid, product_id,
            context={'album_id': album_id})
        return product_proxy.product_image_context

    def get_total_pack_block(self, objects, data=None):
        ''' Read all package objects for decide how much colums
        '''
        # Readability:
        cr = self.cr
        uid = self.uid
        context = {}

        return self.pool.get('campaign.campaign').get_total_pack_block(
            cr, uid, objects, data=data, context=context)

    def get_product_pack(self, relations, data=None):
        ''' Create a list for all package in product
            [(l, h, p, w)]
            fill extra element till pack_max
        '''
        # Readability:
        cr = self.cr
        uid = self.uid
        context = {}

        return self.pool.get('campaign.campaign').get_product_pack(
            cr, uid, relations, data=data, context=context)

# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
<commit_msg>change header split line<commit_after>#!/usr/bin/python
# -*- coding: utf-8 -*-
##############################################################################
#
#   Copyright (C) 2010-2012 Associazione OpenERP Italia
#   (<http://www.openerp-italia.org>).
#   Copyright(c)2008-2010 SIA "KN dati".(http://kndati.lv) All Rights Reserved.
#                   General contacts <info@kndati.lv>
#
#   This program is free software: you can redistribute it and/or modify
#   it under the terms of the GNU Affero General Public License as published by
#   the Free Software Foundation, either version 3 of the License, or
#   (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU Affero General Public License
#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################

import os
import sys
import logging
import openerp
import xlsxwriter # XLSX export
import openerp.netsvc as netsvc
import openerp.addons.decimal_precision as dp
from openerp.report import report_sxw
from openerp.report.report_sxw import rml_parse
from openerp.osv import fields, osv, expression, orm
from datetime import datetime, timedelta
from dateutil.relativedelta import relativedelta
from openerp import SUPERUSER_ID, api
from openerp import tools
from openerp.tools.translate import _
from openerp.tools.float_utils import float_round as round
from openerp.tools import (DEFAULT_SERVER_DATE_FORMAT,
    DEFAULT_SERVER_DATETIME_FORMAT,
    DATETIME_FORMATS_MAP,
    float_compare)

_logger = logging.getLogger(__name__)

class CampaignCampaign(orm.Model):
    """ Model name: CampaignCampaign
    """
    _inherit = 'campaign.campaign'

    # -------------------------------------------------------------------------
    # Button event:
    # -------------------------------------------------------------------------
    def export_report_as_xlsx(self, cr, uid, ids, context=None):
        ''' Export report in XLSX file
        '''
        def get_image(path, code, extension):
            ''' Generate image name
            '''
            name = '%s.%s' % (
                os.path.join(path, line[0]),
                extension,
                )
            # Test if file exists:
            if os.path.isfile(name):
                return name
            else:
                return False

        # ---------------------------------------------------------------------
        # Parameters:
        # ---------------------------------------------------------------------
        path = '/home/administrator/photo/xls/campaign'
        objects = self.browse(cr, uid, ids, context=context)
        filename = 'export.xlsx' #'%s.xlsx' % campaign_proxy.code
        fullname = os.path.join(path, filename)
        data = {} # Not from wizard

        # ---------------------------------------------------------------------
        # Create and open Workbook:
        # ---------------------------------------------------------------------
        WB = xlsxwriter.Workbook(fullname)
        WS = WB.add_worksheet()#campaign_proxy.code)

        # ---------------------------------------------------------------------
        # Format elements:
        # ---------------------------------------------------------------------
        format_header = WB.add_format({
            'bold': True,
            'font_name': 'Arial',
            'font_size': 11,
            })

        format_title = WB.add_format({
            'bold': True,
            'font_color': 'black',
            'font_name': 'Arial',
            'font_size': 10,
            'align': 'center',
            'valign': 'center',
            'bg_color': 'gray',
            'border': 1,
            })

        format_hidden = WB.add_format({
            'font_color': 'white',
            'font_name': 'Arial',
            'font_size': 8,
            })

        format_data = WB.add_format({
            'font_name': 'Arial',
            'font_size': 10,
            })

        # ---------------------------------------------------------------------
        # Export
        # ---------------------------------------------------------------------
        # Init setup:
        self.get_total_pack_block(cr, uid, objects, context=context) # no data

        # Column dimension:
        WS.set_column ('A:A', 0, None, {'hidden': 1}) # ID column
        WS.set_column ('B:B', 30) # Image colums

        row = 1
        for o in objects: # NOTE: only one from button
            path = os.path.expanduser(o.thumb_album_id.path)
            extension = o.thumb_album_id.extension_image

            # -----------------------------------------------------------------
            # Header:
            # -----------------------------------------------------------------
            WS.write(row, 1, 'CAMPAGNA', format_header)
            WS.write(row, 2, o.name, format_header)
            WS.write(row, 4, 'Cliente:', format_header)
            WS.write(row, 5, o.partner_id.name, format_header)
            row += 1

            # -----------------------------------------------------------------
            # Body:
            # -----------------------------------------------------------------
            for mode, line in self.get_product_pack(
                    cr, uid, o.product_ids, data):
                row += 1
                # -------------------------------------------------------------
                # Body mode:
                # -------------------------------------------------------------
                # Title:
                WS.set_row(row, 30)
                if mode == 'HEADER':
                    WS.write(row, 1, _('Immagine'), format_title)
                    col = 1
                    for field in line:
                        col += 1
                        WS.set_column (col, col, 20) # Col large
                        WS.write(row, col, field, format_title)

                    # Add 2 extra col:
                    WS.write(row, col + 1, _('Campagna'), format_title)
                    WS.write(row, col + 2, _('Ordine'), format_title)

                # Hidden:
                elif mode == 'HIDDEN':
                    WS.set_row(row, 0)
                    WS.write(row, 0, 'id', format_hidden)
                    col = 2 + len(line)
                    WS.write(row, col, 'qty', format_hidden)
                    WS.write(row, col + 1, 'qty_ordered', format_hidden)

                # Body:
                else: # Product line
                    WS.set_row(row, 50)
                    WS.write(row, 0, mode, format_hidden)
                    image = get_image(path, line[0], extension)
                    if image:
                        WS.insert_image(row, 1, image, {
                            'x_scale': 1, 'y_scale': 1,
                            'x_offset': 2, 'y_offset': 2,
                            })
                    else:
                        WS.write(row, 1, 'Nessuna immagine', format_data)
                    col = 1
                    for field in line:
                        col += 1
                        WS.write(row, col, field, format_data)
        WB.close()
        return True

    # -------------------------------------------------------------------------
    # Report functions:
    # -------------------------------------------------------------------------
    def _get_active_objects(self, cr, uid, data=None, context=None):
        ''' Return active campaign
        '''
        if data is None:
            data = {} # TODO manage filter confirmed draft

        campaign_pool = self.pool.get('campaign.campaign')

        if data.get('mode', False) == 'draft':
            domain = [('state', 'in', ('draft', 'confirmed'))]
        else: # only confirmed
            domain = [('state', '=', 'confirmed')]

        campaign_ids = campaign_pool.search(cr, uid, domain, context=context)
        if not campaign_ids:
            raise osv.except_osv(
                _('Report error!'),
                _('No data, change filter'),
                )

        return campaign_pool.browse(cr, uid, campaign_ids, context=context)

    def get_total_pack_block(self, cr, uid, objects, data=None, context=None):
        ''' Read all package objects for decide how much colums
        '''
        if data is not None:
            objects = self._get_active_objects(
                cr, uid, data=data, context=context)

        self.pack_max = 1
        for campaign in objects:
            for line in campaign.product_ids:
                product = line.product_id
                if product.has_multipackage:
                    tot = sum([item.number for item in product.multi_pack_ids])
                else:
                    tot = 1
                if tot > self.pack_max:
                    self.pack_max = tot
        return ''

    def get_product_pack(self, cr, uid, relations, data=None, context=None):
        ''' Create a list for all package in product
            [(l, h, p, w)]
            fill extra element till pack_max
        '''
        if data is None:
            data = {}
            from_wizard = False
        else:
            from_wizard = True

        res = []
        empty = ['', '', '', ''] # XXX loop block if empty

        # ---------------------------------------------------------------------
        #                               Header block:
        # ---------------------------------------------------------------------
        header_data = [
            _('Codice prodotto'),
            _('Nome prodotto'),
            _('Quantità\nriservata'),
            _('Prezzo listino\n(IVA inclusa)'),
            _('Prezzo cessione\n(IVA esclusa)'),
            _('Altezza seduta'),
            _('Commenti\nAggiuntivi'),
            _('Altezza'),
            _('Larghezza'),
            _('Lunghezza'),
            _('Peso Prodotto'),
            _('Arriva Montato'),
            _('Unità Imballo'),
            _('Ean'),
            _('Materiali\n(struttura, rivestimenti, imbottiture, piani ecc.)'),
            _('Colore/i\n(indicare tutti i colori presenti)'),
            _('Informazioni\nlavaggio'),
            _('Rivestimento\nsfoderabile'),
            ]
        if from_wizard:
            header_data.append(_('Disponibilità'))

        for i in range(0, self.pack_max):
            header_data.extend([
                _('Lunghezza # %s') % (i + 1),
                _('Altezza # %s') % (i + 1),
                _('Profondità # %s') % (i + 1),
                _('Peso # %s') % (i + 1),
                ])
        res.append(('HEADER', header_data))

        # ---------------------------------------------------------------------
        #                               Hidden block:
        # ---------------------------------------------------------------------
        # Static data list:
        hidden_data = [
            'id', 'default_code', '', '', '', '', '', '', '', '', ''] #, '']
        if from_wizard:
            hidden_data.append('')

        # Dynamic part:
        for i in range(0, self.pack_max):
            hidden_data.extend(empty)

        res.append(('HIDDEN', hidden_data))

        # ---------------------------------------------------------------------
        #                            Data block:
        # ---------------------------------------------------------------------
        for relation in relations:
            product = relation.product_id # readability

            # Ean part:
            ean = product.ean13 or '' # normal
            if relation.packaging_id:
                if relation.packaging_id.ean:
                    ean = relation.packaging_id.ean # normal different pack
                else:
                    if ean: # warning:
                        ean = '%s (prod.)' % ean

            # ------------
            # Common part:
            # ------------
            data = [
                # Product:
                product.default_code,

                # Relation:
                '%s %s' % (
                    relation.description or product.name or '?',
                    product.colour or ''),
                int(relation.qty),
                #relation.price,
                relation.price * 1.22, # TODO parametrize
                relation.campaign_price,
                product.seat_height,
                product.campaign_comment,
                product.height,
                product.width,
                product.length,
                product.weight,
                _('Sì') if product.campaign_mounted else _('No'),
                int(relation.q_x_pack),
                # Product:
                ean,
                product.campaign_material or '',
                product.campaign_color or '',
                product.campaign_wash or '',
                _('Sì') if product.campaign_cover else _('No'),

                #0.0, #TODO what data?!?!? int(product.qty),
                ]

            if from_wizard:
                data.append(int(product.mx_lord_qty or 0.0))

            if product.has_multipackage:
                # -------------------------------------------------------------
                #                   Multipackage product:
                # -------------------------------------------------------------
                i = 0

                for pack in product.multi_pack_ids: # Loop on all elements
                    i += pack.number or 1
                    for item in range(0, pack.number or 1):
                        data.extend([ # pack
                            pack.height,
                            pack.width,
                            pack.length,
                            pack.weight,
                            ])

            elif relation.packaging_id: # extra pack setted
                # -------------------------------------------------------------
                #                  Extra package selected:
                # -------------------------------------------------------------
                i = 1 # only one

                data.extend([ # extra pack selected
                    relation.packaging_id.pack_h,
                    relation.packaging_id.pack_l,
                    relation.packaging_id.pack_p,
                    relation.packaging_id.weight,
                    ])
            else:
                i = 1 # only one
                # -------------------------------------------------------------
                #                    Default package:
                # -------------------------------------------------------------
                data.extend([ # extra pack selected
                    product.pack_h,
                    product.pack_l,
                    product.pack_p,
                    product.weight,
                    ])

            # -----------------------
            # Add empty extra fields:
            # -----------------------
            for item in range(0, self.pack_max - i):
                data.extend(empty)

            res.append((relation.id, data))
        return res

class Parser(report_sxw.rml_parse):
    counters = {}
    context = False

    def __init__(self, cr, uid, name, context):
        self.context = context
        super(Parser, self).__init__(cr, uid, name, context)
        self.localcontext.update({
            'get_objects': self.get_objects,
            'load_context_image': self.load_context_image,
            'get_total_pack_block': self.get_total_pack_block,
            'get_product_pack': self.get_product_pack,
        })

    def get_objects(self, objects, data=None):
        ''' Return active campaign
        '''
        # Readability:
        cr = self.cr
        uid = self.uid
        context = {}

        return self.pool.get('campaign.campaign')._get_active_objects(
            cr, uid, data=data, context=context)

    def load_context_image(self, album_id, product_id):
        ''' Load image from album (used in ODT document, not in ODS)
        '''
        # Readability:
        cr = self.cr
        uid = self.uid
        context = {'album_id': album_id}

        product_pool = self.pool.get('product.product')
        product_proxy = product_pool.browse(cr, uid, product_id,
            context={'album_id': album_id})
        return product_proxy.product_image_context

    def get_total_pack_block(self, objects, data=None):
        ''' Read all package objects for decide how much colums
        '''
        # Readability:
        cr = self.cr
        uid = self.uid
        context = {}

        return self.pool.get('campaign.campaign').get_total_pack_block(
            cr, uid, objects, data=data, context=context)

    def get_product_pack(self, relations, data=None):
        ''' Create a list for all package in product
            [(l, h, p, w)]
            fill extra element till pack_max
        '''
        # Readability:
        cr = self.cr
        uid = self.uid
        context = {}

        return self.pool.get('campaign.campaign').get_product_pack(
            cr, uid, relations, data=data, context=context)

# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
<|endoftext|>


<commit_before>from functools import wraps
import uuid

from flask import request, jsonify
from flask.views import MethodView
from sqlalchemy import desc, inspect, Integer
from sqlalchemy.orm.exc import NoResultFound
from flask import abort
from sqlalchemy.dialects.postgresql import UUID

from radar.database import db
from radar.exceptions import PermissionDenied, NotFound, BadRequest
from radar.serializers.core import Serializer
from radar.serializers.fields import StringField, IntegerField, ListField
from radar.validation.core import ValidationError
from radar.auth.sessions import current_user

class ApiView(MethodView):
    def dispatch_request(self, *args, **kwargs):
        try:
            return super(ApiView, self).dispatch_request(*args, **kwargs)
        except BadRequest:
            abort(400)
        except PermissionDenied:
            abort(403)
        except NotFound:
            abort(404)
        except ValidationError as e:
            print e.errors
            return jsonify(errors=e.errors), 422

class PermissionViewMixin(object):
    permission_classes = []

    def check_permissions(self):
        for permission in self.get_permissions():
            if not permission.has_permission(request, current_user):
                print 'Denied by', permission
                raise PermissionDenied()

    def check_object_permissions(self, obj):
        for permission in self.get_permissions():
            if not permission.has_object_permission(request, current_user, obj):
                print 'Denied by', permission
                raise PermissionDenied()

    def get_permission_classes(self):
        return list(self.permission_classes)

    def get_permissions(self):
        return [permission() for permission in self.get_permission_classes()]

    def dispatch_request(self, *args, **kwargs):
        try:
            self.check_permissions()
        except PermissionDenied:
            abort(403)

        return super(PermissionViewMixin, self).dispatch_request(*args, **kwargs)

class SerializerViewMixin(object):
    serializer_class = None

    def get_serializer(self):
        return self.get_serializer_class()()

    def get_serializer_class(self):
        return self.serializer_class

class ValidationViewMixin(object):
    validation_class = None

    def get_validation_class(self):
        return self.validation_class

    def get_validation(self):
        validation_class = self.get_validation_class()

        if validation_class is None:
            return None
        else:
            return validation_class()

    def get_context(self, deserialized_data):
        return {'user': current_user}

class BaseView(SerializerViewMixin, ValidationViewMixin, PermissionViewMixin, ApiView):
    pass

class ModelView(SerializerViewMixin, ValidationViewMixin, PermissionViewMixin, ApiView):
    sort_fields = {}
    model_class = None

    def filter_query(self, query):
        return query

    def get_sort_args(self):
        sort_serializer = SortRequestSerializer()
        sort_args = sort_serializer.to_value(request.args)
        sort = sort_args.get('sort')

        if sort:
            if sort[0] == '-':
                return sort[1:], True
            else:
                return sort, False
        else:
            return None, False

    def sort_query(self, query):
        sort, reverse = self.get_sort_args()

        if sort is not None:
            sort_fields = self.get_sort_fields()

            if isinstance(sort_fields, dict):
                expression = sort_fields.get(sort)
            elif sort in sort_fields:
                model_class = self.get_model_class()
                expression = getattr(model_class, sort)
            else:
                expression = None

            if expression is not None:
                if reverse:
                    expression = desc(expression)

                query = query.order_by(expression)

        return query

    def paginate_query(self, query):
        pagination_serializer = PaginationRequestSerializer()
        pagination_args = pagination_serializer.to_value(request.args)

        per_page = pagination_args.get('per_page')

        if per_page is not None:
            page = pagination_args.get('page', 1)

            if page < 1:
                page = 1

            if per_page < 1:
                per_page = 1

            count = query.count()
            query = query.limit(per_page).offset((page - 1) * per_page)

            pagination = {
                'page': page,
                'per_page': per_page,
                'count': count
            }
        else:
            pagination = None

        return query, pagination

    def get_object_list(self):
        query = self.get_query()
        query = self.filter_query(query)
        query = self.sort_query(query)
        query, pagination = self.paginate_query(query)

        obj_list = query.all()

        return obj_list, pagination

    def get_object(self):
        query = self.get_query()
        query = self.filter_query(query)

        model_class = self.get_model_class()
        id_type = inspect(model_class).columns['id'].type

        obj_id = request.view_args['id']

        if isinstance(id_type, Integer):
            try:
                obj_id = int(obj_id)
            except ValueError:
                raise NotFound()
        elif isinstance(id_type, UUID):
            try:
                obj_id = uuid.UUID(obj_id)
            except ValueError:
                raise NotFound()

        query = query.filter(model_class.id == obj_id)

        try:
            obj = query.one()
        except NoResultFound:
            raise NotFound()

        self.check_object_permissions(obj)

        return obj

    def get_sort_fields(self):
        return self.sort_fields

    def get_model_class(self):
        return self.model_class

    def get_query(self):
        return self.get_model_class().query

class CreateModelViewMixin(object):
    def create(self, *args, **kwargs):
        serializer = self.get_serializer()

        json = request.get_json()

        if json is None:
            raise BadRequest()

        deserialized_data = serializer.to_value(json)

        validation = self.get_validation()

        if validation is None:
            obj = serializer.create()
            obj = serializer.update(obj, deserialized_data)
        else:
            ctx = self.get_context(deserialized_data)
            obj = serializer.create()

            with db.session.no_autoflush:
                try:
                    validation.before_update(ctx, obj)
                    old_obj = validation.clone(obj)
                    obj = serializer.update(obj, deserialized_data)
                    validation.after_update(ctx, old_obj, obj)
                except ValidationError as e:
                    print e.errors
                    errors = serializer.transform_errors(e.errors)
                    raise ValidationError(errors)

        db.session.add(obj)
        db.session.commit()
        data = serializer.to_data(obj)
        return jsonify(data), 201

class SortRequestSerializer(Serializer):
    sort = StringField()

class PaginationRequestSerializer(Serializer):
    page = IntegerField()
    per_page = IntegerField()

class PaginationResponseSerializer(Serializer):
    page = IntegerField()
    per_page = IntegerField()
    count = IntegerField()

class ListSerializer(Serializer):
    pagination = PaginationResponseSerializer()

    def __init__(self, serializer, *args, **kwargs):
        super(ListSerializer, self).__init__(*args, **kwargs)
        self.serializer = serializer

    def get_fields(self):
        fields = super(ListSerializer, self).get_fields()

        data_field = ListField(self.serializer)
        data_field.bind('data')
        fields['data'] = data_field

        return fields

class ListViewMixin(object):
    def list(self, *args, **kwargs):
        obj_list = self.get_object_list()

        serializer = self.get_serializer()
        list_serializer = ListSerializer(serializer)
        data = list_serializer.to_data({'data': obj_list})

        return jsonify(data)

class ListModelViewMixin(object):
    def list(self, *args, **kwargs):
        obj_list, pagination = self.get_object_list()

        serializer = self.get_serializer()
        list_serializer = ListSerializer(serializer)

        response = {'data': obj_list}

        if pagination:
            response['pagination'] = pagination

        data = list_serializer.to_data(response)

        return jsonify(data)

class RetrieveModelViewMixin(object):
    def retrieve(self, *args, **kwargs):
        obj = self.get_object()
        serializer = self.get_serializer()
        data = serializer.to_data(obj)
        return jsonify(data)

class UpdateModelViewMixin(object):
    def update(self, *args, **kwargs):
        obj = self.get_object()
        serializer = self.get_serializer()

        json = request.get_json()

        if json is None:
            raise BadRequest()

        deserialized_data = serializer.to_value(json)

        validation = self.get_validation()

        if validation is None:
            obj = serializer.update(obj, deserialized_data)
        else:
            ctx = self.get_context(deserialized_data)

            with db.session.no_autoflush:
                try:
                    validation.before_update(ctx, obj)
                    old_obj = validation.clone(obj)
                    obj = serializer.update(obj, deserialized_data)
                    validation.after_update(ctx, old_obj, obj)
                except ValidationError as e:
                    errors = serializer.transform_errors(e.errors)
                    raise ValidationError(errors)

        db.session.commit()
        data = serializer.to_data(obj)
        return jsonify(data)

class DestroyModelViewMixin(object):
    def destroy(self, *args, **kwargs):
        obj = self.get_object()
        db.session.delete(obj)
        db.session.commit()
        return '', 204

class RetrieveModelView(RetrieveModelViewMixin, ModelView):
    def get(self, *args, **kwargs):
        return self.retrieve(*args, **kwargs)

class ListView(ListViewMixin, BaseView):
    def get(self, *args, **kwargs):
        return self.list(*args, **kwargs)

class ListModelView(ListModelViewMixin, ModelView):
    def get(self, *args, **kwargs):
        return self.list(*args, **kwargs)

class ListCreateModelView(ListModelViewMixin, CreateModelViewMixin, ModelView):
    def get(self, *args, **kwargs):
        return self.list(*args, **kwargs)

    def post(self, *args, **kwargs):
        return self.create(*args, **kwargs)

class RetrieveUpdateDestroyModelView(RetrieveModelViewMixin, UpdateModelViewMixin, DestroyModelViewMixin, ModelView):
    def get(self, *args, **kwargs):
        return self.retrieve(*args, **kwargs)

    def put(self, *args, **kwargs):
        return self.update(*args, **kwargs)

    def post(self, *args, **kwargs):
        return self.update(*args, **kwargs)

    def delete(self, *args, **kwargs):
        return self.destroy(*args, **kwargs)

class RetrieveUpdateModelView(RetrieveModelViewMixin, UpdateModelViewMixin, ModelView):
    def get(self, *args, **kwargs):
        return self.retrieve(*args, **kwargs)

    def put(self, *args, **kwargs):
        return self.update(*args, **kwargs)

    def post(self, *args, **kwargs):
        return self.update(*args, **kwargs)

class CreateModelView(CreateModelViewMixin, ModelView):
    def post(self, *args, **kwargs):
        return self.create(*args, **kwargs)

class UpdateModelView(UpdateModelViewMixin, ModelView):
    def put(self, *args, **kwargs):
        return self.update(*args, **kwargs)

class DestroyModelView(DestroyModelViewMixin, ModelView):
    def delete(self, *args, **kwargs):
        return self.destroy(*args, **kwargs)

def request_json(serializer_class, validation_class=None):
    def decorator(f):
        @wraps(f)
        def wrapper(*args, **kwargs):
            json = request.get_json()

            if json is None:
                raise BadRequest()

            serializer = serializer_class()
            data = serializer.to_value(json)

            if validation_class is not None:
                validation = validation_class()

                ctx = {}

                if current_user.is_authenticated():
                    ctx['user'] = current_user

                try:
                    validation.after_update(ctx, {}, data)
                except ValidationError as e:
                    errors = serializer.transform_errors(e.errors)
                    raise ValidationError(errors)

            args = list(args)
            args.append(data)

            return f(*args, **kwargs)

        return wrapper

    return decorator

def response_json(serializer_class):
    def decorator(f):
        @wraps(f)
        def wrapper(*args, **kwargs):
            response = f(*args, **kwargs)
            serializer = serializer_class()
            data = serializer.to_data(response)
            return jsonify(data), 200

        return wrapper

    return decorator
<commit_msg>Keep UUIDs as strings when querying<commit_after>from functools import wraps
import uuid

from flask import request, jsonify
from flask.views import MethodView
from sqlalchemy import desc, inspect, Integer
from sqlalchemy.orm.exc import NoResultFound
from flask import abort
from sqlalchemy.dialects.postgresql import UUID

from radar.database import db
from radar.exceptions import PermissionDenied, NotFound, BadRequest
from radar.serializers.core import Serializer
from radar.serializers.fields import StringField, IntegerField, ListField
from radar.validation.core import ValidationError
from radar.auth.sessions import current_user

class ApiView(MethodView):
    def dispatch_request(self, *args, **kwargs):
        try:
            return super(ApiView, self).dispatch_request(*args, **kwargs)
        except BadRequest:
            abort(400)
        except PermissionDenied:
            abort(403)
        except NotFound:
            abort(404)
        except ValidationError as e:
            print e.errors
            return jsonify(errors=e.errors), 422

class PermissionViewMixin(object):
    permission_classes = []

    def check_permissions(self):
        for permission in self.get_permissions():
            if not permission.has_permission(request, current_user):
                print 'Denied by', permission
                raise PermissionDenied()

    def check_object_permissions(self, obj):
        for permission in self.get_permissions():
            if not permission.has_object_permission(request, current_user, obj):
                print 'Denied by', permission
                raise PermissionDenied()

    def get_permission_classes(self):
        return list(self.permission_classes)

    def get_permissions(self):
        return [permission() for permission in self.get_permission_classes()]

    def dispatch_request(self, *args, **kwargs):
        try:
            self.check_permissions()
        except PermissionDenied:
            abort(403)

        return super(PermissionViewMixin, self).dispatch_request(*args, **kwargs)

class SerializerViewMixin(object):
    serializer_class = None

    def get_serializer(self):
        return self.get_serializer_class()()

    def get_serializer_class(self):
        return self.serializer_class

class ValidationViewMixin(object):
    validation_class = None

    def get_validation_class(self):
        return self.validation_class

    def get_validation(self):
        validation_class = self.get_validation_class()

        if validation_class is None:
            return None
        else:
            return validation_class()

    def get_context(self, deserialized_data):
        return {'user': current_user}

class BaseView(SerializerViewMixin, ValidationViewMixin, PermissionViewMixin, ApiView):
    pass

class ModelView(SerializerViewMixin, ValidationViewMixin, PermissionViewMixin, ApiView):
    sort_fields = {}
    model_class = None

    def filter_query(self, query):
        return query

    def get_sort_args(self):
        sort_serializer = SortRequestSerializer()
        sort_args = sort_serializer.to_value(request.args)
        sort = sort_args.get('sort')

        if sort:
            if sort[0] == '-':
                return sort[1:], True
            else:
                return sort, False
        else:
            return None, False

    def sort_query(self, query):
        sort, reverse = self.get_sort_args()

        if sort is not None:
            sort_fields = self.get_sort_fields()

            if isinstance(sort_fields, dict):
                expression = sort_fields.get(sort)
            elif sort in sort_fields:
                model_class = self.get_model_class()
                expression = getattr(model_class, sort)
            else:
                expression = None

            if expression is not None:
                if reverse:
                    expression = desc(expression)

                query = query.order_by(expression)

        return query

    def paginate_query(self, query):
        pagination_serializer = PaginationRequestSerializer()
        pagination_args = pagination_serializer.to_value(request.args)

        per_page = pagination_args.get('per_page')

        if per_page is not None:
            page = pagination_args.get('page', 1)

            if page < 1:
                page = 1

            if per_page < 1:
                per_page = 1

            count = query.count()
            query = query.limit(per_page).offset((page - 1) * per_page)

            pagination = {
                'page': page,
                'per_page': per_page,
                'count': count
            }
        else:
            pagination = None

        return query, pagination

    def get_object_list(self):
        query = self.get_query()
        query = self.filter_query(query)
        query = self.sort_query(query)
        query, pagination = self.paginate_query(query)

        obj_list = query.all()

        return obj_list, pagination

    def get_object(self):
        query = self.get_query()
        query = self.filter_query(query)

        model_class = self.get_model_class()
        id_type = inspect(model_class).columns['id'].type

        obj_id = request.view_args['id']

        if isinstance(id_type, Integer):
            try:
                obj_id = int(obj_id)
            except ValueError:
                raise NotFound()
        elif isinstance(id_type, UUID):
            try:
                uuid.UUID(obj_id)
            except ValueError:
                raise NotFound()

        query = query.filter(model_class.id == obj_id)

        try:
            obj = query.one()
        except NoResultFound:
            raise NotFound()

        self.check_object_permissions(obj)

        return obj

    def get_sort_fields(self):
        return self.sort_fields

    def get_model_class(self):
        return self.model_class

    def get_query(self):
        return self.get_model_class().query

class CreateModelViewMixin(object):
    def create(self, *args, **kwargs):
        serializer = self.get_serializer()

        json = request.get_json()

        if json is None:
            raise BadRequest()

        deserialized_data = serializer.to_value(json)

        validation = self.get_validation()

        if validation is None:
            obj = serializer.create()
            obj = serializer.update(obj, deserialized_data)
        else:
            ctx = self.get_context(deserialized_data)
            obj = serializer.create()

            with db.session.no_autoflush:
                try:
                    validation.before_update(ctx, obj)
                    old_obj = validation.clone(obj)
                    obj = serializer.update(obj, deserialized_data)
                    validation.after_update(ctx, old_obj, obj)
                except ValidationError as e:
                    print e.errors
                    errors = serializer.transform_errors(e.errors)
                    raise ValidationError(errors)

        db.session.add(obj)
        db.session.commit()
        data = serializer.to_data(obj)
        return jsonify(data), 201

class SortRequestSerializer(Serializer):
    sort = StringField()

class PaginationRequestSerializer(Serializer):
    page = IntegerField()
    per_page = IntegerField()

class PaginationResponseSerializer(Serializer):
    page = IntegerField()
    per_page = IntegerField()
    count = IntegerField()

class ListSerializer(Serializer):
    pagination = PaginationResponseSerializer()

    def __init__(self, serializer, *args, **kwargs):
        super(ListSerializer, self).__init__(*args, **kwargs)
        self.serializer = serializer

    def get_fields(self):
        fields = super(ListSerializer, self).get_fields()

        data_field = ListField(self.serializer)
        data_field.bind('data')
        fields['data'] = data_field

        return fields

class ListViewMixin(object):
    def list(self, *args, **kwargs):
        obj_list = self.get_object_list()

        serializer = self.get_serializer()
        list_serializer = ListSerializer(serializer)
        data = list_serializer.to_data({'data': obj_list})

        return jsonify(data)

class ListModelViewMixin(object):
    def list(self, *args, **kwargs):
        obj_list, pagination = self.get_object_list()

        serializer = self.get_serializer()
        list_serializer = ListSerializer(serializer)

        response = {'data': obj_list}

        if pagination:
            response['pagination'] = pagination

        data = list_serializer.to_data(response)

        return jsonify(data)

class RetrieveModelViewMixin(object):
    def retrieve(self, *args, **kwargs):
        obj = self.get_object()
        serializer = self.get_serializer()
        data = serializer.to_data(obj)
        return jsonify(data)

class UpdateModelViewMixin(object):
    def update(self, *args, **kwargs):
        obj = self.get_object()
        serializer = self.get_serializer()

        json = request.get_json()

        if json is None:
            raise BadRequest()

        deserialized_data = serializer.to_value(json)

        validation = self.get_validation()

        if validation is None:
            obj = serializer.update(obj, deserialized_data)
        else:
            ctx = self.get_context(deserialized_data)

            with db.session.no_autoflush:
                try:
                    validation.before_update(ctx, obj)
                    old_obj = validation.clone(obj)
                    obj = serializer.update(obj, deserialized_data)
                    validation.after_update(ctx, old_obj, obj)
                except ValidationError as e:
                    errors = serializer.transform_errors(e.errors)
                    raise ValidationError(errors)

        db.session.commit()
        data = serializer.to_data(obj)
        return jsonify(data)

class DestroyModelViewMixin(object):
    def destroy(self, *args, **kwargs):
        obj = self.get_object()
        db.session.delete(obj)
        db.session.commit()
        return '', 204

class RetrieveModelView(RetrieveModelViewMixin, ModelView):
    def get(self, *args, **kwargs):
        return self.retrieve(*args, **kwargs)

class ListView(ListViewMixin, BaseView):
    def get(self, *args, **kwargs):
        return self.list(*args, **kwargs)

class ListModelView(ListModelViewMixin, ModelView):
    def get(self, *args, **kwargs):
        return self.list(*args, **kwargs)

class ListCreateModelView(ListModelViewMixin, CreateModelViewMixin, ModelView):
    def get(self, *args, **kwargs):
        return self.list(*args, **kwargs)

    def post(self, *args, **kwargs):
        return self.create(*args, **kwargs)

class RetrieveUpdateDestroyModelView(RetrieveModelViewMixin, UpdateModelViewMixin, DestroyModelViewMixin, ModelView):
    def get(self, *args, **kwargs):
        return self.retrieve(*args, **kwargs)

    def put(self, *args, **kwargs):
        return self.update(*args, **kwargs)

    def post(self, *args, **kwargs):
        return self.update(*args, **kwargs)

    def delete(self, *args, **kwargs):
        return self.destroy(*args, **kwargs)

class RetrieveUpdateModelView(RetrieveModelViewMixin, UpdateModelViewMixin, ModelView):
    def get(self, *args, **kwargs):
        return self.retrieve(*args, **kwargs)

    def put(self, *args, **kwargs):
        return self.update(*args, **kwargs)

    def post(self, *args, **kwargs):
        return self.update(*args, **kwargs)

class CreateModelView(CreateModelViewMixin, ModelView):
    def post(self, *args, **kwargs):
        return self.create(*args, **kwargs)

class UpdateModelView(UpdateModelViewMixin, ModelView):
    def put(self, *args, **kwargs):
        return self.update(*args, **kwargs)

class DestroyModelView(DestroyModelViewMixin, ModelView):
    def delete(self, *args, **kwargs):
        return self.destroy(*args, **kwargs)

def request_json(serializer_class, validation_class=None):
    def decorator(f):
        @wraps(f)
        def wrapper(*args, **kwargs):
            json = request.get_json()

            if json is None:
                raise BadRequest()

            serializer = serializer_class()
            data = serializer.to_value(json)

            if validation_class is not None:
                validation = validation_class()

                ctx = {}

                if current_user.is_authenticated():
                    ctx['user'] = current_user

                try:
                    validation.after_update(ctx, {}, data)
                except ValidationError as e:
                    errors = serializer.transform_errors(e.errors)
                    raise ValidationError(errors)

            args = list(args)
            args.append(data)

            return f(*args, **kwargs)

        return wrapper

    return decorator

def response_json(serializer_class):
    def decorator(f):
        @wraps(f)
        def wrapper(*args, **kwargs):
            response = f(*args, **kwargs)
            serializer = serializer_class()
            data = serializer.to_data(response)
            return jsonify(data), 200

        return wrapper

    return decorator
<|endoftext|>


<commit_before>#!/usr/bin/env python
from math import sqrt

class Ponto(object):
  x = 0
  y = 0
  t = 0.0

  def __init__(self, x, y, t):
        self.x = x
        self.y = y
        self.t = t

text_file = open("in.txt", "r")
lines = text_file.read().split('\n')

pontos = []

for i in range(len(lines)):
  dados = lines[i].split(',')
  p = Ponto(dados[0], dados[1], dados[2])
  pontos.append(p)

for p in pontos:
  print "p = (" + p.x + "," + p.y + "), " + p.t

text_file.close()<commit_msg>Trying to fix angle calc<commit_after>#!/usr/bin/env python
from math import sqrt
from math import atan
from math import degrees

class Ponto(object):
  x = 0.0
  y = 0.0
  t = 0.0
  v = 0.0
  a = 0.0

  def __init__(self, x, y, t, v, a):
        self.x = x
        self.y = y
        self.t = t
        self.v = 0.0
        self.a = 0.0

def velocidade(p1, p2):
  deltaX = p2.x-p1.x
  deltaY = p2.y-p1.y
  deltaT = p2.t-p1.t

  deltaS = sqrt(abs((deltaY^2)-(deltaX^2))) # Calculo de velocidade media
  return (deltaS/deltaT)

def angulo(p1, p2):
  deltaX = p2.x-p1.x
  deltaY = p2.y-p1.y

  if deltaX == 0: # Se nao se deslocou no eixo X, divisao por zero!
    if deltaY > 0: # Se deslocou em Y para cima
      return 90.0
    if deltaY < 0: # Se deslocou em Y para baixo
      return -90.0
    return p1.a # Nao se deslocou nem em X nem em Y

  m = deltaY/deltaX
  a = degrees(atan(m))

  return a # Se deslocou em X e Y

text_file = open("in.txt", "r")
lines = text_file.read().split('\n')

pontos = []

for i in range(len(lines)):
  dados = lines[i].split(',')
  p = Ponto(int(dados[0]), int(dados[1]), float(dados[2]),0.0,0.0)
  if i > 0: # Se estiver a partir do segundo ponto
    p.v = velocidade(pontos[i-1], p)
    p.a = angulo(pontos[i-1], p)

  pontos.append(p)

for i in range(len(lines)):
  p = pontos[i]
  print "P" + str(i) + "= (" + str(p.x) + "," + str(p.y) + ") \t| Tempo " + str(p.t) + "\t | Angulo " + str(p.a) + "\t | Velocidade=> Total: " + str("%0.4f" % p.v) + " \t Cada roda: " + str("%0.4f" % ((p.v)/2))

text_file.close()<|endoftext|>