<commit_before>"""
Topographica Bitmap Class.

Encapsulates the PIL Image class so that an input matrix can be displayed
as a bitmap image without needing to know about PIL proper.

There are three different base image Classes which inherit Bitmap:

PaletteBitmap  - 1 2D Matrix, 1 1D Color Map
HSVBitmap    - 3 2D Matrices, Color (H), Confidence (S), Strength (V)
RGBBitmap    - 3 2D Matrices, Red, Green, Blue Channels.

All maps are assumed to be on a nominal range of 0.0 to 1.0.  Matrices
are passed in as part of the constructor and the image is generaed.
For more information, see the documentation for each of the Bitmap
classes.

The encapsulated PIL Image is accessible through the .bitmap attribute.

$Id$
"""
__version__='$Revision$'

from copy import copy

from colorsys import hsv_to_rgb

import numpy.oldnumeric as Numeric, Image, ImageDraw, math, ImageFont, os
from topo.base.parameterclasses import ListParameter,Integer,CompositeParameter,DictParameter
from topo.base.parameterclasses import NumericTuple
from topo.base.parameterizedobject import ParameterizedObject
from topo.misc.filepaths import application_path

TITLE_FONT = ImageFont.truetype(os.path.join(application_path,'lib/python2.5/site-packages/matplotlib/mpl-data/fonts/ttf/Vera.ttf'),20)

### JCALERT: To do:
###        - Update the test file.
###        - Write PaletteBitmap when the Palette class is fixed
###        - Get rid of accessing function (copy, show...) (should we really?)

class Bitmap(ParameterizedObject):
    """
    Wrapper class for the PIL Image class.

    The main purpose for this base class is to provide a consistent
    interface for defining bitmaps constructed in various different
    ways.  The resulting bitmap is a PIL Image object that can be
    accessed using the normal PIL interface.

    If subclasses use the _arrayToImage() function provided, any
    pixels larger than the maximum that can be displayed will
    be counted before they are clipped; these are stored in the
    clipped_pixels attribute.
    """
    clipped_pixels = 0

    def __init__(self,image):
        self.image = image

    def __copy__(self):
        # avoid calling __getstate__ for copy (not required)
        image = self.image.copy()
        return Bitmap(image)

    # CB: could define a __deepcopy__ too, but we don't need
    # deepcopy to be fast.

    def __getstate__(self):
        """
        Return the object's state (as in the superclass), but replace
        the 'image' attribute's Image with a string representation.
        """
        state = super(Bitmap,self).__getstate__()
        import StringIO
        f = StringIO.StringIO()
        image = state['image']
        image.save(f,format=image.format or 'TIFF') # format could be None (we should probably just not save in that case)
        state['image'] = f.getvalue()
        f.close()

        return state

    def __setstate__(self,state):
        """
        Load the object's state (as in the superclass), but replace
        the 'image' string with an actual Image object.
        """
        import StringIO
        state['image'] = Image.open(StringIO.StringIO(state['image']))
        super(Bitmap,self).__setstate__(state)

    def show(self):
        """
        Renaming of Image.show() for the Bitmap.bitmap attribute.
        """
        self.image.show()

    def width(self): return self.image.size[0]
    def height(self): return self.image.size[1]

    def zoom(self, factor):
        """
        Return a resized Image object, given the input 'factor'
        parameter.  1.0 is the same size, 2.0 is doubling the height
        and width, 0.5 is 1/2 the original size.  The original Image
        is not changed.
        """
        x,y = self.image.size
        zx, zy = int(x*factor), int(y*factor)
        return self.image.resize((zx,zy))

    def _arrayToImage(self, inArray):
        """
        Generate a 1-channel PIL Image from an array of values from 0 to 1.0.

        Values larger than 1.0 are clipped, after adding them to the total
        clipped_pixels.  Returns a one-channel (monochrome) Image.
        """

        # PIL 'L' Images use a range of 0 to 255, so we scale the
        # input array to match.  The pixels are scaled by 255, not
        # 256, so that 1.0 maps to fully white.
        max_pixel_value=255
        inArray = (Numeric.floor(inArray * max_pixel_value)).astype(Numeric.Int)

        # Clip any values that are still larger than max_pixel_value
        to_clip = (Numeric.greater(inArray.ravel(),max_pixel_value)).sum()
	if (to_clip>0):
            self.clipped_pixels = self.clipped_pixels + to_clip
	    inArray.clip(0,max_pixel_value,out=inArray)
	    self.verbose("Bitmap: clipped",to_clip,"image pixels that were out of range")

        r,c = inArray.shape
        # The size is (width,height), so we swap r and c:
        newImage = Image.new('L',(c,r),None)
        newImage.putdata(inArray.ravel())
        return newImage

class PaletteBitmap(Bitmap):
    """
    Bitmap constructed using a single 2D array.

    The image is monochrome by default, but more colorful images can
    be constructed by specifying a Palette.
    """

    def __init__(self,inArray,palette=None):
        """
        inArray should have values in the range from 0.0 to 1.0.

        Palette can be any color scale depending on the type of ColorMap
        desired.  Examples:

        [0,0,0 ... 255,255,255] = grayscale
        [0,0,0 ... 255,0,0] = grayscale but through a Red filter.

        The default palette is grayscale, with 0.0 mapping to black
        and 1.0 mapping to white.
        """
        ### JABALERT: Should accept a Palette class, not a data
        ### structure, unless for some reason we want to get rid of
        ### the Palette classes and always use data structures
        ### instead.
	### JC: not yet properly implemented anyway.
        max_pixel_value=255

        newImage = self._arrayToImage(inArray)
        if palette == None:
            palette = [i for i in range(max_pixel_value+1) for j in range(3)]
        newImage.putpalette(palette)
        newImage = newImage.convert('P')
        super(PaletteBitmap,self).__init__(newImage)

class HSVBitmap(Bitmap):
    """
    Bitmap constructed from 3 2D arrays, for hue, saturation, and value.

    The hue matrix determines the pixel colors.  The saturation matrix
    determines how strongly the pixels are saturated for each hue,
    i.e. how colorful the pixels appear.  The value matrix determines
    how bright each pixel is.

    An RGB image is constructed from the HSV matrices using
    hsv_to_rgb; the resulting image is of the same type that is
    constructed by RGBBitmap, and can be used in the same way.
    """

    def __init__(self,hue,sat,val):
        """Each matrix must be the same size, with values in the range 0.0 to 1.0."""
        shape = hue.shape # Assumed same as sat.shape and val.shape
        self.rmat = Numeric.zeros(shape,Numeric.Float)
        self.gmat = Numeric.zeros(shape,Numeric.Float)
        self.bmat = Numeric.zeros(shape,Numeric.Float)

        # Note: should someday file a feature request for PIL for them
        # to accept an image of type 'HSV', so that they will do this
        # conversion themselves, without us needing an explicit loop
        # here.  That should speed this up.
        ch = hue.clip(0.0,1.0)
        cs = sat.clip(0.0,1.0)
        cv = val.clip(0.0,1.0)

        for i in range(shape[0]):
            for j in range(shape[1]):
                r,g,b = hsv_to_rgb(ch[i,j],cs[i,j],cv[i,j])
                self.rmat[i,j] = r
                self.gmat[i,j] = g
                self.bmat[i,j] = b

        rImage = self._arrayToImage(self.rmat)
        gImage = self._arrayToImage(self.gmat)
        bImage = self._arrayToImage(self.bmat)

        super(HSVBitmap,self).__init__(Image.merge('RGB',(rImage,gImage,bImage)))

class RGBBitmap(Bitmap):
    """
    Bitmap constructed from three 2D arrays, for red, green, and blue.

    Each matrix is used as the corresponding channel of an RGB image.
    """

    def __init__(self,rMapArray,gMapArray,bMapArray):
        """Each matrix must be the same size, with values in the range 0.0 to 1.0."""
        rImage = self._arrayToImage(rMapArray)
        gImage = self._arrayToImage(gMapArray)
        bImage = self._arrayToImage(bMapArray)

        super(RGBBitmap,self).__init__(Image.merge('RGB',(rImage,gImage,bImage)))

class MontageBitmap(Bitmap):
    """
    A bitmap composed of tiles containing other bitmaps.

    Bitmaps are scaled to fit in the given tile size, and tiled
    right-to-left, top-to-bottom into the given number of rows and columns.
    """
    bitmaps = ListParameter(class_=Bitmap,doc="""
        The list of bitmaps to compose.""")

    rows = Integer(default=2, doc="""
        The number of rows in the montage.""")
    cols = Integer(default=2, doc="""
        The number of columns in the montage.""")
    shape = CompositeParameter(attribs=['rows','cols'], doc="""
        The shape of the montage. Same as (self.rows,self.cols).""")

    margin = Integer(default=5,doc="""
        The size in pixels of the margin to put around each
        tile in the montage.""")

    tile_size = NumericTuple(default=(100,100), doc="""
        The size in pixels of a tile in the montage.""")

    titles = ListParameter(class_=str, default=[], doc="""
        A list of titles to overlay on the tiles.""")

    title_pos = NumericTuple(default=(10,10), doc="""
        The position of the upper left corner of the title in each tile.""")

    title_options = DictParameter(default={}, doc="""
        Dictionary of options for drawing the titles.  Dict should
        contain keyword options for the PIL draw.text method.  Possible
        options include 'fill' (fill color), 'outline' (outline color),
        and 'font' (an ImageFont font instance).  The PIL defaults will
        be used for any omitted options.""",
        instantiate=False)

    hooks = ListParameter(default=[], doc="""
        A list of functions, one per tile, that take a PIL image as
        input and return a PIL image as output.  The hooks are applied
        to the tile images before resizing.  The value None can be
        inserted as a placeholder where no hook function is needed.""")

    resize_filter = Integer(default=Image.NEAREST,doc="""
       The filter used for resizing the images.  Defaults
       to NEAREST.  See PIL Image module documentation for other
       options and their meanings.""")

    bg_color = NumericTuple(default=(0,0,0), doc="""
       The background color for the montage, as (r,g,b).""")

    def __init__(self,**params):
        ## JPALERT: The Bitmap class is a Parameterized object,but its
        ## __init__ doesn't take **params and doesn't call super.__init__,
        ## so we have to skip it.
        ## JAB: Good point; Bitmap should be modified to be more like
        ## other PO classes.
        ParameterizedObject.__init__(self,**params)

        rows,cols = self.shape
        tilew,tileh = self.tile_size
        bgr,bgg,bgb = self.bg_color

        width  = tilew*cols + self.margin*(cols*2)
        height = tileh*rows + self.margin*(rows*2)
        self.image = Image.new('RGB',(width,height),
                               (bgr*255,bgg*255,bgb*255))

        self.title_options.setdefault('font',TITLE_FONT)

        for r in xrange(rows):
            for c in xrange(cols):
                i = r*self.cols+c
                if i < len(self.bitmaps):
                    bm = self.bitmaps[i]
                    bmw,bmh = bm.image.size
                    if bmw > bmh:
                        bmh = int( float(tilew)/bmw * bmh )
                        bmw = tilew
                    else:
                        bmw = int( float(tileh)/bmh * bmw )
                        bmh = tileh

                    if self.hooks and self.hooks[i]:
                        f = self.hooks[i]
                    else:
                        f = lambda x:x
                    new_bm = Bitmap(f(bm.image).resize((bmw,bmh)))
                    if self.titles:
                        draw = ImageDraw.Draw(new_bm.image)
                        draw.text(self.title_pos,self.titles[i],**self.title_options)
                    self.image.paste( new_bm.image,
                                      (c * width/cols + tilew/2 - bmw/2 + self.margin,
                                       r * height/rows + tileh/2 - bmh/2 + self.margin) )

                else:
                    break
<commit_msg>No need for rgb matrices to be class attributes, reverted back to be just local variables.<commit_after>"""
Topographica Bitmap Class.

Encapsulates the PIL Image class so that an input matrix can be displayed
as a bitmap image without needing to know about PIL proper.

There are three different base image Classes which inherit Bitmap:

PaletteBitmap  - 1 2D Matrix, 1 1D Color Map
HSVBitmap    - 3 2D Matrices, Color (H), Confidence (S), Strength (V)
RGBBitmap    - 3 2D Matrices, Red, Green, Blue Channels.

All maps are assumed to be on a nominal range of 0.0 to 1.0.  Matrices
are passed in as part of the constructor and the image is generaed.
For more information, see the documentation for each of the Bitmap
classes.

The encapsulated PIL Image is accessible through the .bitmap attribute.

$Id$
"""
__version__='$Revision$'

from copy import copy

from colorsys import hsv_to_rgb

import numpy.oldnumeric as Numeric, Image, ImageDraw, math, ImageFont, os
from topo.base.parameterclasses import ListParameter,Integer,CompositeParameter,DictParameter
from topo.base.parameterclasses import NumericTuple
from topo.base.parameterizedobject import ParameterizedObject
from topo.misc.filepaths import application_path

TITLE_FONT = ImageFont.truetype(os.path.join(application_path,'lib/python2.5/site-packages/matplotlib/mpl-data/fonts/ttf/Vera.ttf'),20)

### JCALERT: To do:
###        - Update the test file.
###        - Write PaletteBitmap when the Palette class is fixed
###        - Get rid of accessing function (copy, show...) (should we really?)

class Bitmap(ParameterizedObject):
    """
    Wrapper class for the PIL Image class.

    The main purpose for this base class is to provide a consistent
    interface for defining bitmaps constructed in various different
    ways.  The resulting bitmap is a PIL Image object that can be
    accessed using the normal PIL interface.

    If subclasses use the _arrayToImage() function provided, any
    pixels larger than the maximum that can be displayed will
    be counted before they are clipped; these are stored in the
    clipped_pixels attribute.
    """
    clipped_pixels = 0

    def __init__(self,image):
        self.image = image

    def __copy__(self):
        # avoid calling __getstate__ for copy (not required)
        image = self.image.copy()
        return Bitmap(image)

    # CB: could define a __deepcopy__ too, but we don't need
    # deepcopy to be fast.

    def __getstate__(self):
        """
        Return the object's state (as in the superclass), but replace
        the 'image' attribute's Image with a string representation.
        """
        state = super(Bitmap,self).__getstate__()
        import StringIO
        f = StringIO.StringIO()
        image = state['image']
        image.save(f,format=image.format or 'TIFF') # format could be None (we should probably just not save in that case)
        state['image'] = f.getvalue()
        f.close()

        return state

    def __setstate__(self,state):
        """
        Load the object's state (as in the superclass), but replace
        the 'image' string with an actual Image object.
        """
        import StringIO
        state['image'] = Image.open(StringIO.StringIO(state['image']))
        super(Bitmap,self).__setstate__(state)

    def show(self):
        """
        Renaming of Image.show() for the Bitmap.bitmap attribute.
        """
        self.image.show()

    def width(self): return self.image.size[0]
    def height(self): return self.image.size[1]

    def zoom(self, factor):
        """
        Return a resized Image object, given the input 'factor'
        parameter.  1.0 is the same size, 2.0 is doubling the height
        and width, 0.5 is 1/2 the original size.  The original Image
        is not changed.
        """
        x,y = self.image.size
        zx, zy = int(x*factor), int(y*factor)
        return self.image.resize((zx,zy))

    def _arrayToImage(self, inArray):
        """
        Generate a 1-channel PIL Image from an array of values from 0 to 1.0.

        Values larger than 1.0 are clipped, after adding them to the total
        clipped_pixels.  Returns a one-channel (monochrome) Image.
        """

        # PIL 'L' Images use a range of 0 to 255, so we scale the
        # input array to match.  The pixels are scaled by 255, not
        # 256, so that 1.0 maps to fully white.
        max_pixel_value=255
        inArray = (Numeric.floor(inArray * max_pixel_value)).astype(Numeric.Int)

        # Clip any values that are still larger than max_pixel_value
        to_clip = (Numeric.greater(inArray.ravel(),max_pixel_value)).sum()
	if (to_clip>0):
            self.clipped_pixels = self.clipped_pixels + to_clip
	    inArray.clip(0,max_pixel_value,out=inArray)
	    self.verbose("Bitmap: clipped",to_clip,"image pixels that were out of range")

        r,c = inArray.shape
        # The size is (width,height), so we swap r and c:
        newImage = Image.new('L',(c,r),None)
        newImage.putdata(inArray.ravel())
        return newImage

class PaletteBitmap(Bitmap):
    """
    Bitmap constructed using a single 2D array.

    The image is monochrome by default, but more colorful images can
    be constructed by specifying a Palette.
    """

    def __init__(self,inArray,palette=None):
        """
        inArray should have values in the range from 0.0 to 1.0.

        Palette can be any color scale depending on the type of ColorMap
        desired.  Examples:

        [0,0,0 ... 255,255,255] = grayscale
        [0,0,0 ... 255,0,0] = grayscale but through a Red filter.

        The default palette is grayscale, with 0.0 mapping to black
        and 1.0 mapping to white.
        """
        ### JABALERT: Should accept a Palette class, not a data
        ### structure, unless for some reason we want to get rid of
        ### the Palette classes and always use data structures
        ### instead.
	### JC: not yet properly implemented anyway.
        max_pixel_value=255

        newImage = self._arrayToImage(inArray)
        if palette == None:
            palette = [i for i in range(max_pixel_value+1) for j in range(3)]
        newImage.putpalette(palette)
        newImage = newImage.convert('P')
        super(PaletteBitmap,self).__init__(newImage)

class HSVBitmap(Bitmap):
    """
    Bitmap constructed from 3 2D arrays, for hue, saturation, and value.

    The hue matrix determines the pixel colors.  The saturation matrix
    determines how strongly the pixels are saturated for each hue,
    i.e. how colorful the pixels appear.  The value matrix determines
    how bright each pixel is.

    An RGB image is constructed from the HSV matrices using
    hsv_to_rgb; the resulting image is of the same type that is
    constructed by RGBBitmap, and can be used in the same way.
    """

    def __init__(self,hue,sat,val):
        """Each matrix must be the same size, with values in the range 0.0 to 1.0."""
        shape = hue.shape # Assumed same as sat.shape and val.shape
        rmat = Numeric.zeros(shape,Numeric.Float)
        gmat = Numeric.zeros(shape,Numeric.Float)
        bmat = Numeric.zeros(shape,Numeric.Float)

        # Note: should someday file a feature request for PIL for them
        # to accept an image of type 'HSV', so that they will do this
        # conversion themselves, without us needing an explicit loop
        # here.  That should speed this up.
        ch = hue.clip(0.0,1.0)
        cs = sat.clip(0.0,1.0)
        cv = val.clip(0.0,1.0)

        for i in range(shape[0]):
            for j in range(shape[1]):
                r,g,b = hsv_to_rgb(ch[i,j],cs[i,j],cv[i,j])
                rmat[i,j] = r
                gmat[i,j] = g
                bmat[i,j] = b

        rImage = self._arrayToImage(rmat)
        gImage = self._arrayToImage(gmat)
        bImage = self._arrayToImage(bmat)

        super(HSVBitmap,self).__init__(Image.merge('RGB',(rImage,gImage,bImage)))

class RGBBitmap(Bitmap):
    """
    Bitmap constructed from three 2D arrays, for red, green, and blue.

    Each matrix is used as the corresponding channel of an RGB image.
    """

    def __init__(self,rMapArray,gMapArray,bMapArray):
        """Each matrix must be the same size, with values in the range 0.0 to 1.0."""
        rImage = self._arrayToImage(rMapArray)
        gImage = self._arrayToImage(gMapArray)
        bImage = self._arrayToImage(bMapArray)

        super(RGBBitmap,self).__init__(Image.merge('RGB',(rImage,gImage,bImage)))

class MontageBitmap(Bitmap):
    """
    A bitmap composed of tiles containing other bitmaps.

    Bitmaps are scaled to fit in the given tile size, and tiled
    right-to-left, top-to-bottom into the given number of rows and columns.
    """
    bitmaps = ListParameter(class_=Bitmap,doc="""
        The list of bitmaps to compose.""")

    rows = Integer(default=2, doc="""
        The number of rows in the montage.""")
    cols = Integer(default=2, doc="""
        The number of columns in the montage.""")
    shape = CompositeParameter(attribs=['rows','cols'], doc="""
        The shape of the montage. Same as (self.rows,self.cols).""")

    margin = Integer(default=5,doc="""
        The size in pixels of the margin to put around each
        tile in the montage.""")

    tile_size = NumericTuple(default=(100,100), doc="""
        The size in pixels of a tile in the montage.""")

    titles = ListParameter(class_=str, default=[], doc="""
        A list of titles to overlay on the tiles.""")

    title_pos = NumericTuple(default=(10,10), doc="""
        The position of the upper left corner of the title in each tile.""")

    title_options = DictParameter(default={}, doc="""
        Dictionary of options for drawing the titles.  Dict should
        contain keyword options for the PIL draw.text method.  Possible
        options include 'fill' (fill color), 'outline' (outline color),
        and 'font' (an ImageFont font instance).  The PIL defaults will
        be used for any omitted options.""",
        instantiate=False)

    hooks = ListParameter(default=[], doc="""
        A list of functions, one per tile, that take a PIL image as
        input and return a PIL image as output.  The hooks are applied
        to the tile images before resizing.  The value None can be
        inserted as a placeholder where no hook function is needed.""")

    resize_filter = Integer(default=Image.NEAREST,doc="""
       The filter used for resizing the images.  Defaults
       to NEAREST.  See PIL Image module documentation for other
       options and their meanings.""")

    bg_color = NumericTuple(default=(0,0,0), doc="""
       The background color for the montage, as (r,g,b).""")

    def __init__(self,**params):
        ## JPALERT: The Bitmap class is a Parameterized object,but its
        ## __init__ doesn't take **params and doesn't call super.__init__,
        ## so we have to skip it.
        ## JAB: Good point; Bitmap should be modified to be more like
        ## other PO classes.
        ParameterizedObject.__init__(self,**params)

        rows,cols = self.shape
        tilew,tileh = self.tile_size
        bgr,bgg,bgb = self.bg_color

        width  = tilew*cols + self.margin*(cols*2)
        height = tileh*rows + self.margin*(rows*2)
        self.image = Image.new('RGB',(width,height),
                               (bgr*255,bgg*255,bgb*255))

        self.title_options.setdefault('font',TITLE_FONT)

        for r in xrange(rows):
            for c in xrange(cols):
                i = r*self.cols+c
                if i < len(self.bitmaps):
                    bm = self.bitmaps[i]
                    bmw,bmh = bm.image.size
                    if bmw > bmh:
                        bmh = int( float(tilew)/bmw * bmh )
                        bmw = tilew
                    else:
                        bmw = int( float(tileh)/bmh * bmw )
                        bmh = tileh

                    if self.hooks and self.hooks[i]:
                        f = self.hooks[i]
                    else:
                        f = lambda x:x
                    new_bm = Bitmap(f(bm.image).resize((bmw,bmh)))
                    if self.titles:
                        draw = ImageDraw.Draw(new_bm.image)
                        draw.text(self.title_pos,self.titles[i],**self.title_options)
                    self.image.paste( new_bm.image,
                                      (c * width/cols + tilew/2 - bmw/2 + self.margin,
                                       r * height/rows + tileh/2 - bmh/2 + self.margin) )

                else:
                    break
<|endoftext|>


<commit_before>## This file is part of Scapy
## See http://www.secdev.org/projects/scapy for more informations
## Copyright (C) Philippe Biondi <phil@secdev.org>
## This program is published under a GPLv2 license

## Copyright (C) 2005  Guillaume Valadon <guedou@hongo.wide.ad.jp>
##                     Arnaud Ebalard <arnaud.ebalard@eads.net>

#############################################################################
#############################################################################
###                      Routing/Interfaces stuff                         ###
#############################################################################
#############################################################################

import socket
from config import conf
from utils6 import *
from arch import *

class Route6:

    def __init__(self):
        self.invalidate_cache()
        self.resync()

    def invalidate_cache(self):
        self.cache = {}

    def flush(self):
        self.invalidate_cache()
        self.routes = []

    def resync(self):
        # TODO : At the moment, resync will drop existing Teredo routes
        #        if any. Change that ...
        self.invalidate_cache()
	self.routes = read_routes6()
	if self.routes == []:
	     log_loading.info("No IPv6 support in kernel")

    def __repr__(self):
        rtlst = [('Destination', 'Next Hop', "iface", "src candidates")]

        for net,msk,gw,iface,cset in self.routes:
	    rtlst.append(('%s/%i'% (net,msk), gw, iface, ", ".join(cset)))

        colwidth = map(lambda x: max(map(lambda y: len(y), x)), apply(zip, rtlst))
        fmt = "  ".join(map(lambda x: "%%-%ds"%x, colwidth))
        rt = "\n".join(map(lambda x: fmt % x, rtlst))

        return rt

    # Unlike Scapy's Route.make_route() function, we do not have 'host' and 'net'
    # parameters. We only have a 'dst' parameter that accepts 'prefix' and
    # 'prefix/prefixlen' values.
    # WARNING: Providing a specific device will at the moment not work correctly.
    def make_route(self, dst, gw=None, dev=None):
        """Internal function : create a route for 'dst' via 'gw'.
        """
        prefix, plen = (dst.split("/")+["128"])[:2]
        plen = int(plen)

        if gw is None:
            gw = "::"
        if dev is None:
            dev, ifaddr, x = self.route(gw)
        else:
            # TODO: do better than that
            # replace that unique address by the list of all addresses
            lifaddr = in6_getifaddr()
            devaddrs = filter(lambda x: x[2] == dev, lifaddr)
            ifaddr = construct_source_candidate_set(prefix, plen, devaddrs)

        return (prefix, plen, gw, dev, ifaddr)

    def add(self, *args, **kargs):
        """Ex:
        add(dst="2001:db8:cafe:f000::/56")
        add(dst="2001:db8:cafe:f000::/56", gw="2001:db8:cafe::1")
        add(dst="2001:db8:cafe:f000::/64", gw="2001:db8:cafe::1", dev="eth0")
        """
        self.invalidate_cache()
        self.routes.append(self.make_route(*args, **kargs))

    def delt(self, dst, gw=None):
        """ Ex:
        delt(dst="::/0")
        delt(dst="2001:db8:cafe:f000::/56")
        delt(dst="2001:db8:cafe:f000::/56", gw="2001:db8:deca::1")
        """
        tmp = dst+"/128"
        dst, plen = tmp.split('/')[:2]
        dst = in6_ptop(dst)
        plen = int(plen)
        l = filter(lambda x: in6_ptop(x[0]) == dst and x[1] == plen, self.routes)
        if gw:
            gw = in6_ptop(gw)
            l = filter(lambda x: in6_ptop(x[0]) == gw, self.routes)
        if len(l) == 0:
            warning("No matching route found")
        elif len(l) > 1:
            warning("Found more than one match. Aborting.")
        else:
            i=self.routes.index(l[0])
            self.invalidate_cache()
            del(self.routes[i])

    def ifchange(self, iff, addr):
        the_addr, the_plen = (addr.split("/")+["128"])[:2]
        the_plen = int(the_plen)

        naddr = inet_pton(socket.AF_INET6, the_addr)
        nmask = in6_cidr2mask(the_plen)
        the_net = inet_ntop(socket.AF_INET6, in6_and(nmask,naddr))

        for i in range(len(self.routes)):
            net,plen,gw,iface,addr = self.routes[i]
            if iface != iff:
                continue
            if gw == '::':
                self.routes[i] = (the_net,the_plen,gw,iface,the_addr)
            else:
                self.routes[i] = (net,the_plen,gw,iface,the_addr)
        self.invalidate_cache()
        ip6_neigh_cache.flush()

    def ifdel(self, iff):
        """ removes all route entries that uses 'iff' interface. """
        new_routes=[]
        for rt in self.routes:
            if rt[3] != iff:
                new_routes.append(rt)
        self.invalidate_cache()
        self.routes = new_routes

    def ifadd(self, iff, addr):
        """
        Add an interface 'iff' with provided address into routing table.

        Ex: ifadd('eth0', '2001:bd8:cafe:1::1/64') will add following entry into
            Scapy6 internal routing table:

            Destination           Next Hop  iface  Def src @
            2001:bd8:cafe:1::/64  ::        eth0   2001:bd8:cafe:1::1

            prefix length value can be omitted. In that case, a value of 128
            will be used.
        """
        addr, plen = (addr.split("/")+["128"])[:2]
        addr = in6_ptop(addr)
        plen = int(plen)
        naddr = inet_pton(socket.AF_INET6, addr)
        nmask = in6_cidr2mask(plen)
        prefix = inet_ntop(socket.AF_INET6, in6_and(nmask,naddr))
        self.invalidate_cache()
        self.routes.append((prefix,plen,'::',iff,[addr]))

    def route(self, dst, dev=None):
        """
        Provide best route to IPv6 destination address, based on Scapy6
        internal routing table content.

        When a set of address is passed (e.g. 2001:db8:cafe:*::1-5) an address
        of the set is used. Be aware of that behavior when using wildcards in
        upper parts of addresses !

        If 'dst' parameter is a FQDN, name resolution is performed and result
        is used.

        if optional 'dev' parameter is provided a specific interface, filtering
        is performed to limit search to route associated to that interface.
        """
        # Transform "2001:db8:cafe:*::1-5:0/120" to one IPv6 address of the set
        dst = dst.split("/")[0]
        savedst = dst # In case following inet_pton() fails
        dst = dst.replace("*","0")
        l = dst.find("-")
        while l >= 0:
            m = (dst[l:]+":").find(":")
            dst = dst[:l]+dst[l+m:]
            l = dst.find("-")

        try:
            inet_pton(socket.AF_INET6, dst)
        except socket.error:
            dst = socket.getaddrinfo(savedst, None, socket.AF_INET6)[0][-1][0]
            # TODO : Check if name resolution went well

        # Deal with dev-specific request for cache search
        k = dst
        if dev is not None:
            k = dst + "%%" + dev
        if k in self.cache:
            return self.cache[k]

        pathes = []

        # TODO : review all kinds of addresses (scope and *cast) to see
        #        if we are able to cope with everything possible. I'm convinced
        #        it's not the case.
        # -- arnaud
        for p, plen, gw, iface, cset in self.routes:
            if dev is not None and iface != dev:
                continue
            if in6_isincluded(dst, p, plen):
                pathes.append((plen, (iface, cset, gw)))
            elif (in6_ismlladdr(dst) and in6_islladdr(p) and in6_islladdr(cset[0])):
                pathes.append((plen, (iface, cset, gw)))

        if not pathes:
            warning("No route found for IPv6 destination %s (no default route?)" % dst)
            return (LOOPBACK_NAME, "::", "::") # XXX Linux specific

        pathes.sort()
        pathes.reverse()

        best_plen = pathes[0][0]
        pathes = filter(lambda x: x[0] == best_plen, pathes)

        res = []
        for p in pathes: # Here we select best source address for every route
            tmp = p[1]
            srcaddr = get_source_addr_from_candidate_set(dst, p[1][1])
            if srcaddr is not None:
                res.append((p[0], (tmp[0], srcaddr, tmp[2])))

        # Symptom  : 2 routes with same weight (our weight is plen)
        # Solution :
        #  - dst is unicast global. Check if it is 6to4 and we have a source
        #    6to4 address in those available
        #  - dst is link local (unicast or multicast) and multiple output
        #    interfaces are available. Take main one (conf.iface6)
        #  - if none of the previous or ambiguity persists, be lazy and keep
        #    first one
        #  XXX TODO : in a _near_ future, include metric in the game

        if len(res) > 1:
            tmp = []
            if in6_isgladdr(dst) and in6_isaddr6to4(dst):
                # TODO : see if taking the longest match between dst and
                #        every source addresses would provide better results
                tmp = filter(lambda x: in6_isaddr6to4(x[1][1]), res)
            elif in6_ismaddr(dst) or in6_islladdr(dst):
                # TODO : I'm sure we are not covering all addresses. Check that
                tmp = filter(lambda x: x[1][0] == conf.iface6, res)

            if tmp:
                res = tmp

        # Fill the cache (including dev-specific request)
        k = dst
        if dev is not None:
            k = dst + "%%" + dev
        self.cache[k] = res[0][1]

        return res[0][1]

conf.route6 = Route6()

_res = conf.route6.route("::/0")
if _res:
    iff, gw, addr = _res
    conf.iface6 = iff
del(_res)

<commit_msg>Fixed missing argument to construct_source_candidate_set() (ticket #185)<commit_after>## This file is part of Scapy
## See http://www.secdev.org/projects/scapy for more informations
## Copyright (C) Philippe Biondi <phil@secdev.org>
## This program is published under a GPLv2 license

## Copyright (C) 2005  Guillaume Valadon <guedou@hongo.wide.ad.jp>
##                     Arnaud Ebalard <arnaud.ebalard@eads.net>

#############################################################################
#############################################################################
###                      Routing/Interfaces stuff                         ###
#############################################################################
#############################################################################

import socket
from config import conf
from utils6 import *
from arch import *

class Route6:

    def __init__(self):
        self.invalidate_cache()
        self.resync()

    def invalidate_cache(self):
        self.cache = {}

    def flush(self):
        self.invalidate_cache()
        self.routes = []

    def resync(self):
        # TODO : At the moment, resync will drop existing Teredo routes
        #        if any. Change that ...
        self.invalidate_cache()
	self.routes = read_routes6()
	if self.routes == []:
	     log_loading.info("No IPv6 support in kernel")

    def __repr__(self):
        rtlst = [('Destination', 'Next Hop', "iface", "src candidates")]

        for net,msk,gw,iface,cset in self.routes:
	    rtlst.append(('%s/%i'% (net,msk), gw, iface, ", ".join(cset)))

        colwidth = map(lambda x: max(map(lambda y: len(y), x)), apply(zip, rtlst))
        fmt = "  ".join(map(lambda x: "%%-%ds"%x, colwidth))
        rt = "\n".join(map(lambda x: fmt % x, rtlst))

        return rt

    # Unlike Scapy's Route.make_route() function, we do not have 'host' and 'net'
    # parameters. We only have a 'dst' parameter that accepts 'prefix' and
    # 'prefix/prefixlen' values.
    # WARNING: Providing a specific device will at the moment not work correctly.
    def make_route(self, dst, gw=None, dev=None):
        """Internal function : create a route for 'dst' via 'gw'.
        """
        prefix, plen = (dst.split("/")+["128"])[:2]
        plen = int(plen)

        if gw is None:
            gw = "::"
        if dev is None:
            dev, ifaddr, x = self.route(gw)
        else:
            # TODO: do better than that
            # replace that unique address by the list of all addresses
            lifaddr = in6_getifaddr()
            devaddrs = filter(lambda x: x[2] == dev, lifaddr)
            ifaddr = construct_source_candidate_set(prefix, plen, devaddrs, LOOPBACK_NAME)

        return (prefix, plen, gw, dev, ifaddr)

    def add(self, *args, **kargs):
        """Ex:
        add(dst="2001:db8:cafe:f000::/56")
        add(dst="2001:db8:cafe:f000::/56", gw="2001:db8:cafe::1")
        add(dst="2001:db8:cafe:f000::/64", gw="2001:db8:cafe::1", dev="eth0")
        """
        self.invalidate_cache()
        self.routes.append(self.make_route(*args, **kargs))

    def delt(self, dst, gw=None):
        """ Ex:
        delt(dst="::/0")
        delt(dst="2001:db8:cafe:f000::/56")
        delt(dst="2001:db8:cafe:f000::/56", gw="2001:db8:deca::1")
        """
        tmp = dst+"/128"
        dst, plen = tmp.split('/')[:2]
        dst = in6_ptop(dst)
        plen = int(plen)
        l = filter(lambda x: in6_ptop(x[0]) == dst and x[1] == plen, self.routes)
        if gw:
            gw = in6_ptop(gw)
            l = filter(lambda x: in6_ptop(x[0]) == gw, self.routes)
        if len(l) == 0:
            warning("No matching route found")
        elif len(l) > 1:
            warning("Found more than one match. Aborting.")
        else:
            i=self.routes.index(l[0])
            self.invalidate_cache()
            del(self.routes[i])

    def ifchange(self, iff, addr):
        the_addr, the_plen = (addr.split("/")+["128"])[:2]
        the_plen = int(the_plen)

        naddr = inet_pton(socket.AF_INET6, the_addr)
        nmask = in6_cidr2mask(the_plen)
        the_net = inet_ntop(socket.AF_INET6, in6_and(nmask,naddr))

        for i in range(len(self.routes)):
            net,plen,gw,iface,addr = self.routes[i]
            if iface != iff:
                continue
            if gw == '::':
                self.routes[i] = (the_net,the_plen,gw,iface,the_addr)
            else:
                self.routes[i] = (net,the_plen,gw,iface,the_addr)
        self.invalidate_cache()
        ip6_neigh_cache.flush()

    def ifdel(self, iff):
        """ removes all route entries that uses 'iff' interface. """
        new_routes=[]
        for rt in self.routes:
            if rt[3] != iff:
                new_routes.append(rt)
        self.invalidate_cache()
        self.routes = new_routes

    def ifadd(self, iff, addr):
        """
        Add an interface 'iff' with provided address into routing table.

        Ex: ifadd('eth0', '2001:bd8:cafe:1::1/64') will add following entry into
            Scapy6 internal routing table:

            Destination           Next Hop  iface  Def src @
            2001:bd8:cafe:1::/64  ::        eth0   2001:bd8:cafe:1::1

            prefix length value can be omitted. In that case, a value of 128
            will be used.
        """
        addr, plen = (addr.split("/")+["128"])[:2]
        addr = in6_ptop(addr)
        plen = int(plen)
        naddr = inet_pton(socket.AF_INET6, addr)
        nmask = in6_cidr2mask(plen)
        prefix = inet_ntop(socket.AF_INET6, in6_and(nmask,naddr))
        self.invalidate_cache()
        self.routes.append((prefix,plen,'::',iff,[addr]))

    def route(self, dst, dev=None):
        """
        Provide best route to IPv6 destination address, based on Scapy6
        internal routing table content.

        When a set of address is passed (e.g. 2001:db8:cafe:*::1-5) an address
        of the set is used. Be aware of that behavior when using wildcards in
        upper parts of addresses !

        If 'dst' parameter is a FQDN, name resolution is performed and result
        is used.

        if optional 'dev' parameter is provided a specific interface, filtering
        is performed to limit search to route associated to that interface.
        """
        # Transform "2001:db8:cafe:*::1-5:0/120" to one IPv6 address of the set
        dst = dst.split("/")[0]
        savedst = dst # In case following inet_pton() fails
        dst = dst.replace("*","0")
        l = dst.find("-")
        while l >= 0:
            m = (dst[l:]+":").find(":")
            dst = dst[:l]+dst[l+m:]
            l = dst.find("-")

        try:
            inet_pton(socket.AF_INET6, dst)
        except socket.error:
            dst = socket.getaddrinfo(savedst, None, socket.AF_INET6)[0][-1][0]
            # TODO : Check if name resolution went well

        # Deal with dev-specific request for cache search
        k = dst
        if dev is not None:
            k = dst + "%%" + dev
        if k in self.cache:
            return self.cache[k]

        pathes = []

        # TODO : review all kinds of addresses (scope and *cast) to see
        #        if we are able to cope with everything possible. I'm convinced
        #        it's not the case.
        # -- arnaud
        for p, plen, gw, iface, cset in self.routes:
            if dev is not None and iface != dev:
                continue
            if in6_isincluded(dst, p, plen):
                pathes.append((plen, (iface, cset, gw)))
            elif (in6_ismlladdr(dst) and in6_islladdr(p) and in6_islladdr(cset[0])):
                pathes.append((plen, (iface, cset, gw)))

        if not pathes:
            warning("No route found for IPv6 destination %s (no default route?)" % dst)
            return (LOOPBACK_NAME, "::", "::") # XXX Linux specific

        pathes.sort()
        pathes.reverse()

        best_plen = pathes[0][0]
        pathes = filter(lambda x: x[0] == best_plen, pathes)

        res = []
        for p in pathes: # Here we select best source address for every route
            tmp = p[1]
            srcaddr = get_source_addr_from_candidate_set(dst, p[1][1])
            if srcaddr is not None:
                res.append((p[0], (tmp[0], srcaddr, tmp[2])))

        # Symptom  : 2 routes with same weight (our weight is plen)
        # Solution :
        #  - dst is unicast global. Check if it is 6to4 and we have a source
        #    6to4 address in those available
        #  - dst is link local (unicast or multicast) and multiple output
        #    interfaces are available. Take main one (conf.iface6)
        #  - if none of the previous or ambiguity persists, be lazy and keep
        #    first one
        #  XXX TODO : in a _near_ future, include metric in the game

        if len(res) > 1:
            tmp = []
            if in6_isgladdr(dst) and in6_isaddr6to4(dst):
                # TODO : see if taking the longest match between dst and
                #        every source addresses would provide better results
                tmp = filter(lambda x: in6_isaddr6to4(x[1][1]), res)
            elif in6_ismaddr(dst) or in6_islladdr(dst):
                # TODO : I'm sure we are not covering all addresses. Check that
                tmp = filter(lambda x: x[1][0] == conf.iface6, res)

            if tmp:
                res = tmp

        # Fill the cache (including dev-specific request)
        k = dst
        if dev is not None:
            k = dst + "%%" + dev
        self.cache[k] = res[0][1]

        return res[0][1]

conf.route6 = Route6()

_res = conf.route6.route("::/0")
if _res:
    iff, gw, addr = _res
    conf.iface6 = iff
del(_res)

<|endoftext|>


<commit_before>import requests

url = "https://ua.api.yle.fi/graphql?app_id=8d7303fe&app_key=105875199ef3a1f7e0fbf7e2834b2dc&query={uutisetMostRecentNews:articleList(publisher:YLE_UUTISET,limit:100,offset:0,coverage:NATIONAL){meta{count,total,remaining},items{fullUrl,properties}}}"

i = 0

while True:
    url = "https://ua.api.yle.fi/graphql?app_id=8d7303fe&app_key=105875199ef3a1f7e0fbf7e2834b2dc&query={uutisetMostRecentNews:articleList(publisher:YLE_UUTISET,limit:100,offset:" + str( i * 100 ) + ",coverage:NATIONAL){meta{count,total,remaining},items{fullUrl,properties}}}"

    r = requests.get( url )

    r = r.json()
    d = r['data']
    items = d['uutisetMostRecentNews']['items']

    for item in items:
        print item['fullUrl']

    if d['meta']['remaining'] < 100:
        return

    i += 1
<commit_msg>Make script run and fix all typos<commit_after>
import requests

url = "https://ua.api.yle.fi/graphql?app_id=8d7303fe&app_key=105875199ef3a1f7e0fbf7e2834b2dc&query={uutisetMostRecentNews:articleList(publisher:YLE_UUTISET,limit:100,offset:0,coverage:NATIONAL){meta{count,total,remaining},items{fullUrl,properties}}}"

i = 0

while True:
    url = "https://ua.api.yle.fi/graphql?app_id=8d7303fe&app_key=105875199ef3a1f7e0fbf7e2834b2dc&query={uutisetMostRecentNews:articleList(publisher:YLE_UUTISET,limit:100,offset:" + str( i * 100 ) + ",coverage:NATIONAL){meta{count,total,remaining},items{fullUrl,properties}}}"

    r = requests.get( url )

    r = r.json()
    d = r['data']['uutisetMostRecentNews']
    items = d['items']

    for item in items:
        print item['fullUrl']

    if d['meta']['remaining'] < 100:
        break

    i += 1
<|endoftext|>


<commit_before>import sublime
import sublime_plugin

try:
    from .format_date import FormatDate, UnknownTimeZoneError  # ST3
except ValueError:
    from format_date import FormatDate, UnknownTimeZoneError  # ST2

ST2 = int(sublime.version()) < 3000

if not ST2:
    basestring = str

# Global variables
fdate = FormatDate()
# Global settings object
s = None
# Print tracebacks
DEBUG = False

def status(msg, e=None):
    msg = "[InsertDate] " + msg
    sublime.status_message(msg)
    if e is not None:
        msg += "\n%s: %s" % (type(e).__name__, e)
    print(msg)

    if e and DEBUG:
        import traceback
        traceback.print_exc()

# I wrote this for InactivePanes, but why not just use it here as well?
class Settings(object):
    """Provides various helping functions for wrapping the sublime settings objects.

    `settings` should be provided as a dict of tuples and attribute names should not be one of the
    existing functions. And of course they should be valid attribute names.

    Example constructor:
    Settings(
        sublime.load_settings("Preferences.sublime-settings"),
        dict(
            attr_name_to_save_as=('settings_key_to_read_from', 'default_value'),
            attr_name_to_save_as2='settings_key_to_read_from_with_default_None',
            attr_name_and_settings_key_with_default_None=None
            #, ...
        ),
        on_settings_changed,  # optional, callback
        auto_update  # optional, bool
                     # (whether the attributes should be kept up to date; default: True)
    )

    `settings_changed` will be called when the registered settings changed, and this time for real.
    Sublime Text currently behaves weird with `add_on_change` calls and the callback is run more
    often than it should be (as in, the specified setting didn't actually change), this wrapper
    however tests if one of the values has changed and then calls the callback.
    `update()` is called before the callback.

    Methods:
        * update()
            Reads all the settings and saves them in their respective attributes.
        * has_changed()
            Returns a boolean if the currently cached settings differ.
        * get_state()
            Returns a dict with the tracked settings as keys and their values (NOT the attribute
            names). With the above example: `{"settings_key_to_read_from": 'current_value'}`.
        * get_real_state()
            Same as above but ALWAYS returns the actual current values in the settings object.
        * set_callback(callback, auto_update=True)
            Calls `callback` whenever a tracked setting's value changes. See above on why this
            behavior differs to `register`.
            If `auto_update` is true it will automatically update the attributes when the settings
            changes. This is always true when a callback is set.
        * clear_callback(clear_auto_update=False)
            Clears the callback set above and returns it in the process.
    """
    _sobj = None
    _settings = None
    _callback = None
    _auto_update = False

    def __init__(self, settings_obj, settings, callback=None, auto_update=True):
        self._sobj = settings_obj

        for k, v in settings.items():
            if v is None:
                # Use the attr name as settings key and `None` as default
                settings[k] = (k, None)
            if isinstance(v, basestring):
                # Set default to `None` if a string was supplied
                settings[k] = (v, None)
        self._settings = settings

        self.update()
        self.set_callback(callback, auto_update)

    def update(self):
        for attr, (name, def_value) in self._settings.items():
            setattr(self, attr, self._sobj.get(name, def_value))

    def _on_change(self):
        # Only trigger if relevant settings changed
        if self.has_changed():
            self.update()
            if self._callback:
                self._callback()

    def _register(self, callback):
        for name, _ in self._settings.values():
            self._sobj.add_on_change(name, callback)

    def _unregister(self):
        for name, _ in self._settings.values():
            self._sobj.clear_on_change(name)

    def has_changed(self):
        return self.get_state() != self.get_real_state()

    def get_state(self):
        return dict((name, getattr(self, attr))
                    for attr, (name, _) in self._settings.items())

    def get_real_state(self):
        return dict((name, self._sobj.get(name, def_value))
                    for name, def_value in self._settings.values())

    def set_callback(self, callback, auto_update=True):
        if callback is not None and not callable(callback):
            raise TypeError("callback must be callable")

        cb = self._callback
        self._callback = callback
        if (not cb and not self._auto_update) and (callback or auto_update):
            self._register(self._on_change)

        self._auto_update = auto_update
        return cb

    def clear_callback(self, clear_auto_update=False):
        cb = self._callback
        if cb or not self._auto_update or clear_auto_update:
            self._unregister()
        self._callback = None
        return cb

# The actual commands
class InsertDateCommand(sublime_plugin.TextCommand):

    """Prints Date according to given format string."""

    def run(self, edit, format=None, tz_in=None, tz_out=None):
        if format is not None:
            if format == '' or not isinstance(format, basestring) or format.isspace():
                # Not a string, empty or only whitespaces
                return

        # Do the actual parse action
        try:
            text = fdate.parse(format, tz_in, tz_out)
        except UnknownTimeZoneError as e:
            status(str(e).strip('"'), e)
            return
        except Exception as e:
            status('Error parsing format string `%s`' % format, e)
            return

        # Don't bother replacing selections with actually nothing
        if text == '' or text.isspace():
            return

        # Do replacements
        for r in self.view.sel():
            # Insert when sel is empty to not select the contents
            if r.empty():
                self.view.insert(edit, r.a, text)
            else:
                self.view.replace(edit, r, text)

class InsertDatePromptCommand(sublime_plugin.TextCommand):

    """Ask for a format string, while preserving the other parameters.

    If "format" is provided, it will be pre-inserted into the prompt.
    """

    def run(self, edit, format=None, tz_in=None, tz_out=None):
        def on_done(fmt):
            self.view.run_command(
                "insert_date",
                {"format": fmt, "tz_in": tz_in, "tz_out": tz_out}
            )

        self.view.window().show_input_panel(
            # Caption
            "Date format string:",
            # Default text
            str(format) if format else '',
            # on_done callback (call this command again)
            on_done,
            # Unnecessary callbacks
            None, None
        )

class InsertDatePanelCommand(sublime_plugin.TextCommand):

    """Shows a quick panel with configurable templates that are previewed."""

    panel_cache = []
    config_map = {}

    def run(self, edit, tz_in=None, tz_out=None):
        self.panel_cache = []
        self.config_map = {}

        if not isinstance(s.prompt_config, list):
            status("`prompt_config` setting is invalid")
            return

        configs = s.prompt_config
        if not isinstance(s.user_prompt_config, list):
            status("`user_prompt_config` setting is invalid")
        else:
            configs = configs + s.user_prompt_config

        # Generate panel cache for quick_panel
        for conf in configs:
            # Read config
            c = dict()
            c['tz_in']  = tz_in if tz_in else conf.get('tz_in')
            c['tz_out'] = tz_out if tz_out else conf.get('tz_out')
            c['format'] = conf.get('format')

            if isinstance(c['format'], basestring):
                c['format'] = c['format'].replace("$default", fdate.default['format'])

            # Do the actual parse action
            try:
                text = fdate.parse(**c)
            except UnknownTimeZoneError as e:
                status(str(e).strip('"'), e)
                return
            except Exception as e:
                status('Error parsing format string `%s`' % format, e)
                return

            self.panel_cache.append([conf['name'], text])
            self.config_map[conf['name']] = c

        self.view.window().show_quick_panel(self.panel_cache, self.on_done)

    def on_done(self, index):
        if index == -1:
            return

        name = self.panel_cache[index][0]
        self.view.run_command("insert_date", self.config_map[name])

# Handle context
def plugin_loaded():
    global s, fdate

    s = Settings(
        sublime.load_settings('insert_date.sublime-settings'),
        settings=dict(
            format=('format', '%c'),
            tz_in=('tz_in', 'local'),
            prompt_config=None,
            user_prompt_config=None
        )
    )

    # Register on settings changes
    def on_settings_changed():
        print("InsertDate settings changed")
        # These defaults will be used when the command's parameters are None
        fdate.set_default(s.get_state())

    on_settings_changed()  # Apply initial settings
    s.set_callback(on_settings_changed)

def plugin_unloaded():
    global s

    s.clear_callback(True)

# ST2 backwards (and don't call it twice in ST3)
unload_handler = plugin_unloaded if ST2 else lambda: None

# Call manually if on ST2
if ST2:
    plugin_loaded()
<commit_msg>Pre-select the default format string in prompt<commit_after>import sublime
import sublime_plugin

try:
    from .format_date import FormatDate, UnknownTimeZoneError  # ST3
except ValueError:
    from format_date import FormatDate, UnknownTimeZoneError  # ST2

ST2 = int(sublime.version()) < 3000

if not ST2:
    basestring = str

# Global variables
fdate = FormatDate()
# Global settings object
s = None
# Print tracebacks
DEBUG = False

def status(msg, e=None):
    msg = "[InsertDate] " + msg
    sublime.status_message(msg)
    if e is not None:
        msg += "\n%s: %s" % (type(e).__name__, e)
    print(msg)

    if e and DEBUG:
        import traceback
        traceback.print_exc()

# I wrote this for InactivePanes, but why not just use it here as well?
class Settings(object):
    """Provides various helping functions for wrapping the sublime settings objects.

    `settings` should be provided as a dict of tuples and attribute names should not be one of the
    existing functions. And of course they should be valid attribute names.

    Example constructor:
    Settings(
        sublime.load_settings("Preferences.sublime-settings"),
        dict(
            attr_name_to_save_as=('settings_key_to_read_from', 'default_value'),
            attr_name_to_save_as2='settings_key_to_read_from_with_default_None',
            attr_name_and_settings_key_with_default_None=None
            #, ...
        ),
        on_settings_changed,  # optional, callback
        auto_update  # optional, bool
                     # (whether the attributes should be kept up to date; default: True)
    )

    `settings_changed` will be called when the registered settings changed, and this time for real.
    Sublime Text currently behaves weird with `add_on_change` calls and the callback is run more
    often than it should be (as in, the specified setting didn't actually change), this wrapper
    however tests if one of the values has changed and then calls the callback.
    `update()` is called before the callback.

    Methods:
        * update()
            Reads all the settings and saves them in their respective attributes.
        * has_changed()
            Returns a boolean if the currently cached settings differ.
        * get_state()
            Returns a dict with the tracked settings as keys and their values (NOT the attribute
            names). With the above example: `{"settings_key_to_read_from": 'current_value'}`.
        * get_real_state()
            Same as above but ALWAYS returns the actual current values in the settings object.
        * set_callback(callback, auto_update=True)
            Calls `callback` whenever a tracked setting's value changes. See above on why this
            behavior differs to `register`.
            If `auto_update` is true it will automatically update the attributes when the settings
            changes. This is always true when a callback is set.
        * clear_callback(clear_auto_update=False)
            Clears the callback set above and returns it in the process.
    """
    _sobj = None
    _settings = None
    _callback = None
    _auto_update = False

    def __init__(self, settings_obj, settings, callback=None, auto_update=True):
        self._sobj = settings_obj

        for k, v in settings.items():
            if v is None:
                # Use the attr name as settings key and `None` as default
                settings[k] = (k, None)
            if isinstance(v, basestring):
                # Set default to `None` if a string was supplied
                settings[k] = (v, None)
        self._settings = settings

        self.update()
        self.set_callback(callback, auto_update)

    def update(self):
        for attr, (name, def_value) in self._settings.items():
            setattr(self, attr, self._sobj.get(name, def_value))

    def _on_change(self):
        # Only trigger if relevant settings changed
        if self.has_changed():
            self.update()
            if self._callback:
                self._callback()

    def _register(self, callback):
        for name, _ in self._settings.values():
            self._sobj.add_on_change(name, callback)

    def _unregister(self):
        for name, _ in self._settings.values():
            self._sobj.clear_on_change(name)

    def has_changed(self):
        return self.get_state() != self.get_real_state()

    def get_state(self):
        return dict((name, getattr(self, attr))
                    for attr, (name, _) in self._settings.items())

    def get_real_state(self):
        return dict((name, self._sobj.get(name, def_value))
                    for name, def_value in self._settings.values())

    def set_callback(self, callback, auto_update=True):
        if callback is not None and not callable(callback):
            raise TypeError("callback must be callable")

        cb = self._callback
        self._callback = callback
        if (not cb and not self._auto_update) and (callback or auto_update):
            self._register(self._on_change)

        self._auto_update = auto_update
        return cb

    def clear_callback(self, clear_auto_update=False):
        cb = self._callback
        if cb or not self._auto_update or clear_auto_update:
            self._unregister()
        self._callback = None
        return cb

# The actual commands
class InsertDateCommand(sublime_plugin.TextCommand):

    """Prints Date according to given format string."""

    def run(self, edit, format=None, tz_in=None, tz_out=None):
        if format is not None:
            if format == '' or not isinstance(format, basestring) or format.isspace():
                # Not a string, empty or only whitespaces
                return

        # Do the actual parse action
        try:
            text = fdate.parse(format, tz_in, tz_out)
        except UnknownTimeZoneError as e:
            status(str(e).strip('"'), e)
            return
        except Exception as e:
            status('Error parsing format string `%s`' % format, e)
            return

        # Don't bother replacing selections with actually nothing
        if text == '' or text.isspace():
            return

        # Do replacements
        for r in self.view.sel():
            # Insert when sel is empty to not select the contents
            if r.empty():
                self.view.insert(edit, r.a, text)
            else:
                self.view.replace(edit, r, text)

class InsertDatePromptCommand(sublime_plugin.TextCommand):

    """Ask for a format string, while preserving the other parameters.

    If "format" is provided, it will be pre-inserted into the prompt.
    """

    def run(self, edit, format=None, tz_in=None, tz_out=None):
        def on_done(fmt):
            self.view.run_command(
                "insert_date",
                {"format": fmt, "tz_in": tz_in, "tz_out": tz_out}
            )

        i_panel = self.view.window().show_input_panel(
            # Caption
            "Date format string:",
            # Default text
            str(format) if format else '',
            # on_done callback (call this command again)
            on_done,
            # Unnecessary callbacks
            None, None
        )

        # Select the default text
        i_panel.sel().clear()
        i_panel.sel().add(sublime.Region(0, i_panel.size()))

class InsertDatePanelCommand(sublime_plugin.TextCommand):

    """Shows a quick panel with configurable templates that are previewed."""

    panel_cache = []
    config_map = {}

    def run(self, edit, tz_in=None, tz_out=None):
        self.panel_cache = []
        self.config_map = {}

        if not isinstance(s.prompt_config, list):
            status("`prompt_config` setting is invalid")
            return

        configs = s.prompt_config
        if not isinstance(s.user_prompt_config, list):
            status("`user_prompt_config` setting is invalid")
        else:
            configs = configs + s.user_prompt_config

        # Generate panel cache for quick_panel
        for conf in configs:
            # Read config
            c = dict()
            c['tz_in']  = tz_in if tz_in else conf.get('tz_in')
            c['tz_out'] = tz_out if tz_out else conf.get('tz_out')
            c['format'] = conf.get('format')

            if isinstance(c['format'], basestring):
                c['format'] = c['format'].replace("$default", fdate.default['format'])

            # Do the actual parse action
            try:
                text = fdate.parse(**c)
            except UnknownTimeZoneError as e:
                status(str(e).strip('"'), e)
                return
            except Exception as e:
                status('Error parsing format string `%s`' % format, e)
                return

            self.panel_cache.append([conf['name'], text])
            self.config_map[conf['name']] = c

        self.view.window().show_quick_panel(self.panel_cache, self.on_done)

    def on_done(self, index):
        if index == -1:
            return

        name = self.panel_cache[index][0]
        self.view.run_command("insert_date", self.config_map[name])

# Handle context
def plugin_loaded():
    global s, fdate

    s = Settings(
        sublime.load_settings('insert_date.sublime-settings'),
        settings=dict(
            format=('format', '%c'),
            tz_in=('tz_in', 'local'),
            prompt_config=None,
            user_prompt_config=None
        )
    )

    # Register on settings changes
    def on_settings_changed():
        print("InsertDate settings changed")
        # These defaults will be used when the command's parameters are None
        fdate.set_default(s.get_state())

    on_settings_changed()  # Apply initial settings
    s.set_callback(on_settings_changed)

def plugin_unloaded():
    global s

    s.clear_callback(True)

# ST2 backwards (and don't call it twice in ST3)
unload_handler = plugin_unloaded if ST2 else lambda: None

# Call manually if on ST2
if ST2:
    plugin_loaded()
<|endoftext|>


<commit_before>from lxml import etree

import os

def xml_from_file(path, filename):
    cwd = os.path.dirname(os.path.realpath(__file__))
    return etree.tostring(etree.parse("%s/%s/%s" % (cwd, path, filename)))

def generate_xml_root(xml):
    try:
        parser = etree.XMLParser(
            ns_clean=True,
            recover=False,
            encoding='utf-8',
            remove_blank_text=True
        )
        root = etree.XML(xml, parser)
    except etree.XMLSyntaxError:
        parser = etree.XMLParser(
            ns_clean=True,
            recover=True,
            encoding='utf-8',
            remove_blank_text=True
        )
        root = etree.XML(xml, parser)

    return root

def sanitize_xml(xml_root):
    # TODO
    # - Sanitize by whitelist regex: [a-zA-Z0-9] and underscore (_)
    # - Sanitize tag/element names to support Python __getattr__ (tag.tag.tag)
    # - Prevent duplicates

    mapping = {}

    for e in xml_root.xpath('//*[contains(local-name(),"-") or contains(local-name(), ".")]'):
        old_tag = e.tag

        # replacements
        e.tag = e.tag.replace('-', '')
        e.tag = e.tag.replace('.', '_')

        mapping[e.tag] = old_tag

    return mapping

def etree_to_dict(root):
    tags_count = {}

    # Count tag (types), to determine it's a single or
    # multiple/redundant one.
    for item in root:
        if item.tag not in tags_count:
            tags_count[item.tag] = 1
        else:
            tags_count[item.tag] += 1

    datadict = {}
    for item in root:
        if item.tag not in datadict:
            if tags_count[item.tag] > 1:
                datadict[item.tag] = []
            else:
                datadict[item.tag] = None

    for item in root:
        d = {}
        for elem in item:
            d[elem.tag] = elem.text

        if tags_count[item.tag] > 1:
            datadict[item.tag].append(d)
        else:
            datadict[item.tag] = item.text

    return datadict
<commit_msg>Fix: `ValueError: Unicode strings with encoding declaration are not supported`<commit_after>from lxml import etree

import os

def xml_from_file(path, filename):
    cwd = os.path.dirname(os.path.realpath(__file__))
    return etree.tostring(etree.parse("%s/%s/%s" % (cwd, path, filename)))

def generate_xml_root(xml):
    try:
        parser = etree.XMLParser(
            ns_clean=True,
            recover=False,
            encoding='utf-8',
            remove_blank_text=True
        )
        root = etree.XML(xml.encode("utf-8"), parser)
    except etree.XMLSyntaxError:
        parser = etree.XMLParser(
            ns_clean=True,
            recover=True,
            encoding='utf-8',
            remove_blank_text=True
        )
        root = etree.XML(xml.encode("utf-8"), parser)

    return root

def sanitize_xml(xml_root):
    # TODO
    # - Sanitize by whitelist regex: [a-zA-Z0-9] and underscore (_)
    # - Sanitize tag/element names to support Python __getattr__ (tag.tag.tag)
    # - Prevent duplicates

    mapping = {}

    for e in xml_root.xpath('//*[contains(local-name(),"-") or contains(local-name(), ".")]'):
        old_tag = e.tag

        # replacements
        e.tag = e.tag.replace('-', '')
        e.tag = e.tag.replace('.', '_')

        mapping[e.tag] = old_tag

    return mapping

def etree_to_dict(root):
    tags_count = {}

    # Count tag (types), to determine it's a single or
    # multiple/redundant one.
    for item in root:
        if item.tag not in tags_count:
            tags_count[item.tag] = 1
        else:
            tags_count[item.tag] += 1

    datadict = {}
    for item in root:
        if item.tag not in datadict:
            if tags_count[item.tag] > 1:
                datadict[item.tag] = []
            else:
                datadict[item.tag] = None

    for item in root:
        d = {}
        for elem in item:
            d[elem.tag] = elem.text

        if tags_count[item.tag] > 1:
            datadict[item.tag].append(d)
        else:
            datadict[item.tag] = item.text

    return datadict
<|endoftext|>


<commit_before>#!/usr/bin/env python
# coding: utf-8
#
# Copyright 2012 Facebook
#
# 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
#
# 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.

"""Data used by the tornado.locale module."""

from tornado.util import u

LOCALE_NAMES = {
    "af_ZA": {"name_en": u("Afrikaans"), "name": u("Afrikaans")},
    "am_ET": {"name_en": u("Amharic"), "name": u("አማርኛ")},
    "ar_AR": {"name_en": u("Arabic"), "name": u("العربية")},
    "bg_BG": {"name_en": u("Bulgarian"), "name": u("Български")},
    "bn_IN": {"name_en": u("Bengali"), "name": u("বাংলা")},
    "bs_BA": {"name_en": u("Bosnian"), "name": u("Bosanski")},
    "ca_ES": {"name_en": u("Catalan"), "name": u("Català")},
    "cs_CZ": {"name_en": u("Czech"), "name": u("Čeština")},
    "cy_GB": {"name_en": u("Welsh"), "name": u("Cymraeg")},
    "da_DK": {"name_en": u("Danish"), "name": u("Dansk")},
    "de_DE": {"name_en": u("German"), "name": u("Deutsch")},
    "el_GR": {"name_en": u("Greek"), "name": u("Ελληνικά")},
    "en_GB": {"name_en": u("English (UK)"), "name": u("English (UK)")},
    "en_US": {"name_en": u("English (US)"), "name": u("English (US)")},
    "es_ES": {"name_en": u("Spanish (Spain)"), "name": u("Español (España)")},
    "es_LA": {"name_en": u("Spanish"), "name": u("Español")},
    "et_EE": {"name_en": u("Estonian"), "name": u("Eesti")},
    "eu_ES": {"name_en": u("Basque"), "name": u("Euskara")},
    "fa_IR": {"name_en": u("Persian"), "name": u("فارسی")},
    "fi_FI": {"name_en": u("Finnish"), "name": u("Suomi")},
    "fr_CA": {"name_en": u("French (Canada)"), "name": u("Français (Canada)")},
    "fr_FR": {"name_en": u("French"), "name": u("Français")},
    "ga_IE": {"name_en": u("Irish"), "name": u("Gaeilge")},
    "gl_ES": {"name_en": u("Galician"), "name": u("Galego")},
    "he_IL": {"name_en": u("Hebrew"), "name": u("עברית")},
    "hi_IN": {"name_en": u("Hindi"), "name": u("हिन्दी")},
    "hr_HR": {"name_en": u("Croatian"), "name": u("Hrvatski")},
    "hu_HU": {"name_en": u("Hungarian"), "name": u("Magyar")},
    "id_ID": {"name_en": u("Indonesian"), "name": u("Bahasa Indonesia")},
    "is_IS": {"name_en": u("Icelandic"), "name": u("Íslenska")},
    "it_IT": {"name_en": u("Italian"), "name": u("Italiano")},
    "ja_JP": {"name_en": u("Japanese"), "name": u("日本語")},
    "ko_KR": {"name_en": u("Korean"), "name": u("한국어")},
    "lt_LT": {"name_en": u("Lithuanian"), "name": u("Lietuvių")},
    "lv_LV": {"name_en": u("Latvian"), "name": u("Latviešu")},
    "mk_MK": {"name_en": u("Macedonian"), "name": u("Македонски")},
    "ml_IN": {"name_en": u("Malayalam"), "name": u("മലയാളം")},
    "ms_MY": {"name_en": u("Malay"), "name": u("Bahasa Melayu")},
    "nb_NO": {"name_en": u("Norwegian (bokmal)"), "name": u("Norsk (bokmål)")},
    "nl_NL": {"name_en": u("Dutch"), "name": u("Nederlands")},
    "nn_NO": {"name_en": u("Norwegian (nynorsk)"), "name": u("Norsk (nynorsk)")},
    "pa_IN": {"name_en": u("Punjabi"), "name": u("ਪੰਜਾਬੀ")},
    "pl_PL": {"name_en": u("Polish"), "name": u("Polski")},
    "pt_BR": {"name_en": u("Portuguese (Brazil)"), "name": u("Português (Brasil)")},
    "pt_PT": {"name_en": u("Portuguese (Portugal)"), "name": u("Português (Portugal)")},
    "ro_RO": {"name_en": u("Romanian"), "name": u("Română")},
    "ru_RU": {"name_en": u("Russian"), "name": u("Русский")},
    "sk_SK": {"name_en": u("Slovak"), "name": u("Slovenčina")},
    "sl_SI": {"name_en": u("Slovenian"), "name": u("Slovenščina")},
    "sq_AL": {"name_en": u("Albanian"), "name": u("Shqip")},
    "sr_RS": {"name_en": u("Serbian"), "name": u("Српски")},
    "sv_SE": {"name_en": u("Swedish"), "name": u("Svenska")},
    "sw_KE": {"name_en": u("Swahili"), "name": u("Kiswahili")},
    "ta_IN": {"name_en": u("Tamil"), "name": u("தமிழ்")},
    "te_IN": {"name_en": u("Telugu"), "name": u("తెలుగు")},
    "th_TH": {"name_en": u("Thai"), "name": u("ภาษาไทย")},
    "tl_PH": {"name_en": u("Filipino"), "name": u("Filipino")},
    "tr_TR": {"name_en": u("Turkish"), "name": u("Türkçe")},
    "uk_UA": {"name_en": u("Ukraini "), "name": u("Українська")},
    "vi_VN": {"name_en": u("Vietnamese"), "name": u("Tiếng Việt")},
    "zh_CN": {"name_en": u("Chinese (Simplified)"), "name": u("中文(简体)")},
    "zh_TW": {"name_en": u("Chinese (Traditional)"), "name": u("中文(繁體)")},
}
<commit_msg>Third time's the charm for _locale_data.py<commit_after>#!/usr/bin/env python
# coding: utf-8
#
# Copyright 2012 Facebook
#
# 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
#
# 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.

"""Data used by the tornado.locale module."""

# NOTE: This file is supposed to contain unicode strings, which is
# exactly what you'd get with e.g. u"Español" in most python versions.
# However, Python 3.2 doesn't support the u"" syntax, so we use a u()
# function instead. tornado.util.u cannot be used because it doesn't
# support non-ascii characters on python 2.
# When we drop support for Python 3.2, we can remove the parens
# and make these plain unicode strings.
from tornado.escape import to_unicode as u

LOCALE_NAMES = {
    "af_ZA": {"name_en": u("Afrikaans"), "name": u("Afrikaans")},
    "am_ET": {"name_en": u("Amharic"), "name": u("አማርኛ")},
    "ar_AR": {"name_en": u("Arabic"), "name": u("العربية")},
    "bg_BG": {"name_en": u("Bulgarian"), "name": u("Български")},
    "bn_IN": {"name_en": u("Bengali"), "name": u("বাংলা")},
    "bs_BA": {"name_en": u("Bosnian"), "name": u("Bosanski")},
    "ca_ES": {"name_en": u("Catalan"), "name": u("Català")},
    "cs_CZ": {"name_en": u("Czech"), "name": u("Čeština")},
    "cy_GB": {"name_en": u("Welsh"), "name": u("Cymraeg")},
    "da_DK": {"name_en": u("Danish"), "name": u("Dansk")},
    "de_DE": {"name_en": u("German"), "name": u("Deutsch")},
    "el_GR": {"name_en": u("Greek"), "name": u("Ελληνικά")},
    "en_GB": {"name_en": u("English (UK)"), "name": u("English (UK)")},
    "en_US": {"name_en": u("English (US)"), "name": u("English (US)")},
    "es_ES": {"name_en": u("Spanish (Spain)"), "name": u("Español (España)")},
    "es_LA": {"name_en": u("Spanish"), "name": u("Español")},
    "et_EE": {"name_en": u("Estonian"), "name": u("Eesti")},
    "eu_ES": {"name_en": u("Basque"), "name": u("Euskara")},
    "fa_IR": {"name_en": u("Persian"), "name": u("فارسی")},
    "fi_FI": {"name_en": u("Finnish"), "name": u("Suomi")},
    "fr_CA": {"name_en": u("French (Canada)"), "name": u("Français (Canada)")},
    "fr_FR": {"name_en": u("French"), "name": u("Français")},
    "ga_IE": {"name_en": u("Irish"), "name": u("Gaeilge")},
    "gl_ES": {"name_en": u("Galician"), "name": u("Galego")},
    "he_IL": {"name_en": u("Hebrew"), "name": u("עברית")},
    "hi_IN": {"name_en": u("Hindi"), "name": u("हिन्दी")},
    "hr_HR": {"name_en": u("Croatian"), "name": u("Hrvatski")},
    "hu_HU": {"name_en": u("Hungarian"), "name": u("Magyar")},
    "id_ID": {"name_en": u("Indonesian"), "name": u("Bahasa Indonesia")},
    "is_IS": {"name_en": u("Icelandic"), "name": u("Íslenska")},
    "it_IT": {"name_en": u("Italian"), "name": u("Italiano")},
    "ja_JP": {"name_en": u("Japanese"), "name": u("日本語")},
    "ko_KR": {"name_en": u("Korean"), "name": u("한국어")},
    "lt_LT": {"name_en": u("Lithuanian"), "name": u("Lietuvių")},
    "lv_LV": {"name_en": u("Latvian"), "name": u("Latviešu")},
    "mk_MK": {"name_en": u("Macedonian"), "name": u("Македонски")},
    "ml_IN": {"name_en": u("Malayalam"), "name": u("മലയാളം")},
    "ms_MY": {"name_en": u("Malay"), "name": u("Bahasa Melayu")},
    "nb_NO": {"name_en": u("Norwegian (bokmal)"), "name": u("Norsk (bokmål)")},
    "nl_NL": {"name_en": u("Dutch"), "name": u("Nederlands")},
    "nn_NO": {"name_en": u("Norwegian (nynorsk)"), "name": u("Norsk (nynorsk)")},
    "pa_IN": {"name_en": u("Punjabi"), "name": u("ਪੰਜਾਬੀ")},
    "pl_PL": {"name_en": u("Polish"), "name": u("Polski")},
    "pt_BR": {"name_en": u("Portuguese (Brazil)"), "name": u("Português (Brasil)")},
    "pt_PT": {"name_en": u("Portuguese (Portugal)"), "name": u("Português (Portugal)")},
    "ro_RO": {"name_en": u("Romanian"), "name": u("Română")},
    "ru_RU": {"name_en": u("Russian"), "name": u("Русский")},
    "sk_SK": {"name_en": u("Slovak"), "name": u("Slovenčina")},
    "sl_SI": {"name_en": u("Slovenian"), "name": u("Slovenščina")},
    "sq_AL": {"name_en": u("Albanian"), "name": u("Shqip")},
    "sr_RS": {"name_en": u("Serbian"), "name": u("Српски")},
    "sv_SE": {"name_en": u("Swedish"), "name": u("Svenska")},
    "sw_KE": {"name_en": u("Swahili"), "name": u("Kiswahili")},
    "ta_IN": {"name_en": u("Tamil"), "name": u("தமிழ்")},
    "te_IN": {"name_en": u("Telugu"), "name": u("తెలుగు")},
    "th_TH": {"name_en": u("Thai"), "name": u("ภาษาไทย")},
    "tl_PH": {"name_en": u("Filipino"), "name": u("Filipino")},
    "tr_TR": {"name_en": u("Turkish"), "name": u("Türkçe")},
    "uk_UA": {"name_en": u("Ukraini "), "name": u("Українська")},
    "vi_VN": {"name_en": u("Vietnamese"), "name": u("Tiếng Việt")},
    "zh_CN": {"name_en": u("Chinese (Simplified)"), "name": u("中文(简体)")},
    "zh_TW": {"name_en": u("Chinese (Traditional)"), "name": u("中文(繁體)")},
}
<|endoftext|>


<commit_before># urllib3/poolmanager.py
# Copyright 2008-2012 Andrey Petrov and contributors (see CONTRIBUTORS.txt)
#
# This module is part of urllib3 and is released under
# the MIT License: http://www.opensource.org/licenses/mit-license.php

import logging

from ._collections import RecentlyUsedContainer
from .connectionpool import HTTPConnectionPool, HTTPSConnectionPool
from .connectionpool import connection_from_url, port_by_scheme
from .request import RequestMethods
from .util import parse_url

__all__ = ['PoolManager', 'ProxyManager', 'proxy_from_url']

pool_classes_by_scheme = {
    'http': HTTPConnectionPool,
    'https': HTTPSConnectionPool,
}

log = logging.getLogger(__name__)

class PoolManager(RequestMethods):
    """
    Allows for arbitrary requests while transparently keeping track of
    necessary connection pools for you.

    :param num_pools:
        Number of connection pools to cache before discarding the least
        recently used pool.

    :param headers:
        Headers to include with all requests, unless other headers are given
        explicitly.

    :param \**connection_pool_kw:
        Additional parameters are used to create fresh
        :class:`urllib3.connectionpool.ConnectionPool` instances.

    Example: ::

        >>> manager = PoolManager(num_pools=2)
        >>> r = manager.request('GET', 'http://google.com/')
        >>> r = manager.request('GET', 'http://google.com/mail')
        >>> r = manager.request('GET', 'http://yahoo.com/')
        >>> len(manager.pools)
        2

    """

    def __init__(self, num_pools=10, headers=None, **connection_pool_kw):
        RequestMethods.__init__(self, headers)
        self.connection_pool_kw = connection_pool_kw
        self.pools = RecentlyUsedContainer(num_pools,
                                           dispose_func=lambda p: p.close())

    def clear(self):
        """
        Empty our store of pools and direct them all to close.

        This will not affect in-flight connections, but they will not be
        re-used after completion.
        """
        self.pools.clear()

    def connection_from_host(self, host, port=None, scheme='http'):
        """
        Get a :class:`ConnectionPool` based on the host, port, and scheme.

        If ``port`` isn't given, it will be derived from the ``scheme`` using
        ``urllib3.connectionpool.port_by_scheme``.
        """
        port = port or port_by_scheme.get(scheme, 80)

        pool_key = (scheme, host, port)

        # If the scheme, host, or port doesn't match existing open connections,
        # open a new ConnectionPool.
        pool = self.pools.get(pool_key)
        if pool:
            return pool

        # Make a fresh ConnectionPool of the desired type
        pool_cls = pool_classes_by_scheme[scheme]
        pool = pool_cls(host, port, **self.connection_pool_kw)

        self.pools[pool_key] = pool

        return pool

    def connection_from_url(self, url):
        """
        Similar to :func:`urllib3.connectionpool.connection_from_url` but
        doesn't pass any additional parameters to the
        :class:`urllib3.connectionpool.ConnectionPool` constructor.

        Additional parameters are taken from the :class:`.PoolManager`
        constructor.
        """
        u = parse_url(url)
        return self.connection_from_host(u.host, port=u.port, scheme=u.scheme)

    def urlopen(self, method, url, redirect=True, **kw):
        """
        Same as :meth:`urllib3.connectionpool.HTTPConnectionPool.urlopen`
        with custom cross-host redirect logic and only sends the request-uri
        portion of the ``url``.

        The given ``url`` parameter must be absolute, such that an appropriate
        :class:`urllib3.connectionpool.ConnectionPool` can be chosen for it.
        """
        u = parse_url(url)
        conn = self.connection_from_host(u.host, port=u.port, scheme=u.scheme)

        kw['assert_same_host'] = False
        kw['redirect'] = False
        if 'headers' not in kw:
            kw['headers'] = self.headers

        response = conn.urlopen(method, u.request_uri, **kw)

        redirect_location = redirect and response.get_redirect_location()
        if not redirect_location:
            return response

        if response.status == 303:
            method = 'GET'

        log.info("Redirecting %s -> %s" % (url, redirect_location))
        kw['retries'] = kw.get('retries', 3) - 1  # Persist retries countdown
        return self.urlopen(method, redirect_location, **kw)

class ProxyManager(RequestMethods):
    """
    Given a ConnectionPool to a proxy, the ProxyManager's ``urlopen`` method
    will make requests to any url through the defined proxy.
    """

    def __init__(self, proxy_pool):
        self.proxy_pool = proxy_pool

    def _set_proxy_headers(self, headers=None):
        headers_ = {'Accept': '*/*'}
        if headers:
            headers_.update(headers)

        return headers_

    def urlopen(self, method, url, **kw):
        "Same as HTTP(S)ConnectionPool.urlopen, ``url`` must be absolute."
        kw['assert_same_host'] = False
        kw['headers'] = self._set_proxy_headers(kw.get('headers'))
        return self.proxy_pool.urlopen(method, url, **kw)

def proxy_from_url(url, **pool_kw):
    proxy_pool = connection_from_url(url, **pool_kw)
    return ProxyManager(proxy_pool)
<commit_msg>Add default scheme. (Related to #134)<commit_after># urllib3/poolmanager.py
# Copyright 2008-2012 Andrey Petrov and contributors (see CONTRIBUTORS.txt)
#
# This module is part of urllib3 and is released under
# the MIT License: http://www.opensource.org/licenses/mit-license.php

import logging

from ._collections import RecentlyUsedContainer
from .connectionpool import HTTPConnectionPool, HTTPSConnectionPool
from .connectionpool import connection_from_url, port_by_scheme
from .request import RequestMethods
from .util import parse_url

__all__ = ['PoolManager', 'ProxyManager', 'proxy_from_url']

pool_classes_by_scheme = {
    'http': HTTPConnectionPool,
    'https': HTTPSConnectionPool,
}

log = logging.getLogger(__name__)

class PoolManager(RequestMethods):
    """
    Allows for arbitrary requests while transparently keeping track of
    necessary connection pools for you.

    :param num_pools:
        Number of connection pools to cache before discarding the least
        recently used pool.

    :param headers:
        Headers to include with all requests, unless other headers are given
        explicitly.

    :param \**connection_pool_kw:
        Additional parameters are used to create fresh
        :class:`urllib3.connectionpool.ConnectionPool` instances.

    Example: ::

        >>> manager = PoolManager(num_pools=2)
        >>> r = manager.request('GET', 'http://google.com/')
        >>> r = manager.request('GET', 'http://google.com/mail')
        >>> r = manager.request('GET', 'http://yahoo.com/')
        >>> len(manager.pools)
        2

    """

    def __init__(self, num_pools=10, headers=None, **connection_pool_kw):
        RequestMethods.__init__(self, headers)
        self.connection_pool_kw = connection_pool_kw
        self.pools = RecentlyUsedContainer(num_pools,
                                           dispose_func=lambda p: p.close())

    def clear(self):
        """
        Empty our store of pools and direct them all to close.

        This will not affect in-flight connections, but they will not be
        re-used after completion.
        """
        self.pools.clear()

    def connection_from_host(self, host, port=None, scheme='http'):
        """
        Get a :class:`ConnectionPool` based on the host, port, and scheme.

        If ``port`` isn't given, it will be derived from the ``scheme`` using
        ``urllib3.connectionpool.port_by_scheme``.
        """
        scheme = scheme or 'http'
        port = port or port_by_scheme.get(scheme, 80)

        pool_key = (scheme, host, port)

        # If the scheme, host, or port doesn't match existing open connections,
        # open a new ConnectionPool.
        pool = self.pools.get(pool_key)
        if pool:
            return pool

        # Make a fresh ConnectionPool of the desired type
        pool_cls = pool_classes_by_scheme[scheme]
        pool = pool_cls(host, port, **self.connection_pool_kw)

        self.pools[pool_key] = pool

        return pool

    def connection_from_url(self, url):
        """
        Similar to :func:`urllib3.connectionpool.connection_from_url` but
        doesn't pass any additional parameters to the
        :class:`urllib3.connectionpool.ConnectionPool` constructor.

        Additional parameters are taken from the :class:`.PoolManager`
        constructor.
        """
        u = parse_url(url)
        return self.connection_from_host(u.host, port=u.port, scheme=u.scheme)

    def urlopen(self, method, url, redirect=True, **kw):
        """
        Same as :meth:`urllib3.connectionpool.HTTPConnectionPool.urlopen`
        with custom cross-host redirect logic and only sends the request-uri
        portion of the ``url``.

        The given ``url`` parameter must be absolute, such that an appropriate
        :class:`urllib3.connectionpool.ConnectionPool` can be chosen for it.
        """
        u = parse_url(url)
        conn = self.connection_from_host(u.host, port=u.port, scheme=u.scheme)

        kw['assert_same_host'] = False
        kw['redirect'] = False
        if 'headers' not in kw:
            kw['headers'] = self.headers

        response = conn.urlopen(method, u.request_uri, **kw)

        redirect_location = redirect and response.get_redirect_location()
        if not redirect_location:
            return response

        if response.status == 303:
            method = 'GET'

        log.info("Redirecting %s -> %s" % (url, redirect_location))
        kw['retries'] = kw.get('retries', 3) - 1  # Persist retries countdown
        return self.urlopen(method, redirect_location, **kw)

class ProxyManager(RequestMethods):
    """
    Given a ConnectionPool to a proxy, the ProxyManager's ``urlopen`` method
    will make requests to any url through the defined proxy.
    """

    def __init__(self, proxy_pool):
        self.proxy_pool = proxy_pool

    def _set_proxy_headers(self, headers=None):
        headers_ = {'Accept': '*/*'}
        if headers:
            headers_.update(headers)

        return headers_

    def urlopen(self, method, url, **kw):
        "Same as HTTP(S)ConnectionPool.urlopen, ``url`` must be absolute."
        kw['assert_same_host'] = False
        kw['headers'] = self._set_proxy_headers(kw.get('headers'))
        return self.proxy_pool.urlopen(method, url, **kw)

def proxy_from_url(url, **pool_kw):
    proxy_pool = connection_from_url(url, **pool_kw)
    return ProxyManager(proxy_pool)
<|endoftext|>


<commit_before>"""OrderPortal: A portal for orders to a facility from its users.
An order can be a project application, a request, a report, etc.
"""

from __future__ import print_function, absolute_import

import os

__version__ = '3.6.30'

# Default settings, may be changed in a settings YAML file.
settings = dict(
    ROOT_DIR=os.path.dirname(__file__),
    BASE_URL='http://localhost/',
    TORNADO_DEBUG=False,
    LOGGING_DEBUG=False,
    LOGGING_FORMAT='%(levelname)s [%(asctime)s] %(message)s',
    LOGGING_FILEPATH=None,
    LOGGING_FILEMODE=None,
    DATABASE_SERVER='http://localhost:5984/',
    DATABASE_NAME='orderportal',
    MARKDOWN_URL='http://agea.github.io/tutorial.md/',
    SITE_DIR='{ROOT_DIR}/site',
    SITE_NAME='OrderPortal',
    ACCOUNT_MESSAGES_FILEPATH='{SITE_DIR}/account_messages.yaml',
    ORDER_STATUSES_FILEPATH='{SITE_DIR}/order_statuses.yaml',
    ORDER_TRANSITIONS_FILEPATH='{SITE_DIR}/order_transitions.yaml',
    ORDER_MESSAGES_FILEPATH='{SITE_DIR}/order_messages.yaml',
    UNIVERSITIES_FILEPATH='{SITE_DIR}/swedish_universities.yaml',
    COUNTRY_CODES_FILEPATH='{SITE_DIR}/country_codes.yaml',
    SUBJECT_TERMS_FILEPATH='{SITE_DIR}/subject_terms.yaml',
    TERMINOLOGY=dict(),         # Terms translation lookup.
    MIN_PASSWORD_LENGTH=8,
    LOGIN_MAX_AGE_DAYS=14,
    LOGIN_MAX_FAILURES=6,
    DISPLAY_DEFAULT_PAGE_SIZE=25,
    DISPLAY_MAX_RECENT_ORDERS=10,
    DISPLAY_ORDERS_MOST_RECENT=500,
    DISPLAY_MAX_PENDING_ACCOUNTS=10,
    DISPLAY_DEFAULT_MAX_LOG=20,
    DISPLAY_NEWS=True,
    DISPLAY_MAX_NEWS=4,
    DISPLAY_EVENTS=True,
    DISPLAY_MENU_INFORMATION=True,
    DISPLAY_MENU_DOCUMENTS=True,
    DISPLAY_MENU_ABOUT_US=True,
    ORDER_IDENTIFIER_FORMAT=None,
    ORDER_IDENTIFIER_REGEXP=None,
    ORDER_TAGS=True,
    ORDER_USER_TAGS=True,
    ORDER_LINKS=True,
    ORDER_REPORT=True,
    ORDERS_LIST_TAGS=True,
    ORDERS_LIST_FIELDS=[],
    ORDERS_LIST_STATUSES=[],
    ORDERS_SEARCH_DELIMS_LINT=[':', ',', ';', "'"],
    ORDERS_SEARCH_LINT=['an', 'to', 'in', 'on', 'of',
                        'and', 'the', 'is', 'was', 'not'],
    ORDERS_SEARCH_FIELDS=[],
    ACCOUNT_PI_INFO=True,
    ACCOUNT_POSTAL_INFO=True,
    ACCOUNT_INVOICE_INFO=True,
    ACCOUNT_FUNDER_INFO=True,
    ACCOUNT_FUNDER_INFO_GENDER=True,
    ACCOUNT_FUNDER_INFO_GROUP_SIZE=True,
    ACCOUNT_FUNDER_INFO_SUBJECT=True,
    ACCOUNT_DEFAULT_COUNTRY_CODE='SE',
    )
<commit_msg>Bumped micro version number.<commit_after>"""OrderPortal: A portal for orders to a facility from its users.
An order can be a project application, a request, a report, etc.
"""

from __future__ import print_function, absolute_import

import os

__version__ = '3.6.31'

# Default settings, may be changed in a settings YAML file.
settings = dict(
    ROOT_DIR=os.path.dirname(__file__),
    BASE_URL='http://localhost/',
    TORNADO_DEBUG=False,
    LOGGING_DEBUG=False,
    LOGGING_FORMAT='%(levelname)s [%(asctime)s] %(message)s',
    LOGGING_FILEPATH=None,
    LOGGING_FILEMODE=None,
    DATABASE_SERVER='http://localhost:5984/',
    DATABASE_NAME='orderportal',
    MARKDOWN_URL='http://agea.github.io/tutorial.md/',
    SITE_DIR='{ROOT_DIR}/site',
    SITE_NAME='OrderPortal',
    ACCOUNT_MESSAGES_FILEPATH='{SITE_DIR}/account_messages.yaml',
    ORDER_STATUSES_FILEPATH='{SITE_DIR}/order_statuses.yaml',
    ORDER_TRANSITIONS_FILEPATH='{SITE_DIR}/order_transitions.yaml',
    ORDER_MESSAGES_FILEPATH='{SITE_DIR}/order_messages.yaml',
    UNIVERSITIES_FILEPATH='{SITE_DIR}/swedish_universities.yaml',
    COUNTRY_CODES_FILEPATH='{SITE_DIR}/country_codes.yaml',
    SUBJECT_TERMS_FILEPATH='{SITE_DIR}/subject_terms.yaml',
    TERMINOLOGY=dict(),         # Terms translation lookup.
    MIN_PASSWORD_LENGTH=8,
    LOGIN_MAX_AGE_DAYS=14,
    LOGIN_MAX_FAILURES=6,
    DISPLAY_DEFAULT_PAGE_SIZE=25,
    DISPLAY_MAX_RECENT_ORDERS=10,
    DISPLAY_ORDERS_MOST_RECENT=500,
    DISPLAY_MAX_PENDING_ACCOUNTS=10,
    DISPLAY_DEFAULT_MAX_LOG=20,
    DISPLAY_NEWS=True,
    DISPLAY_MAX_NEWS=4,
    DISPLAY_EVENTS=True,
    DISPLAY_MENU_INFORMATION=True,
    DISPLAY_MENU_DOCUMENTS=True,
    DISPLAY_MENU_ABOUT_US=True,
    ORDER_IDENTIFIER_FORMAT=None,
    ORDER_IDENTIFIER_REGEXP=None,
    ORDER_TAGS=True,
    ORDER_USER_TAGS=True,
    ORDER_LINKS=True,
    ORDER_REPORT=True,
    ORDERS_LIST_TAGS=True,
    ORDERS_LIST_FIELDS=[],
    ORDERS_LIST_STATUSES=[],
    ORDERS_SEARCH_DELIMS_LINT=[':', ',', ';', "'"],
    ORDERS_SEARCH_LINT=['an', 'to', 'in', 'on', 'of',
                        'and', 'the', 'is', 'was', 'not'],
    ORDERS_SEARCH_FIELDS=[],
    ACCOUNT_PI_INFO=True,
    ACCOUNT_POSTAL_INFO=True,
    ACCOUNT_INVOICE_INFO=True,
    ACCOUNT_FUNDER_INFO=True,
    ACCOUNT_FUNDER_INFO_GENDER=True,
    ACCOUNT_FUNDER_INFO_GROUP_SIZE=True,
    ACCOUNT_FUNDER_INFO_SUBJECT=True,
    ACCOUNT_DEFAULT_COUNTRY_CODE='SE',
    )
<|endoftext|>