<commit_before>"""This module handles the Stage Select Screen and all of its various
components.

Module Constants:
    BORDER_WIDTH (int): The thickness, in pixels, of the borders of
        the stage preview as well as each stage thumbnail.
    TOP_THUMB_Y (int): The y-position of the top-most thumbnail
        on-screen.
    THUMB_X (int): The shared x-position of all thumbnails on-screen.
    THUMB_SIZE (int): The width and height, in pixels, of each thumbnail
        image.
    THUMB_BORDER_COLOR (tuple of int): The RGB values for the color of
        the thumbnail border.
    THUMB_HIGHLIGHT_COLOR (tuple of int): The RGB values for the color
        of the thumbnail border when a particular thumbnail is selected.
    PREVIEW_X (int): The x-position of the stage preview on-screen.
    PREVIEW_Y (int): The y-position of the stage preview on-screen.
    PREVIEW_WIDTH (int): The width, in pixels, of the stage preview.
    PREVIEW_HEIGHT (int): The height, in pixels, of the stage preview.
    PREVIEW_OUTER_BORDER_COLOR (tuple): The RGB values for the color of
        the outermost preview border.
    PREVIEW_INNER_BORDER_COLOR (tuple): The RGB values for the color of
        the innermost preview border.
    LINE_WIDTHS (tuple of int): The respective widths, in pixels, of
        each BackgroundLine.
    LINE_COLOR (tuple of int): The RGB value for the color of the
        BackgroundLines.
    LINE_SPEED (int): The speed, in pixels per second, at which the
        BackgroundLines travel and bounce horizontally.
    LINE_LEFT_BOUND (int): The on-screen x-position of the furthest left
        that the BackgroundLines can travel.
    LINE_RIGHT_BOUND (int): The on-screen x-position of the furthest
        right that the BackgroundLines can travel.
    TRANSITION_SLIDE_SPEED (int): The speed, in pixels per second, that
        Graphics move in and out of the screen at when transitioning in
        or out of this State.
"""
import pygame.draw
from lib.graphics import Graphic, get_line_center
from lib.globals import SCREEN_SIZE
from pygame.surface import Surface
from pygame.rect import Rect

BORDER_WIDTH = 2
TOP_THUMB_Y = 34
THUMB_X = 302
THUMB_SIZE = 50
THUMB_BORDER_COLOR = (102, 102, 102)
THUMB_HIGHLIGHT_COLOR = (192, 0, 255)
PREVIEW_X = 14
PREVIEW_Y = 11
PREVIEW_WIDTH = 245
PREVIEW_HEIGHT = 130
PREVIEW_OUTER_BORDER_COLOR = (0, 7, 51)
PREVIEW_INNER_BORDER_COLOR = (0, 19, 127)
LINE_WIDTHS = (3, 4, 12, 6)
LINE_COLOR = (0, 19, 127)
LINE_SPEED = 200
LINE_LEFT_BOUND = 292
LINE_RIGHT_BOUND = 363
TRANSITION_SLIDE_SPEED = 500

class StageThumbnail(Graphic):
    """A small icon for a Stage that can be selected by the players.
    """
    def __init__(self, thumbnail_image, y):
        """Declare and initialize instance variables.

        Args:
            thumbnail_image (Surface): The Stage's icon image.
            y (int): The thumbnail's y-position on-screen.
        """
        position = (THUMB_X, y)
        super(StageThumbnail, self).__init__(thumbnail_image, position)
        self.add_border()

    def add_border(self):
        """Draw a border around the thumbnail image Surface."""
        new_surf = Surface((THUMB_SIZE + (BORDER_WIDTH * 2),
                            THUMB_SIZE + (BORDER_WIDTH * 2)))
        new_surf.blit(self.image, (BORDER_WIDTH, BORDER_WIDTH))
        border_rect = Rect(get_line_center(BORDER_WIDTH),
                           get_line_center(BORDER_WIDTH),
                           THUMB_SIZE + BORDER_WIDTH + 1,
                           THUMB_SIZE + BORDER_WIDTH + 1)
        pygame.draw.rect(new_surf, THUMB_BORDER_COLOR, border_rect,
                         BORDER_WIDTH)
        self.image = new_surf

    def change_stage(self, new_image):
        """Change the icon image to represent a different Stage.

        Args:
            new_image (Surface): The new Stage icon to display.
        """
        self.image.blit(new_image, (BORDER_WIDTH, BORDER_WIDTH))

    def change_border(self, color):
        """Redraw the border with a specific color.

        Args:
            color (tuple of int, int, int): The RGB values for the new
                border color.
        """
        border_rect = Rect(0, 0, self.image.get_width() - 1,
                           self.image.get_height() - 1)
        pygame.draw.rect(self.image, color, border_rect, BORDER_WIDTH)

    def highlight(self):
        """Recolor the border to show that the thumbnail is selected."""
        self.change_border(THUMB_HIGHLIGHT_COLOR)

    def unhighlight(self):
        """Recolor the border to show the thumbnail deselected."""
        self.change_border(THUMB_BORDER_COLOR)

class StagePreview(Graphic):
    """A snapshot of the currently-selected Stage."""
    def __init__(self, image):
        """Declare and initialize instance variables.

        Args:
            image (Surface): The snapshot image initially displayed.
        """
        super(StagePreview, self).__init__(image, (PREVIEW_X, PREVIEW_Y))
        self.add_borders()

    def add_borders(self):
        """Draw an outer and inner border around the snapshot image."""
        new_surf = Surface((PREVIEW_WIDTH + (BORDER_WIDTH * 4),
                            PREVIEW_HEIGHT + (BORDER_WIDTH * 4)))
        new_surf.blit(self.image, (BORDER_WIDTH * 2, BORDER_WIDTH * 2))

        inner_rect = Rect(BORDER_WIDTH + get_line_center(BORDER_WIDTH),
                          BORDER_WIDTH + get_line_center(BORDER_WIDTH),
                          PREVIEW_WIDTH + BORDER_WIDTH + 1,
                          PREVIEW_HEIGHT + BORDER_WIDTH + 1)
        outer_rect = Rect(get_line_center(BORDER_WIDTH),
                          get_line_center(BORDER_WIDTH),
                          PREVIEW_WIDTH + (BORDER_WIDTH * 3) + 1,
                          PREVIEW_HEIGHT + (BORDER_WIDTH * 3) + 1)
        pygame.draw.rect(new_surf, PREVIEW_INNER_BORDER_COLOR, inner_rect,
                         BORDER_WIDTH)
        pygame.draw.rect(new_surf, PREVIEW_OUTER_BORDER_COLOR, outer_rect,
                          BORDER_WIDTH)

        self.image = new_surf

    def change_stage(self, new_image):
        """Change the displayed snapshot to represent another Stage.

        Args:
            new_image (Surface): The new Stage snapshot to be displayed.
        """
        self.image.blit(new_image, (BORDER_WIDTH * 2, BORDER_WIDTH * 2))

class BackgroundLine(Graphic):
    """A vertical line that moves back and forth horizontally across the
    the screen.

    Attributes:
        is_moving_right (Boolean): This indicates whether the line is
            currently moving to the right horizontally.
    """
    def __init__(self, x, thickness, is_moving_right):
        """Declare and initialize instance variables.

        Args:
            x (int): The initial x-position of the line's left edge.
            thickness (int): The thickness of the line, in pixels.
            is_moving_right (Boolean): Indicates whether the line is
                moving to the right initially.
        """
        image = self.render(thickness)
        super(BackgroundLine, self).__init__(image, (x, 0))
        self.is_moving_right = is_moving_right

    def render(self, thickness):
        """Return a Surface containing the drawn line.

        Args:
            thickness (int): The thickness of the line, in pixels.
        """
        surf = Surface((thickness, SCREEN_SIZE[1]))
        x = get_line_center(thickness)
        pygame.draw.line(surf, LINE_COLOR, (x, 0),
                         (x, SCREEN_SIZE[1]), thickness)
        return surf

    def update_movement(self, time_elapsed):
        """Update the line's horizontal movement.

        Args:
            time_elapsed (float): The time elapsed, in seconds, since
                the last update cycle.
        """
        distance = LINE_SPEED * time_elapsed

        if self.is_moving_right:
            if self.get_right_edge() + distance > LINE_RIGHT_BOUND:
                # Line bounces off right edge.
                distance = LINE_RIGHT_BOUND - self.get_right_edge()
                self.move(distance * -1, 0)
                self.is_moving_right = False
            else:
                self.move(distance, 0)
        else:
            if self.rect.x - distance < LINE_LEFT_BOUND:
                # Line bounces off left edge.
                distance = self.rect.x - LINE_LEFT_BOUND
                self.move(distance, 0)
                self.is_moving_right = True
            else:
                self.move(distance * -1, 0)
<commit_msg>Define the StageMetadata namedtuple<commit_after>"""This module handles the Stage Select Screen and all of its various
components.

Module Constants:
    BORDER_WIDTH (int): The thickness, in pixels, of the borders of
        the stage preview as well as each stage thumbnail.
    TOP_THUMB_Y (int): The y-position of the top-most thumbnail
        on-screen.
    THUMB_X (int): The shared x-position of all thumbnails on-screen.
    THUMB_SIZE (int): The width and height, in pixels, of each thumbnail
        image.
    THUMB_BORDER_COLOR (tuple of int): The RGB values for the color of
        the thumbnail border.
    THUMB_HIGHLIGHT_COLOR (tuple of int): The RGB values for the color
        of the thumbnail border when a particular thumbnail is selected.
    PREVIEW_X (int): The x-position of the stage preview on-screen.
    PREVIEW_Y (int): The y-position of the stage preview on-screen.
    PREVIEW_WIDTH (int): The width, in pixels, of the stage preview.
    PREVIEW_HEIGHT (int): The height, in pixels, of the stage preview.
    PREVIEW_OUTER_BORDER_COLOR (tuple): The RGB values for the color of
        the outermost preview border.
    PREVIEW_INNER_BORDER_COLOR (tuple): The RGB values for the color of
        the innermost preview border.
    LINE_WIDTHS (tuple of int): The respective widths, in pixels, of
        each BackgroundLine.
    LINE_COLOR (tuple of int): The RGB value for the color of the
        BackgroundLines.
    LINE_SPEED (int): The speed, in pixels per second, at which the
        BackgroundLines travel and bounce horizontally.
    LINE_LEFT_BOUND (int): The on-screen x-position of the furthest left
        that the BackgroundLines can travel.
    LINE_RIGHT_BOUND (int): The on-screen x-position of the furthest
        right that the BackgroundLines can travel.
    TRANSITION_SLIDE_SPEED (int): The speed, in pixels per second, that
        Graphics move in and out of the screen at when transitioning in
        or out of this State.
"""
import pygame.draw
from collections import namedtuple
from lib.graphics import Graphic, get_line_center
from lib.globals import SCREEN_SIZE
from pygame.surface import Surface
from pygame.rect import Rect

BORDER_WIDTH = 2
TOP_THUMB_Y = 34
THUMB_X = 302
THUMB_SIZE = 50
THUMB_BORDER_COLOR = (102, 102, 102)
THUMB_HIGHLIGHT_COLOR = (192, 0, 255)
PREVIEW_X = 14
PREVIEW_Y = 11
PREVIEW_WIDTH = 245
PREVIEW_HEIGHT = 130
PREVIEW_OUTER_BORDER_COLOR = (0, 7, 51)
PREVIEW_INNER_BORDER_COLOR = (0, 19, 127)
LINE_WIDTHS = (3, 4, 12, 6)
LINE_COLOR = (0, 19, 127)
LINE_SPEED = 200
LINE_LEFT_BOUND = 292
LINE_RIGHT_BOUND = 363
TRANSITION_SLIDE_SPEED = 500

StageMetadata = namedtuple('StageMetadata', 'name subtitle preview thumbnail')

class StageThumbnail(Graphic):
    """A small icon for a Stage that can be selected by the players.
    """
    def __init__(self, thumbnail_image, y):
        """Declare and initialize instance variables.

        Args:
            thumbnail_image (Surface): The Stage's icon image.
            y (int): The thumbnail's y-position on-screen.
        """
        position = (THUMB_X, y)
        super(StageThumbnail, self).__init__(thumbnail_image, position)
        self.add_border()

    def add_border(self):
        """Draw a border around the thumbnail image Surface."""
        new_surf = Surface((THUMB_SIZE + (BORDER_WIDTH * 2),
                            THUMB_SIZE + (BORDER_WIDTH * 2)))
        new_surf.blit(self.image, (BORDER_WIDTH, BORDER_WIDTH))
        border_rect = Rect(get_line_center(BORDER_WIDTH),
                           get_line_center(BORDER_WIDTH),
                           THUMB_SIZE + BORDER_WIDTH + 1,
                           THUMB_SIZE + BORDER_WIDTH + 1)
        pygame.draw.rect(new_surf, THUMB_BORDER_COLOR, border_rect,
                         BORDER_WIDTH)
        self.image = new_surf

    def change_stage(self, new_image):
        """Change the icon image to represent a different Stage.

        Args:
            new_image (Surface): The new Stage icon to display.
        """
        self.image.blit(new_image, (BORDER_WIDTH, BORDER_WIDTH))

    def change_border(self, color):
        """Redraw the border with a specific color.

        Args:
            color (tuple of int, int, int): The RGB values for the new
                border color.
        """
        border_rect = Rect(0, 0, self.image.get_width() - 1,
                           self.image.get_height() - 1)
        pygame.draw.rect(self.image, color, border_rect, BORDER_WIDTH)

    def highlight(self):
        """Recolor the border to show that the thumbnail is selected."""
        self.change_border(THUMB_HIGHLIGHT_COLOR)

    def unhighlight(self):
        """Recolor the border to show the thumbnail deselected."""
        self.change_border(THUMB_BORDER_COLOR)

class StagePreview(Graphic):
    """A snapshot of the currently-selected Stage."""
    def __init__(self, image):
        """Declare and initialize instance variables.

        Args:
            image (Surface): The snapshot image initially displayed.
        """
        super(StagePreview, self).__init__(image, (PREVIEW_X, PREVIEW_Y))
        self.add_borders()

    def add_borders(self):
        """Draw an outer and inner border around the snapshot image."""
        new_surf = Surface((PREVIEW_WIDTH + (BORDER_WIDTH * 4),
                            PREVIEW_HEIGHT + (BORDER_WIDTH * 4)))
        new_surf.blit(self.image, (BORDER_WIDTH * 2, BORDER_WIDTH * 2))

        inner_rect = Rect(BORDER_WIDTH + get_line_center(BORDER_WIDTH),
                          BORDER_WIDTH + get_line_center(BORDER_WIDTH),
                          PREVIEW_WIDTH + BORDER_WIDTH + 1,
                          PREVIEW_HEIGHT + BORDER_WIDTH + 1)
        outer_rect = Rect(get_line_center(BORDER_WIDTH),
                          get_line_center(BORDER_WIDTH),
                          PREVIEW_WIDTH + (BORDER_WIDTH * 3) + 1,
                          PREVIEW_HEIGHT + (BORDER_WIDTH * 3) + 1)
        pygame.draw.rect(new_surf, PREVIEW_INNER_BORDER_COLOR, inner_rect,
                         BORDER_WIDTH)
        pygame.draw.rect(new_surf, PREVIEW_OUTER_BORDER_COLOR, outer_rect,
                          BORDER_WIDTH)

        self.image = new_surf

    def change_stage(self, new_image):
        """Change the displayed snapshot to represent another Stage.

        Args:
            new_image (Surface): The new Stage snapshot to be displayed.
        """
        self.image.blit(new_image, (BORDER_WIDTH * 2, BORDER_WIDTH * 2))

class BackgroundLine(Graphic):
    """A vertical line that moves back and forth horizontally across the
    the screen.

    Attributes:
        is_moving_right (Boolean): This indicates whether the line is
            currently moving to the right horizontally.
    """
    def __init__(self, x, thickness, is_moving_right):
        """Declare and initialize instance variables.

        Args:
            x (int): The initial x-position of the line's left edge.
            thickness (int): The thickness of the line, in pixels.
            is_moving_right (Boolean): Indicates whether the line is
                moving to the right initially.
        """
        image = self.render(thickness)
        super(BackgroundLine, self).__init__(image, (x, 0))
        self.is_moving_right = is_moving_right

    def render(self, thickness):
        """Return a Surface containing the drawn line.

        Args:
            thickness (int): The thickness of the line, in pixels.
        """
        surf = Surface((thickness, SCREEN_SIZE[1]))
        x = get_line_center(thickness)
        pygame.draw.line(surf, LINE_COLOR, (x, 0),
                         (x, SCREEN_SIZE[1]), thickness)
        return surf

    def update_movement(self, time_elapsed):
        """Update the line's horizontal movement.

        Args:
            time_elapsed (float): The time elapsed, in seconds, since
                the last update cycle.
        """
        distance = LINE_SPEED * time_elapsed

        if self.is_moving_right:
            if self.get_right_edge() + distance > LINE_RIGHT_BOUND:
                # Line bounces off right edge.
                distance = LINE_RIGHT_BOUND - self.get_right_edge()
                self.move(distance * -1, 0)
                self.is_moving_right = False
            else:
                self.move(distance, 0)
        else:
            if self.rect.x - distance < LINE_LEFT_BOUND:
                # Line bounces off left edge.
                distance = self.rect.x - LINE_LEFT_BOUND
                self.move(distance, 0)
                self.is_moving_right = True
            else:
                self.move(distance * -1, 0)
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
##############################################################################
#
#    Copyright (C) 2012 Agile Business Group sagl (<http://www.agilebg.com>)
#    Copyright (C) 2012 Domsense srl (<http://www.domsense.com>)
#
#    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/>.
#
##############################################################################

from openerp.osv import fields, osv, orm
from openerp.tools.translate import _
from openerp import netsvc
from mako.template import Template
from datetime import datetime
from openerp import tools

def _models_get(self, cr, uid, context=None):
    obj = self.pool.get('ir.model')
    ids = obj.search(cr, uid, [])
    res = obj.read(cr, uid, ids, ['model', 'name'], context)
    return [(r['model'], r['name']) for r in res]

class super_calendar_configurator(orm.Model):
    _logger = netsvc.Logger()
    _name = 'super.calendar.configurator'
    _columns  = {
        'name': fields.char('Name', size=64, required=True),
        'line_ids': fields.one2many('super.calendar.configurator.line', 'configurator_id', 'Lines'),
        }

    def generate_calendar_records(self, cr, uid, ids, context=None):
        configurator_ids = self.search(cr, uid, [])
        super_calendar_pool = self.pool.get('super.calendar')

        # removing old records
        super_calendar_ids = super_calendar_pool.search(cr, uid, [])
        super_calendar_pool.unlink(cr, uid, super_calendar_ids)

        for configurator_id in configurator_ids:
            configurator = self.browse(cr, uid, configurator_id)
            for line in configurator.line_ids:
                current_pool = self.pool.get(line.name.model)
                current_record_ids = current_pool.search(cr, uid, line.domain and eval(line.domain) or [])
                for current_record_id in current_record_ids:
                    current_record  = current_pool.browse(cr, uid, current_record_id)
                    if line.user_field_id and \
                        current_record[line.user_field_id.name] and current_record[line.user_field_id.name]._table_name != 'res.users':
                        raise osv.except_osv(_('Error'),
                            _("The 'User' field of record %s (%s) does not refer to res.users")
                            % (current_record[line.description_field_id.name], line.name.model))
                    if ((line.description_field_id and current_record[line.description_field_id.name]) or line.description_code)  \
                        and current_record[line.date_start_field_id.name]:
                        duration = False
                        if not line.duration_field_id and line.date_stop_field_id and current_record[line.date_start_field_id.name] and current_record[line.date_stop_field_id.name]:
                            date_start= datetime.strptime(current_record[line.date_start_field_id.name], tools.DEFAULT_SERVER_DATETIME_FORMAT)
                            date_stop= datetime.strptime(current_record[line.date_stop_field_id.name], tools.DEFAULT_SERVER_DATETIME_FORMAT)
                            duration = (date_stop - date_start).total_seconds() / 3600
                        elif line.duration_field_id:
                            duration = current_record[line.duration_field_id.name]
                        if line.description_type != 'code':
                            name = current_record[line.description_field_id.name]
                        else:
                            parse_dict = {'o': current_record}
                            mytemplate = Template(line.description_code)
                            name= mytemplate.render(**parse_dict)
                        super_calendar_values = {
                            'name': name,
                            'model_description': line.description,
                            'date_start': current_record[line.date_start_field_id.name],
                            'duration': duration,
                            'user_id': line.user_field_id and current_record[line.user_field_id.name] and current_record[line.user_field_id.name].id or False,
                            'configurator_id': configurator.id,
                            'res_id': line.name.model+','+str(current_record['id']),
                            'model_id': line.name.id,
                            }
                        super_calendar_pool.create(cr, uid, super_calendar_values)
        self._logger.notifyChannel('super_calendar', netsvc.LOG_INFO, "Calendar generated")
        return True

super_calendar_configurator()

class super_calendar_configurator_line(orm.Model):
    _name = 'super.calendar.configurator.line'
    _columns  = {
        'name': fields.many2one('ir.model', 'Model', required=True),
        'description': fields.char('Description', size=128, required=True),
        'domain': fields.char('Domain', size=512),
        'configurator_id': fields.many2one('super.calendar.configurator', 'Configurator'),
        'description_type': fields.selection([
            ('field', 'Field'),
            ('code', 'Code'),
            ], string="Description Type"),
        'description_field_id': fields.many2one('ir.model.fields', 'Description field',
            domain="[('model_id', '=', name),('ttype', '=', 'char')]"),
        'description_code': fields.text('Description field', help="Use '${o}' to refer to the involved object. E.g.: '${o.project_id.name}'"),
        'date_start_field_id': fields.many2one('ir.model.fields', 'Start date field',
            domain="['&','|',('ttype', '=', 'datetime'),('ttype', '=', 'date'),('model_id', '=', name)]",
            required=True),
        'date_stop_field_id': fields.many2one('ir.model.fields', 'End date field',
            domain="['&',('ttype', '=', 'datetime'),('model_id', '=', name)]"),
        'duration_field_id': fields.many2one('ir.model.fields', 'Duration field',
            domain="['&',('ttype', '=', 'float'),('model_id', '=', name)]"),
        'user_field_id': fields.many2one('ir.model.fields', 'User field',
            domain="['&',('ttype', '=', 'many2one'),('model_id', '=', name)]"),
        }

super_calendar_configurator_line()

class super_calendar(orm.Model):
    _name = 'super.calendar'
    _columns  = {
        'name': fields.char('Description', size=512, required=True),
        'model_description': fields.char('Model Description', size=128, required=True),
        'date_start':fields.datetime('Start date', required=True),
        #'date_stop':fields.datetime('End date'), # to be removed?
        'duration':fields.float('Duration'),
        'user_id': fields.many2one('res.users', 'User'),
        'configurator_id': fields.many2one('super.calendar.configurator', 'Configurator'),
        'res_id': fields.reference('Resource', selection=_models_get, size=128),
        'model_id': fields.many2one('ir.model', 'Model'),
        }
super_calendar()
<commit_msg>[FIX] using right logger<commit_after># -*- coding: utf-8 -*-
##############################################################################
#
#    Copyright (C) 2012 Agile Business Group sagl (<http://www.agilebg.com>)
#    Copyright (C) 2012 Domsense srl (<http://www.domsense.com>)
#
#    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/>.
#
##############################################################################

from openerp.osv import fields, osv, orm
from openerp.tools.translate import _
from openerp import logging
from mako.template import Template
from datetime import datetime
from openerp import tools

def _models_get(self, cr, uid, context=None):
    obj = self.pool.get('ir.model')
    ids = obj.search(cr, uid, [])
    res = obj.read(cr, uid, ids, ['model', 'name'], context)
    return [(r['model'], r['name']) for r in res]

class super_calendar_configurator(orm.Model):
    _logger = logging.getLogger('super.calendar')
    _name = 'super.calendar.configurator'
    _columns  = {
        'name': fields.char('Name', size=64, required=True),
        'line_ids': fields.one2many('super.calendar.configurator.line', 'configurator_id', 'Lines'),
        }

    def generate_calendar_records(self, cr, uid, ids, context=None):
        configurator_ids = self.search(cr, uid, [])
        super_calendar_pool = self.pool.get('super.calendar')

        # removing old records
        super_calendar_ids = super_calendar_pool.search(cr, uid, [])
        super_calendar_pool.unlink(cr, uid, super_calendar_ids)

        for configurator_id in configurator_ids:
            configurator = self.browse(cr, uid, configurator_id)
            for line in configurator.line_ids:
                current_pool = self.pool.get(line.name.model)
                current_record_ids = current_pool.search(cr, uid, line.domain and eval(line.domain) or [])
                for current_record_id in current_record_ids:
                    current_record  = current_pool.browse(cr, uid, current_record_id)
                    if line.user_field_id and \
                        current_record[line.user_field_id.name] and current_record[line.user_field_id.name]._table_name != 'res.users':
                        raise osv.except_osv(_('Error'),
                            _("The 'User' field of record %s (%s) does not refer to res.users")
                            % (current_record[line.description_field_id.name], line.name.model))
                    if ((line.description_field_id and current_record[line.description_field_id.name]) or line.description_code)  \
                        and current_record[line.date_start_field_id.name]:
                        duration = False
                        if not line.duration_field_id and line.date_stop_field_id and current_record[line.date_start_field_id.name] and current_record[line.date_stop_field_id.name]:
                            date_start= datetime.strptime(current_record[line.date_start_field_id.name], tools.DEFAULT_SERVER_DATETIME_FORMAT)
                            date_stop= datetime.strptime(current_record[line.date_stop_field_id.name], tools.DEFAULT_SERVER_DATETIME_FORMAT)
                            duration = (date_stop - date_start).total_seconds() / 3600
                        elif line.duration_field_id:
                            duration = current_record[line.duration_field_id.name]
                        if line.description_type != 'code':
                            name = current_record[line.description_field_id.name]
                        else:
                            parse_dict = {'o': current_record}
                            mytemplate = Template(line.description_code)
                            name= mytemplate.render(**parse_dict)
                        super_calendar_values = {
                            'name': name,
                            'model_description': line.description,
                            'date_start': current_record[line.date_start_field_id.name],
                            'duration': duration,
                            'user_id': line.user_field_id and current_record[line.user_field_id.name] and current_record[line.user_field_id.name].id or False,
                            'configurator_id': configurator.id,
                            'res_id': line.name.model+','+str(current_record['id']),
                            'model_id': line.name.id,
                            }
                        super_calendar_pool.create(cr, uid, super_calendar_values)
        self._logger.info('Calendar generated')
        return True

super_calendar_configurator()

class super_calendar_configurator_line(orm.Model):
    _name = 'super.calendar.configurator.line'
    _columns  = {
        'name': fields.many2one('ir.model', 'Model', required=True),
        'description': fields.char('Description', size=128, required=True),
        'domain': fields.char('Domain', size=512),
        'configurator_id': fields.many2one('super.calendar.configurator', 'Configurator'),
        'description_type': fields.selection([
            ('field', 'Field'),
            ('code', 'Code'),
            ], string="Description Type"),
        'description_field_id': fields.many2one('ir.model.fields', 'Description field',
            domain="[('model_id', '=', name),('ttype', '=', 'char')]"),
        'description_code': fields.text('Description field', help="Use '${o}' to refer to the involved object. E.g.: '${o.project_id.name}'"),
        'date_start_field_id': fields.many2one('ir.model.fields', 'Start date field',
            domain="['&','|',('ttype', '=', 'datetime'),('ttype', '=', 'date'),('model_id', '=', name)]",
            required=True),
        'date_stop_field_id': fields.many2one('ir.model.fields', 'End date field',
            domain="['&',('ttype', '=', 'datetime'),('model_id', '=', name)]"),
        'duration_field_id': fields.many2one('ir.model.fields', 'Duration field',
            domain="['&',('ttype', '=', 'float'),('model_id', '=', name)]"),
        'user_field_id': fields.many2one('ir.model.fields', 'User field',
            domain="['&',('ttype', '=', 'many2one'),('model_id', '=', name)]"),
        }

super_calendar_configurator_line()

class super_calendar(orm.Model):
    _name = 'super.calendar'
    _columns  = {
        'name': fields.char('Description', size=512, required=True),
        'model_description': fields.char('Model Description', size=128, required=True),
        'date_start':fields.datetime('Start date', required=True),
        #'date_stop':fields.datetime('End date'), # to be removed?
        'duration':fields.float('Duration'),
        'user_id': fields.many2one('res.users', 'User'),
        'configurator_id': fields.many2one('super.calendar.configurator', 'Configurator'),
        'res_id': fields.reference('Resource', selection=_models_get, size=128),
        'model_id': fields.many2one('ir.model', 'Model'),
        }
super_calendar()
<|endoftext|>


<commit_before>from fabric.api import task, local, cd, settings, run, sudo, put, get, abort
from fabric.contrib import files
from fabric.contrib.console import confirm
import aws, utils
from decorators import requires_project, requires_aws_stack, requires_steady_stack, echo_output, setdefault, debugtask
import os
from os.path import join
from buildercore import core, cfngen, utils as core_utils, bootstrap, project, checks
from buildercore.core import stack_conn, stack_pem
from buildercore.config import DEPLOY_USER, BOOTSTRAP_USER
from distutils.util import strtobool

import logging
LOG = logging.getLogger(__name__)

# these aliases are deprecated
@task(alias='aws_delete_stack')
@requires_steady_stack
def destroy(stackname):
    "tell aws to delete a stack."
    print 'this is a BIG DEAL. you cannot recover from this.'
    print 'type the name of the stack to continue or anything else to quit'
    uin = raw_input('> ')
    if not uin or not uin.strip().lower() == stackname.lower():
        import difflib
        print 'you needed to type "%s" to continue.' % stackname
        print 'got:'
        print '\n'.join(difflib.ndiff([stackname], [uin]))
        exit(1)
    return bootstrap.delete_stack(stackname)

# these aliases are deprecated
@task(alias='aws_update_stack')
@requires_aws_stack
def update(stackname):
    """Updates the environment within the stack's ec2 instance.

    does *not* call Cloudformation's `update` command on the stack"""
    return bootstrap.update_stack(stackname)

@task
def update_master():
    return bootstrap.update_stack(core.find_master(aws.find_region()))

@requires_project
def create_stack(pname):
    """creates a new CloudFormation template for the given project."""
    default_instance_id = core_utils.ymd()
    inst_id = utils.uin("instance id", default_instance_id)
    stackname = core.mk_stackname(pname, inst_id)
    more_context = {'instance_id': stackname}

    # prompt user for alternate configurations
    pdata = project.project_data(pname)
    if pdata.has_key('aws-alt'):
        def helpfn(altkey):
            try:
                return pdata['aws-alt'][altkey]['description']
            except KeyError:
                return None
        default = 'skip this step'
        alt_config = [default] + pdata['aws-alt'].keys()
        alt_config = utils._pick('alternative config', alt_config, helpfn=helpfn)
        if alt_config != default:
            more_context['alt-config'] = alt_config
    cfngen.generate_stack(pname, **more_context)
    return stackname

def create_update(stackname):
    if not core.stack_is_active(stackname):
        print 'stack does not exist, creating'
        bootstrap.create_stack(stackname)
    print 'updating stack'
    bootstrap.update_stack(stackname)
    return stackname

# these aliases are deprecated
@task(alias='aws_launch_instance')
@requires_project
def launch(pname):
    try:
        stackname = create_stack(pname)
        pdata = core.project_data_for_stackname(stackname)

        print 'attempting to create stack:'
        print '  stackname: ' + stackname
        print '  region:    ' + pdata['aws']['region']
        print

        if core.is_master_server_stack(stackname):
            if not checks.can_access_builder_private(pname):
                print "failed to access your organisation's 'builder-private' repository:"
                print '  ' + pdata['private-repo']
                print "you'll need access to this repository to add a deploy key later"
                print
                return

        stackname = create_update(stackname)
        if stackname:
            setdefault('.active-stack', stackname)
    except core.NoMasterException, e:
        LOG.warn(e.message)
        print "\n%s\ntry `./bldr master.create`'" % e.message

@debugtask
@requires_aws_stack
def highstate(stackname):
    "a fast update with many caveats. prefer `update` instead"
    with stack_conn(stackname, username=BOOTSTRAP_USER):
        bootstrap.run_script('highstate.sh')

@debugtask
@requires_aws_stack
def pillar(stackname):
    "returns the pillar data a minion is using"
    with stack_conn(stackname, username=BOOTSTRAP_USER):
        sudo('salt-call pillar.items')

@debugtask
@echo_output
def aws_stack_list():
    "returns a list of realized stacks. does not include deleted stacks"
    region = aws.find_region()
    return core.active_stack_names(region)

@task
@requires_aws_stack
def ssh(stackname, username=DEPLOY_USER):
    public_ip = core.stack_data(stackname)['instance']['ip_address']
    # -A forwarding of authentication agent connection
    local("ssh %s@%s" % (username, public_ip))

@task
@requires_aws_stack
def owner_ssh(stackname):
    "maintainence ssh. uses the pem key and the bootstrap user to login."
    public_ip = core.stack_data(stackname)['instance']['ip_address']
    # -i identify file
    # -A forwarding of authentication agent connection
    local("ssh %s@%s -i %s" % (BOOTSTRAP_USER, public_ip, stack_pem(stackname)))

@task
@requires_aws_stack
def download_file(stackname, path, destination, allow_missing):
    fname = os.path.basename(path)
    utils.mkdirp(destination)
    with stack_conn(stackname):
        if not files.exists(path) and strtobool(allow_missing):
            return
        get(path, destination, use_sudo=True)

@task
@requires_aws_stack
def upload_file(stackname, local_path, remote_path, overwrite=False):
    with stack_conn(stackname):
        print 'stack:',stackname
        print 'local:',local_path
        print 'remote:',remote_path
        print 'overwrite:',overwrite
        raw_input('continue?')
        if files.exists(remote_path) and not overwrite:
            print 'remote file exists, not overwriting'
            exit(1)
        put(local_path, remote_path)

#
# these might need a better home
#

@task
@requires_aws_stack
def cmd(stackname, command=None):
    if command is None:
        abort("Please specify a command e.g. ./bldr cmd:%s,ls" % stackname)
    with stack_conn(stackname):
        with settings(abort_on_prompts=True):
            run(command)

@task
def project_list():
    for org, plist in project.org_project_map().items():
        print org
        for p in plist:
            print '  ',p
        print

@task
@requires_project
@echo_output
def project_config(pname):
    return core_utils.remove_ordereddict(project.project_data(pname))
<commit_msg>Option to use owner_ssh key for download_file<commit_after>from distutils.util import strtobool
from fabric.api import task, local, cd, settings, run, sudo, put, get, abort
from fabric.contrib import files
from fabric.contrib.console import confirm
import aws, utils
from decorators import requires_project, requires_aws_stack, requires_steady_stack, echo_output, setdefault, debugtask
import os
from os.path import join
from buildercore import core, cfngen, utils as core_utils, bootstrap, project, checks
from buildercore.core import stack_conn, stack_pem
from buildercore.config import DEPLOY_USER, BOOTSTRAP_USER
from distutils.util import strtobool

import logging
LOG = logging.getLogger(__name__)

# these aliases are deprecated
@task(alias='aws_delete_stack')
@requires_steady_stack
def destroy(stackname):
    "tell aws to delete a stack."
    print 'this is a BIG DEAL. you cannot recover from this.'
    print 'type the name of the stack to continue or anything else to quit'
    uin = raw_input('> ')
    if not uin or not uin.strip().lower() == stackname.lower():
        import difflib
        print 'you needed to type "%s" to continue.' % stackname
        print 'got:'
        print '\n'.join(difflib.ndiff([stackname], [uin]))
        exit(1)
    return bootstrap.delete_stack(stackname)

# these aliases are deprecated
@task(alias='aws_update_stack')
@requires_aws_stack
def update(stackname):
    """Updates the environment within the stack's ec2 instance.

    does *not* call Cloudformation's `update` command on the stack"""
    return bootstrap.update_stack(stackname)

@task
def update_master():
    return bootstrap.update_stack(core.find_master(aws.find_region()))

@requires_project
def create_stack(pname):
    """creates a new CloudFormation template for the given project."""
    default_instance_id = core_utils.ymd()
    inst_id = utils.uin("instance id", default_instance_id)
    stackname = core.mk_stackname(pname, inst_id)
    more_context = {'instance_id': stackname}

    # prompt user for alternate configurations
    pdata = project.project_data(pname)
    if pdata.has_key('aws-alt'):
        def helpfn(altkey):
            try:
                return pdata['aws-alt'][altkey]['description']
            except KeyError:
                return None
        default = 'skip this step'
        alt_config = [default] + pdata['aws-alt'].keys()
        alt_config = utils._pick('alternative config', alt_config, helpfn=helpfn)
        if alt_config != default:
            more_context['alt-config'] = alt_config
    cfngen.generate_stack(pname, **more_context)
    return stackname

def create_update(stackname):
    if not core.stack_is_active(stackname):
        print 'stack does not exist, creating'
        bootstrap.create_stack(stackname)
    print 'updating stack'
    bootstrap.update_stack(stackname)
    return stackname

# these aliases are deprecated
@task(alias='aws_launch_instance')
@requires_project
def launch(pname):
    try:
        stackname = create_stack(pname)
        pdata = core.project_data_for_stackname(stackname)

        print 'attempting to create stack:'
        print '  stackname: ' + stackname
        print '  region:    ' + pdata['aws']['region']
        print

        if core.is_master_server_stack(stackname):
            if not checks.can_access_builder_private(pname):
                print "failed to access your organisation's 'builder-private' repository:"
                print '  ' + pdata['private-repo']
                print "you'll need access to this repository to add a deploy key later"
                print
                return

        stackname = create_update(stackname)
        if stackname:
            setdefault('.active-stack', stackname)
    except core.NoMasterException, e:
        LOG.warn(e.message)
        print "\n%s\ntry `./bldr master.create`'" % e.message

@debugtask
@requires_aws_stack
def highstate(stackname):
    "a fast update with many caveats. prefer `update` instead"
    with stack_conn(stackname, username=BOOTSTRAP_USER):
        bootstrap.run_script('highstate.sh')

@debugtask
@requires_aws_stack
def pillar(stackname):
    "returns the pillar data a minion is using"
    with stack_conn(stackname, username=BOOTSTRAP_USER):
        sudo('salt-call pillar.items')

@debugtask
@echo_output
def aws_stack_list():
    "returns a list of realized stacks. does not include deleted stacks"
    region = aws.find_region()
    return core.active_stack_names(region)

@task
@requires_aws_stack
def ssh(stackname, username=DEPLOY_USER):
    public_ip = core.stack_data(stackname)['instance']['ip_address']
    # -A forwarding of authentication agent connection
    local("ssh %s@%s" % (username, public_ip))

@task
@requires_aws_stack
def owner_ssh(stackname):
    "maintainence ssh. uses the pem key and the bootstrap user to login."
    public_ip = core.stack_data(stackname)['instance']['ip_address']
    # -i identify file
    # -A forwarding of authentication agent connection
    local("ssh %s@%s -i %s" % (BOOTSTRAP_USER, public_ip, stack_pem(stackname)))

@task
@requires_aws_stack
def download_file(stackname, path, destination, allow_missing="False", use_bootstrap_user="False"):
    """
    Downloads `path` from `stackname` putting it into the `destination` folder, or the `destination` file if it exists and it is a file.

    If `allow_missing` is "True", a not existing `path` will be skipped without errors.

    If `use_bootstrap_user` is "True", the owner_ssh user will be used for connecting instead of the standard deploy user.

    Boolean arguments are expressed as strings as this is the idiomatic way of passing them from the command line.
    """
    fname = os.path.basename(path)
    utils.mkdirp(destination)
    with stack_conn(stackname, username=_user(use_bootstrap_user)):
        if _should_be_skipped(path, allow_missing):
            return
        get(path, destination, use_sudo=True)

@task
@requires_aws_stack
def upload_file(stackname, local_path, remote_path, overwrite=False):
    with stack_conn(stackname):
        print 'stack:',stackname
        print 'local:',local_path
        print 'remote:',remote_path
        print 'overwrite:',overwrite
        raw_input('continue?')
        if files.exists(remote_path) and not overwrite:
            print 'remote file exists, not overwriting'
            exit(1)
        put(local_path, remote_path)

def _should_be_skipped(path, allow_missing):
    return not files.exists(path) and strtobool(allow_missing)

def _user(use_bootstrap_user):
    if bool(strtobool(use_bootstrap_user)):
        return BOOTSTRAP_USER
    else:
        return DEPLOY_USER

#
# these might need a better home
#

@task
@requires_aws_stack
def cmd(stackname, command=None):
    if command is None:
        abort("Please specify a command e.g. ./bldr cmd:%s,ls" % stackname)
    with stack_conn(stackname):
        with settings(abort_on_prompts=True):
            run(command)

@task
def project_list():
    for org, plist in project.org_project_map().items():
        print org
        for p in plist:
            print '  ',p
        print

@task
@requires_project
@echo_output
def project_config(pname):
    return core_utils.remove_ordereddict(project.project_data(pname))
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
#
# RDKit documentation build configuration file, created by
# sphinx-quickstart on Sun Aug  7 18:51:45 2011.
#
# This file is execfile()d with the current directory set to its containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.

import sys, os

# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
sys.path.insert(0, os.path.abspath('exts'))

# -- General configuration -----------------------------------------------------

# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'

# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest','extapi']

# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']

# The suffix of source filenames.
source_suffix = '.rst'

# The encoding of source files.
#source_encoding = 'utf-8-sig'

# The master toctree document.
master_doc = 'index'

# General information about the project.
project = u'The RDKit'
copyright = u'2011, Greg Landrum'

# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '2011.09'
# The full version, including alpha/beta/rc tags.
release = '2011.09.1'

# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None

# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'

# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = ['_build']

# The reST default role (used for this markup: `text`) to use for all documents.
#default_role = None

# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True

# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True

# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False

# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'

# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []

# -- Options for HTML output ---------------------------------------------------

# The theme to use for HTML and HTML Help pages.  See the documentation for
# a list of builtin themes.
html_theme = 'sphinxdoc'

# Theme options are theme-specific and customize the look and feel of a theme
# further.  For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}

# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []

# The name for this set of Sphinx documents.  If None, it defaults to
# "<project> v<release> documentation".
#html_title = None

# A shorter title for the navigation bar.  Default is the same as html_title.
#html_short_title = None

# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
html_logo = '../Images/logo.png'

# The name of an image file (within the static path) to use as favicon of the
# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None

# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']

# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'

# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True

# Custom sidebar templates, maps document names to template names.
html_sidebars = {'**':['globaltoc.html','relations.html','sourcelink.html']}

# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}

# If false, no module index is generated.
#html_domain_indices = True

# If false, no index is generated.
#html_use_index = True

# If true, the index is split into individual pages for each letter.
#html_split_index = False

# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True

# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True

# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True

# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it.  The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''

# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None

# Output file base name for HTML help builder.
htmlhelp_basename = 'RDKitdoc'

# -- Options for LaTeX output --------------------------------------------------

# The paper size ('letter' or 'a4').
#latex_paper_size = 'letter'

# The font size ('10pt', '11pt' or '12pt').
#latex_font_size = '10pt'

# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
  ('index', 'RDKit.tex', u'RDKit Documentation',
   u'Greg Landrum', 'manual'),
]

# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None

# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False

# If true, show page references after internal links.
#latex_show_pagerefs = False

# If true, show URL addresses after external links.
#latex_show_urls = False

# Additional stuff for the LaTeX preamble.
#latex_preamble = ''

# Documents to append as an appendix to all manuals.
#latex_appendices = []

# If false, no module index is generated.
#latex_domain_indices = True

# -- Options for manual page output --------------------------------------------

# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
    ('index', 'rdkit', u'RDKit Documentation',
     [u'Greg Landrum'], 1)
]
<commit_msg>version bump<commit_after># -*- coding: utf-8 -*-
#
# RDKit documentation build configuration file, created by
# sphinx-quickstart on Sun Aug  7 18:51:45 2011.
#
# This file is execfile()d with the current directory set to its containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.

import sys, os

# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
sys.path.insert(0, os.path.abspath('exts'))

# -- General configuration -----------------------------------------------------

# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'

# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest','extapi']

# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']

# The suffix of source filenames.
source_suffix = '.rst'

# The encoding of source files.
#source_encoding = 'utf-8-sig'

# The master toctree document.
master_doc = 'index'

# General information about the project.
project = u'The RDKit'
copyright = u'2011, Greg Landrum'

# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '2011.12'
# The full version, including alpha/beta/rc tags.
release = '2011.12.1'

# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None

# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'

# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = ['_build']

# The reST default role (used for this markup: `text`) to use for all documents.
#default_role = None

# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True

# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True

# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False

# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'

# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []

# -- Options for HTML output ---------------------------------------------------

# The theme to use for HTML and HTML Help pages.  See the documentation for
# a list of builtin themes.
html_theme = 'sphinxdoc'

# Theme options are theme-specific and customize the look and feel of a theme
# further.  For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}

# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []

# The name for this set of Sphinx documents.  If None, it defaults to
# "<project> v<release> documentation".
#html_title = None

# A shorter title for the navigation bar.  Default is the same as html_title.
#html_short_title = None

# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
html_logo = '../Images/logo.png'

# The name of an image file (within the static path) to use as favicon of the
# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None

# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']

# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'

# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True

# Custom sidebar templates, maps document names to template names.
html_sidebars = {'**':['globaltoc.html','relations.html','sourcelink.html']}

# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}

# If false, no module index is generated.
#html_domain_indices = True

# If false, no index is generated.
#html_use_index = True

# If true, the index is split into individual pages for each letter.
#html_split_index = False

# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True

# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True

# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True

# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it.  The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''

# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None

# Output file base name for HTML help builder.
htmlhelp_basename = 'RDKitdoc'

# -- Options for LaTeX output --------------------------------------------------

# The paper size ('letter' or 'a4').
#latex_paper_size = 'letter'

# The font size ('10pt', '11pt' or '12pt').
#latex_font_size = '10pt'

# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
  ('index', 'RDKit.tex', u'RDKit Documentation',
   u'Greg Landrum', 'manual'),
]

# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None

# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False

# If true, show page references after internal links.
#latex_show_pagerefs = False

# If true, show URL addresses after external links.
#latex_show_urls = False

# Additional stuff for the LaTeX preamble.
#latex_preamble = ''

# Documents to append as an appendix to all manuals.
#latex_appendices = []

# If false, no module index is generated.
#latex_domain_indices = True

# -- Options for manual page output --------------------------------------------

# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
    ('index', 'rdkit', u'RDKit Documentation',
     [u'Greg Landrum'], 1)
]
<|endoftext|>


<commit_before>__version__ = '1.2.0'
<commit_msg>Bump version<commit_after>__version__ = '1.3.0'
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
#
# Copyright 2018 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Generated by synthtool. DO NOT EDIT!

from __future__ import absolute_import
import os
import shutil

import nox

BLACK_VERSION = "black==19.3b0"
BLACK_PATHS = ["docs", "google", "tests", "noxfile.py", "setup.py"]

if os.path.exists("samples"):
    BLACK_PATHS.append("samples")

@nox.session(python="3.7")
def lint(session):
    """Run linters.

    Returns a failure if the linters find linting errors or sufficiently
    serious code quality issues.
    """
    session.install("flake8", BLACK_VERSION)
    session.run("black", "--check", *BLACK_PATHS)
    session.run("flake8", "google", "tests")

@nox.session(python="3.6")
def blacken(session):
    """Run black.

    Format code to uniform standard.

    This currently uses Python 3.6 due to the automated Kokoro run of synthtool.
    That run uses an image that doesn't have 3.6 installed. Before updating this
    check the state of the `gcp_ubuntu_config` we use for that Kokoro run.
    """
    session.install(BLACK_VERSION)
    session.run("black", *BLACK_PATHS)

@nox.session(python="3.7")
def lint_setup_py(session):
    """Verify that setup.py is valid (including RST check)."""
    session.install("docutils", "pygments")
    session.run("python", "setup.py", "check", "--restructuredtext", "--strict")

def default(session):
    # Install all test dependencies, then install this package in-place.
    session.install("mock", "pytest", "pytest-cov")
    session.install("-e", ".")

    # Run py.test against the unit tests.
    session.run(
        "py.test",
        "--quiet",
        "--cov=google.cloud.container",
        "--cov=google.cloud",
        "--cov=tests.unit",
        "--cov-append",
        "--cov-config=.coveragerc",
        "--cov-report=",
        "--cov-fail-under=0",
        os.path.join("tests", "unit"),
        *session.posargs,
    )

@nox.session(python=["2.7", "3.5", "3.6", "3.7", "3.8"])
def unit(session):
    """Run the unit test suite."""
    default(session)

@nox.session(python=["2.7", "3.7"])
def system(session):
    """Run the system test suite."""
    system_test_path = os.path.join("tests", "system.py")
    system_test_folder_path = os.path.join("tests", "system")
    # Sanity check: Only run tests if the environment variable is set.
    if not os.environ.get("GOOGLE_APPLICATION_CREDENTIALS", ""):
        session.skip("Credentials must be set via environment variable")

    system_test_exists = os.path.exists(system_test_path)
    system_test_folder_exists = os.path.exists(system_test_folder_path)
    # Sanity check: only run tests if found.
    if not system_test_exists and not system_test_folder_exists:
        session.skip("System tests were not found")

    # Use pre-release gRPC for system tests.
    session.install("--pre", "grpcio")

    # Install all test dependencies, then install this package into the
    # virtualenv's dist-packages.
    session.install("mock", "pytest")
    session.install("git+https://github.com/googleapis/python-test-utils")
    session.install("-e", ".")

    # Run py.test against the system tests.
    if system_test_exists:
        session.run("py.test", "--quiet", system_test_path, *session.posargs)
    if system_test_folder_exists:
        session.run("py.test", "--quiet", system_test_folder_path, *session.posargs)

@nox.session(python="3.7")
def cover(session):
    """Run the final coverage report.

    This outputs the coverage report aggregating coverage from the unit
    test runs (not system test runs), and then erases coverage data.
    """
    session.install("coverage", "pytest-cov")
    session.run("coverage", "report", "--show-missing", "--fail-under=70")

    session.run("coverage", "erase")

@nox.session(python="3.7")
def docs(session):
    """Build the docs for this library."""

    session.install("-e", ".")
    session.install("sphinx<3.0.0", "alabaster", "recommonmark")

    shutil.rmtree(os.path.join("docs", "_build"), ignore_errors=True)
    session.run(
        "sphinx-build",
        "-W",  # warnings as errors
        "-T",  # show full traceback on exception
        "-N",  # no colors
        "-b",
        "html",
        "-d",
        os.path.join("docs", "_build", "doctrees", ""),
        os.path.join("docs", ""),
        os.path.join("docs", "_build", "html", ""),
    )
<commit_msg>chore: install google-cloud-testutils (#18)<commit_after># -*- coding: utf-8 -*-
#
# Copyright 2018 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Generated by synthtool. DO NOT EDIT!

from __future__ import absolute_import
import os
import shutil

import nox

BLACK_VERSION = "black==19.3b0"
BLACK_PATHS = ["docs", "google", "tests", "noxfile.py", "setup.py"]

if os.path.exists("samples"):
    BLACK_PATHS.append("samples")

@nox.session(python="3.7")
def lint(session):
    """Run linters.

    Returns a failure if the linters find linting errors or sufficiently
    serious code quality issues.
    """
    session.install("flake8", BLACK_VERSION)
    session.run("black", "--check", *BLACK_PATHS)
    session.run("flake8", "google", "tests")

@nox.session(python="3.6")
def blacken(session):
    """Run black.

    Format code to uniform standard.

    This currently uses Python 3.6 due to the automated Kokoro run of synthtool.
    That run uses an image that doesn't have 3.6 installed. Before updating this
    check the state of the `gcp_ubuntu_config` we use for that Kokoro run.
    """
    session.install(BLACK_VERSION)
    session.run("black", *BLACK_PATHS)

@nox.session(python="3.7")
def lint_setup_py(session):
    """Verify that setup.py is valid (including RST check)."""
    session.install("docutils", "pygments")
    session.run("python", "setup.py", "check", "--restructuredtext", "--strict")

def default(session):
    # Install all test dependencies, then install this package in-place.
    session.install("mock", "pytest", "pytest-cov")
    session.install("-e", ".")

    # Run py.test against the unit tests.
    session.run(
        "py.test",
        "--quiet",
        "--cov=google.cloud.container",
        "--cov=google.cloud",
        "--cov=tests.unit",
        "--cov-append",
        "--cov-config=.coveragerc",
        "--cov-report=",
        "--cov-fail-under=0",
        os.path.join("tests", "unit"),
        *session.posargs,
    )

@nox.session(python=["2.7", "3.5", "3.6", "3.7", "3.8"])
def unit(session):
    """Run the unit test suite."""
    default(session)

@nox.session(python=["2.7", "3.7"])
def system(session):
    """Run the system test suite."""
    system_test_path = os.path.join("tests", "system.py")
    system_test_folder_path = os.path.join("tests", "system")
    # Sanity check: Only run tests if the environment variable is set.
    if not os.environ.get("GOOGLE_APPLICATION_CREDENTIALS", ""):
        session.skip("Credentials must be set via environment variable")

    system_test_exists = os.path.exists(system_test_path)
    system_test_folder_exists = os.path.exists(system_test_folder_path)
    # Sanity check: only run tests if found.
    if not system_test_exists and not system_test_folder_exists:
        session.skip("System tests were not found")

    # Use pre-release gRPC for system tests.
    session.install("--pre", "grpcio")

    # Install all test dependencies, then install this package into the
    # virtualenv's dist-packages.
    session.install("mock", "pytest", "google-cloud-testutils")
    session.install("-e", ".")

    # Run py.test against the system tests.
    if system_test_exists:
        session.run("py.test", "--quiet", system_test_path, *session.posargs)
    if system_test_folder_exists:
        session.run("py.test", "--quiet", system_test_folder_path, *session.posargs)

@nox.session(python="3.7")
def cover(session):
    """Run the final coverage report.

    This outputs the coverage report aggregating coverage from the unit
    test runs (not system test runs), and then erases coverage data.
    """
    session.install("coverage", "pytest-cov")
    session.run("coverage", "report", "--show-missing", "--fail-under=70")

    session.run("coverage", "erase")

@nox.session(python="3.7")
def docs(session):
    """Build the docs for this library."""

    session.install("-e", ".")
    session.install("sphinx<3.0.0", "alabaster", "recommonmark")

    shutil.rmtree(os.path.join("docs", "_build"), ignore_errors=True)
    session.run(
        "sphinx-build",
        "-W",  # warnings as errors
        "-T",  # show full traceback on exception
        "-N",  # no colors
        "-b",
        "html",
        "-d",
        os.path.join("docs", "_build", "doctrees", ""),
        os.path.join("docs", ""),
        os.path.join("docs", "_build", "html", ""),
    )
<|endoftext|>


<commit_before>"""
Sphinx configuration file. This file serves to provide the information needed to
generate HTML and PDF based documentation for the Feronia project. Be advised,
generators other than HTML and PDF are not supported by the Feronia team.

For a list of configuration options not specified here, please see
http://is.gd/0n9l6I.
"""

### General configuration. ###

# The document name of the “master” document, that is, the document that
# contains the root toctree directive. Default is 'contents'.
master_doc = "toc"

# The name of the default domain. Can also be None to disable a default domain.
# The default is 'py'. Those objects in other domains (whether the domain name
# is given explicitly, or selected by a default-domain directive) will have the
# domain name explicitly prepended when named (e.g., when the default domain is
# C, Python functions will be named “Python function”, not just “function”).
primary_domain = "cpp"

# If true, Sphinx will warn about all references where the target cannot be
# found. Default is False. You can activate this mode temporarily using the -n
# command-line switch.
nitpicky = True

### Project information. ###

# The documented project’s name.
project = "Feronia"

# A copyright statement in the style '2008, Author Name'.
copyright = "2012, Michael Rodriguez"

# The major project version, used as the replacement for |version|. For example,
# for the Python documentation, this may be something like 2.6.
version = "1.0"

# The default language to highlight source code in. The default is 'python'. The
# value should be a valid Pygments lexer name, see Showing code examples for
# more details.
highlight_language = "cpp"

# The code for the language the docs are written in. Any text automatically
# generated by Sphinx will be in that language. Also, Sphinx will try to
# substitute individual paragraphs from your documents with the translation sets
# obtained from locale_dirs. In the LaTeX builder, a suitable language will be
# selected as an option for the Babel package. Default is None, which means that
# no translation will be done.
language = "en"
<commit_msg>Let's not be selfish kids.<commit_after>"""
Sphinx configuration file. This file serves to provide the information needed to
generate HTML and PDF based documentation for the Feronia project. Be advised,
generators other than HTML and PDF are not supported by the Feronia team.

For a list of configuration options not specified here, please see
http://is.gd/0n9l6I.
"""

### General configuration. ###

# The document name of the “master” document, that is, the document that
# contains the root toctree directive. Default is 'contents'.
master_doc = "toc"

# The name of the default domain. Can also be None to disable a default domain.
# The default is 'py'. Those objects in other domains (whether the domain name
# is given explicitly, or selected by a default-domain directive) will have the
# domain name explicitly prepended when named (e.g., when the default domain is
# C, Python functions will be named “Python function”, not just “function”).
primary_domain = "cpp"

# If true, Sphinx will warn about all references where the target cannot be
# found. Default is False. You can activate this mode temporarily using the -n
# command-line switch.
nitpicky = True

### Project information. ###

# The documented project’s name.
project = "Feronia"

# A copyright statement in the style '2008, Author Name'.
copyright = "2012, Corks Development Group"

# The major project version, used as the replacement for |version|. For example,
# for the Python documentation, this may be something like 2.6.
version = "1.0"

# The default language to highlight source code in. The default is 'python'. The
# value should be a valid Pygments lexer name, see Showing code examples for
# more details.
highlight_language = "cpp"

# The code for the language the docs are written in. Any text automatically
# generated by Sphinx will be in that language. Also, Sphinx will try to
# substitute individual paragraphs from your documents with the translation sets
# obtained from locale_dirs. In the LaTeX builder, a suitable language will be
# selected as an option for the Babel package. Default is None, which means that
# no translation will be done.
language = "en"
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
##############################################################################
#
#    Copyright (C) 2012 Agile Business Group sagl (<http://www.agilebg.com>)
#    Copyright (C) 2012 Domsense srl (<http://www.domsense.com>)
#
#    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/>.
#
##############################################################################

from osv import fields, osv
from tools.translate import _
import netsvc
from mako.template import Template
from datetime import datetime
from openerp import tools

def _models_get(self, cr, uid, context={}):
    obj = self.pool.get('ir.model')
    ids = obj.search(cr, uid, [])
    res = obj.read(cr, uid, ids, ['model', 'name'], context)
    return [(r['model'], r['name']) for r in res]

class super_calendar_configurator(osv.osv):
    _logger = netsvc.Logger()
    _name = 'super.calendar.configurator'
    _columns  = {
        'name': fields.char('Name', size=64, required=True),
        'line_ids': fields.one2many('super.calendar.configurator.line', 'configurator_id', 'Lines'),
        }

    def generate_calendar_records(self, cr, uid, ids, context=None):
        configurator_ids = self.search(cr, uid, [])
        super_calendar_pool = self.pool.get('super.calendar')

        # removing old records
        super_calendar_ids = super_calendar_pool.search(cr, uid, [])
        super_calendar_pool.unlink(cr, uid, super_calendar_ids)

        for configurator_id in configurator_ids:
            configurator = self.browse(cr, uid, configurator_id)
            for line in configurator.line_ids:
                current_pool = self.pool.get(line.name.model)
                current_record_ids = current_pool.search(cr, uid, line.domain and eval(line.domain) or [])
                for current_record_id in current_record_ids:
                    current_record  = current_pool.browse(cr, uid, current_record_id)
                    if line.user_field_id and \
                        current_record[line.user_field_id.name] and current_record[line.user_field_id.name]._table_name != 'res.users':
                        raise osv.except_osv(_('Error'),
                            _("The 'User' field of record %s (%s) does not refer to res.users")
                            % (current_record[line.description_field_id.name], line.name.model))
                    if ((line.description_field_id and current_record[line.description_field_id.name]) or line.description_code)  \
                        and current_record[line.date_start_field_id.name]:
                        duration = False
                        if not line.duration_field_id and line.date_stop_field_id and current_record[line.date_start_field_id.name] and current_record[line.date_stop_field_id.name]:
                            date_start= datetime.strptime(current_record[line.date_start_field_id.name], tools.DEFAULT_SERVER_DATETIME_FORMAT)
                            date_stop= datetime.strptime(current_record[line.date_stop_field_id.name], tools.DEFAULT_SERVER_DATETIME_FORMAT)
                            duration = (date_stop - date_start).total_seconds() / 3600
                        elif line.duration_field_id:
                            duration = current_record[line.duration_field_id.name]
                        if line.description_type != 'code':
                            name = current_record[line.description_field_id.name]
                        else:
                            parse_dict = {'o': current_record}
                            mytemplate = Template(line.description_code)
                            name= mytemplate.render(**parse_dict)
                        super_calendar_values = {
                            'name': name,
                            'model_description': line.description,
                            'date_start': current_record[line.date_start_field_id.name],
                            'duration': duration,
                            'user_id': line.user_field_id and current_record[line.user_field_id.name] and current_record[line.user_field_id.name].id or False,
                            'configurator_id': configurator.id,
                            'res_id': line.name.model+','+str(current_record['id']),
                            'model_id': line.name.id,
                            }
                        super_calendar_pool.create(cr, uid, super_calendar_values)
        self._logger.notifyChannel('super_calendar', netsvc.LOG_INFO, "Calendar generated")
        return True

super_calendar_configurator()

class super_calendar_configurator_line(osv.osv):
    _name = 'super.calendar.configurator.line'
    _columns  = {
        'name': fields.many2one('ir.model', 'Model', required=True),
        'description': fields.char('Description', size=128, required=True),
        'domain': fields.char('Domain', size=512),
        'configurator_id': fields.many2one('super.calendar.configurator', 'Configurator'),
        'description_type': fields.selection([
            ('field', 'Field'),
            ('code', 'Code'),
            ], string="Description Type"),
        'description_field_id': fields.many2one('ir.model.fields', 'Description field',
            domain="[('model_id', '=', name),('ttype', '=', 'char')]"),
        'description_code': fields.text('Description field', help="Use '${o}' to refer to the involved object. E.g.: '${o.project_id.name}'"),
        'date_start_field_id': fields.many2one('ir.model.fields', 'Start date field',
            domain="['&','|',('ttype', '=', 'datetime'),('ttype', '=', 'date'),('model_id', '=', name)]",
            required=True),
        'date_stop_field_id': fields.many2one('ir.model.fields', 'End date field',
            domain="['&',('ttype', '=', 'datetime'),('model_id', '=', name)]"),
        'duration_field_id': fields.many2one('ir.model.fields', 'Duration field',
            domain="['&',('ttype', '=', 'float'),('model_id', '=', name)]"),
        'user_field_id': fields.many2one('ir.model.fields', 'User field',
            domain="['&',('ttype', '=', 'many2one'),('model_id', '=', name)]"),
        }

super_calendar_configurator_line()

class super_calendar(osv.osv):
    _name = 'super.calendar'
    _columns  = {
        'name': fields.char('Description', size=512, required=True),
        'model_description': fields.char('Model Description', size=128, required=True),
        'date_start':fields.datetime('Start date', required=True),
        #'date_stop':fields.datetime('End date'), # to be removed?
        'duration':fields.float('Duration'),
        'user_id': fields.many2one('res.users', 'User'),
        'configurator_id': fields.many2one('super.calendar.configurator', 'Configurator'),
        'res_id': fields.reference('Resource', selection=_models_get, size=128),
        'model_id': fields.many2one('ir.model', 'Model'),
        }
super_calendar()
<commit_msg>[FIX] minor fixes<commit_after># -*- coding: utf-8 -*-
##############################################################################
#
#    Copyright (C) 2012 Agile Business Group sagl (<http://www.agilebg.com>)
#    Copyright (C) 2012 Domsense srl (<http://www.domsense.com>)
#
#    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/>.
#
##############################################################################

from openerp.osv import fields, osv, orm
from openerp.tools.translate import _
from openerp import netsvc
from mako.template import Template
from datetime import datetime
from openerp import tools

def _models_get(self, cr, uid, context=None):
    obj = self.pool.get('ir.model')
    ids = obj.search(cr, uid, [])
    res = obj.read(cr, uid, ids, ['model', 'name'], context)
    return [(r['model'], r['name']) for r in res]

class super_calendar_configurator(orm.Model):
    _logger = netsvc.Logger()
    _name = 'super.calendar.configurator'
    _columns  = {
        'name': fields.char('Name', size=64, required=True),
        'line_ids': fields.one2many('super.calendar.configurator.line', 'configurator_id', 'Lines'),
        }

    def generate_calendar_records(self, cr, uid, ids, context=None):
        configurator_ids = self.search(cr, uid, [])
        super_calendar_pool = self.pool.get('super.calendar')

        # removing old records
        super_calendar_ids = super_calendar_pool.search(cr, uid, [])
        super_calendar_pool.unlink(cr, uid, super_calendar_ids)

        for configurator_id in configurator_ids:
            configurator = self.browse(cr, uid, configurator_id)
            for line in configurator.line_ids:
                current_pool = self.pool.get(line.name.model)
                current_record_ids = current_pool.search(cr, uid, line.domain and eval(line.domain) or [])
                for current_record_id in current_record_ids:
                    current_record  = current_pool.browse(cr, uid, current_record_id)
                    if line.user_field_id and \
                        current_record[line.user_field_id.name] and current_record[line.user_field_id.name]._table_name != 'res.users':
                        raise osv.except_osv(_('Error'),
                            _("The 'User' field of record %s (%s) does not refer to res.users")
                            % (current_record[line.description_field_id.name], line.name.model))
                    if ((line.description_field_id and current_record[line.description_field_id.name]) or line.description_code)  \
                        and current_record[line.date_start_field_id.name]:
                        duration = False
                        if not line.duration_field_id and line.date_stop_field_id and current_record[line.date_start_field_id.name] and current_record[line.date_stop_field_id.name]:
                            date_start= datetime.strptime(current_record[line.date_start_field_id.name], tools.DEFAULT_SERVER_DATETIME_FORMAT)
                            date_stop= datetime.strptime(current_record[line.date_stop_field_id.name], tools.DEFAULT_SERVER_DATETIME_FORMAT)
                            duration = (date_stop - date_start).total_seconds() / 3600
                        elif line.duration_field_id:
                            duration = current_record[line.duration_field_id.name]
                        if line.description_type != 'code':
                            name = current_record[line.description_field_id.name]
                        else:
                            parse_dict = {'o': current_record}
                            mytemplate = Template(line.description_code)
                            name= mytemplate.render(**parse_dict)
                        super_calendar_values = {
                            'name': name,
                            'model_description': line.description,
                            'date_start': current_record[line.date_start_field_id.name],
                            'duration': duration,
                            'user_id': line.user_field_id and current_record[line.user_field_id.name] and current_record[line.user_field_id.name].id or False,
                            'configurator_id': configurator.id,
                            'res_id': line.name.model+','+str(current_record['id']),
                            'model_id': line.name.id,
                            }
                        super_calendar_pool.create(cr, uid, super_calendar_values)
        self._logger.notifyChannel('super_calendar', netsvc.LOG_INFO, "Calendar generated")
        return True

super_calendar_configurator()

class super_calendar_configurator_line(orm.Model):
    _name = 'super.calendar.configurator.line'
    _columns  = {
        'name': fields.many2one('ir.model', 'Model', required=True),
        'description': fields.char('Description', size=128, required=True),
        'domain': fields.char('Domain', size=512),
        'configurator_id': fields.many2one('super.calendar.configurator', 'Configurator'),
        'description_type': fields.selection([
            ('field', 'Field'),
            ('code', 'Code'),
            ], string="Description Type"),
        'description_field_id': fields.many2one('ir.model.fields', 'Description field',
            domain="[('model_id', '=', name),('ttype', '=', 'char')]"),
        'description_code': fields.text('Description field', help="Use '${o}' to refer to the involved object. E.g.: '${o.project_id.name}'"),
        'date_start_field_id': fields.many2one('ir.model.fields', 'Start date field',
            domain="['&','|',('ttype', '=', 'datetime'),('ttype', '=', 'date'),('model_id', '=', name)]",
            required=True),
        'date_stop_field_id': fields.many2one('ir.model.fields', 'End date field',
            domain="['&',('ttype', '=', 'datetime'),('model_id', '=', name)]"),
        'duration_field_id': fields.many2one('ir.model.fields', 'Duration field',
            domain="['&',('ttype', '=', 'float'),('model_id', '=', name)]"),
        'user_field_id': fields.many2one('ir.model.fields', 'User field',
            domain="['&',('ttype', '=', 'many2one'),('model_id', '=', name)]"),
        }

super_calendar_configurator_line()

class super_calendar(orm.Model):
    _name = 'super.calendar'
    _columns  = {
        'name': fields.char('Description', size=512, required=True),
        'model_description': fields.char('Model Description', size=128, required=True),
        'date_start':fields.datetime('Start date', required=True),
        #'date_stop':fields.datetime('End date'), # to be removed?
        'duration':fields.float('Duration'),
        'user_id': fields.many2one('res.users', 'User'),
        'configurator_id': fields.many2one('super.calendar.configurator', 'Configurator'),
        'res_id': fields.reference('Resource', selection=_models_get, size=128),
        'model_id': fields.many2one('ir.model', 'Model'),
        }
super_calendar()
<|endoftext|>