<commit_before>#!/usr/bin/env python
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gs
import ipywidgets as ipy
from . import util
from .slicer import Slicer, Axis_map
from .layer import Layer, blend_layers
from .colorbar import colorbar, alphabar

def three_plane(images, orient='clin', samples=128,
                cbar=None, contour=None,
                interactive=False):
    """
    Draw a standard 3-plane view through the center of the image

    Parameters:

    - images -- Either a filename (in a string or Path object) or a list of Layer objects
    - orient -- 'clin' or 'preclin'
    - sample -- Number of samples, default is 128, higher is better but slower
    - cbar -- Adds a colorbar. Either 'True' or an integer giving the layer the colorbar is from
    - contour -- Value(s) that contours are drawn at. Requires that cbar be set - contours will come from same layer
    - interactive -- Add sliders and make the view interactive
    """

def three_plane(images, orient='clin', samples=128,
                cbar=None, contour=None,
                interactive=False, title=None):
    if interactive:
        plt.ion()
    else:
        plt.ioff()
    if isinstance(images, str):
        layers = [Layer(images), ]
    elif isinstance(images, Layer):
        layers = [images, ]
    elif isinstance(images[0], str):
        layers = [Layer(img) for img in images]
    else:
        layers = images
    bbox = layers[0].bbox
    gs1 = gs.GridSpec(1, 3)
    fig = plt.figure(facecolor='black', figsize=(9, 3))
    if cbar:
        if isinstance(cbar, bool):
            cbar = 0
        gs1.update(left=0.01, right=0.88, bottom=0.01,
                   top=0.99, wspace=0.01, hspace=0.01)
        gs2 = gs.GridSpec(1, 1)
        gs2.update(left=0.92, right=0.98, bottom=0.1,
                   top=0.9, wspace=0.1, hspace=0.1)
        cax = fig.add_subplot(gs2[0], facecolor='white')
        clayer = layers[cbar]
        if clayer.alpha_image:
            if contour:
                try:
                    iterator = iter(contour)
                except:
                    contour = (contour,)
            alphabar(cax,
                     clayer.cmap, clayer.clim, clayer.label,
                     clayer.alpha_lim, clayer.alpha_label,
                     alines=contour, black_backg=True, orient='v')
        else:
            colorbar(cax,
                     clayer.cmap, clayer.clim, clayer.label,
                     black_backg=True, orient='v')
    else:
        gs1.update(left=0.01, right=0.99, bottom=0.01,
                   top=0.99, wspace=0.01, hspace=0.01)
    implots = [None, None, None]
    iax = [None, None, None]

    def wrap_sections(pos_x, pos_y, pos_z):
        pos = (pos_x, pos_y, pos_z)
        for i in range(3):
            slcr = Slicer(bbox, pos[i], i, samples=samples, orient=orient)
            blended_slice = blend_layers(layers, slcr)
            if implots[i]:
                implots[i].set_data(blended_slice)
            else:
                iax[i] = fig.add_subplot(gs1[i], facecolor='black')
                implots[i] = iax[i].imshow(
                    blended_slice, origin='lower', extent=slcr.extent, interpolation='nearest')
                iax[i].axis('off')
            if contour:
                sl_contour = layers[cbar].get_alpha(slcr)
                iax[i].contour(sl_contour, levels=contour, origin='lower', extent=slcr.extent,
                               colors='k', linestyles='-', linewidths=1)
    wrap_sections(bbox.center[0], bbox.center[1], bbox.center[2])
    if title:
        fig.suptitle(title, color='white')
    if interactive:
        # Setup widgets
        slider_x = ipy.FloatSlider(min=bbox.start[0], max=bbox.end[0], value=bbox.center[0],
                                   continuous_update=True, description='X:')
        slider_y = ipy.FloatSlider(min=bbox.start[1], max=bbox.end[1], value=bbox.center[1],
                                   continuous_update=True, description='Y:')
        slider_z = ipy.FloatSlider(min=bbox.start[2], max=bbox.end[2], value=bbox.center[2],
                                   continuous_update=True, description='Z:')
        widgets = ipy.interactive(
            wrap_sections, pos_x=slider_x, pos_y=slider_y, pos_z=slider_z)
        # Now do some manual layout
        # Set the sliders to horizontal layout
        hbox = ipy.HBox(widgets.children[0:3])
        vbox = ipy.VBox((hbox, widgets.children[3]))
        # iplot.widget.children[-1].layout.height = '350px'
        return vbox
    else:
        plt.close()
        return fig

def slice_axis(images, nrows=1, ncols=3, slice_axis='z', slice_lims=(0.25, 0.75),
               orient='clin', samples=128,
               cbar=None, contour=None, title=None):
    ntotal = nrows*ncols
    slice_axes = slice_axis * ntotal
    slice_pos = np.linspace(slice_lims[0], slice_lims[1], num=ntotal)
    return slices(images, nrows, ncols, slice_axes, slice_pos, False, orient, samples, cbar, contour, title)

def slices(images, nrows=1, ncols=1, slice_axes=['z', ], slice_pos=[0.5, ], absolute=False,
           orient='clin', samples=128,
           cbar=None, contour=None, title=None):
    if isinstance(images, str):
        layers = [Layer(images), ]
    elif isinstance(images, Layer):
        layers = [images, ]
    elif isinstance(images[0], str):
        layers = [Layer(img) for img in images]
    else:
        layers = images
    plt.ioff()
    bbox = layers[0].bbox
    gs1 = gs.GridSpec(nrows, ncols)
    fig = plt.figure(facecolor='black', figsize=(3*ncols, 3*nrows))
    if cbar:
        if isinstance(cbar, bool):
            cbar = 0
        gs1.update(left=0.01, right=0.88, bottom=0.01,
                   top=0.99, wspace=0.01, hspace=0.01)
        gs2 = gs.GridSpec(1, 1)
        gs2.update(left=0.92, right=0.98, bottom=0.1,
                   top=0.9, wspace=0.1, hspace=0.1)
        cax = fig.add_subplot(gs2[0], facecolor='white')
        clayer = layers[cbar]
        if clayer.alpha_image:
            if contour:
                try:
                    iterator = iter(contour)
                except:
                    contour = (contour,)
            alphabar(cax,
                     clayer.cmap, clayer.clim, clayer.label,
                     clayer.alpha_lim, clayer.alpha_label,
                     alines=contour, black_backg=True, orient='v')
        else:
            colorbar(cax,
                     clayer.cmap, clayer.clim, clayer.label,
                     black_backg=True, orient='v')
    else:
        gs1.update(left=0.01, right=0.99, bottom=0.01,
                   top=0.99, wspace=0.01, hspace=0.01)
    for row in range(nrows):
        for col in range(ncols):
            i = row*ncols + col
            axis = slice_axes[i]
            if absolute:
                pos = slice_pos[i]
            else:
                pos = bbox.start[Axis_map[axis]] + \
                    bbox.diag[Axis_map[axis]]*slice_pos[i]
            slcr = Slicer(bbox, pos, axis, samples=samples, orient=orient)
            blended_slice = blend_layers(layers, slcr)
            iax = fig.add_subplot(gs1[row, col], facecolor='black')
            iax.imshow(blended_slice, origin='lower',
                       extent=slcr.extent, interpolation='nearest')
            iax.axis('off')
            if contour:
                sl_contour = layers[cbar].get_alpha(slcr)
                iax.contour(sl_contour, levels=contour, origin='lower', extent=slcr.extent,
                            colors='k', linestyles='-', linewidths=1)
    if title:
        fig.suptitle(title, color='white')
    plt.close()
    return fig

def timeseries(image, axis='z', orient='clin', clim=None, title=None):
    series = Layer(image, clim=clim)
    plt.ioff()
    bbox = series.bbox
    N = series.matrix[3]
    gs1 = gs.GridSpec(1, N)
    fig = plt.figure(facecolor='black', figsize=(3*N, 3))

    ax_ind = Axis_map[axis]
    slcr = Slicer(bbox, bbox.center[ax_ind],
                  axis, samples=series.matrix[ax_ind], orient=orient)
    for i in range(N):
        series.volume = i
        sl = series.get_color(slcr)
        iax = fig.add_subplot(gs1[i], facecolor='black')
        iax.imshow(sl, origin='lower', extent=slcr.extent,
                   interpolation='nearest')
        iax.axis('off')
    if title:
        plt.suptitle(title, color='w')
    plt.close()
    return fig

def compare(image1, image2, axis='z', orient='clin', samples=128,
            clim=None, title=None):
    layer1 = Layer(image1, interp_order=0, clim=clim)
    layer2 = Layer(image2, interp_order=0, clim=layer1.clim)
    plt.ioff()
    bbox = layer1.bbox
    gs1 = gs.GridSpec(1, 2)
    fig = plt.figure(facecolor='black', figsize=(6, 3))

    gs1.update(left=0.01, right=0.88, bottom=0.01,
               top=0.99, wspace=0.01, hspace=0.01)
    gs2 = gs.GridSpec(1, 1)
    gs2.update(left=0.92, right=0.98, bottom=0.1,
               top=0.9, wspace=0.1, hspace=0.1)
    cax = fig.add_subplot(gs2[0], facecolor='white')
    colorbar(cax,
             layer1.cmap, layer1.clim, layer1.label,
             black_backg=True, orient='v')

    ax_ind = Axis_map[axis]
    slcr = Slicer(bbox, bbox.center[ax_ind],
                  axis, samples=layer1.matrix[ax_ind], orient=orient)
    slice1 = layer1.get_color(slcr)
    slice2 = layer2.get_color(slcr)
    iax = fig.add_subplot(gs1[0], facecolor='black')
    iax.imshow(slice1, origin='lower', extent=slcr.extent,
               interpolation='nearest')
    iax.axis('off')
    iax = fig.add_subplot(gs1[1], facecolor='black')
    iax.imshow(slice2, origin='lower', extent=slcr.extent,
               interpolation='nearest')
    iax.axis('off')
    if title:
        fig.suptitle(title, color='white')
    plt.close()
    return fig
<commit_msg>ENH Add a volume option to three_plane<commit_after>#!/usr/bin/env python
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gs
import ipywidgets as ipy
from . import util
from .slicer import Slicer, Axis_map
from .layer import Layer, blend_layers
from .colorbar import colorbar, alphabar

def three_plane(images, orient='clin', samples=128,
                cbar=None, contour=None,
                interactive=False):
    """
    Draw a standard 3-plane view through the center of the image

    Parameters:

    - images -- Either a filename (in a string or Path object) or a list of Layer objects
    - orient -- 'clin' or 'preclin'
    - sample -- Number of samples, default is 128, higher is better but slower
    - cbar -- Adds a colorbar. Either 'True' or an integer giving the layer the colorbar is from
    - contour -- Value(s) that contours are drawn at. Requires that cbar be set - contours will come from same layer
    - interactive -- Add sliders and make the view interactive
    """

def three_plane(images, orient='clin', samples=128,
                volume=0, cbar=None, contour=None,
                interactive=False, title=None):
    if interactive:
        plt.ion()
    else:
        plt.ioff()
    if isinstance(images, str):
        layers = [Layer(images, volume=volume), ]
    elif isinstance(images, Layer):
        layers = [images, ]
    elif isinstance(images[0], str):
        layers = [Layer(img, volume=volume) for img in images]
    else:
        layers = images
    bbox = layers[0].bbox
    gs1 = gs.GridSpec(1, 3)
    fig = plt.figure(facecolor='black', figsize=(9, 3))
    if cbar:
        if isinstance(cbar, bool):
            cbar = 0
        gs1.update(left=0.01, right=0.88, bottom=0.01,
                   top=0.99, wspace=0.01, hspace=0.01)
        gs2 = gs.GridSpec(1, 1)
        gs2.update(left=0.92, right=0.98, bottom=0.1,
                   top=0.9, wspace=0.1, hspace=0.1)
        cax = fig.add_subplot(gs2[0], facecolor='white')
        clayer = layers[cbar]
        if clayer.alpha_image:
            if contour:
                try:
                    iterator = iter(contour)
                except:
                    contour = (contour,)
            alphabar(cax,
                     clayer.cmap, clayer.clim, clayer.label,
                     clayer.alpha_lim, clayer.alpha_label,
                     alines=contour, black_backg=True, orient='v')
        else:
            colorbar(cax,
                     clayer.cmap, clayer.clim, clayer.label,
                     black_backg=True, orient='v')
    else:
        gs1.update(left=0.01, right=0.99, bottom=0.01,
                   top=0.99, wspace=0.01, hspace=0.01)
    implots = [None, None, None]
    iax = [None, None, None]

    def wrap_sections(pos_x, pos_y, pos_z):
        pos = (pos_x, pos_y, pos_z)
        for i in range(3):
            slcr = Slicer(bbox, pos[i], i, samples=samples, orient=orient)
            blended_slice = blend_layers(layers, slcr)
            if implots[i]:
                implots[i].set_data(blended_slice)
            else:
                iax[i] = fig.add_subplot(gs1[i], facecolor='black')
                implots[i] = iax[i].imshow(
                    blended_slice, origin='lower', extent=slcr.extent, interpolation='nearest')
                iax[i].axis('off')
            if contour:
                sl_contour = layers[cbar].get_alpha(slcr)
                iax[i].contour(sl_contour, levels=contour, origin='lower', extent=slcr.extent,
                               colors='k', linestyles='-', linewidths=1)
    wrap_sections(bbox.center[0], bbox.center[1], bbox.center[2])
    if title:
        fig.suptitle(title, color='white')
    if interactive:
        # Setup widgets
        slider_x = ipy.FloatSlider(min=bbox.start[0], max=bbox.end[0], value=bbox.center[0],
                                   continuous_update=True, description='X:')
        slider_y = ipy.FloatSlider(min=bbox.start[1], max=bbox.end[1], value=bbox.center[1],
                                   continuous_update=True, description='Y:')
        slider_z = ipy.FloatSlider(min=bbox.start[2], max=bbox.end[2], value=bbox.center[2],
                                   continuous_update=True, description='Z:')
        widgets = ipy.interactive(
            wrap_sections, pos_x=slider_x, pos_y=slider_y, pos_z=slider_z)
        # Now do some manual layout
        # Set the sliders to horizontal layout
        hbox = ipy.HBox(widgets.children[0:3])
        vbox = ipy.VBox((hbox, widgets.children[3]))
        # iplot.widget.children[-1].layout.height = '350px'
        return vbox
    else:
        plt.close()
        return fig

def slice_axis(images, nrows=1, ncols=3, slice_axis='z', slice_lims=(0.25, 0.75),
               orient='clin', samples=128,
               cbar=None, contour=None, title=None):
    ntotal = nrows*ncols
    slice_axes = slice_axis * ntotal
    slice_pos = np.linspace(slice_lims[0], slice_lims[1], num=ntotal)
    return slices(images, nrows, ncols, slice_axes, slice_pos, False, orient, samples, cbar, contour, title)

def slices(images, nrows=1, ncols=1, slice_axes=['z', ], slice_pos=[0.5, ], absolute=False,
           orient='clin', samples=128,
           cbar=None, contour=None, title=None):
    if isinstance(images, str):
        layers = [Layer(images), ]
    elif isinstance(images, Layer):
        layers = [images, ]
    elif isinstance(images[0], str):
        layers = [Layer(img) for img in images]
    else:
        layers = images
    plt.ioff()
    bbox = layers[0].bbox
    gs1 = gs.GridSpec(nrows, ncols)
    fig = plt.figure(facecolor='black', figsize=(3*ncols, 3*nrows))
    if cbar:
        if isinstance(cbar, bool):
            cbar = 0
        gs1.update(left=0.01, right=0.88, bottom=0.01,
                   top=0.99, wspace=0.01, hspace=0.01)
        gs2 = gs.GridSpec(1, 1)
        gs2.update(left=0.92, right=0.98, bottom=0.1,
                   top=0.9, wspace=0.1, hspace=0.1)
        cax = fig.add_subplot(gs2[0], facecolor='white')
        clayer = layers[cbar]
        if clayer.alpha_image:
            if contour:
                try:
                    iterator = iter(contour)
                except:
                    contour = (contour,)
            alphabar(cax,
                     clayer.cmap, clayer.clim, clayer.label,
                     clayer.alpha_lim, clayer.alpha_label,
                     alines=contour, black_backg=True, orient='v')
        else:
            colorbar(cax,
                     clayer.cmap, clayer.clim, clayer.label,
                     black_backg=True, orient='v')
    else:
        gs1.update(left=0.01, right=0.99, bottom=0.01,
                   top=0.99, wspace=0.01, hspace=0.01)
    for row in range(nrows):
        for col in range(ncols):
            i = row*ncols + col
            axis = slice_axes[i]
            if absolute:
                pos = slice_pos[i]
            else:
                pos = bbox.start[Axis_map[axis]] + \
                    bbox.diag[Axis_map[axis]]*slice_pos[i]
            slcr = Slicer(bbox, pos, axis, samples=samples, orient=orient)
            blended_slice = blend_layers(layers, slcr)
            iax = fig.add_subplot(gs1[row, col], facecolor='black')
            iax.imshow(blended_slice, origin='lower',
                       extent=slcr.extent, interpolation='nearest')
            iax.axis('off')
            if contour:
                sl_contour = layers[cbar].get_alpha(slcr)
                iax.contour(sl_contour, levels=contour, origin='lower', extent=slcr.extent,
                            colors='k', linestyles='-', linewidths=1)
    if title:
        fig.suptitle(title, color='white')
    plt.close()
    return fig

def timeseries(image, axis='z', orient='clin', clim=None, title=None):
    series = Layer(image, clim=clim)
    plt.ioff()
    bbox = series.bbox
    N = series.matrix[3]
    gs1 = gs.GridSpec(1, N)
    fig = plt.figure(facecolor='black', figsize=(3*N, 3))

    ax_ind = Axis_map[axis]
    slcr = Slicer(bbox, bbox.center[ax_ind],
                  axis, samples=series.matrix[ax_ind], orient=orient)
    for i in range(N):
        series.volume = i
        sl = series.get_color(slcr)
        iax = fig.add_subplot(gs1[i], facecolor='black')
        iax.imshow(sl, origin='lower', extent=slcr.extent,
                   interpolation='nearest')
        iax.axis('off')
    if title:
        plt.suptitle(title, color='w')
    plt.close()
    return fig

def compare(image1, image2, axis='z', orient='clin', samples=128,
            clim=None, title=None):
    layer1 = Layer(image1, interp_order=0, clim=clim)
    layer2 = Layer(image2, interp_order=0, clim=layer1.clim)
    plt.ioff()
    bbox = layer1.bbox
    gs1 = gs.GridSpec(1, 2)
    fig = plt.figure(facecolor='black', figsize=(6, 3))

    gs1.update(left=0.01, right=0.88, bottom=0.01,
               top=0.99, wspace=0.01, hspace=0.01)
    gs2 = gs.GridSpec(1, 1)
    gs2.update(left=0.92, right=0.98, bottom=0.1,
               top=0.9, wspace=0.1, hspace=0.1)
    cax = fig.add_subplot(gs2[0], facecolor='white')
    colorbar(cax,
             layer1.cmap, layer1.clim, layer1.label,
             black_backg=True, orient='v')

    ax_ind = Axis_map[axis]
    slcr = Slicer(bbox, bbox.center[ax_ind],
                  axis, samples=layer1.matrix[ax_ind], orient=orient)
    slice1 = layer1.get_color(slcr)
    slice2 = layer2.get_color(slcr)
    iax = fig.add_subplot(gs1[0], facecolor='black')
    iax.imshow(slice1, origin='lower', extent=slcr.extent,
               interpolation='nearest')
    iax.axis('off')
    iax = fig.add_subplot(gs1[1], facecolor='black')
    iax.imshow(slice2, origin='lower', extent=slcr.extent,
               interpolation='nearest')
    iax.axis('off')
    if title:
        fig.suptitle(title, color='white')
    plt.close()
    return fig
<|endoftext|>


<commit_before>#! /usr/bin/env python3
"""An alternative Python freeze implementation.

The two primary motivations for this implementation of freeze (when
compared to the standard freeze distributed with Python) are

1) Correctly works with Python3.

2) Includes the entire standard library (rather than searching
for specific modules).

The primary reason for this is that the applications I wish to
target allow some form of plugins, so it is not possible to
know the entire set of required modules ahead of time.

Obviously there is a space trade-off and this may not be the best
solution in other use-cases. The standard library, is relatively
large, so if you don't use much of it, and don't need plugins, then
this is probably not for you (try cxFreeze).

Additional motivations:

For all I know cxFreeze, or some other tool out there already supports
this use case (or could be shoe-horned in to supporting it). My other
motivations for creating this are as a learning experience to ensure
that I fully understand the workings of Python frozen modules. Finally
this provides a simple code base for additional experimentation.

Frozen Library:

This module does two main things:

1) Create `frozen libraries`

2) Create an application 'main.c' from a list of frozen libraries.

A frozen library is a group of individual modules frozen in a single
C file. The C file basically contains a C array representation of
the compiled (and optimised) byte code for the module. Additionally
the frozen library has a <library_name>_struct.h and
<library_name>_extern.h file that contains structure elements,
and extern definitions of the library. These header files are
used when creating an app, but can be included in a C file directly
if you know what you are doing.

Usage:

The primary interfaces that will be used are:

  create_stdlib: Creates a frozen version of the standard library.
  create_lib: Create a frozen version of a an existing library.
  create_app: Create a main.c suitable for intialising a list of frozen libraries.

Static Python:

My end goal when using a freeze application is to ensure that I can
distribute a single binary with minimal external dependencies. To
achieve this it is ideal if the targetted Python does not need to use
dynamic extensions. This can be achieved by statically compiling
Python. The exact mechanics for that are beyond the scope fo this
documentation, however the `xyz` packaging tool can be used to
compile an appropriate Python: https://github.com/BreakawayConsulting/xyz
Or if (like me) you prefer full control over what you are doing
see the specific rules and Setup.dist files:

https://github.com/BreakawayConsulting/xyz/blob/master/rules/python.py
https://github.com/BreakawayConsulting/xyz/blob/master/rules/pySetup.dist.darwin

Drawbacks:

This current version does not really have any explicit support for
libraries outside of the standard library. It wouldn't be hard to add.

The command line interface is relatively limited right now. You will
probably get more out of it using it as a library, than as a raw tool.

Currently this tool is just about creating the raw C files. It doen't
create any Makefile or similar for compiling the frozen libraries or
application. This is intentional as my primary use cases involved
systems and application embedded in existing programs with their
own build system.

This has only been tested with my use-cases so your milage may vary!

"""
import marshal
import os
import re
import sys
import tokenize

STDLIB_EXCLUDE_LIST = ['test', 'tkinter', 'turtledemo',
                       'tkinter', 'lib2to3', 'idlelib',
                       'distutils']

SUFFIX = '.py'

HEADER = """/* Generated by freeze.py */
#include <Python.h>

"""

MAIN_FN = """
#include <locale.h>

int
main(int argc, char *argv[])
{
    wchar_t **argv_copy = (wchar_t **)PyMem_Malloc(sizeof(wchar_t*)*(argc + 1));
    /* We need a second copies, as Python might modify the first one. */
    wchar_t **argv_copy2 = (wchar_t **)PyMem_Malloc(sizeof(wchar_t*)*(argc + 1));
    int i, n, res = 0;
    char *oldloc;

    if (!argv_copy || !argv_copy2)
    {
        fprintf(stderr, "out of memory\\n");
        return 1;
    }

    oldloc = strdup(setlocale(LC_ALL, NULL));
    setlocale(LC_ALL, "");
    for (i = 0; i < argc; i++)
    {
        argv_copy[i] = _Py_char2wchar(argv[i], NULL);
        if (!argv_copy[i])
        {
            free(oldloc);
            fprintf(stderr, "Fatal Python error: "
                            "unable to decode the command line argument #%i\\n",
                            i + 1);
            return 1;
        }
        argv_copy2[i] = argv_copy[i];
    }
    argv_copy2[argc] = argv_copy[argc] = NULL;

    setlocale(LC_ALL, oldloc);
    free(oldloc);

    Py_FrozenFlag = 1; /* suppress errors from getpath.c */

    Py_Initialize();
    PySys_SetArgvEx(argc, argv_copy, 0);

    n = PyImport_ImportFrozenModule("__main__");

    if (n < 0)
    {
        PyErr_Print();
        res = 1;
    }

    Py_Finalize();
    for (i = 0; i < argc; i++) {
        PyMem_Free(argv_copy2[i]);
    }
    PyMem_Free(argv_copy);
    PyMem_Free(argv_copy2);

    return res;
}

"""

ARRAY_HEADER = """
static struct _frozen _PyImport_FrozenModules[] = {
"""

ARRAY_TRAILER = """\
    {0, 0, 0} /* sentinel */
};

struct _frozen *PyImport_FrozenModules = _PyImport_FrozenModules;
"""

def dict_inverse(dct, exact=False):
    """Given an input dictionary (`dct`), create a new dictionary
    where the keys are indexed by the values. In the original
    dictionary multiple keys may reference the same value, so the
    values in the new dictionary is a list of keys. The order of keys
    in the list is undefined.

    Example:

    > dict_inverse({1: 'a', 2: 'a', 3: 'c'})
    { 'a': [1, 2], 'c': [3]

    If `dct` has an exact inverse mapping `exact` can be passed as
    True. In this case, the values will be just the original key (not
    a list).

    Example:

    > dict_inverse({1: 'a', 2: 'b', 3: 'c'}, exact=True)
    { 'a': 1, 'b': 2, 'c': 3}

    Note: No checking is done when exact is True, so in the case
    where there are multiple keys mapping the same value it is
    undefined as to which key the value will map to.

    From: https://github.com/bennoleslie/pyutil.git

    """
    if exact:
        return {value: key for key, value in dct.items()}

    r = {}
    for key, value in dct.items():
        r.setdefault(value, []).append(key)
    return r

def write_byte_code(outf, var_name, byte_code):
    """Write out `byte_code` as variable `var_name` to a file-like object `outf`."""

    outf.write('unsigned char {}[] = {{'.format(var_name))
    for i in range(0, len(byte_code), 16):
        outf.write('\n    ')
        for c in bytes(byte_code[i:i + 16]):
            outf.write('%d,' % c)
    outf.write('\n};\n')

def create_frozen_lib(name, mods, aliases={}):
    """Create a new *frozen library* called `name`.

    `mods` is a dictionary of module descriptions indexed by module
    name.  A module description is a triple of
      (filename, short_filename, is_pkg).

    This is the same format as returned by `find_modules`.

    A frozen library can contain a number of aliases. Specifically
    that means that a given Python module may be importable under its
    normal name, plus any number of aliases names. The alias is a
    dictionary indexed by the alias name, with the value being the
    name of the underlying module.

    """
    extern_fmt = 'extern unsigned char {}[];\n'
    struct_fmt = '    {{"{}", {}, {}}},\n'
    c_filename = '{}.c'.format(name)
    h_struct_filename = '{}_struct.h'.format(name)
    h_extern_filename = '{}_extern.h'.format(name)

    # Although easier for the user to specify {alias: module}
    # the code is simpler if we have {module: [aliases]}
    aliases = dict_inverse(aliases)

    with open(h_struct_filename, 'w') as h_struct, \
            open(h_extern_filename, 'w') as h_ext, \
            open(c_filename, 'w') as c_out:

        for mod_name in sorted(mods.keys()):
            (filename, short_filename, is_pkg) = mods[mod_name]
            with tokenize.open(filename) as f:
                code = compile(f.read(), short_filename, 'exec', optimize=2)
            var_name = "M_" + "__".join(mod_name.split("."))
            raw_code = marshal.dumps(code)
            size = len(raw_code)
            # Packages are indicated by negative size; this is part of
            # the Pythohn frozen library internals.
            if is_pkg:
                size = -size

            write_byte_code(c_out, var_name, raw_code)

            h_ext.write(extern_fmt.format(var_name))

            h_struct.write(struct_fmt.format(mod_name, var_name, size))

            # Write out all the aliases
            for alias in aliases.get(mod_name, []):
                h_struct.write(struct_fmt.format(alias, var_name, size))

def find_modules(libdir, excluded=[]):
    """Find all the Python modules (and packages) in a given directory `libdir`.

    Note: The 'libdir' is generally something you would otherwise place in
    the Python path. It must not be a package itself. (i.e.: it should not contain
    an __init__.py file.)

    Return a dictionary of (full_filename, short_filename, is_pkg) tuples
    indexed by fully qualified module name.

    full_filename is a complete path to the module.
    short_filename is the path with the `libdir` prefix removed.
    is_pkg is True if the module is a package.

    This only tries to find .py modules.

    Any module that prefix matches a module listed in 'excluded' will
    be ignored.

    """
    # Ensure libdir endswith a trailing slash
    if not libdir.endswith(os.path.sep):
        libdir += os.path.sep

    modules = {}

    for root, dirs, fns in os.walk(libdir):
        if "__pycache__" in dirs:  # pycache directories are ignored
            dirs.remove("__pycache__")

        for d in dirs:
            # If a directory doesn't look like a package, ignore it.
            if not os.path.exists(os.path.join(root, d, '__init__' + SUFFIX)):
                dirs.remove(d)

        pkg_name = root[len(libdir):].replace(os.path.sep, '.')
        for fn in [fn for fn in fns if fn.endswith(SUFFIX)]:
            filename = os.path.join(root, fn)
            short_filename = filename[len(libdir):]
            mod_name = fn[:-len(SUFFIX)]
            is_pkg = mod_name == "__init__"
            if is_pkg and pkg_name == '':
                raise Exception("The libdir can't include an __init__.py file.")

            if pkg_name != '':
                mod_name = pkg_name if is_pkg else pkg_name + '.' + mod_name

            exclude = False
            for e in excluded:
                if mod_name.startswith(e):
                    exclude = True
                    break

            if not exclude:
                modules[mod_name] = (filename, short_filename, is_pkg)

    return modules

def merge_dict(dict1, dict2):
    return dict(list(dict1.items()) + list(dict2.items()))

def create_stdlib(excluded=STDLIB_EXCLUDE_LIST):
    """Create a frozen version of the standard library.

    The location of the standard library is determined automatically
    through introspection.

    Specific modules can be excluded with the frozen library. `excluded`
    is a list of modules to exclude (via a simple prefix match).

    """
    version = sys.version[:3]
    libdir = os.path.join(sys.prefix, 'lib', 'python{}'.format(version))
    elibdir = os.path.join(sys.exec_prefix, 'lib', 'python{}'.format(version), 'lib-dynload')
    create_frozen_lib('stdlib',
                      merge_dict(find_modules(libdir, excluded=excluded),
                                 find_modules(elibdir, excluded=excluded)),
                      {'_frozen_importlib': 'importlib._bootstrap'})

def create_lib(name, path, main=None):
    """Create a new frozen library with modules from the specified
    path. `main` can be set to the name of a module, which will be
    aliases as '__main__' in the frozen library.

    NOTE: The main parameter may be deprecated in the future in favour
    of passing it directly to create_app.

    """
    mods = find_modules(path)
    aliases = {}
    if main is not None:
        aliases['__main__'] = main
    create_frozen_lib(name, mods, aliases)

def create_app(libs, filename='main.c'):
    """Create an application from a list of frozen libraries.

    One (and only one) of the frozen libraries should have been
    created with the 'main' argument.

    The application is output in file `filename` (which defaults to
    main.c

    NOTE: In the future create_app may directly specify the module
    to use as __main__, rather than relying on a create_lib.

    """
    with open(filename, 'w') as outf:
        outf.write(HEADER)
        outf.write(MAIN_FN)

        for l in libs:
            with open('{}_extern.h'.format(l)) as f:
                outf.write(f.read())

        outf.write(ARRAY_HEADER)
        for l in libs:
            with open('{}_struct.h'.format(l)) as f:
                outf.write(f.read())

        outf.write(ARRAY_TRAILER)

def main(argv):
    import argparse

    parser = argparse.ArgumentParser()
    subparsers = parser.add_subparsers(dest='command')

    stdlib_p = subparsers.add_parser('stdlib', help='Create frozen standard library.')

    lib_p = subparsers.add_parser('lib', help='Create frozen library')
    lib_p.add_argument('name', help='library name')
    lib_p.add_argument('path', help='library path')
    lib_p.add_argument('--main', default=None, help='library path')

    app_p = subparsers.add_parser('app', help='Create app main.c from frozen libraries')
    app_p.add_argument('libs', nargs='+', help='libraries')

    args = parser.parse_args()

    if args.command is None:
        parser.print_help()
        return 1

    if args.command == 'stdlib':
        create_stdlib()
    elif args.command == 'lib':
        create_lib(args.name, args.path, args.main)
    elif args.command == 'app':
        create_app(args.libs)

    return 0

if __name__ == "__main__":
    sys.exit(main(sys.argv))
<commit_msg>Copy dirs so the remove() works correctly.<commit_after>#! /usr/bin/env python3
"""An alternative Python freeze implementation.

The two primary motivations for this implementation of freeze (when
compared to the standard freeze distributed with Python) are

1) Correctly works with Python3.

2) Includes the entire standard library (rather than searching
for specific modules).

The primary reason for this is that the applications I wish to
target allow some form of plugins, so it is not possible to
know the entire set of required modules ahead of time.

Obviously there is a space trade-off and this may not be the best
solution in other use-cases. The standard library, is relatively
large, so if you don't use much of it, and don't need plugins, then
this is probably not for you (try cxFreeze).

Additional motivations:

For all I know cxFreeze, or some other tool out there already supports
this use case (or could be shoe-horned in to supporting it). My other
motivations for creating this are as a learning experience to ensure
that I fully understand the workings of Python frozen modules. Finally
this provides a simple code base for additional experimentation.

Frozen Library:

This module does two main things:

1) Create `frozen libraries`

2) Create an application 'main.c' from a list of frozen libraries.

A frozen library is a group of individual modules frozen in a single
C file. The C file basically contains a C array representation of
the compiled (and optimised) byte code for the module. Additionally
the frozen library has a <library_name>_struct.h and
<library_name>_extern.h file that contains structure elements,
and extern definitions of the library. These header files are
used when creating an app, but can be included in a C file directly
if you know what you are doing.

Usage:

The primary interfaces that will be used are:

  create_stdlib: Creates a frozen version of the standard library.
  create_lib: Create a frozen version of a an existing library.
  create_app: Create a main.c suitable for intialising a list of frozen libraries.

Static Python:

My end goal when using a freeze application is to ensure that I can
distribute a single binary with minimal external dependencies. To
achieve this it is ideal if the targetted Python does not need to use
dynamic extensions. This can be achieved by statically compiling
Python. The exact mechanics for that are beyond the scope fo this
documentation, however the `xyz` packaging tool can be used to
compile an appropriate Python: https://github.com/BreakawayConsulting/xyz
Or if (like me) you prefer full control over what you are doing
see the specific rules and Setup.dist files:

https://github.com/BreakawayConsulting/xyz/blob/master/rules/python.py
https://github.com/BreakawayConsulting/xyz/blob/master/rules/pySetup.dist.darwin

Drawbacks:

This current version does not really have any explicit support for
libraries outside of the standard library. It wouldn't be hard to add.

The command line interface is relatively limited right now. You will
probably get more out of it using it as a library, than as a raw tool.

Currently this tool is just about creating the raw C files. It doen't
create any Makefile or similar for compiling the frozen libraries or
application. This is intentional as my primary use cases involved
systems and application embedded in existing programs with their
own build system.

This has only been tested with my use-cases so your milage may vary!

"""
import marshal
import os
import re
import sys
import tokenize

STDLIB_EXCLUDE_LIST = ['test', 'tkinter', 'turtledemo',
                       'tkinter', 'lib2to3', 'idlelib',
                       'distutils']

SUFFIX = '.py'

HEADER = """/* Generated by freeze.py */
#include <Python.h>

"""

MAIN_FN = """
#include <locale.h>

int
main(int argc, char *argv[])
{
    wchar_t **argv_copy = (wchar_t **)PyMem_Malloc(sizeof(wchar_t*)*(argc + 1));
    /* We need a second copies, as Python might modify the first one. */
    wchar_t **argv_copy2 = (wchar_t **)PyMem_Malloc(sizeof(wchar_t*)*(argc + 1));
    int i, n, res = 0;
    char *oldloc;

    if (!argv_copy || !argv_copy2)
    {
        fprintf(stderr, "out of memory\\n");
        return 1;
    }

    oldloc = strdup(setlocale(LC_ALL, NULL));
    setlocale(LC_ALL, "");
    for (i = 0; i < argc; i++)
    {
        argv_copy[i] = _Py_char2wchar(argv[i], NULL);
        if (!argv_copy[i])
        {
            free(oldloc);
            fprintf(stderr, "Fatal Python error: "
                            "unable to decode the command line argument #%i\\n",
                            i + 1);
            return 1;
        }
        argv_copy2[i] = argv_copy[i];
    }
    argv_copy2[argc] = argv_copy[argc] = NULL;

    setlocale(LC_ALL, oldloc);
    free(oldloc);

    Py_FrozenFlag = 1; /* suppress errors from getpath.c */

    Py_Initialize();
    PySys_SetArgvEx(argc, argv_copy, 0);

    n = PyImport_ImportFrozenModule("__main__");

    if (n < 0)
    {
        PyErr_Print();
        res = 1;
    }

    Py_Finalize();
    for (i = 0; i < argc; i++) {
        PyMem_Free(argv_copy2[i]);
    }
    PyMem_Free(argv_copy);
    PyMem_Free(argv_copy2);

    return res;
}

"""

ARRAY_HEADER = """
static struct _frozen _PyImport_FrozenModules[] = {
"""

ARRAY_TRAILER = """\
    {0, 0, 0} /* sentinel */
};

struct _frozen *PyImport_FrozenModules = _PyImport_FrozenModules;
"""

def dict_inverse(dct, exact=False):
    """Given an input dictionary (`dct`), create a new dictionary
    where the keys are indexed by the values. In the original
    dictionary multiple keys may reference the same value, so the
    values in the new dictionary is a list of keys. The order of keys
    in the list is undefined.

    Example:

    > dict_inverse({1: 'a', 2: 'a', 3: 'c'})
    { 'a': [1, 2], 'c': [3]

    If `dct` has an exact inverse mapping `exact` can be passed as
    True. In this case, the values will be just the original key (not
    a list).

    Example:

    > dict_inverse({1: 'a', 2: 'b', 3: 'c'}, exact=True)
    { 'a': 1, 'b': 2, 'c': 3}

    Note: No checking is done when exact is True, so in the case
    where there are multiple keys mapping the same value it is
    undefined as to which key the value will map to.

    From: https://github.com/bennoleslie/pyutil.git

    """
    if exact:
        return {value: key for key, value in dct.items()}

    r = {}
    for key, value in dct.items():
        r.setdefault(value, []).append(key)
    return r

def write_byte_code(outf, var_name, byte_code):
    """Write out `byte_code` as variable `var_name` to a file-like object `outf`."""

    outf.write('unsigned char {}[] = {{'.format(var_name))
    for i in range(0, len(byte_code), 16):
        outf.write('\n    ')
        for c in bytes(byte_code[i:i + 16]):
            outf.write('%d,' % c)
    outf.write('\n};\n')

def create_frozen_lib(name, mods, aliases={}):
    """Create a new *frozen library* called `name`.

    `mods` is a dictionary of module descriptions indexed by module
    name.  A module description is a triple of
      (filename, short_filename, is_pkg).

    This is the same format as returned by `find_modules`.

    A frozen library can contain a number of aliases. Specifically
    that means that a given Python module may be importable under its
    normal name, plus any number of aliases names. The alias is a
    dictionary indexed by the alias name, with the value being the
    name of the underlying module.

    """
    extern_fmt = 'extern unsigned char {}[];\n'
    struct_fmt = '    {{"{}", {}, {}}},\n'
    c_filename = '{}.c'.format(name)
    h_struct_filename = '{}_struct.h'.format(name)
    h_extern_filename = '{}_extern.h'.format(name)

    # Although easier for the user to specify {alias: module}
    # the code is simpler if we have {module: [aliases]}
    aliases = dict_inverse(aliases)

    with open(h_struct_filename, 'w') as h_struct, \
            open(h_extern_filename, 'w') as h_ext, \
            open(c_filename, 'w') as c_out:

        for mod_name in sorted(mods.keys()):
            (filename, short_filename, is_pkg) = mods[mod_name]
            with tokenize.open(filename) as f:
                code = compile(f.read(), short_filename, 'exec', optimize=2)
            var_name = "M_" + "__".join(mod_name.split("."))
            raw_code = marshal.dumps(code)
            size = len(raw_code)
            # Packages are indicated by negative size; this is part of
            # the Pythohn frozen library internals.
            if is_pkg:
                size = -size

            write_byte_code(c_out, var_name, raw_code)

            h_ext.write(extern_fmt.format(var_name))

            h_struct.write(struct_fmt.format(mod_name, var_name, size))

            # Write out all the aliases
            for alias in aliases.get(mod_name, []):
                h_struct.write(struct_fmt.format(alias, var_name, size))

def find_modules(libdir, excluded=[]):
    """Find all the Python modules (and packages) in a given directory `libdir`.

    Note: The 'libdir' is generally something you would otherwise place in
    the Python path. It must not be a package itself. (i.e.: it should not contain
    an __init__.py file.)

    Return a dictionary of (full_filename, short_filename, is_pkg) tuples
    indexed by fully qualified module name.

    full_filename is a complete path to the module.
    short_filename is the path with the `libdir` prefix removed.
    is_pkg is True if the module is a package.

    This only tries to find .py modules.

    Any module that prefix matches a module listed in 'excluded' will
    be ignored.

    """
    # Ensure libdir endswith a trailing slash
    if not libdir.endswith(os.path.sep):
        libdir += os.path.sep

    modules = {}

    for root, dirs, fns in os.walk(libdir):
        if "__pycache__" in dirs:  # pycache directories are ignored
            dirs.remove("__pycache__")

        for d in dirs[:]:
            # If a directory doesn't look like a package, ignore it.
            if not os.path.exists(os.path.join(root, d, '__init__' + SUFFIX)):
                dirs.remove(d)

        pkg_name = root[len(libdir):].replace(os.path.sep, '.')
        for fn in [fn for fn in fns if fn.endswith(SUFFIX)]:
            filename = os.path.join(root, fn)
            short_filename = filename[len(libdir):]
            mod_name = fn[:-len(SUFFIX)]
            is_pkg = mod_name == "__init__"
            if is_pkg and pkg_name == '':
                raise Exception("The libdir can't include an __init__.py file.")

            if pkg_name != '':
                mod_name = pkg_name if is_pkg else pkg_name + '.' + mod_name

            exclude = False
            for e in excluded:
                if mod_name.startswith(e):
                    exclude = True
                    break

            if not exclude:
                modules[mod_name] = (filename, short_filename, is_pkg)

    return modules

def merge_dict(dict1, dict2):
    return dict(list(dict1.items()) + list(dict2.items()))

def create_stdlib(excluded=STDLIB_EXCLUDE_LIST):
    """Create a frozen version of the standard library.

    The location of the standard library is determined automatically
    through introspection.

    Specific modules can be excluded with the frozen library. `excluded`
    is a list of modules to exclude (via a simple prefix match).

    """
    version = sys.version[:3]
    libdir = os.path.join(sys.prefix, 'lib', 'python{}'.format(version))
    elibdir = os.path.join(sys.exec_prefix, 'lib', 'python{}'.format(version), 'lib-dynload')
    create_frozen_lib('stdlib',
                      merge_dict(find_modules(libdir, excluded=excluded),
                                 find_modules(elibdir, excluded=excluded)),
                      {'_frozen_importlib': 'importlib._bootstrap'})

def create_lib(name, path, main=None):
    """Create a new frozen library with modules from the specified
    path. `main` can be set to the name of a module, which will be
    aliases as '__main__' in the frozen library.

    NOTE: The main parameter may be deprecated in the future in favour
    of passing it directly to create_app.

    """
    mods = find_modules(path)
    aliases = {}
    if main is not None:
        aliases['__main__'] = main
    create_frozen_lib(name, mods, aliases)

def create_app(libs, filename='main.c'):
    """Create an application from a list of frozen libraries.

    One (and only one) of the frozen libraries should have been
    created with the 'main' argument.

    The application is output in file `filename` (which defaults to
    main.c

    NOTE: In the future create_app may directly specify the module
    to use as __main__, rather than relying on a create_lib.

    """
    with open(filename, 'w') as outf:
        outf.write(HEADER)
        outf.write(MAIN_FN)

        for l in libs:
            with open('{}_extern.h'.format(l)) as f:
                outf.write(f.read())

        outf.write(ARRAY_HEADER)
        for l in libs:
            with open('{}_struct.h'.format(l)) as f:
                outf.write(f.read())

        outf.write(ARRAY_TRAILER)

def main(argv):
    import argparse

    parser = argparse.ArgumentParser()
    subparsers = parser.add_subparsers(dest='command')

    stdlib_p = subparsers.add_parser('stdlib', help='Create frozen standard library.')

    lib_p = subparsers.add_parser('lib', help='Create frozen library')
    lib_p.add_argument('name', help='library name')
    lib_p.add_argument('path', help='library path')
    lib_p.add_argument('--main', default=None, help='library path')

    app_p = subparsers.add_parser('app', help='Create app main.c from frozen libraries')
    app_p.add_argument('libs', nargs='+', help='libraries')

    args = parser.parse_args()

    if args.command is None:
        parser.print_help()
        return 1

    if args.command == 'stdlib':
        create_stdlib()
    elif args.command == 'lib':
        create_lib(args.name, args.path, args.main)
    elif args.command == 'app':
        create_app(args.libs)

    return 0

if __name__ == "__main__":
    sys.exit(main(sys.argv))
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
#
# inventory/common/api/fields.py
#
"""
Invoice, InvoiceItem and Item serializers.
"""
__docformat__ = "restructuredtext en"

import logging

from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist
from django.utils import six
from django.utils.translation import ugettext_lazy as _

from rest_framework import serializers
from rest_framework.compat import NoReverseMatch
from rest_framework.fields import Field
from rest_framework.reverse import reverse

log = logging.getLogger('api.common.fields')

#
# HyperlinkedCustomIdentityField
#
class HyperlinkedCustomIdentityField(serializers.HyperlinkedIdentityField):
    """
    This field creates a proper URI as an identity field on a non
    model serializer. This field is used on dcolumn meta models.
    """

    def get_object(self, view_name, view_args, view_kwargs):
        """
        Return the object corresponding to a matched URL.

        Takes the matched URL conf arguments, and should return an
        object instance, or raise an `ObjectDoesNotExist` exception.
        """
        value = view_kwargs[self.lookup_url_kwarg]
        value = int(value) if value.isdigit() else value
        obj = None

        for result in self.queryset:
            v = getattr(result, self.lookup_field, '')
            v = int(v) if v.isdigit() else v

            if value == v:
                obj = result
                break

        if not obj:
            msg = _("Could not find object with field '{}' and value '{}'.")
            raise ObjectDoesNotExist(msg.format(self.lookup_field, value))

        return obj

#
# HyperlinkedFilterField
#
class HyperlinkedFilterField(serializers.Field):
    lookup_field = 'pk'

    def __init__(self, view_name=None, query_name=None, **kwargs):
        if view_name is not None:
            self.view_name = view_name

        assert self.view_name is not None, \
               'The `view_name` argument is required.'

        if query_name is not None:
             self.query_name = query_name

        assert self.query_name is not None, \
               'The `query_name` argument is required.'
        self.lookup_field = kwargs.pop('lookup_field', self.lookup_field)
        self.lookup_url_kwarg = kwargs.pop('lookup_url_kwarg',
                                           self.lookup_field)
        self.reverse = reverse
        super(HyperlinkedFilterField, self).__init__(**kwargs)

    def get_attribute(self, instance):
        return instance

    def get_url(self, obj, view_name, request, format):
        """
        Given filter criteria return the url with the query string.

        May raise a `NoReverseMatch` if the `view_name` or `query_name`
        attributes are not configured to correctly match the URL conf.
        """
        lookup_value = getattr(obj, self.lookup_field)
        search = six.moves.urllib.parse.urlencode(
            {self.query_name: lookup_value})
        return self.reverse(view_name, request=request, format=format
                            ) + '?' + search

    def to_representation(self, obj):
        request = self.context['request']
        format = self.context.get('format')

        if format and self.format and self.format != format:
            format = self.format

        try:
            url = self.get_url(obj, self.view_name, request, format)
        except NoReverseMatch:
            msg = ('Could not resolve URL for hyperlinked relationship '
                   'using view name "{}". You may have failed to include '
                   'the related model in your API, or incorrectly '
                   'configured the `lookup_field` attribute on this field.')

            if obj in ('', None):
                value_string = {'': 'the empty string', None: 'None'}[obj]
                msg += (" WARNING: The value of the model instance "
                        "was '{}', which may be why it didn't match any "
                        "entries in your URL conf.").format(value_string)

            raise ImproperlyConfigured(msg.format(self.view_name))

        return url
<commit_msg>Changed import and started Python 3.x only code.<commit_after># -*- coding: utf-8 -*-
#
# inventory/common/api/fields.py
#
"""
Invoice, InvoiceItem and Item serializers.
"""
__docformat__ = "restructuredtext en"

import logging

from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist
from django.urls import NoReverseMatch
from django.utils import six
from django.utils.translation import ugettext_lazy as _

from rest_framework import serializers
from rest_framework.fields import Field
from rest_framework.reverse import reverse

log = logging.getLogger('api.common.fields')

#
# HyperlinkedCustomIdentityField
#
class HyperlinkedCustomIdentityField(serializers.HyperlinkedIdentityField):
    """
    This field creates a proper URI as an identity field on a non
    model serializer. This field is used on dcolumn meta models.
    """

    def get_object(self, view_name, view_args, view_kwargs):
        """
        Return the object corresponding to a matched URL.

        Takes the matched URL conf arguments, and should return an
        object instance, or raise an `ObjectDoesNotExist` exception.
        """
        value = view_kwargs[self.lookup_url_kwarg]
        value = int(value) if value.isdigit() else value
        obj = None

        for result in self.queryset:
            v = getattr(result, self.lookup_field, '')
            v = int(v) if v.isdigit() else v

            if value == v:
                obj = result
                break

        if not obj:
            msg = _("Could not find object with field '{}' and value '{}'.")
            raise ObjectDoesNotExist(msg.format(self.lookup_field, value))

        return obj

#
# HyperlinkedFilterField
#
class HyperlinkedFilterField(serializers.Field):
    lookup_field = 'pk'

    def __init__(self, view_name=None, query_name=None, **kwargs):
        if view_name is not None:
            self.view_name = view_name

        assert self.view_name is not None, \
               'The `view_name` argument is required.'

        if query_name is not None:
             self.query_name = query_name

        assert self.query_name is not None, \
               'The `query_name` argument is required.'
        self.lookup_field = kwargs.pop('lookup_field', self.lookup_field)
        self.lookup_url_kwarg = kwargs.pop('lookup_url_kwarg',
                                           self.lookup_field)
        self.reverse = reverse
        super().__init__(**kwargs)

    def get_attribute(self, instance):
        return instance

    def get_url(self, obj, view_name, request, format):
        """
        Given filter criteria return the url with the query string.

        May raise a `NoReverseMatch` if the `view_name` or `query_name`
        attributes are not configured to correctly match the URL conf.
        """
        lookup_value = getattr(obj, self.lookup_field)
        search = six.moves.urllib.parse.urlencode(
            {self.query_name: lookup_value})
        return self.reverse(view_name, request=request, format=format
                            ) + '?' + search

    def to_representation(self, obj):
        request = self.context['request']
        format = self.context.get('format')

        if format and self.format and self.format != format:
            format = self.format

        try:
            url = self.get_url(obj, self.view_name, request, format)
        except NoReverseMatch:
            msg = ('Could not resolve URL for hyperlinked relationship '
                   'using view name "{}". You may have failed to include '
                   'the related model in your API, or incorrectly '
                   'configured the `lookup_field` attribute on this field.')

            if obj in ('', None):
                value_string = {'': 'the empty string', None: 'None'}[obj]
                msg += (" WARNING: The value of the model instance "
                        "was '{}', which may be why it didn't match any "
                        "entries in your URL conf.").format(value_string)

            raise ImproperlyConfigured(msg.format(self.view_name))

        return url
<|endoftext|>


<commit_before># Author: Alfredo Deza
# Email: alfredodeza [at] gmail dot com
# License: MIT
# Copyright 2009-2010 Alfredo Deza
#
"""SSH connections and file transfers with limited options like non
standard ports. This is a simple wrapper to suit Pacha."""

from subprocess import call, PIPE
import os
from time import strftime
import log
import confparser
import host
import log

class Hg(object):
    """Does local commits and pushed to a central Pacha Master location"""

    def __init__(self,
            port = 22,
            host = None,
            user = None,
            dir = None
            ):
        self.port = port
        self.host = host
        self.user = user
        self.dir = dir

    def commit(self):
        """hg local commits that are needed before a push to a centralized
        server"""
        #TODO:
        # Automatically detect if a user modified a file to commit and then
        # push the changes
        # For now, the user has to manually commit

    def push(self):
        """Pushes the repository to the centralized Pacha Master server"""
        #command = "scp -P%s ~/.cuy/keys/%s_%s.keys %s@%s:~/.ssh/authorized_keys" % (
        #        self.port, self.user, self.host, self.user, self.host)
        #try:
        #    call(command, shell=True, stdout=PIPE, stderr=PIPE)
        #except Exception:
        #    print Exception

    def hgrc(self, path):
        """An option to write the default path in hgrc for pushing
        via hg"""
        if self.validate(path):
            conf = '/opt/pacha/conf/pacha.conf'
            parse = confparser.Parse(conf)
            parse.options() # get all the options in the config file
            log.append(module='hg', line="parsed options from config file")
            norm_path = os.path.normpath(path)
            base_path = os.path.basename(path)
            machine = host.hostname()
            try:
                hgrc = open(norm_path+'/.hg/hgrc', 'w')
                hgrc.write('[paths]\n')
                ssh_line = "default = ssh://%s@%s/%s/%s/%s" % (parse.user, parse.host,
                           parse.path, machine, base_path)
                hgrc.write(ssh_line)
                hgrc.close()
                log.append(module='hg', line="wrote hgrc in %s" % path)

            except Exception, e:
                log.append(module='hg', type='ERROR', line=e)

        else:
            sys.stderr.write("No repository found here: %s" % path)
            log.append(module='hg', type='ERROR',
                    line="no repository found: %s" % path)

    def validate(self, path):
        """Validates a working HG path"""
        #normalize the path:
        norm_path = os.path.normpath(path)
        hg_dir = norm_path+'/.hg'
        log.append(module='hg', line="validating repository at %s" % path)
        if os.path.exists(hg_dir):
            log.append(module='hg', line="hg repository found at %s" % path)
            return True
        else:
            log.append(module='hg', type='ERROR',  line="hg repository not found at %s" % path)
            return False
<commit_msg>added import sys to hg lib<commit_after># Author: Alfredo Deza
# Email: alfredodeza [at] gmail dot com
# License: MIT
# Copyright 2009-2010 Alfredo Deza
#
"""SSH connections and file transfers with limited options like non
standard ports. This is a simple wrapper to suit Pacha."""

from subprocess import call, PIPE
import os
import sys
from time import strftime
import log
import confparser
import host
import log

class Hg(object):
    """Does local commits and pushed to a central Pacha Master location"""

    def __init__(self,
            port = 22,
            host = None,
            user = None,
            dir = None
            ):
        self.port = port
        self.host = host
        self.user = user
        self.dir = dir

    def commit(self):
        """hg local commits that are needed before a push to a centralized
        server"""
        #TODO:
        # Automatically detect if a user modified a file to commit and then
        # push the changes
        # For now, the user has to manually commit

    def push(self):
        """Pushes the repository to the centralized Pacha Master server"""
        #command = "scp -P%s ~/.cuy/keys/%s_%s.keys %s@%s:~/.ssh/authorized_keys" % (
        #        self.port, self.user, self.host, self.user, self.host)
        #try:
        #    call(command, shell=True, stdout=PIPE, stderr=PIPE)
        #except Exception:
        #    print Exception

    def hgrc(self, path):
        """An option to write the default path in hgrc for pushing
        via hg"""
        if self.validate(path):
            conf = '/opt/pacha/conf/pacha.conf'
            parse = confparser.Parse(conf)
            parse.options() # get all the options in the config file
            log.append(module='hg', line="parsed options from config file")
            norm_path = os.path.normpath(path)
            base_path = os.path.basename(path)
            machine = host.hostname()
            try:
                hgrc = open(norm_path+'/.hg/hgrc', 'w')
                hgrc.write('[paths]\n')
                ssh_line = "default = ssh://%s@%s/%s/%s/%s" % (parse.user, parse.host,
                           parse.path, machine, base_path)
                hgrc.write(ssh_line)
                hgrc.close()
                log.append(module='hg', line="wrote hgrc in %s" % path)

            except Exception, e:
                log.append(module='hg', type='ERROR', line=e)

        else:
            sys.stderr.write("No repository found here: %s" % path)
            log.append(module='hg', type='ERROR',
                    line="no repository found: %s" % path)

    def validate(self, path):
        """Validates a working HG path"""
        #normalize the path:
        norm_path = os.path.normpath(path)
        hg_dir = norm_path+'/.hg'
        log.append(module='hg', line="validating repository at %s" % path)
        if os.path.exists(hg_dir):
            log.append(module='hg', line="hg repository found at %s" % path)
            return True
        else:
            log.append(module='hg', type='ERROR',  line="hg repository not found at %s" % path)
            return False
<|endoftext|>


<commit_before>import sys
import pexpect

class UCIEngine(object):

    def __init__(self, executable="stockfish", debug=True):
        self._p = pexpect.spawn("stockfish")
        if debug:
            self._p.logfile = sys.stdout
        self._p.sendline("uci")
        self._p.sendline("setoption name Hash value 1024")
        self._p.expect("uciok")

    def new_game(self):
        self._p.sendline("ucinewgame")
        self._p.sendline("isready")
        self._p.expect("readyok")

    def set_position(self, initial_position=None, moves=None):
        """
        Sets the position on the internal chessboard.

        initial_position ... If None, start position is used, otherwise specify
                             a position in a "fen" format.
        moves ... List of moves to make, in algebraic notation from
                  "initial_position". Moves have to valid, otherwise the engine
                  can segfault later on.
        """
        if moves:
            assert len(moves) >= 1
            s_moves = "moves " + " ".join(moves)
        else:
            s_moves = ""
        if initial_position:
            self._p.sendline("position fen %s %s" % (initial_position,
                s_moves))
        else:
            self._p.sendline("position startpos %s" % s_moves)

    def find_best_move(self, movetime=2):
        if movetime is None:
            self._p.sendline("go infinite")
        else:
            self._p.sendline("go movetime %d" % movetime)
        self._p.expect("bestmove (\S+) ponder (\S+)", timeout=None)
        best_move, ponder = self._p.match.groups()
        return best_move, ponder

def get_move_from_user(default="e2e4"):
    print "Your move (%s):" % default
    move = raw_input()
    if move == "":
        move = default
    print "Using the move:", move
    return move

if __name__ == "__main__":
    e = UCIEngine()
    e.new_game()
    ponder = "e2e4"
    i = 0
    moves = []
    while 1:
        i += 1
        if i < 30:
            move = ponder
        else:
            move = get_move_from_user(ponder)
        print "you:", move
        moves.append(move)
        e.set_position(moves=moves)
        best_move, ponder = e.find_best_move()
        moves.append(best_move)
        print "computer:", best_move
<commit_msg>Implement multi_pv<commit_after>import sys
import pexpect

class UCIEngine(object):

    def __init__(self, executable="stockfish", debug=True, multi_pv=1):
        self._p = pexpect.spawn("stockfish")
        if debug:
            self._p.logfile = sys.stdout
        self._p.sendline("uci")
        self._p.sendline("setoption name Hash value 1024")
        self._p.sendline("setoption name MultiPV value %d" % multi_pv)
        self._p.expect("uciok")

    def new_game(self):
        self._p.sendline("ucinewgame")
        self._p.sendline("isready")
        self._p.expect("readyok")

    def set_position(self, initial_position=None, moves=None):
        """
        Sets the position on the internal chessboard.

        initial_position ... If None, start position is used, otherwise specify
                             a position in a "fen" format.
        moves ... List of moves to make, in algebraic notation from
                  "initial_position". Moves have to valid, otherwise the engine
                  can segfault later on.
        """
        if moves:
            assert len(moves) >= 1
            s_moves = "moves " + " ".join(moves)
        else:
            s_moves = ""
        if initial_position:
            self._p.sendline("position fen %s %s" % (initial_position,
                s_moves))
        else:
            self._p.sendline("position startpos %s" % s_moves)

    def find_best_move(self, movetime=2):
        if movetime is None:
            self._p.sendline("go infinite")
        else:
            self._p.sendline("go movetime %d" % movetime)
        self._p.expect("bestmove (\S+) ponder (\S+)", timeout=None)
        best_move, ponder = self._p.match.groups()
        return best_move, ponder

def get_move_from_user(default="e2e4"):
    print "Your move (%s):" % default
    move = raw_input()
    if move == "":
        move = default
    print "Using the move:", move
    return move

if __name__ == "__main__":
    e = UCIEngine()
    e.new_game()
    ponder = "e2e4"
    i = 0
    moves = []
    while 1:
        i += 1
        if i < 30:
            move = ponder
        else:
            move = get_move_from_user(ponder)
        print "you:", move
        moves.append(move)
        e.set_position(moves=moves)
        best_move, ponder = e.find_best_move()
        moves.append(best_move)
        print "computer:", best_move
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
'''Wrapper for MeCab dictionary information.'''

class DictionaryInfo(object):
    '''Representation of a MeCab dictionary, wrapping mecab_dictionary_info_t.

    A list of dictionaries used by MeCab is returned by the dicts attribute of
    MeCab. Each dictionary information includes the attributes listed below.

    Attributes:
        ptr: This dictionary's pointer.
        filename: Full path to the dictionary file.
        charset: Dictionary character set, e.g., "SHIFT-JIS", "UTF-8".
        size: Number of words registered in this dictionary.
        type: Dictionary type; 0 (SYS_DIC), 1 (USR_DIC), 2 (UNK_DIC)
        lsize: Left attributes size.
        rsize: Right attributes size.
        version: Dictionary version.
        next: Pointer to next dictionary information struct.

    Example usage:

        from natto import MeCab

        with MeCab() as nm:
            # first dictionary info is MeCab's system dictionary
            sysdic = nm.dicts[0]

            print(sysdic.filename)

            print(sysdic.charset)

            print(sysdic.is_sysdic())
    '''
    _REPR_FMT = '<%s.%s pointer=%s, type=%d, filename="%s", charset="%s">'

    # System dictionary
    SYS_DIC = 0
    # User dictionary.
    USR_DIC = 1
    # Unknown dictionary.
    UNK_DIC = 2

    def __init__(self, dptr, filename, charset):
        '''Initializes the MeCab dictionary information.'''
        self.ptr = dptr
        self.filename = filename
        self.charset = charset
        self.size = dptr.size
        self.type = dptr.type
        self.lsize = dptr.lsize
        self.rsize = dptr.rsize
        self.version = dptr.version
        self.next = getattr(dptr, 'next')

    def is_sysdic(self):
        '''Returns True if this is a system dictionary.'''
        return self.type == self.SYS_DIC

    def is_usrdic(self):
        '''Returns True if this is a user-defined dictionary.'''
        return self.type == self.USR_DIC

    def is_unkdic(self):
        '''Returns True if this is a unknown dictionary.'''
        return self.type == self.UNK_DIC

    def __repr__(self):
        '''Returns a string representation of this MeCab dictionary.'''
        return self._REPR_FMT % (type(self).__module__,
                                 type(self).__name__,
                                 self.ptr,
                                 self.type,
                                 self.filename,
                                 self.charset)

'''
Copyright (c) 2014, Brooke M. Fujita.
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above
   copyright notice, this list of conditions and the
   following disclaimer.

 * Redistributions in binary form must reproduce the above
   copyright notice, this list of conditions and the
   following disclaimer in the documentation and/or other
   materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
'''
<commit_msg>dictionary.py edited online with Bitbucket; minor changes to string formatting.<commit_after># -*- coding: utf-8 -*-
'''Wrapper for MeCab dictionary information.'''

class DictionaryInfo(object):
    '''Representation of a MeCab dictionary, wrapping mecab_dictionary_info_t.

    A list of dictionaries used by MeCab is returned by the dicts attribute of
    MeCab. Each dictionary information includes the attributes listed below.

    Attributes:
        ptr: This dictionary's pointer.
        filename: Full path to the dictionary file.
        charset: Dictionary character set, e.g., "SHIFT-JIS", "UTF-8".
        size: Number of words registered in this dictionary.
        type: Dictionary type; 0 (SYS_DIC), 1 (USR_DIC), 2 (UNK_DIC)
        lsize: Left attributes size.
        rsize: Right attributes size.
        version: Dictionary version.
        next: Pointer to next dictionary information struct.

    Example usage:

        from natto import MeCab

        with MeCab() as nm:
            # first dictionary info is MeCab's system dictionary
            sysdic = nm.dicts[0]

            print(sysdic.filename)

            print(sysdic.charset)

            print(sysdic.is_sysdic())
    '''
    _REPR_FMT = '<{}.{} pointer={}, type={}, filename="{}", charset="{}">'

    # System dictionary
    SYS_DIC = 0
    # User dictionary.
    USR_DIC = 1
    # Unknown dictionary.
    UNK_DIC = 2

    def __init__(self, dptr, filename, charset):
        '''Initializes the MeCab dictionary information.'''
        self.ptr = dptr
        self.filename = filename
        self.charset = charset
        self.size = dptr.size
        self.type = dptr.type
        self.lsize = dptr.lsize
        self.rsize = dptr.rsize
        self.version = dptr.version
        self.next = getattr(dptr, 'next')

    def is_sysdic(self):
        '''Returns True if this is a system dictionary.'''
        return self.type == self.SYS_DIC

    def is_usrdic(self):
        '''Returns True if this is a user-defined dictionary.'''
        return self.type == self.USR_DIC

    def is_unkdic(self):
        '''Returns True if this is a unknown dictionary.'''
        return self.type == self.UNK_DIC

    def __repr__(self):
        '''Returns a string representation of this MeCab dictionary.'''
        return self._REPR_FMT.format(type(self).__module__,
                                     type(self).__name__,
                                     self.ptr,
                                     self.type,
                                     self.filename,
                                     self.charset)

'''
Copyright (c) 2014, Brooke M. Fujita.
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above
   copyright notice, this list of conditions and the
   following disclaimer.

 * Redistributions in binary form must reproduce the above
   copyright notice, this list of conditions and the
   following disclaimer in the documentation and/or other
   materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
'''
<|endoftext|>


<commit_before># Copyright 2010 Google Inc. All Rights Reserved.
#
# 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.

"""Class used for connecting to the results site."""

import os
import platform
import sys
import tempfile
import urllib
import zlib

# external dependencies (from third_party)
try:
  import third_party
except ImportError:
  pass

import httplib2
import simplejson

class SiteConnector(object):

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

  def GetGeoIPData(self, ip):
    h = httplib2.Http(tempfile.gettempdir(), timeout=10)
    post_data = dict(ip=ip)
    resp, content = h.request(url, 'POST', urllib.urlencode(post_data))
    return simplejson.loads(content)

  def GetIndexHosts(self):
    url = self.config.site_url + '/index_hosts'
    h = httplib2.Http(tempfile.gettempdir(), timeout=10)
    content = None
    try:
      resp, content = h.request(url, 'GET')
      hosts = []
      for record_type, host in simplejson.loads(content):
        hosts.append((str(record_type), str(host)))
      return hosts
    except (IndexError, AttributeError):
      print '* Unable to fetch %s' % url
      return []
    except simplejson.decoder.JSONDecodeError:
      print '* Failed to decode: "%s"' % content
      return []

  def UploadJsonResults(self, json_data):
    """Data is generated by reporter.CreateJsonData"""

    url = self.config.site_url + '/submit'
    if not url or not url.startswith('http'):
      return False
    h = httplib2.Http()
    post_data = dict(duplicate_check=self._CalculateDuplicateCheckId(), data=json_data)
    try:
      resp, content = h.request(url, 'POST', urllib.urlencode(post_data))
      print "RESPONSE: [%s]: %s" % (resp, content)
      return True
    # See http://code.google.com/p/httplib2/issues/detail?id=62
    except AttributeError:
      print "%s refused connection" % url
    return False

  def _CalculateDuplicateCheckId(self):
    """This is so that we can detect duplicate submissions from a particular host.

    Returns:
      checksum: integer
    """
    # From http://docs.python.org/release/2.5.2/lib/module-zlib.html
    # "not suitable for use as a general hash algorithm."
    #
    # We are only using it as a temporary way to detect duplicate runs on the
    # same host in a short time period, so it's accuracy is not important.
    return zlib.crc32(platform.platform() + sys.version + platform.node() +
                      os.getenv('HOME', '') + os.getenv('USERPROFILE', ''))
<commit_msg>Remove GetGeoIPData(), strip trailing / from URL<commit_after># Copyright 2010 Google Inc. All Rights Reserved.
#
# 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.

"""Class used for connecting to the results site."""

import os
import platform
import sys
import tempfile
import urllib
import zlib

# external dependencies (from third_party)
try:
  import third_party
except ImportError:
  pass

import httplib2
import simplejson

class SiteConnector(object):

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

  def GetIndexHosts(self):
    url = self.config.site_url.rstrip('/') + '/index_hosts'
    h = httplib2.Http(tempfile.gettempdir(), timeout=10)
    content = None
    try:
      resp, content = h.request(url, 'GET')
      hosts = []
      for record_type, host in simplejson.loads(content):
        hosts.append((str(record_type), str(host)))
      return hosts
    except (IndexError, AttributeError):
      print '* Unable to fetch %s' % url
      return []
    except simplejson.decoder.JSONDecodeError:
      print '* Failed to decode: "%s"' % content
      return []

  def UploadJsonResults(self, json_data):
    """Data is generated by reporter.CreateJsonData"""

    url = self.config.site_url.rstrip('/') + '/submit'
    if not url or not url.startswith('http'):
      return False
    h = httplib2.Http()
    post_data = dict(duplicate_check=self._CalculateDuplicateCheckId(), data=json_data)
    try:
      resp, content = h.request(url, 'POST', urllib.urlencode(post_data))
      print "RESPONSE for %s: [%s]:\n  %s" % (url, resp, content)
      return True
    # See http://code.google.com/p/httplib2/issues/detail?id=62
    except AttributeError:
      print "%s refused connection" % url
    return False

  def _CalculateDuplicateCheckId(self):
    """This is so that we can detect duplicate submissions from a particular host.

    Returns:
      checksum: integer
    """
    # From http://docs.python.org/release/2.5.2/lib/module-zlib.html
    # "not suitable for use as a general hash algorithm."
    #
    # We are only using it as a temporary way to detect duplicate runs on the
    # same host in a short time period, so it's accuracy is not important.
    return zlib.crc32(platform.platform() + sys.version + platform.node() +
                      os.getenv('HOME', '') + os.getenv('USERPROFILE', ''))
<|endoftext|>