<commit_before># -*- coding: utf-8 -*-

###########################################################################
## Python code generated with wxFormBuilder (version Jun 17 2015)
## http://www.wxformbuilder.org/
##
## PLEASE DO "NOT" EDIT THIS FILE! -- Ummmm... Oops?
###########################################################################

import wx
import wx.xrc

###########################################################################
## Class ReadifyFrame
###########################################################################

class ReadifyFrame ( wx.Frame ):

    def __init__( self, parent ):
        """
        Create a new frame with various controls for selecting fonts and options.
        :param parent:
        :return:
        """
        wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = u"Readify Font", pos = wx.DefaultPosition, \
                            size = wx.Size( 800,600 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )

        self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )

        parentCont = wx.BoxSizer( wx.VERTICAL )

        # Font Chooser #
        contFont = wx.BoxSizer( wx.HORIZONTAL )

        contFonts = wx.BoxSizer( wx.VERTICAL )

        listContFontLayout = []

        self.listTxtFont = []
        self.listChoiceStyle = []
        chceStyleChoices = [ u"Regular", u"Italic", u"Bold", u"Bold Italic", wx.EmptyString ]

        for i in range(0,4):
            listContFontLayout.append( wx.BoxSizer( wx.HORIZONTAL ) )
            self.listTxtFont.append(wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 ))
            listContFontLayout[i].Add( self.listTxtFont[i], 1, wx.ALL, 5 )
            self.listChoiceStyle.append(wx.Choice( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, chceStyleChoices, 0 ))
            self.listChoiceStyle[i].SetSelection( 4 )
            self.listChoiceStyle[i].SetToolTipString("Set the font style")
            listContFontLayout[i].Add( self.listChoiceStyle[i], 0, wx.ALL, 5 )

            contFonts.Add( listContFontLayout[i], 1, wx.EXPAND, 5 )

        contFont.Add( contFonts, 1, wx.EXPAND, 5 )

        self.btnChooseFont = wx.Button( self, wx.ID_ANY, u"Browse Fonts...", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.btnChooseFont.SetToolTipString("Choose one or more fonts to modify.")
        contFont.Add( self.btnChooseFont, 0, wx.ALL, 5 )

        parentCont.Add( contFont, 0, wx.EXPAND|wx.TOP, 5 )

        # Font Name #
        contFontName = wx.BoxSizer( wx.HORIZONTAL )

        self.lblFontFamName = wx.StaticText( self, wx.ID_ANY, u"Font Family Name", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.lblFontFamName.Wrap( -1 )
        self.lblFontFamName.SetFont( wx.Font( wx.NORMAL_FONT.GetPointSize(), 70, 90, 92, False, wx.EmptyString ) )

        contFontName.Add( self.lblFontFamName, 0, wx.ALIGN_CENTRE_VERTICAL|wx.ALL|wx.EXPAND, 5 )

        self.txtFontFamName = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.Size( -1,-1 ), 0 )
        self.txtFontFamName.SetToolTipString("Enter a name for the modified font.")
        contFontName.Add( self.txtFontFamName, 1, wx.ALIGN_CENTRE_VERTICAL|wx.ALL, 5 )

        parentCont.Add( contFontName, 0, wx.EXPAND, 5 )

        # Options #
        contOptions = wx.BoxSizer( wx.HORIZONTAL )
        """
        self.chkHint = wx.CheckBox( self, wx.ID_ANY, u"Remove Hinting", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.chkHint.SetToolTipString("Strip hinting information from the generated TrueType font")
        contOptions.Add( self.chkHint, 1, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )
        """
        self.chkKern = wx.CheckBox( self, wx.ID_ANY, u"Legacy Kerning", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.chkKern.SetToolTipString("Some readers and software require 'legacy', or 'old style' kerning to be "
                                      "present for kerning to work.")
        contOptions.Add( self.chkKern, 1, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )

        self.chkPANOSE = wx.CheckBox( self, wx.ID_ANY, u"Remove PANOSE", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.chkPANOSE.SetToolTipString("Kobo readers can get confused by PANOSE settings. This option sets all "
                                        "PANOSE information to 0, or 'any'")
        contOptions.Add( self.chkPANOSE, 1, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )

        self.chkAltName = wx.CheckBox( self, wx.ID_ANY, u"Alt. Name", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.chkAltName.SetToolTipString("Some fonts have issues with renaming. If the generated font does not have "
                                         "the same internal font name as you entered, try enabling this option.")
        contOptions.Add( self.chkAltName, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )

        rboxHintsChoices = [ u"Keep Existing", u"Remove Existing", u"Autohint" ]
        self.rboxHints = wx.RadioBox( self, wx.ID_ANY, u"Hints", wx.DefaultPosition, wx.DefaultSize, rboxHintsChoices, 1, wx.RA_SPECIFY_ROWS )
        self.rboxHints.SetSelection( 0 )
        contOptions.Add( self.rboxHints, 1, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )

        parentCont.Add( contOptions, 0, wx.EXPAND, 5 )

        # Darken Settings #
        contDarkenFont = wx.BoxSizer( wx.HORIZONTAL )

        self.lblDarkenAmount = wx.StaticText( self, wx.ID_ANY, u"Darken Font Amount", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.lblDarkenAmount.Wrap( -1 )
        self.lblDarkenAmount.SetFont( wx.Font( wx.NORMAL_FONT.GetPointSize(), 70, 90, 92, False, wx.EmptyString ) )

        contDarkenFont.Add( self.lblDarkenAmount, 0, wx.ALIGN_CENTRE_VERTICAL|wx.ALL, 5 )

        self.txtDarkenAmount = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.Size( 50,-1 ), 0 )
        self.txtDarkenAmount.SetToolTipString("Enter a number between 1 and 100 to add weight to the font. 50 is "
                                              "considered bold"
                                              "\n10-15 seems to work well to make fonts a bit darker.")
        contDarkenFont.Add( self.txtDarkenAmount, 0, wx.ALIGN_CENTRE_VERTICAL|wx.ALL, 5 )

        self.chkBearing = wx.CheckBox( self, wx.ID_ANY, u"Adjust Bearing", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.chkBearing.SetToolTipString("By default, adding weight to a font increases glyph width. Enable this "
                                         "option to set the glyph width to be roughly equal to the original.\n"
                                         "WARNING: This reduces the spacing between glyphs, and should not be used if "
                                         "you have added too much weight.")
        contDarkenFont.Add( self.chkBearing, 0, wx.ALIGN_CENTRE_VERTICAL|wx.ALL, 5 )

        parentCont.Add( contDarkenFont, 0, wx.EXPAND, 5 )

        # Output Directory Picker #
        contOut = wx.BoxSizer( wx.HORIZONTAL )

        self.lblOutDir = wx.StaticText( self, wx.ID_ANY, u"Output Directory", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.lblOutDir.Wrap( -1 )
        self.lblOutDir.SetFont( wx.Font( wx.NORMAL_FONT.GetPointSize(), 70, 90, 92, False, wx.EmptyString ) )
        contOut.Add( self.lblOutDir, 0, wx.ALIGN_CENTRE_VERTICAL|wx.ALL, 5 )

        self.pickerOutDir = wx.DirPickerCtrl( self, wx.ID_ANY, u"", u"Select a folder", wx.DefaultPosition, wx.DefaultSize, wx.DIRP_DEFAULT_STYLE )
        self.pickerOutDir.SetToolTipString("Choose the output directory to save the modified font files in.")
        contOut.Add( self.pickerOutDir, 1, wx.ALIGN_CENTRE_VERTICAL|wx.ALL, 5 )

        parentCont.Add( contOut, 0, wx.EXPAND, 5 )

        # Preview Font
        contPreviewFont = wx.BoxSizer( wx.HORIZONTAL )

        self.lblPreviewFont = wx.StaticText( self, wx.ID_ANY, u"Preview Text", wx.DefaultPosition, wx.DefaultSize,
                                          0 )
        self.lblPreviewFont.Wrap( -1 )
        self.lblPreviewFont.SetFont( wx.Font( wx.NORMAL_FONT.GetPointSize(), 70, 90, 92, False, wx.EmptyString ) )
        contPreviewFont.Add( self.lblPreviewFont, 0, wx.ALIGN_CENTRE_VERTICAL|wx.ALL, 5 )

        self.txtPreview = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.Size( -1,-1 ), 0 )
        contPreviewFont.Add( self.txtPreview, 1, wx.ALIGN_CENTRE_VERTICAL|wx.ALL, 5 )

        self.btnPrevFont = wx.Button( self, wx.ID_ANY, u"Preview Font", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.btnPrevFont.SetToolTipString("Preview the changes using a small subset of the font.")
        contPreviewFont.Add( self.btnPrevFont, 0, wx.ALL, 5 )

        parentCont.Add( contPreviewFont, 0, wx.EXPAND, 5 )

        # Log Output #
        contOutput = wx.BoxSizer( wx.VERTICAL )

        self.lblOutputLog = wx.StaticText( self, wx.ID_ANY, u"Output Log", wx.DefaultPosition, wx.DefaultSize, wx.TE_MULTILINE )
        self.lblOutputLog.Wrap( -1 )
        self.lblOutputLog.SetFont( wx.Font( wx.NORMAL_FONT.GetPointSize(), 70, 90, 92, False, wx.EmptyString ) )

        contOutput.Add( self.lblOutputLog, 0, wx.ALL, 5 )
        self.txtOutput = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, wx.HSCROLL|wx.TE_DONTWRAP|wx.TE_MULTILINE|wx.TE_READONLY )
        self.txtOutput.SetFont( wx.Font( wx.NORMAL_FONT.GetPointSize(), 76, 90, 90, False, wx.EmptyString ) )
        #self.txtOutput.Enable( False )

        contOutput.Add( self.txtOutput, 1, wx.ALL|wx.EXPAND, 5 )

        parentCont.Add( contOutput, 1, wx.EXPAND, 5 )

        # Buttons #
        contGenerate = wx.BoxSizer( wx.HORIZONTAL )

        self.btnGenTTF = wx.Button( self, wx.ID_ANY, u"Generate TTF", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.btnGenTTF.SetToolTipString("Generates a new set of font files using the information entered above.")
        contGenerate.Add( self.btnGenTTF, 0, wx.ALL, 5 )

        self.btnClear = wx.Button( self, wx.ID_ANY, u"Clear", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.btnClear.SetToolTipString("Clear all fields in the form.")
        contGenerate.Add( self.btnClear, 0, wx.ALL, 5 )

        parentCont.Add( contGenerate, 0, wx.CENTER|wx.BOTTOM, 5 )

        self.SetSizer( parentCont )
        self.Layout()

        self.Centre( wx.BOTH )

        # Connect Events
        self.btnChooseFont.Bind( wx.EVT_BUTTON, self.chooseFiles )
        self.btnGenTTF.Bind( wx.EVT_BUTTON, self.genTTF )
        self.btnPrevFont.Bind(wx.EVT_BUTTON, self.previewFont )
        self.btnClear.Bind( wx.EVT_BUTTON, self.clearForm )

    def __del__( self ):
        pass

    # Virtual event handlers, overide them in your derived class
    def chooseFiles( self, event ):
        event.Skip()

    def genTTF( self, event ):
        event.Skip()

    def previewFont(self, event ):
        event.Skip()

    def clearForm( self, event ):
        event.Skip()
<commit_msg>Converted ReadifyFrame to use Unicode literals by default by importing unicode_literals from __future__<commit_after># -*- coding: utf-8 -*-

###########################################################################
## Python code generated with wxFormBuilder (version Jun 17 2015)
## http://www.wxformbuilder.org/
##
## PLEASE DO "NOT" EDIT THIS FILE! -- Ummmm... Oops?
###########################################################################

from __future__ import unicode_literals
import wx
import wx.xrc

###########################################################################
## Class ReadifyFrame
###########################################################################

class ReadifyFrame ( wx.Frame ):

    def __init__( self, parent ):
        """
        Create a new frame with various controls for selecting fonts and options.
        :param parent:
        :return:
        """
        wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = u"Readify Font", pos = wx.DefaultPosition, \
                            size = wx.Size( 800,600 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )

        self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )

        parentCont = wx.BoxSizer( wx.VERTICAL )

        # Font Chooser #
        contFont = wx.BoxSizer( wx.HORIZONTAL )

        contFonts = wx.BoxSizer( wx.VERTICAL )

        listContFontLayout = []

        self.listTxtFont = []
        self.listChoiceStyle = []
        chceStyleChoices = [ "Regular", "Italic", "Bold", "Bold Italic", wx.EmptyString ]

        for i in range(0,4):
            listContFontLayout.append( wx.BoxSizer( wx.HORIZONTAL ) )
            self.listTxtFont.append(wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 ))
            listContFontLayout[i].Add( self.listTxtFont[i], 1, wx.ALL, 5 )
            self.listChoiceStyle.append(wx.Choice( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, chceStyleChoices, 0 ))
            self.listChoiceStyle[i].SetSelection( 4 )
            self.listChoiceStyle[i].SetToolTipString("Set the font style")
            listContFontLayout[i].Add( self.listChoiceStyle[i], 0, wx.ALL, 5 )

            contFonts.Add( listContFontLayout[i], 1, wx.EXPAND, 5 )

        contFont.Add( contFonts, 1, wx.EXPAND, 5 )

        self.btnChooseFont = wx.Button( self, wx.ID_ANY, "Browse Fonts...", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.btnChooseFont.SetToolTipString("Choose one or more fonts to modify.")
        contFont.Add( self.btnChooseFont, 0, wx.ALL, 5 )

        parentCont.Add( contFont, 0, wx.EXPAND|wx.TOP, 5 )

        # Font Name #
        contFontName = wx.BoxSizer( wx.HORIZONTAL )

        self.lblFontFamName = wx.StaticText( self, wx.ID_ANY, "Font Family Name", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.lblFontFamName.Wrap( -1 )
        self.lblFontFamName.SetFont( wx.Font( wx.NORMAL_FONT.GetPointSize(), 70, 90, 92, False, wx.EmptyString ) )

        contFontName.Add( self.lblFontFamName, 0, wx.ALIGN_CENTRE_VERTICAL|wx.ALL|wx.EXPAND, 5 )

        self.txtFontFamName = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.Size( -1,-1 ), 0 )
        self.txtFontFamName.SetToolTipString("Enter a name for the modified font.")
        contFontName.Add( self.txtFontFamName, 1, wx.ALIGN_CENTRE_VERTICAL|wx.ALL, 5 )

        parentCont.Add( contFontName, 0, wx.EXPAND, 5 )

        # Options #
        contOptions = wx.BoxSizer( wx.HORIZONTAL )
        """
        self.chkHint = wx.CheckBox( self, wx.ID_ANY, u"Remove Hinting", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.chkHint.SetToolTipString("Strip hinting information from the generated TrueType font")
        contOptions.Add( self.chkHint, 1, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )
        """
        self.chkKern = wx.CheckBox( self, wx.ID_ANY, "Legacy Kerning", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.chkKern.SetToolTipString("Some readers and software require 'legacy', or 'old style' kerning to be "
                                      "present for kerning to work.")
        contOptions.Add( self.chkKern, 1, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )

        self.chkPANOSE = wx.CheckBox( self, wx.ID_ANY, "Remove PANOSE", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.chkPANOSE.SetToolTipString("Kobo readers can get confused by PANOSE settings. This option sets all "
                                        "PANOSE information to 0, or 'any'")
        contOptions.Add( self.chkPANOSE, 1, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )

        self.chkAltName = wx.CheckBox( self, wx.ID_ANY, "Alt. Name", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.chkAltName.SetToolTipString("Some fonts have issues with renaming. If the generated font does not have "
                                         "the same internal font name as you entered, try enabling this option.")
        contOptions.Add( self.chkAltName, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )

        rboxHintsChoices = [ "Keep Existing", "Remove Existing", "Autohint" ]
        self.rboxHints = wx.RadioBox( self, wx.ID_ANY, u"Hints", wx.DefaultPosition, wx.DefaultSize, rboxHintsChoices, 1, wx.RA_SPECIFY_ROWS )
        self.rboxHints.SetSelection( 0 )
        contOptions.Add( self.rboxHints, 1, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )

        parentCont.Add( contOptions, 0, wx.EXPAND, 5 )

        # Darken Settings #
        contDarkenFont = wx.BoxSizer( wx.HORIZONTAL )

        self.lblDarkenAmount = wx.StaticText( self, wx.ID_ANY, "Darken Font Amount", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.lblDarkenAmount.Wrap( -1 )
        self.lblDarkenAmount.SetFont( wx.Font( wx.NORMAL_FONT.GetPointSize(), 70, 90, 92, False, wx.EmptyString ) )

        contDarkenFont.Add( self.lblDarkenAmount, 0, wx.ALIGN_CENTRE_VERTICAL|wx.ALL, 5 )

        self.txtDarkenAmount = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.Size( 50,-1 ), 0 )
        self.txtDarkenAmount.SetToolTipString("Enter a number between 1 and 100 to add weight to the font. 50 is "
                                              "considered bold"
                                              "\n10-15 seems to work well to make fonts a bit darker.")
        contDarkenFont.Add( self.txtDarkenAmount, 0, wx.ALIGN_CENTRE_VERTICAL|wx.ALL, 5 )

        self.chkBearing = wx.CheckBox( self, wx.ID_ANY, "Adjust Bearing", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.chkBearing.SetToolTipString("By default, adding weight to a font increases glyph width. Enable this "
                                         "option to set the glyph width to be roughly equal to the original.\n"
                                         "WARNING: This reduces the spacing between glyphs, and should not be used if "
                                         "you have added too much weight.")
        contDarkenFont.Add( self.chkBearing, 0, wx.ALIGN_CENTRE_VERTICAL|wx.ALL, 5 )

        parentCont.Add( contDarkenFont, 0, wx.EXPAND, 5 )

        # Output Directory Picker #
        contOut = wx.BoxSizer( wx.HORIZONTAL )

        self.lblOutDir = wx.StaticText( self, wx.ID_ANY, "Output Directory", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.lblOutDir.Wrap( -1 )
        self.lblOutDir.SetFont( wx.Font( wx.NORMAL_FONT.GetPointSize(), 70, 90, 92, False, wx.EmptyString ) )
        contOut.Add( self.lblOutDir, 0, wx.ALIGN_CENTRE_VERTICAL|wx.ALL, 5 )

        self.pickerOutDir = wx.DirPickerCtrl( self, wx.ID_ANY, "", "Select a folder", wx.DefaultPosition, wx.DefaultSize, wx.DIRP_DEFAULT_STYLE )
        self.pickerOutDir.SetToolTipString("Choose the output directory to save the modified font files in.")
        contOut.Add( self.pickerOutDir, 1, wx.ALIGN_CENTRE_VERTICAL|wx.ALL, 5 )

        parentCont.Add( contOut, 0, wx.EXPAND, 5 )

        # Preview Font
        contPreviewFont = wx.BoxSizer( wx.HORIZONTAL )

        self.lblPreviewFont = wx.StaticText( self, wx.ID_ANY, "Preview Text", wx.DefaultPosition, wx.DefaultSize,
                                          0 )
        self.lblPreviewFont.Wrap( -1 )
        self.lblPreviewFont.SetFont( wx.Font( wx.NORMAL_FONT.GetPointSize(), 70, 90, 92, False, wx.EmptyString ) )
        contPreviewFont.Add( self.lblPreviewFont, 0, wx.ALIGN_CENTRE_VERTICAL|wx.ALL, 5 )

        self.txtPreview = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.Size( -1,-1 ), 0 )
        contPreviewFont.Add( self.txtPreview, 1, wx.ALIGN_CENTRE_VERTICAL|wx.ALL, 5 )

        self.btnPrevFont = wx.Button( self, wx.ID_ANY, "Preview Font", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.btnPrevFont.SetToolTipString("Preview the changes using a small subset of the font.")
        contPreviewFont.Add( self.btnPrevFont, 0, wx.ALL, 5 )

        parentCont.Add( contPreviewFont, 0, wx.EXPAND, 5 )

        # Log Output #
        contOutput = wx.BoxSizer( wx.VERTICAL )

        self.lblOutputLog = wx.StaticText( self, wx.ID_ANY, "Output Log", wx.DefaultPosition, wx.DefaultSize, wx.TE_MULTILINE )
        self.lblOutputLog.Wrap( -1 )
        self.lblOutputLog.SetFont( wx.Font( wx.NORMAL_FONT.GetPointSize(), 70, 90, 92, False, wx.EmptyString ) )

        contOutput.Add( self.lblOutputLog, 0, wx.ALL, 5 )
        self.txtOutput = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, wx.HSCROLL|wx.TE_DONTWRAP|wx.TE_MULTILINE|wx.TE_READONLY )
        self.txtOutput.SetFont( wx.Font( wx.NORMAL_FONT.GetPointSize(), 76, 90, 90, False, wx.EmptyString ) )
        #self.txtOutput.Enable( False )

        contOutput.Add( self.txtOutput, 1, wx.ALL|wx.EXPAND, 5 )

        parentCont.Add( contOutput, 1, wx.EXPAND, 5 )

        # Buttons #
        contGenerate = wx.BoxSizer( wx.HORIZONTAL )

        self.btnGenTTF = wx.Button( self, wx.ID_ANY, "Generate TTF", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.btnGenTTF.SetToolTipString("Generates a new set of font files using the information entered above.")
        contGenerate.Add( self.btnGenTTF, 0, wx.ALL, 5 )

        self.btnClear = wx.Button( self, wx.ID_ANY, "Clear", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.btnClear.SetToolTipString("Clear all fields in the form.")
        contGenerate.Add( self.btnClear, 0, wx.ALL, 5 )

        parentCont.Add( contGenerate, 0, wx.CENTER|wx.BOTTOM, 5 )

        self.SetSizer( parentCont )
        self.Layout()

        self.Centre( wx.BOTH )

        # Connect Events
        self.btnChooseFont.Bind( wx.EVT_BUTTON, self.chooseFiles )
        self.btnGenTTF.Bind( wx.EVT_BUTTON, self.genTTF )
        self.btnPrevFont.Bind(wx.EVT_BUTTON, self.previewFont )
        self.btnClear.Bind( wx.EVT_BUTTON, self.clearForm )

    def __del__( self ):
        pass

    # Virtual event handlers, overide them in your derived class
    def chooseFiles( self, event ):
        event.Skip()

    def genTTF( self, event ):
        event.Skip()

    def previewFont(self, event ):
        event.Skip()

    def clearForm( self, event ):
        event.Skip()
<|endoftext|>


<commit_before># ==========================================================================
#
#   Copyright NumFOCUS
#
#   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
#
#          http://www.apache.org/licenses/LICENSE-2.0.txt
#
#   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.
#
# ==========================================================================*/

from typing import Union, Optional, Tuple, TYPE_CHECKING
try:
    from numpy.typing import ArrayLike
except ImportError:
    from numpy import ndarray as ArrayLike

_HAVE_XARRAY = False
try:
    import xarray as xr

    _HAVE_XARRAY = True
except ImportError:
    pass
_HAVE_TORCH = False
try:
    import torch

    _HAVE_TORCH = True
except ImportError:
    pass

# noinspection PyPep8Naming
class itkCType:
    # import locally to facilitate dynamic loading in itk/__init__.py
    import numpy as np
    from typing import Any, Dict, Optional, Tuple

    __c_types__: Dict[str, "itkCType"] = {}
    __c_types_for_dtype__: Dict[str, np.dtype] = {}

    def __init__(self, name: str, short_name: str, np_dtype: np.dtype = None) -> None:
        # Remove potential white space around type names
        self.name = name.strip()
        self.short_name = short_name.strip()
        self.dtype = np_dtype

        itkCType.__c_types__[self.name] = self
        if np_dtype:
            itkCType.__c_types_for_dtype__[np_dtype] = self

    def __del__(self) -> None:
        try:
            del itkCType.__c_types__[self.name]
        except KeyError:
            pass

    def __repr__(self) -> str:
        return f"<itkCType {self.name}>"

    @staticmethod
    def GetCType(name: str) -> Optional["itkCType"]:
        # import locally to facilitate dynamic loading in itk/__init__.py
        from typing import Dict

        """Get the type corresponding to the provided C primitive type name."""
        aliases: Dict[str, str] = {
            "short": "signed short",
            "int": "signed int",
            "long": "signed long",
            "long long": "signed long long",
        }
        # Remove potential white space around types
        name = name.strip()
        desired_name: str = aliases.get(name, name)
        try:
            return itkCType.__c_types__[desired_name]
        except KeyError:
            return None

    @staticmethod
    def GetCTypeForDType(np_dtype: np.dtype) -> Optional["itkCType"]:
        """Get the type corresponding to the provided numpy.dtype."""
        try:
            return itkCType.__c_types_for_dtype__[np_dtype]
        except KeyError:
            return None

    @staticmethod
    def initialize_c_types_once() -> (
        "itkCType",
        "itkCType",
        "itkCType",
        "itkCType",
        "itkCType",
        "itkCType",
        "itkCType",
        "itkCType",
        "itkCType",
        "itkCType",
        "itkCType",
        "itkCType",
        "itkCType",
        "itkCType",
    ):
        """
        This function is intended to be run only one time
        """
        import os
        import numpy as np

        _F: "itkCType" = itkCType("float", "F", np.float32)
        _D: "itkCType" = itkCType("double", "D", np.float64)
        _UC: "itkCType" = itkCType("unsigned char", "UC", np.uint8)
        _US: "itkCType" = itkCType("unsigned short", "US", np.uint16)
        _UI: "itkCType" = itkCType("unsigned int", "UI", np.uint32)
        if os.name == "nt":
            _UL: "itkCType" = itkCType("unsigned long", "UL", np.uint32)
            _SL: "itkCType" = itkCType("signed long", "SL", np.int32)
            _LD: "itkCType" = itkCType("long double", "LD")
        else:
            _UL: "itkCType" = itkCType("unsigned long", "UL", np.uint64)
            _SL: "itkCType" = itkCType("signed long", "SL", np.int64)
            _LD: "itkCType" = itkCType("long double", "LD", np.float128)
        _ULL: "itkCType" = itkCType("unsigned long long", "ULL", np.uint64)
        _SC: "itkCType" = itkCType("signed char", "SC", np.int8)
        _SS: "itkCType" = itkCType("signed short", "SS", np.int16)
        _SI: "itkCType" = itkCType("signed int", "SI", np.int32)
        _SLL: "itkCType" = itkCType("signed long long", "SLL", np.int64)
        _B: "itkCType" = itkCType("bool", "B", np.bool)
        return _F, _D, _UC, _US, _UI, _UL, _SL, _LD, _ULL, _SC, _SS, _SI, _SLL, _B

# Define typing hints
F: itkCType
D: itkCType
UC: itkCType
US: itkCType
UI: itkCType
UL: itkCType
SL: itkCType
LD: itkCType
ULL: itkCType
SC: itkCType
SS: itkCType
SI: itkCType
SLL: itkCType
B: itkCType

(
    F,
    D,
    UC,
    US,
    UI,
    UL,
    SL,
    LD,
    ULL,
    SC,
    SS,
    SI,
    SLL,
    B,
) = itkCType.initialize_c_types_once()

# Type aliases to avoid expensive import, circular references. Use with forward references.
if TYPE_CHECKING:
    import itk

# These should eventually explicitly be marked as TypeAlias's per PEP 613, available in CPython 3.10
ImageBase = "itk.ImageBase"
Image = "itk.Image"
VectorImage = "itk.VectorImage"

RGBPixel = "itk.RGBPixel"
Vector = "itk.Vector"
CovariantVector = "itk.CovariantVector"
SymmetricSecondRankTensor = "itk.SymmetricSecondRankTensor"
Offset = "itk.Offset"
FixedArray = "itk.FixedArray"
VariableLengthVector = "itk.VariableLengthVector"
complex_ = "itk.complex"

PixelTypes = Union[
    itkCType,
    RGBPixel,
    Vector,
    CovariantVector,
    SymmetricSecondRankTensor,
    Offset,
    FixedArray,
    complex_,
]

ImageSource = "itk.ImageSource"

ImageOrImageSource = Union[ImageBase, ImageSource]
# Can be coerced into an itk.ImageBase
if _HAVE_XARRAY and _HAVE_TORCH:
    ImageLike = Union[ImageBase, ArrayLike, xr.DataArray, torch.Tensor]
elif _HAVE_XARRAY:
    ImageLike = Union[ImageBase, ArrayLike, xr.DataArray]
elif _HAVE_TORCH:
    ImageLike = Union[ImageBase, ArrayLike, torch.Tensor]
else:
    ImageLike = Union[ImageBase, ArrayLike]

ImageIOBase = "itk.ImageIOBase"

LightObject = "itk.LightObject"
Object = "itk.Object"
DataObject = "itk.DataObject"

PointSet = "itk.PointSet"
Mesh = "itk.Mesh"
QuadEdgeMesh = "itk.QuadEdgeMesh"

Path = "itk.Path"
ParametricPath = "itk.ParametricPath"
PolyLineParametricPath = "itk.PolyLineParametricPath"
SpatialObject = "itk.SpatialObject"

TransformBase = "itk.TransformBaseTemplate"
Transform = "itk.Transform"

ImageRegion = "itk.ImageRegion"

VectorContainer = "itk.VectorContainer"
Matrix = "itk.Matrix"

# Return types for the functional interfaces to ProcessObject's.
# When there is a single indexed output, it is returned directly.
# When there are multiple indexed outputs, a tuple of the indexed outputs is
# returned.
ImageSourceReturn = Union[ImageLike, Tuple[ImageLike, ...]]
MeshSourceReturn = Union[Mesh, Tuple[Mesh, ...]]
PathSourceReturn = Union[Path, Tuple[Path, ...]]

InterpolateImageFunction = "itk.InterpolateImageFunction"
ExtrapolateImageFunction = "itk.ExtrapolateImageFunction"
ImageBoundaryCondition = "itk.ImageBoundaryCondition"
FlatStructuringElement = "itk.FlatStructuringElement"
<commit_msg>COMP: Only use np.float128 when available<commit_after># ==========================================================================
#
#   Copyright NumFOCUS
#
#   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
#
#          http://www.apache.org/licenses/LICENSE-2.0.txt
#
#   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.
#
# ==========================================================================*/

from typing import Union, Optional, Tuple, TYPE_CHECKING
try:
    from numpy.typing import ArrayLike
except ImportError:
    from numpy import ndarray as ArrayLike

_HAVE_XARRAY = False
try:
    import xarray as xr

    _HAVE_XARRAY = True
except ImportError:
    pass
_HAVE_TORCH = False
try:
    import torch

    _HAVE_TORCH = True
except ImportError:
    pass

# noinspection PyPep8Naming
class itkCType:
    # import locally to facilitate dynamic loading in itk/__init__.py
    import numpy as np
    from typing import Any, Dict, Optional, Tuple

    __c_types__: Dict[str, "itkCType"] = {}
    __c_types_for_dtype__: Dict[str, np.dtype] = {}

    def __init__(self, name: str, short_name: str, np_dtype: np.dtype = None) -> None:
        # Remove potential white space around type names
        self.name = name.strip()
        self.short_name = short_name.strip()
        self.dtype = np_dtype

        itkCType.__c_types__[self.name] = self
        if np_dtype:
            itkCType.__c_types_for_dtype__[np_dtype] = self

    def __del__(self) -> None:
        try:
            del itkCType.__c_types__[self.name]
        except KeyError:
            pass

    def __repr__(self) -> str:
        return f"<itkCType {self.name}>"

    @staticmethod
    def GetCType(name: str) -> Optional["itkCType"]:
        # import locally to facilitate dynamic loading in itk/__init__.py
        from typing import Dict

        """Get the type corresponding to the provided C primitive type name."""
        aliases: Dict[str, str] = {
            "short": "signed short",
            "int": "signed int",
            "long": "signed long",
            "long long": "signed long long",
        }
        # Remove potential white space around types
        name = name.strip()
        desired_name: str = aliases.get(name, name)
        try:
            return itkCType.__c_types__[desired_name]
        except KeyError:
            return None

    @staticmethod
    def GetCTypeForDType(np_dtype: np.dtype) -> Optional["itkCType"]:
        """Get the type corresponding to the provided numpy.dtype."""
        try:
            return itkCType.__c_types_for_dtype__[np_dtype]
        except KeyError:
            return None

    @staticmethod
    def initialize_c_types_once() -> (
        "itkCType",
        "itkCType",
        "itkCType",
        "itkCType",
        "itkCType",
        "itkCType",
        "itkCType",
        "itkCType",
        "itkCType",
        "itkCType",
        "itkCType",
        "itkCType",
        "itkCType",
        "itkCType",
    ):
        """
        This function is intended to be run only one time
        """
        import os
        import numpy as np

        _F: "itkCType" = itkCType("float", "F", np.float32)
        _D: "itkCType" = itkCType("double", "D", np.float64)
        _UC: "itkCType" = itkCType("unsigned char", "UC", np.uint8)
        _US: "itkCType" = itkCType("unsigned short", "US", np.uint16)
        _UI: "itkCType" = itkCType("unsigned int", "UI", np.uint32)
        if os.name == "nt":
            _UL: "itkCType" = itkCType("unsigned long", "UL", np.uint32)
            _SL: "itkCType" = itkCType("signed long", "SL", np.int32)
            _LD: "itkCType" = itkCType("long double", "LD")
        else:
            _UL: "itkCType" = itkCType("unsigned long", "UL", np.uint64)
            _SL: "itkCType" = itkCType("signed long", "SL", np.int64)
            if hasattr(np, 'float128'):
                _LD: "itkCType" = itkCType("long double", "LD", np.float128)
            else:
                _LD: "itkCType" = itkCType("long double", "LD")
        _ULL: "itkCType" = itkCType("unsigned long long", "ULL", np.uint64)
        _SC: "itkCType" = itkCType("signed char", "SC", np.int8)
        _SS: "itkCType" = itkCType("signed short", "SS", np.int16)
        _SI: "itkCType" = itkCType("signed int", "SI", np.int32)
        _SLL: "itkCType" = itkCType("signed long long", "SLL", np.int64)
        _B: "itkCType" = itkCType("bool", "B", np.bool)
        return _F, _D, _UC, _US, _UI, _UL, _SL, _LD, _ULL, _SC, _SS, _SI, _SLL, _B

# Define typing hints
F: itkCType
D: itkCType
UC: itkCType
US: itkCType
UI: itkCType
UL: itkCType
SL: itkCType
LD: itkCType
ULL: itkCType
SC: itkCType
SS: itkCType
SI: itkCType
SLL: itkCType
B: itkCType

(
    F,
    D,
    UC,
    US,
    UI,
    UL,
    SL,
    LD,
    ULL,
    SC,
    SS,
    SI,
    SLL,
    B,
) = itkCType.initialize_c_types_once()

# Type aliases to avoid expensive import, circular references. Use with forward references.
if TYPE_CHECKING:
    import itk

# These should eventually explicitly be marked as TypeAlias's per PEP 613, available in CPython 3.10
ImageBase = "itk.ImageBase"
Image = "itk.Image"
VectorImage = "itk.VectorImage"

RGBPixel = "itk.RGBPixel"
Vector = "itk.Vector"
CovariantVector = "itk.CovariantVector"
SymmetricSecondRankTensor = "itk.SymmetricSecondRankTensor"
Offset = "itk.Offset"
FixedArray = "itk.FixedArray"
VariableLengthVector = "itk.VariableLengthVector"
complex_ = "itk.complex"

PixelTypes = Union[
    itkCType,
    RGBPixel,
    Vector,
    CovariantVector,
    SymmetricSecondRankTensor,
    Offset,
    FixedArray,
    complex_,
]

ImageSource = "itk.ImageSource"

ImageOrImageSource = Union[ImageBase, ImageSource]
# Can be coerced into an itk.ImageBase
if _HAVE_XARRAY and _HAVE_TORCH:
    ImageLike = Union[ImageBase, ArrayLike, xr.DataArray, torch.Tensor]
elif _HAVE_XARRAY:
    ImageLike = Union[ImageBase, ArrayLike, xr.DataArray]
elif _HAVE_TORCH:
    ImageLike = Union[ImageBase, ArrayLike, torch.Tensor]
else:
    ImageLike = Union[ImageBase, ArrayLike]

ImageIOBase = "itk.ImageIOBase"

LightObject = "itk.LightObject"
Object = "itk.Object"
DataObject = "itk.DataObject"

PointSet = "itk.PointSet"
Mesh = "itk.Mesh"
QuadEdgeMesh = "itk.QuadEdgeMesh"

Path = "itk.Path"
ParametricPath = "itk.ParametricPath"
PolyLineParametricPath = "itk.PolyLineParametricPath"
SpatialObject = "itk.SpatialObject"

TransformBase = "itk.TransformBaseTemplate"
Transform = "itk.Transform"

ImageRegion = "itk.ImageRegion"

VectorContainer = "itk.VectorContainer"
Matrix = "itk.Matrix"

# Return types for the functional interfaces to ProcessObject's.
# When there is a single indexed output, it is returned directly.
# When there are multiple indexed outputs, a tuple of the indexed outputs is
# returned.
ImageSourceReturn = Union[ImageLike, Tuple[ImageLike, ...]]
MeshSourceReturn = Union[Mesh, Tuple[Mesh, ...]]
PathSourceReturn = Union[Path, Tuple[Path, ...]]

InterpolateImageFunction = "itk.InterpolateImageFunction"
ExtrapolateImageFunction = "itk.ExtrapolateImageFunction"
ImageBoundaryCondition = "itk.ImageBoundaryCondition"
FlatStructuringElement = "itk.FlatStructuringElement"
<|endoftext|>


<commit_before>#!/usr/bin/env python

from itertools import izip
from contextlib import contextmanager
import redis
import pickle
import atexit

class RedisConnectionManager(object):
    cons = {}

    @classmethod
    def r(cls, obj):
        success = False
        while not success:
            try:
                success = cls.cons[(obj.host, obj.port)].ping()
            except (redis.ConnectionError, KeyError):
                cls.cons[(obj.host, obj.port)] = redis.Redis(obj.host, obj.port)
        return cls.cons[(obj.host, obj.port)]

class RedisLockInUse(Exception):
    pass

class RedisObject(object):
    instances = []

    def __init__(self, name, host='localhost', port=6379):
        self.name = name
        self.host = host
        self.port = port
        self.instances.append(self)

    @property
    def r(self):
        return RedisConnectionManager.r(self)

    @property
    def lock_name(self):
        return '{}LOCK'.format(self.name)

    def __del__(self):
        self.r.delete(self.name)

    def delete_lock(self):
        self.r.delete(self.lock_name)

    @contextmanager
    def acquire_lock(self, raise_exception=False):
        while self.r.incr(self.lock_name) != 1:
            self.r.decr(self.lock_name)
            if raise_exception:
                raise RedisLockInUse('Cannot acquire lock for {}'.format(self.name))
        yield
        if self.r.exists(self.lock_name):
            self.r.decr(self.lock_name)

    @classmethod
    def cleanup(cls):
        for instance in cls.instances:
            instance.delete_lock()
            instance.clear()

    def pickle(self, value):
        return pickle.dumps(value)

    def unpickle(self, value):
        return pickle.loads(value)

class RedisDict(RedisObject):
    def clear(self):
        self.r.delete(self.name)

    def pop(self, key, default=None):
        value = self.__getitem__(key)
        self.__delitem__(key)
        return value or default

    def popitem(self):
        key = self.keys()[0]
        value = self.__getitem__(key)
        self.__delitem__(key)
        return key, value

    def set_to(self, py_dict):
        self.r.delete(self.name)
        self.update(py_dict)

    def setdefault(self, key, default=None):
        value = self.__getitem__(key)
        if value is not None:
            return value
        self.__setitem__(key, default)
        return default

    def get(self, key, default=None):
        return self.__getitem__(key) or default

    def update(self, obj, **kwargs):
        for key, value in kwargs.iteritems():
            self.__setitem__(key, value)
        if type(obj) in (dict, RedisDict):
            for key, value in obj.iteritems():
                self.__setitem__(key, value)
        if type(obj) is list:
            for key, value in obj:
                self.__setitem__(key, value)

    def iterkeys(self):
        return self.__iter__()

    def keys(self):
        return list(self.__iter__())

    def sorted_keys(self):
        return sorted(self.__iter__())

    def itervalues(self):
        return (self.unpickle(value) for value in self.r.hvals(self.name))

    def values(self):
        return list(self.itervalues())

    def iteritems(self):
        return ((self.unpickle(key), self.unpickle(value)) for key, value in self.r.hgetall(self.name).iteritems())

    def items(self):
        return list(self.iteritems())

    def __getitem__(self, key):
        return self.unpickle(self.r.hget(self.name, self.pickle(key)))

    def __setitem__(self, key, value):
        self.r.hset(self.name, self.pickle(key), self.pickle(value))

    def __delitem__(self, key):
        self.r.hdel(self.name, self.pickle(key))

    def __contains__(self, key):
        return self.r.hexists(self.name, self.pickle(key))

    def __iter__(self):
        return (self.unpickle(key) for key in self.r.hkeys(self.name))

    def __reversed__(self):
        return (key for key in self.keys()[::-1])

    def __str__(self):
        return str(self.__dict__())

    def __repr__(self):
        return repr(self.__dict__())

    def __dict__(self):
        return dict(self.items())

    def __eq__(self, other):
        if type(other) not in (dict, RedisDict):
            return False
        self_keys = self.keys()
        other_keys = other.keys()
        if set(self_keys) != set(other_keys):
            return False
        for k in self_keys:
            if self[k] != other[k]:
                return False
        return True

    def __ne__(self, other):
        return not self.__eq__(other)

    def __len__(self):
        return self.r.hlen(self.name)

class RedisList(RedisObject):
    def append(self, value):
        self.r.rpush(self.name, self.pickle(value))

    def extend(self, values):
        self.r.rpush(self.name, *(self.pickle(value) for value in values))

    def insert(self, index, value):
        self.r.linsert(self.name, index, self.pickle(value))

    def remove(self, value):
        self.r.lrem(self.name, value)

    def pop(self, index=-1):
        length = len(self)
        if index < 0:
            if index + length < 0:
                raise IndexError('RedisList index out of range')
            return self.unpickle(self.r.lrem(self.name, length + index))
        if index > length - 1:
            raise IndexError('RedisList index out of range')
        return self.unpickle(self.r.lrem(self.name, index))

    def index(self, value):
        index = self.r.index(self.name, self.pickle(value))
        if index is None:
            raise ValueError('{} is not in RedisList'.format(repr(value)))
        return index

    def count(self, value):
        count = 0
        for v in self.__list__():
            if v == value:
                count += 1
        return count

    def sort(self, *args, **kwargs):
        temp = sorted(self.__list__(), *args, **kwargs)
        self.r.delete(self.name)
        self.r.rpush(self.name, *temp)
        return temp

    def reverse(self):
        temp = self.__list__()[::-1]
        self.r.delete(self.name)
        self.r.rpush(self.name, *(self.pickle(value) for value in temp))

    def clear(self):
        self.r.delete(self.name)

    def set_to(self, py_list):
        self.clear()
        self.r.rpush(self.name, *(self.pickle(value) for value in py_list))

    def __add__(self, value):
        if type(value) is list:
            return self.__list__() + value
        if type(value) is RedisList:
            return self.__list__() + value.__list__()
        raise TypeError('can only concatenate list or RedisList (not "{}") to RedisList'.format(type(value)))

    def __delitem__(self, index):
        temp = self.__list__()
        del(temp[index])
        self.r.delete(self.name)
        self.r.rpush(self.name, *(self.pickle(value) for value in temp))

    def __delslice__(self, *coords):
        i, j = coords
        n = 1 if len(coords) != 3 else coords[2]
        temp = self.__list__()
        del(temp[i:j:n])
        self.r.delete(self.name)
        self.r.rpush(self.name, *(self.pickle(value) for value in temp))

    def __list__(self):
        return [self.unpickle(value) for value in self.r.lrange(self.name, 0, -1)]

    def __str__(self):
        return str(self.__list__())

    def __repr__(self):
        return repr(self.__list__())

    def __eq__(self, other):
        if type(other) in (list, RedisList):
            if len(self) != len(other):
                return False
            return all(a == b for a, b in izip(self.__list__(), other))
        return False

    def __ne__(self, other):
        return not self.__eq__(other)

    def __contains__(self, value):
        return any(self_value == value for self_value in self.__iter__())

    def __iter__(self):
        return (self.unpickle(self.r.lindex(self.name, i)) for i in xrange(self.__len__()))

    def __len__(self):
        return self.r.llen(self.name)

    def __getitem__(self, coords):
        if type(coords) is slice:
            return [self.unpickle(value) for value in self.r.lrange(self.name, 0, -1)[coords]]
        if type(coords) is int:
            return self.unpickle(self.r.lindex(self.name, coords))

class RedisSet(RedisObject):
    pass

class RedisSortedSet(RedisObject):
    pass

atexit.register(RedisObject.cleanup)
<commit_msg>fixes for get and getitem<commit_after>#!/usr/bin/env python

from itertools import izip
from contextlib import contextmanager
import redis
import pickle
import atexit

class RedisConnectionManager(object):
    cons = {}

    @classmethod
    def r(cls, obj):
        success = False
        while not success:
            try:
                success = cls.cons[(obj.host, obj.port)].ping()
            except (redis.ConnectionError, KeyError):
                cls.cons[(obj.host, obj.port)] = redis.Redis(obj.host, obj.port)
        return cls.cons[(obj.host, obj.port)]

class RedisLockInUse(Exception):
    pass

class RedisObject(object):
    instances = []

    def __init__(self, name, host='localhost', port=6379):
        self.name = name
        self.host = host
        self.port = port
        self.instances.append(self)

    @property
    def r(self):
        return RedisConnectionManager.r(self)

    @property
    def lock_name(self):
        return '{}LOCK'.format(self.name)

    def __del__(self):
        self.r.delete(self.name)

    def delete_lock(self):
        self.r.delete(self.lock_name)

    @contextmanager
    def acquire_lock(self, raise_exception=False):
        while self.r.incr(self.lock_name) != 1:
            self.r.decr(self.lock_name)
            if raise_exception:
                raise RedisLockInUse('Cannot acquire lock for {}'.format(self.name))
        yield
        if self.r.exists(self.lock_name):
            self.r.decr(self.lock_name)

    @classmethod
    def cleanup(cls):
        for instance in cls.instances:
            instance.delete_lock()

    def pickle(self, value):
        return pickle.dumps(value)

    def unpickle(self, value):
        return pickle.loads(value)

class RedisDict(RedisObject):
    def clear(self):
        self.r.delete(self.name)

    def pop(self, key, default=None):
        value = self.__getitem__(key)
        self.__delitem__(key)
        return value or default

    def popitem(self):
        key = self.keys()[0]
        value = self.__getitem__(key)
        self.__delitem__(key)
        return key, value

    def set_to(self, py_dict):
        self.r.delete(self.name)
        self.update(py_dict)

    def setdefault(self, key, default=None):
        value = self.__getitem__(key)
        if value is not None:
            return value
        self.__setitem__(key, default)
        return default

    def get(self, key, default=None):
        pickled_value = self.r.hget(self.name, self.pickle(key))
        if pickled_value is None:
            return default
        return self.unpickle(pickled_value)

    def update(self, obj, **kwargs):
        for key, value in kwargs.iteritems():
            self.__setitem__(key, value)
        if type(obj) in (dict, RedisDict):
            for key, value in obj.iteritems():
                self.__setitem__(key, value)
        if type(obj) is list:
            for key, value in obj:
                self.__setitem__(key, value)

    def iterkeys(self):
        return self.__iter__()

    def keys(self):
        return list(self.__iter__())

    def sorted_keys(self):
        return sorted(self.__iter__())

    def itervalues(self):
        return (self.unpickle(value) for value in self.r.hvals(self.name))

    def values(self):
        return list(self.itervalues())

    def iteritems(self):
        return ((self.unpickle(key), self.unpickle(value)) for key, value in self.r.hgetall(self.name).iteritems())

    def items(self):
        return list(self.iteritems())

    def __getitem__(self, key):
        pickled_value = self.r.hget(self.name, self.pickle(key))
        if pickled_value is None:
            raise KeyError('Key "{}" is not valid'.format(key))
        return self.unpickle(pickled_value)

    def __setitem__(self, key, value):
        self.r.hset(self.name, self.pickle(key), self.pickle(value))

    def __delitem__(self, key):
        self.r.hdel(self.name, self.pickle(key))

    def __contains__(self, key):
        return self.r.hexists(self.name, self.pickle(key))

    def __iter__(self):
        return (self.unpickle(key) for key in self.r.hkeys(self.name))

    def __reversed__(self):
        return (key for key in self.keys()[::-1])

    def __str__(self):
        return str(self.__dict__())

    def __repr__(self):
        return repr(self.__dict__())

    def __dict__(self):
        return dict(self.items())

    def __eq__(self, other):
        if type(other) not in (dict, RedisDict):
            return False
        self_keys = self.keys()
        other_keys = other.keys()
        if set(self_keys) != set(other_keys):
            return False
        for k in self_keys:
            if self[k] != other[k]:
                return False
        return True

    def __ne__(self, other):
        return not self.__eq__(other)

    def __len__(self):
        return self.r.hlen(self.name)

class RedisList(RedisObject):
    def append(self, value):
        self.r.rpush(self.name, self.pickle(value))

    def extend(self, values):
        self.r.rpush(self.name, *(self.pickle(value) for value in values))

    def insert(self, index, value):
        self.r.linsert(self.name, index, self.pickle(value))

    def remove(self, value):
        self.r.lrem(self.name, value)

    def pop(self, index=-1):
        length = len(self)
        if index < 0:
            if index + length < 0:
                raise IndexError('RedisList index out of range')
            return self.unpickle(self.r.lrem(self.name, length + index))
        if index > length - 1:
            raise IndexError('RedisList index out of range')
        return self.unpickle(self.r.lrem(self.name, index))

    def index(self, value):
        index = self.r.index(self.name, self.pickle(value))
        if index is None:
            raise ValueError('{} is not in RedisList'.format(repr(value)))
        return index

    def count(self, value):
        count = 0
        for v in self.__list__():
            if v == value:
                count += 1
        return count

    def sort(self, *args, **kwargs):
        temp = sorted(self.__list__(), *args, **kwargs)
        self.r.delete(self.name)
        self.r.rpush(self.name, *temp)
        return temp

    def reverse(self):
        temp = self.__list__()[::-1]
        self.r.delete(self.name)
        self.r.rpush(self.name, *(self.pickle(value) for value in temp))

    def clear(self):
        self.r.delete(self.name)

    def set_to(self, py_list):
        self.clear()
        self.r.rpush(self.name, *(self.pickle(value) for value in py_list))

    def __add__(self, value):
        if type(value) is list:
            return self.__list__() + value
        if type(value) is RedisList:
            return self.__list__() + value.__list__()
        raise TypeError('can only concatenate list or RedisList (not "{}") to RedisList'.format(type(value)))

    def __delitem__(self, index):
        temp = self.__list__()
        del(temp[index])
        self.r.delete(self.name)
        self.r.rpush(self.name, *(self.pickle(value) for value in temp))

    def __delslice__(self, *coords):
        i, j = coords
        n = 1 if len(coords) != 3 else coords[2]
        temp = self.__list__()
        del(temp[i:j:n])
        self.r.delete(self.name)
        self.r.rpush(self.name, *(self.pickle(value) for value in temp))

    def __list__(self):
        return [self.unpickle(value) for value in self.r.lrange(self.name, 0, -1)]

    def __str__(self):
        return str(self.__list__())

    def __repr__(self):
        return repr(self.__list__())

    def __eq__(self, other):
        if type(other) in (list, RedisList):
            if len(self) != len(other):
                return False
            return all(a == b for a, b in izip(self.__list__(), other))
        return False

    def __ne__(self, other):
        return not self.__eq__(other)

    def __contains__(self, value):
        return any(self_value == value for self_value in self.__iter__())

    def __iter__(self):
        return (self.unpickle(self.r.lindex(self.name, i)) for i in xrange(self.__len__()))

    def __len__(self):
        return self.r.llen(self.name)

    def __getitem__(self, coords):
        if type(coords) is slice:
            return [self.unpickle(value) for value in self.r.lrange(self.name, 0, -1)[coords]]
        if type(coords) is int:
            return self.unpickle(self.r.lindex(self.name, coords))

class RedisSet(RedisObject):
    pass

class RedisSortedSet(RedisObject):
    pass

atexit.register(RedisObject.cleanup)
<|endoftext|>


<commit_before># Copyright (c) 2010 gocept gmbh & co. kg
# See also LICENSE.txt

import mock
import unittest2
import zeit.cms.testing
import zeit.content.article.testing

class GalleryTest(unittest2.TestCase,
                  zeit.cms.testing.BrowserAssertions):

    layer = zeit.content.article.testing.TestBrowserLayer

    expected_type = 'gallery'
    attribute = 'href'

    def setUp(self):
        from zope.testbrowser.testing import Browser
        self.browser = browser = Browser()
        browser.addHeader('Authorization', 'Basic user:userpw')
        browser.open('http://localhost:8080/++skin++vivi/repository/online'
                     '/2007/01/Somalia/@@checkout')
        self.article_url = browser.url
        browser.open('@@contents')
        self.contents_url = browser.url
        browser.open(self.contents_url)

    def setup_content(self):
        """Create a gallery (requires folder with images)"""
        from zeit.content.gallery.browser.testing import add_folder, add_image
        browser = self.browser
        browser.open('http://localhost/++skin++cms/repository/online/2007/01')
        _ = add_folder(browser, 'gallery')
        _ = add_image(browser, '01.jpg')
        _ = add_image(browser, '02.jpg')
        browser.getLink('01').click()
        menu = browser.getControl(name='add_menu')
        menu.displayValue = ['Gallery']
        browser.open(menu.value[0])
        browser.getControl('File name').value = 'island'
        browser.getControl('Title').value = 'Auf den Spuren der Elfen'
        browser.getControl('Ressort').displayValue = ['Reisen']
        browser.getControl(name="form.image_folder").value = (
            'http://xml.zeit.de/online/2007/01/gallery')
        browser.getControl(name='form.authors.0.').value = 'Hans Sachs'
        browser.getControl(name="form.actions.add").click()
        browser.getLink('Checkin').click()
        self.content_id = 'http://xml.zeit.de/online/2007/01/island'
        browser.open(self.contents_url)

    def get_article(self, with_empty_block=False):
        import transaction
        article = self.layer.setup.getRootFolder()[
            'workingcopy']['zope.user']['Somalia']
        for p in article.xml.findall('//division/*'):
            p.getparent().remove(p)
        if with_empty_block:
            article.xml.body.division[self.expected_type] = ''
            article.xml.body.division[self.expected_type].set(
                '{http://namespaces.zeit.de/CMS/cp}__name__', 'blockname')
        article._p_changed = True
        transaction.commit()
        return article

    def test_no_reference_should_render(self):
        article = self.get_article(with_empty_block=True)
        self.browser.open('editable-body/@@contents')
        self.assert_ellipsis(
            """<...
            <div ...class="block type-%s...""" % self.expected_type)

    def test_empty_block_should_be_landing_zone(self):
        article = self.get_article(with_empty_block=True)
        self.setup_content()
        self.browser.open(
            'editable-body/blockname/@@set_reference?uniqueId=%s' %
            self.content_id)
        self.assert_json(
            {'signals': [{'args': [
                'blockname',
                'http://localhost:8080/++skin++vivi/workingcopy/zope.user/Somalia/editable-body/blockname/@@contents'],
                'name': 'reload',
                'when': None}]})
        self.browser.open('@@contents')
        self.assert_ellipsis(
            """<div ...class="block type-%s...""" % self.expected_type)

    def test_only_specific_type_should_be_droppable(self):
        article = self.get_article(with_empty_block=True)
        self.setup_content()
        with self.assertRaises(Exception):
            self.browser.open(
                'editable-body/blockname/@@set_reference?uniqueId='
                'http://xml.zeit.de/testcontent')
        # NOTE: the error message should be improved
        self.assert_ellipsis(
            "ConstraintNotSatisfied(<zeit.cms.repository.unknown."
            "PersistentUnknownResource object at 0x...>)")

    def test_droping_type_on_landing_zone_creates_block(self):
        article = self.get_article()
        self.setup_content()
        self.assert_ellipsis(
            """...cms:drop-url="http://localhost:8080/++skin++vivi/workingcopy/zope.user/Somalia/editable-body/@@article-landing-zone-drop"...""")
        uuid4 = mock.Mock(side_effect=lambda: uuid4.call_count)
        with mock.patch('uuid.uuid4', new=uuid4):
            self.browser.open(
                'editable-body/@@article-landing-zone-drop?uniqueId=%s' %
                self.content_id)
        data = self.assert_json(
            {'signals': [{'args': ['1'], 'name': 'added', 'when': 'after-reload'},
                         {'args': ['editable-body',
                                   'http://localhost:8080/++skin++vivi/workingcopy/zope.user/Somalia/editable-body/@@contents'],
                          'name': 'reload',
                          'when': None}]})
        self.browser.open(self.contents_url)
        self.assert_ellipsis(
            """<...
                <div ...class="block type-%s...""" % self.expected_type)
        # Each block has its own landing zone:
        id = data['signals'][0]['args'][0]
        with mock.patch('uuid.uuid4', new=uuid4):
            self.browser.open(
                'editable-body/%s/@@article-landing-zone-drop?uniqueId=%s' % (
                    id, self.content_id))
        self.assert_json(
            {'signals': [{'args': ['2'], 'name': 'added', 'when': 'after-reload'},
                         {'args': ['editable-body',
                                   'http://localhost:8080/++skin++vivi/workingcopy/zope.user/Somalia/editable-body/@@contents'],
                          'name': 'reload',
                          'when': None}]})

    def test_checkin_should_work_with_empty_block(self):
        article = self.get_article(with_empty_block=True)
        self.browser.open(self.article_url)
        # Assertion is that no error is raised
        self.browser.handleErrors = False
        self.browser.getLink('Checkin').click()

    def test_should_be_visible_in_read_only_mode(self):
        article = self.get_article(with_empty_block=True)
        self.setup_content()
        self.browser.open(
            'editable-body/blockname/@@set_reference?uniqueId=%s' %
            self.content_id)
        self.browser.open(self.article_url)
        self.browser.getLink('Checkin').click()
        self.browser.open('@@contents')
        self.assert_ellipsis(
            """<div ...class="block type-%s...""" % self.expected_type)

    def test_reference_should_be_stored_by_set_ref(self):
        article = self.get_article(with_empty_block=True)
        self.setup_content()
        self.browser.open(
            'editable-body/blockname/@@set_reference?uniqueId={0}'.format(
                self.content_id))
        self.assertEqual(
            self.content_id,
            article.xml.body.division[self.expected_type].get(self.attribute))

    def test_reference_should_be_stored_after_checkin(self):
        import zeit.cms.interfaces
        article = self.get_article(with_empty_block=True)
        self.setup_content()
        self.browser.open(
            'editable-body/blockname/@@set_reference?uniqueId={0}'.format(
                self.content_id))
        self.browser.open(self.article_url)
        self.browser.getLink('Checkin').click()
        with zeit.cms.testing.site(self.layer.setup.getRootFolder()):
            article = zeit.cms.interfaces.ICMSContent(article.uniqueId)
        self.assertEqual(
            self.content_id,
            article.xml.body.division[self.expected_type].get(self.attribute))

    def test_empty_block_should_not_provide_drop_in_readonly_mode(self):
        article = self.get_article(with_empty_block=True)
        self.browser.open(self.article_url)
        self.browser.getLink('Checkin').click()
        self.browser.open('@@contents')
        self.assert_ellipsis(
            '<div ...class="block type-{0}...No content referenced...'.format(
                self.expected_type))

class InfoboxTest(GalleryTest):

    expected_type = 'infobox'

    def setup_content(self):
        from zeit.content.infobox.infobox import Infobox
        import transaction
        ib = Infobox()
        ib.supertitle = u'infobox title'
        root = self.layer.setup.getRootFolder()
        with zeit.cms.testing.site(root):
            root['repository']['infobox'] = ib
        self.content_id = 'http://xml.zeit.de/infobox'
        transaction.commit()

class PortraitboxTest(GalleryTest):

    expected_type = 'portraitbox'

    def setup_content(self):
        from zeit.content.portraitbox.portraitbox import Portraitbox
        import transaction
        import zeit.cms.testing
        pb = Portraitbox()
        root = self.layer.setup.getRootFolder()
        with zeit.cms.testing.site(root):
            with zeit.cms.testing.interaction():
                root['repository']['pb'] = pb
        self.content_id = 'http://xml.zeit.de/pb'
        transaction.commit()

    def test_layout_should_be_editable(self):
        self.setup_content()
        article = self.get_article(with_empty_block=True)
        article.xml.body.division[self.expected_type].set(
            'href', self.content_id)
        article._p_changed = True
        self.browser.open(self.contents_url)
        self.browser.getLink('Edit').click()
        self.assertEqual(
            ['(no value)', 'short', 'wide'],
            self.browser.getControl('Layout').displayOptions)
        self.browser.getControl('Layout').displayValue = ['wide']
        self.browser.getControl('Apply').click()
        self.assert_ellipsis("<...self.close()...")
        # The layout is used as a css-class:
        self.browser.open(self.contents_url)
        self.assert_ellipsis(
            """...<div ...class="wide ...""")

class ImageTest(GalleryTest):

    expected_type = 'image'
    attribute = 'src'

    def setup_content(self):
        self.content_id = 'http://xml.zeit.de/2006/DSC00109_2.JPG'

    def test_only_specific_type_should_be_droppable(self):
        article = self.get_article(with_empty_block=True)
        self.setup_content()
        with self.assertRaises(Exception):
            self.browser.open(
                'editable-body/blockname/@@set_reference?uniqueId='
                'http://xml.zeit.de/testcontent')
        # NOTE: the error message should be improved
        self.assert_ellipsis("ComponentLookupError...")

    def test_layout_should_be_editable(self):
        article = self.get_article(with_empty_block=True)
        self.browser.open(self.contents_url)
        self.browser.getLink('Edit').click()
        self.assertEqual(
            ['(no value)', 'small', 'large', 'Infobox', 'Hochkant'],
            self.browser.getControl('Layout').displayOptions)
        self.browser.getControl('Layout').displayValue = ['large']
        self.browser.getControl('Apply').click()
        self.assert_ellipsis("<...self.close()...")
        # The layout is used as a css-class:
        self.browser.open(self.contents_url)
        self.assert_ellipsis(
            """...<div ...class="large ...""")

    def test_empty_block_should_not_provide_drop_in_readonly_mode(self):
        # Disable inherited test because empty images are removed during
        # checkin. This will change hopefully once #8194 is implemented.
        pass

class VideoTest(GalleryTest):

    layer = zeit.content.article.testing.ArticleBrightcoveLayer
    expected_type = 'video'

    def setup_content(self):
        self.content_id = 'http://video.zeit.de/video/1234'

    def test_layout_should_be_editable(self):
        article = self.get_article(with_empty_block=True)
        self.browser.open(self.contents_url)
        self.browser.getLink('Edit').click()
        self.assertEqual(
            ['(no value)', 'small', 'with info', 'large', 'double'],
            self.browser.getControl('Layout').displayOptions)
        self.browser.getControl('Layout').displayValue = ['large']
        self.browser.getControl('Apply').click()
        self.assert_ellipsis("<...self.close()...")
        # The layout is used as a css-class:
        self.browser.open(self.contents_url)
        self.assert_ellipsis(
            """...<div ...class="large ...""")

    def test_two_videos_should_be_editable(self):
        article = self.get_article(with_empty_block=True)
        self.browser.open(self.contents_url)
        self.browser.getLink('Edit').click()
        self.browser.getControl('Video', index=0).value = (
            'http://video.zeit.de/video/1234')
        self.browser.getControl('Video 2').value = (
            'http://video.zeit.de/video/6789')
        self.browser.getControl('Apply').click()
        self.assert_ellipsis("<...self.close()...")
        self.browser.open(self.contents_url)
        self.assert_ellipsis(
            """...
               ......""")
<commit_msg>Make sure there are no Cache-Control headers (see commit:8a4afc1040dc in zeit.cms)<commit_after># Copyright (c) 2010 gocept gmbh & co. kg
# See also LICENSE.txt

import mock
import unittest2
import zeit.cms.testing
import zeit.content.article.testing

class GalleryTest(unittest2.TestCase,
                  zeit.cms.testing.BrowserAssertions):

    layer = zeit.content.article.testing.TestBrowserLayer

    expected_type = 'gallery'
    attribute = 'href'

    def setUp(self):
        from zope.testbrowser.testing import Browser
        self.browser = browser = Browser()
        browser.addHeader('Authorization', 'Basic user:userpw')
        browser.open('http://localhost:8080/++skin++vivi/repository/online'
                     '/2007/01/Somalia/@@checkout')
        self.article_url = browser.url
        browser.open('@@contents')
        self.contents_url = browser.url
        browser.open(self.contents_url)

    def setup_content(self):
        """Create a gallery (requires folder with images)"""
        from zeit.content.gallery.browser.testing import add_folder, add_image
        browser = self.browser
        browser.open('http://localhost/++skin++cms/repository/online/2007/01')
        _ = add_folder(browser, 'gallery')
        _ = add_image(browser, '01.jpg')
        _ = add_image(browser, '02.jpg')
        browser.getLink('01').click()
        menu = browser.getControl(name='add_menu')
        menu.displayValue = ['Gallery']
        browser.open(menu.value[0])
        browser.getControl('File name').value = 'island'
        browser.getControl('Title').value = 'Auf den Spuren der Elfen'
        browser.getControl('Ressort').displayValue = ['Reisen']
        browser.getControl(name="form.image_folder").value = (
            'http://xml.zeit.de/online/2007/01/gallery')
        browser.getControl(name='form.authors.0.').value = 'Hans Sachs'
        browser.getControl(name="form.actions.add").click()
        browser.getLink('Checkin').click()
        self.content_id = 'http://xml.zeit.de/online/2007/01/island'
        browser.open(self.contents_url)

    def get_article(self, with_empty_block=False):
        import transaction
        article = self.layer.setup.getRootFolder()[
            'workingcopy']['zope.user']['Somalia']
        for p in article.xml.findall('//division/*'):
            p.getparent().remove(p)
        if with_empty_block:
            article.xml.body.division[self.expected_type] = ''
            article.xml.body.division[self.expected_type].set(
                '{http://namespaces.zeit.de/CMS/cp}__name__', 'blockname')
        article._p_changed = True
        transaction.commit()
        return article

    def test_no_reference_should_render(self):
        article = self.get_article(with_empty_block=True)
        self.browser.open('editable-body/@@contents')
        self.assert_ellipsis(
            """<...
            <div ...class="block type-%s...""" % self.expected_type)

    def test_empty_block_should_be_landing_zone(self):
        article = self.get_article(with_empty_block=True)
        self.setup_content()
        self.browser.open(
            'editable-body/blockname/@@set_reference?uniqueId=%s' %
            self.content_id)
        self.assert_json(
            {'signals': [{'args': [
                'blockname',
                'http://localhost:8080/++skin++vivi/workingcopy/zope.user/Somalia/editable-body/blockname/@@contents'],
                'name': 'reload',
                'when': None}]})
        self.browser.open('@@contents')
        self.assert_ellipsis(
            """<div ...class="block type-%s...""" % self.expected_type)

    def test_only_specific_type_should_be_droppable(self):
        article = self.get_article(with_empty_block=True)
        self.setup_content()
        with self.assertRaises(Exception):
            self.browser.open(
                'editable-body/blockname/@@set_reference?uniqueId='
                'http://xml.zeit.de/testcontent')
        # NOTE: the error message should be improved
        self.assert_ellipsis(
            "ConstraintNotSatisfied(<zeit.cms.repository.unknown."
            "PersistentUnknownResource object at 0x...>)")

    def test_droping_type_on_landing_zone_creates_block(self):
        article = self.get_article()
        self.setup_content()
        self.assert_ellipsis(
            """...cms:drop-url="http://localhost:8080/++skin++vivi/workingcopy/zope.user/Somalia/editable-body/@@article-landing-zone-drop"...""")
        uuid4 = mock.Mock(side_effect=lambda: uuid4.call_count)
        with mock.patch('uuid.uuid4', new=uuid4):
            self.browser.open(
                'editable-body/@@article-landing-zone-drop?uniqueId=%s' %
                self.content_id)
        data = self.assert_json(
            {'signals': [{'args': ['1'], 'name': 'added', 'when': 'after-reload'},
                         {'args': ['editable-body',
                                   'http://localhost:8080/++skin++vivi/workingcopy/zope.user/Somalia/editable-body/@@contents'],
                          'name': 'reload',
                          'when': None}]})
        self.browser.open(self.contents_url)
        self.assert_ellipsis(
            """<...
                <div ...class="block type-%s...""" % self.expected_type)
        # Each block has its own landing zone:
        id = data['signals'][0]['args'][0]
        with mock.patch('uuid.uuid4', new=uuid4):
            self.browser.open(
                'editable-body/%s/@@article-landing-zone-drop?uniqueId=%s' % (
                    id, self.content_id))
        self.assert_json(
            {'signals': [{'args': ['2'], 'name': 'added', 'when': 'after-reload'},
                         {'args': ['editable-body',
                                   'http://localhost:8080/++skin++vivi/workingcopy/zope.user/Somalia/editable-body/@@contents'],
                          'name': 'reload',
                          'when': None}]})

    def test_checkin_should_work_with_empty_block(self):
        article = self.get_article(with_empty_block=True)
        self.browser.open(self.article_url)
        # Assertion is that no error is raised
        self.browser.handleErrors = False
        self.browser.getLink('Checkin').click()

    def test_should_be_visible_in_read_only_mode(self):
        article = self.get_article(with_empty_block=True)
        self.setup_content()
        self.browser.open(
            'editable-body/blockname/@@set_reference?uniqueId=%s' %
            self.content_id)
        self.browser.open(self.article_url)
        self.browser.getLink('Checkin').click()
        self.browser.open('@@contents')
        self.assert_ellipsis(
            """<div ...class="block type-%s...""" % self.expected_type)

    def test_reference_should_be_stored_by_set_ref(self):
        article = self.get_article(with_empty_block=True)
        self.setup_content()
        self.browser.open(
            'editable-body/blockname/@@set_reference?uniqueId={0}'.format(
                self.content_id))
        self.assertEqual(
            self.content_id,
            article.xml.body.division[self.expected_type].get(self.attribute))

    def test_reference_should_be_stored_after_checkin(self):
        import zeit.cms.interfaces
        article = self.get_article(with_empty_block=True)
        self.setup_content()
        self.browser.open(
            'editable-body/blockname/@@set_reference?uniqueId={0}'.format(
                self.content_id))
        self.browser.open(self.article_url)
        self.browser.getLink('Checkin').click()
        with zeit.cms.testing.site(self.layer.setup.getRootFolder()):
            article = zeit.cms.interfaces.ICMSContent(article.uniqueId)
        self.assertEqual(
            self.content_id,
            article.xml.body.division[self.expected_type].get(self.attribute))

    def test_empty_block_should_not_provide_drop_in_readonly_mode(self):
        article = self.get_article(with_empty_block=True)
        self.browser.open(self.article_url)
        self.browser.getLink('Checkin').click()
        self.browser.open('@@contents')
        self.assert_ellipsis(
            '<div ...class="block type-{0}...No content referenced...'.format(
                self.expected_type))

    def test_contents_should_not_have_cache_control_header(self):
        self.get_article(with_empty_block=True)
        self.setup_content()
        self.browser.open(
            'editable-body/blockname/@@set_reference?uniqueId={0}'.format(
                self.content_id))
        self.browser.open('@@contents')
        self.assertNotIn('Cache-Control', self.browser.headers)

class InfoboxTest(GalleryTest):

    expected_type = 'infobox'

    def setup_content(self):
        from zeit.content.infobox.infobox import Infobox
        import transaction
        ib = Infobox()
        ib.supertitle = u'infobox title'
        root = self.layer.setup.getRootFolder()
        with zeit.cms.testing.site(root):
            root['repository']['infobox'] = ib
        self.content_id = 'http://xml.zeit.de/infobox'
        transaction.commit()

class PortraitboxTest(GalleryTest):

    expected_type = 'portraitbox'

    def setup_content(self):
        from zeit.content.portraitbox.portraitbox import Portraitbox
        import transaction
        import zeit.cms.testing
        pb = Portraitbox()
        root = self.layer.setup.getRootFolder()
        with zeit.cms.testing.site(root):
            with zeit.cms.testing.interaction():
                root['repository']['pb'] = pb
        self.content_id = 'http://xml.zeit.de/pb'
        transaction.commit()

    def test_layout_should_be_editable(self):
        self.setup_content()
        article = self.get_article(with_empty_block=True)
        article.xml.body.division[self.expected_type].set(
            'href', self.content_id)
        article._p_changed = True
        self.browser.open(self.contents_url)
        self.browser.getLink('Edit').click()
        self.assertEqual(
            ['(no value)', 'short', 'wide'],
            self.browser.getControl('Layout').displayOptions)
        self.browser.getControl('Layout').displayValue = ['wide']
        self.browser.getControl('Apply').click()
        self.assert_ellipsis("<...self.close()...")
        # The layout is used as a css-class:
        self.browser.open(self.contents_url)
        self.assert_ellipsis(
            """...<div ...class="wide ...""")

class ImageTest(GalleryTest):

    expected_type = 'image'
    attribute = 'src'

    def setup_content(self):
        self.content_id = 'http://xml.zeit.de/2006/DSC00109_2.JPG'

    def test_only_specific_type_should_be_droppable(self):
        article = self.get_article(with_empty_block=True)
        self.setup_content()
        with self.assertRaises(Exception):
            self.browser.open(
                'editable-body/blockname/@@set_reference?uniqueId='
                'http://xml.zeit.de/testcontent')
        # NOTE: the error message should be improved
        self.assert_ellipsis("ComponentLookupError...")

    def test_layout_should_be_editable(self):
        article = self.get_article(with_empty_block=True)
        self.browser.open(self.contents_url)
        self.browser.getLink('Edit').click()
        self.assertEqual(
            ['(no value)', 'small', 'large', 'Infobox', 'Hochkant'],
            self.browser.getControl('Layout').displayOptions)
        self.browser.getControl('Layout').displayValue = ['large']
        self.browser.getControl('Apply').click()
        self.assert_ellipsis("<...self.close()...")
        # The layout is used as a css-class:
        self.browser.open(self.contents_url)
        self.assert_ellipsis(
            """...<div ...class="large ...""")

    def test_empty_block_should_not_provide_drop_in_readonly_mode(self):
        # Disable inherited test because empty images are removed during
        # checkin. This will change hopefully once #8194 is implemented.
        pass

class VideoTest(GalleryTest):

    layer = zeit.content.article.testing.ArticleBrightcoveLayer
    expected_type = 'video'

    def setup_content(self):
        self.content_id = 'http://video.zeit.de/video/1234'

    def test_layout_should_be_editable(self):
        article = self.get_article(with_empty_block=True)
        self.browser.open(self.contents_url)
        self.browser.getLink('Edit').click()
        self.assertEqual(
            ['(no value)', 'small', 'with info', 'large', 'double'],
            self.browser.getControl('Layout').displayOptions)
        self.browser.getControl('Layout').displayValue = ['large']
        self.browser.getControl('Apply').click()
        self.assert_ellipsis("<...self.close()...")
        # The layout is used as a css-class:
        self.browser.open(self.contents_url)
        self.assert_ellipsis(
            """...<div ...class="large ...""")

    def test_two_videos_should_be_editable(self):
        article = self.get_article(with_empty_block=True)
        self.browser.open(self.contents_url)
        self.browser.getLink('Edit').click()
        self.browser.getControl('Video', index=0).value = (
            'http://video.zeit.de/video/1234')
        self.browser.getControl('Video 2').value = (
            'http://video.zeit.de/video/6789')
        self.browser.getControl('Apply').click()
        self.assert_ellipsis("<...self.close()...")
        self.browser.open(self.contents_url)
        self.assert_ellipsis(
            """...
               ......""")
<|endoftext|>


<commit_before>##############################################################################
# Copyright (c) 2013-2016, Lawrence Livermore National Security, LLC.
# Produced at the Lawrence Livermore National Laboratory.
#
# This file is part of Spack.
# Created by Todd Gamblin, tgamblin@llnl.gov, All rights reserved.
# LLNL-CODE-647188
#
# For details, see https://github.com/llnl/spack
# Please also see the LICENSE file for our notice and the LGPL.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License (as
# published by the Free Software Foundation) version 2.1, February 1999.
#
# 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 terms and
# conditions of the GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
##############################################################################
import os
import shutil
import glob
import llnl.util.tty as tty
from spack import *

# - vanilla CentOS 7, and possibly other systems, fail a test:
#   TestCloneNEWUSERAndRemapRootDisableSetgroups
#
#   The Fix, discussed here: https://github.com/golang/go/issues/16283
#   is to enable "user_namespace".
#
#   On a Digital Ocean image, this can be achieved by updating
#   `/etc/default/grub` so that the `GRUB_CMDLINE_LINUX` variable
#   includes `user_namespace.enable=1`, re-cooking the grub
#   configuration with `sudo grub2-mkconfig -o /boot/grub2/grub.cfg`,
#   and then rebooting.
#
# - on CentOS 7 systems (and possibly others) you need to have the
#   glibc package installed or various static cgo tests fail.
#
# - When building on a *large* machine (144 cores, 1.5TB RAM) I need
#   to run `ulimit -u 8192` to bump up the max number of user processes.
#   Failure to do so results in an explosion in one of the tests and an
#   epic stack trace....

class Go(Package):
    """The golang compiler and build environment"""
    homepage = "https://golang.org"
    url = 'https://storage.googleapis.com/golang/go1.7.4.src.tar.gz'

    extendable = True

    version('1.7.5', '506de2d870409e9003e1440bcfeb3a65')
    version('1.7.4', '49c1076428a5d3b5ad7ac65233fcca2f')
    version('1.6.4', 'b023240be707b34059d2c114d3465c92')

    variant('test', default=True, description='Build and run tests as part of the build.')

    provides('golang')

    depends_on('git', type=('build', 'link', 'run'))
    # TODO: Make non-c self-hosting compilers feasible without backflips
    # should be a dep on external go compiler
    depends_on('go-bootstrap', type='build')

    # https://github.com/golang/go/issues/17545
    patch('time_test.patch', when='@1.6.4:1.7.4')

    # https://github.com/golang/go/issues/17986
    patch('misc-cgo-testcshared.patch', level=0, when='@1.6.4:1.7.5')

    # NOTE: Older versions of Go attempt to download external files that have
    # since been moved while running the test suite.  This patch modifies the
    # test files so that these tests don't cause false failures.
    # See: https://github.com/golang/go/issues/15694
    @when('@:1.4.3')
    def patch(self):
        test_suite_file = FileFilter(join_path('src', 'run.bash'))
        test_suite_file.filter(
            r'^(.*)(\$GOROOT/src/cmd/api/run.go)(.*)$',
            r'# \1\2\3',
        )

    @when('@1.5.0:')
    def patch(self):
        pass

    def url_for_version(self, version):
        return "https://storage.googleapis.com/golang/go{0}.src.tar.gz".format(version)

    def install(self, spec, prefix):
        bash = which('bash')
        with working_dir('src'):
            bash('{0}.bash'.format('all' if '+test' in spec else 'make'))

        try:
            os.makedirs(prefix)
        except OSError:
            pass
        for f in glob.glob('*'):
            if os.path.isdir(f):
                shutil.copytree(f, os.path.join(prefix, f))
            else:
                shutil.copy2(f, os.path.join(prefix, f))

    def setup_environment(self, spack_env, run_env):
        spack_env.set('GOROOT_FINAL', self.spec.prefix)

    def setup_dependent_package(self, module, ext_spec):
        """Called before go modules' install() methods.

        In most cases, extensions will only need to set GOPATH and use go::

        env = os.environ
        env['GOPATH'] = self.source_path + ':' + env['GOPATH']
        go('get', '<package>', env=env)
        shutil.copytree('bin', os.path.join(prefix, '/bin'))
        """
        #  Add a go command/compiler for extensions
        module.go = Executable(join_path(self.spec.prefix.bin, 'go'))

    def setup_dependent_environment(self, spack_env, run_env, ext_spec):
        if os.environ.get('GOROOT', False):
            tty.warn('GOROOT is set, this is not recommended')

        path_components = []
        # Set GOPATH to include paths of dependencies
        for d in ext_spec.traverse():
            if d.package.extends(self.spec):
                path_components.append(d.prefix)

        # This *MUST* be first, this is where new code is installed
        spack_env.set('GOPATH', ':'.join(path_components))

        # Allow packages to find this when using module or dotkit
        run_env.prepend_path('GOPATH', ':'.join(
            [ext_spec.prefix] + path_components))
<commit_msg>Add comment explaining why patch is still needed (#3054)<commit_after>##############################################################################
# Copyright (c) 2013-2016, Lawrence Livermore National Security, LLC.
# Produced at the Lawrence Livermore National Laboratory.
#
# This file is part of Spack.
# Created by Todd Gamblin, tgamblin@llnl.gov, All rights reserved.
# LLNL-CODE-647188
#
# For details, see https://github.com/llnl/spack
# Please also see the LICENSE file for our notice and the LGPL.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License (as
# published by the Free Software Foundation) version 2.1, February 1999.
#
# 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 terms and
# conditions of the GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
##############################################################################
import os
import shutil
import glob
import llnl.util.tty as tty
from spack import *

# - vanilla CentOS 7, and possibly other systems, fail a test:
#   TestCloneNEWUSERAndRemapRootDisableSetgroups
#
#   The Fix, discussed here: https://github.com/golang/go/issues/16283
#   is to enable "user_namespace".
#
#   On a Digital Ocean image, this can be achieved by updating
#   `/etc/default/grub` so that the `GRUB_CMDLINE_LINUX` variable
#   includes `user_namespace.enable=1`, re-cooking the grub
#   configuration with `sudo grub2-mkconfig -o /boot/grub2/grub.cfg`,
#   and then rebooting.
#
# - on CentOS 7 systems (and possibly others) you need to have the
#   glibc package installed or various static cgo tests fail.
#
# - When building on a *large* machine (144 cores, 1.5TB RAM) I need
#   to run `ulimit -u 8192` to bump up the max number of user processes.
#   Failure to do so results in an explosion in one of the tests and an
#   epic stack trace....

class Go(Package):
    """The golang compiler and build environment"""
    homepage = "https://golang.org"
    url = 'https://storage.googleapis.com/golang/go1.7.4.src.tar.gz'

    extendable = True

    version('1.7.5', '506de2d870409e9003e1440bcfeb3a65')
    version('1.7.4', '49c1076428a5d3b5ad7ac65233fcca2f')
    version('1.6.4', 'b023240be707b34059d2c114d3465c92')

    variant('test', default=True, description='Build and run tests as part of the build.')

    provides('golang')

    depends_on('git', type=('build', 'link', 'run'))
    # TODO: Make non-c self-hosting compilers feasible without backflips
    # should be a dep on external go compiler
    depends_on('go-bootstrap', type='build')

    # https://github.com/golang/go/issues/17545
    patch('time_test.patch', when='@1.6.4:1.7.4')

    # https://github.com/golang/go/issues/17986
    # The fix for this issue has been merged into the 1.8 tree.
    patch('misc-cgo-testcshared.patch', level=0, when='@1.6.4:1.7.5')

    # NOTE: Older versions of Go attempt to download external files that have
    # since been moved while running the test suite.  This patch modifies the
    # test files so that these tests don't cause false failures.
    # See: https://github.com/golang/go/issues/15694
    @when('@:1.4.3')
    def patch(self):
        test_suite_file = FileFilter(join_path('src', 'run.bash'))
        test_suite_file.filter(
            r'^(.*)(\$GOROOT/src/cmd/api/run.go)(.*)$',
            r'# \1\2\3',
        )

    @when('@1.5.0:')
    def patch(self):
        pass

    def url_for_version(self, version):
        return "https://storage.googleapis.com/golang/go{0}.src.tar.gz".format(version)

    def install(self, spec, prefix):
        bash = which('bash')
        with working_dir('src'):
            bash('{0}.bash'.format('all' if '+test' in spec else 'make'))

        try:
            os.makedirs(prefix)
        except OSError:
            pass
        for f in glob.glob('*'):
            if os.path.isdir(f):
                shutil.copytree(f, os.path.join(prefix, f))
            else:
                shutil.copy2(f, os.path.join(prefix, f))

    def setup_environment(self, spack_env, run_env):
        spack_env.set('GOROOT_FINAL', self.spec.prefix)

    def setup_dependent_package(self, module, ext_spec):
        """Called before go modules' install() methods.

        In most cases, extensions will only need to set GOPATH and use go::

        env = os.environ
        env['GOPATH'] = self.source_path + ':' + env['GOPATH']
        go('get', '<package>', env=env)
        shutil.copytree('bin', os.path.join(prefix, '/bin'))
        """
        #  Add a go command/compiler for extensions
        module.go = Executable(join_path(self.spec.prefix.bin, 'go'))

    def setup_dependent_environment(self, spack_env, run_env, ext_spec):
        if os.environ.get('GOROOT', False):
            tty.warn('GOROOT is set, this is not recommended')

        path_components = []
        # Set GOPATH to include paths of dependencies
        for d in ext_spec.traverse():
            if d.package.extends(self.spec):
                path_components.append(d.prefix)

        # This *MUST* be first, this is where new code is installed
        spack_env.set('GOPATH', ':'.join(path_components))

        # Allow packages to find this when using module or dotkit
        run_env.prepend_path('GOPATH', ':'.join(
            [ext_spec.prefix] + path_components))
<|endoftext|>