<commit_before>""" Plotting utilities.

"""
from itertools import cycle

import numpy as np
import plotly.colors
from astropy import units as u
from plotly.graph_objects import Figure, Layout, Scatter, Scatter3d, Surface

from poliastro.frames import Planes
from poliastro.plotting._base import BaseOrbitPlotter, Mixin2D
from poliastro.plotting.util import generate_sphere

class _PlotlyOrbitPlotter(BaseOrbitPlotter):
    def __init__(self, figure=None, *, num_points=150, plane=None, unit=u.km):
        super().__init__(num_points=num_points, plane=plane)

        self._figure = figure or Figure()
        self._layout = None

        self._color_cycle = cycle(plotly.colors.DEFAULT_PLOTLY_COLORS)

        self._unit = unit

    def _clear_attractor(self):
        # FIXME: Implement
        pass

    def _get_colors(self, color, trail):
        # TODO: Support trail
        if color is None:
            color = next(self._color_cycle)

        return [color]

    def plot_trajectory(self, coordinates, *, label=None, color=None, trail=False):
        """Plots a precomputed trajectory.

        An attractor must be set first.

        Parameters
        ----------
        coordinates : ~astropy.coordinates.CartesianRepresentation
            Trajectory to plot.
        label : str, optional
            Label of the trajectory.
        color : str, optional
            Color of the trajectory.
        trail : bool, optional
            Fade the orbit trail, default to False.

        """

        super().plot_trajectory(coordinates, label=label, color=color, trail=trail)

        if not self._figure._in_batch_mode:
            return self.show()

    def plot(self, orbit, *, label=None, color=None, trail=False):
        """Plots state and osculating orbit in their plane.

        Parameters
        ----------
        orbit : ~poliastro.twobody.orbit.Orbit
            Orbit to plot.
        label : str, optional
            Label of the orbit.
        color : str, optional
            Color of the line and the position.
        trail : bool, optional
            Fade the orbit trail, default to False.

        """
        super().plot(orbit, label=label, color=color, trail=trail)

        if not self._figure._in_batch_mode:
            return self.show()

    def plot_body_orbit(
        self,
        body,
        epoch,
        *,
        label=None,
        color=None,
        trail=False,
    ):
        """Plots complete revolution of body and current position.

        Parameters
        ----------
        body : poliastro.bodies.SolarSystemPlanet
            Body.
        epoch : astropy.time.Time
            Epoch of current position.
        label : str, optional
            Label of the orbit, default to the name of the body.
        color : str, optional
            Color of the line and the position.
        trail : bool, optional
            Fade the orbit trail, default to False.

        """
        super().plot_body_orbit(body, epoch, label=label, color=color, trail=trail)

        if not self._figure._in_batch_mode:
            return self.show()

    def plot_ephem(self, ephem, epoch=None, *, label=None, color=None, trail=False):
        """Plots Ephem object over its sampling period.

        Parameters
        ----------
        ephem : ~poliastro.ephem.Ephem
            Ephemerides to plot.
        epoch : astropy.time.Time, optional
            Epoch of the current position, none will be used if not given.
        label : str, optional
            Label of the orbit, default to the name of the body.
        color : str, optional
            Color of the line and the position.
        trail : bool, optional
            Fade the orbit trail, default to False.

        """

        super().plot_ephem(ephem, epoch, label=label, color=color, trail=trail)

        if not self._figure._in_batch_mode:
            return self.show()

    def show(self):
        """Shows the plot in the Notebook.

        Updates the layout and returns the underlying figure.

        """
        if self._attractor is not None:
            self._redraw_attractor()

        self._figure.layout.update(self._layout)
        return self._figure

class OrbitPlotter3D(_PlotlyOrbitPlotter):
    """OrbitPlotter3D class."""

    def __init__(self, figure=None, dark=False, *, num_points=150, plane=None, unit=u.km):
        super().__init__(figure, num_points=num_points, plane=plane, unit=unit)
        self._layout = Layout(
            autosize=True,
            scene=dict(
                xaxis=dict(title="x f"({self._unit})""),
                yaxis=dict(title="y f"({self._unit})""),
                zaxis=dict(title="z f"({self._unit})""),
                aspectmode="data",  # Important!
            ),
        )
        if dark:
            self._layout.template = "plotly_dark"

    def _draw_point(self, radius, color, name, center=[0, 0, 0] * u.km):
        # We use _plot_sphere here because it's not easy to specify the size of a marker
        # in data units instead of pixels, see
        # https://stackoverflow.com/q/47086547
        return self._draw_sphere(radius, color, name, center)

    def _draw_sphere(self, radius, color, name, center=[0, 0, 0] * u.km):
        xx, yy, zz = generate_sphere(radius, center)
        sphere = Surface(
            x=xx.to_value(self._unit),
            y=yy.to_value(self._unit),
            z=zz.to_value(self._unit),
            name=name,
            colorscale=[[0, color], [1, color]],
            cauto=False,
            cmin=1,
            cmax=1,
            showscale=False,
        )
        self._figure.add_trace(sphere)

        return sphere

    def _plot_coordinates(self, coordinates, label, colors, dashed):
        trace = Scatter3d(
            x=coordinates.x.to_value(self._unit),
            y=coordinates.y.to_value(self._unit),
            z=coordinates.z.to_value(self._unit),
            name=label,
            line=dict(color=colors[0], width=5, dash="dash" if dashed else "solid"),
            mode="lines",  # Boilerplate
        )
        self._figure.add_trace(trace)

        return trace, [trace.line.color]

    def plot(self, orbit, *, label=None, color=None, trail=False):
        """Plots state and osculating orbit in their plane.

        Parameters
        ----------
        orbit : ~poliastro.twobody.orbit.Orbit
            Orbit to plot.
        label : str, optional
            Label of the orbit.
        color : str, optional
            Color of the line and the position.
        trail : bool, optional
            Fade the orbit trail, default to False.

        """
        if trail:
            raise NotImplementedError("trail not supported yet")

        return super().plot(orbit, label=label, color=color, trail=trail)

    @u.quantity_input(elev=u.rad, azim=u.rad, distance=u.km)
    def set_view(self, elev, azim, distance=5 * u.km):
        """Changes 3D view."""
        x = distance * np.cos(elev) * np.cos(azim)
        y = distance * np.cos(elev) * np.sin(azim)
        z = distance * np.sin(elev)

        self._layout.update(
            {
                "scene": {
                    "camera": {
                        "eye": {
                            "x": x.to_value(self._unit),
                            "y": y.to_value(self._unit),
                            "z": z.to_value(self._unit),
                        }
                    }
                }
            }
        )

        if not self._figure._in_batch_mode:
            return self.show()

class OrbitPlotter2D(_PlotlyOrbitPlotter, Mixin2D):
    """OrbitPlotter2D class.

    .. versionadded:: 0.9.0
    """

    def __init__(self, figure=None, *, num_points=150, plane=None, unit=u.km):
        super().__init__(figure, num_points=num_points, plane=plane, unit=unit )
        self._layout = Layout(
            autosize=True,
            xaxis=dict(title="x f"({self._unit})"", constrain="domain"),
            yaxis=dict(title="y f"({self._unit})"", scaleanchor="x"),
            shapes=[],
        )

        self._frame = None

    def _redraw(self):
        raise NotImplementedError("OrbitPlotter2D does not support reprojecting yet")

    def _draw_point(self, radius, color, name, center=[0, 0, 0] * u.km):
        x_center, y_center = self._project(
            center[None]
        )  # Indexing trick to add one extra dimension

        trace = Scatter(
            x=x_center.to_value(self._unit),
            y=y_center.to_value(self._unit),
            mode="markers",
            marker=dict(size=10, color=color),
            name=name,
        )
        self._figure.add_trace(trace)

        return trace

    def _draw_sphere(self, radius, color, name, center=[0, 0, 0] * u.km):
        x_center, y_center = self._project(
            center[None]
        )  # Indexing trick to add one extra dimension

        shape = {
            "type": "circle",
            "xref": "x",
            "yref": "y",
            "x0": (x_center[0] - radius).to_value(self._unit),
            "y0": (y_center[0] - radius).to_value(self._unit),
            "x1": (x_center[0] + radius).to_value(self._unit),
            "y1": (y_center[0] + radius).to_value(self._unit),
            "opacity": 1,
            "fillcolor": color,
            "line": {"color": color},
        }

        self._layout.shapes += (shape,)

        return shape

    def _plot_coordinates(self, coordinates, label, colors, dashed):
        if self._frame is None:
            raise ValueError(
                "A frame must be set up first, please use "
                "set_orbit_frame(orbit) or plot(orbit)"
            )

        rr = coordinates.xyz.transpose()
        x, y = self._project(rr)

        trace = Scatter(
            x=x.to_value(self._unit),
            y=y.to_value(self._unit),
            name=label,
            line=dict(color=colors[0], width=2, dash="dash" if dashed else "solid"),
            hoverinfo="none",  # TODO: Review
            mode="lines",  # Boilerplate
        )
        self._figure.add_trace(trace)

        return trace

    def plot_trajectory(self, coordinates, *, label=None, color=None, trail=False):
        """Plots a precomputed trajectory.

        An attractor must be set first.

        Parameters
        ----------
        coordinates : ~astropy.coordinates.CartesianRepresentation
            Trajectory to plot.
        label : str, optional
            Label of the trajectory.
        color : str, optional
            Color of the trajectory.
        trail : bool, optional
            Fade the orbit trail, default to False.

        """
        if self._frame is None:
            raise ValueError(
                "A frame must be set up first, please use "
                "set_orbit_frame(orbit) or plot(orbit)"
            )

        return super().plot_trajectory(
            coordinates, label=label, color=color, trail=trail
        )

    def plot_ephem(self, ephem, epoch=None, *, label=None, color=None, trail=False):
        """Plots Ephem object over its sampling period.

        Parameters
        ----------
        ephem : ~poliastro.ephem.Ephem
            Ephemerides to plot.
        epoch : astropy.time.Time, optional
            Epoch of the current position, none will be used if not given.
        label : str, optional
            Label of the orbit, default to the name of the body.
        color : str, optional
            Color of the line and the position.
        trail : bool, optional
            Fade the orbit trail, default to False.

        """
        if self._frame is None:
            raise ValueError(
                "A frame must be set up first, please use "
                "set_orbit_frame(orbit) or plot(orbit)"
            )
        super().plot_ephem(ephem, epoch, label=label, color=color, trail=trail)

    def plot(self, orbit, *, label=None, color=None, trail=False):
        """Plots state and osculating orbit in their plane.

        Parameters
        ----------
        orbit : ~poliastro.twobody.orbit.Orbit
            Orbit to plot.
        label : str, optional
            Label of the orbit.
        color : str, optional
            Color of the line and the position.
        trail : bool, optional
            Fade the orbit trail, default to False.

        """

        if trail:
            raise NotImplementedError("trail not supported yet")

        if not self._frame:
            self.set_orbit_frame(orbit)

        return super().plot(orbit, label=label, color=color, trail=trail)

    def plot_body_orbit(
        self,
        body,
        epoch,
        plane=Planes.EARTH_ECLIPTIC,
        *,
        label=None,
        color=None,
        trail=False,
    ):
        """Plots complete revolution of body and current position.

        Parameters
        ----------
        body : poliastro.bodies.SolarSystemPlanet
            Body.
        epoch : astropy.time.Time
            Epoch of current position.
        plane : ~poliastro.frames.enums.Planes
            Reference plane.
        label : str, optional
            Label of the orbit, default to the name of the body.
        color : str, optional
            Color of the line and the position.
        trail : bool, optional
            Fade the orbit trail, default to False.

        """
        if self._frame is None:
            self.set_body_frame(body, epoch)

        return super().plot_body_orbit(
            body, epoch, label=label, color=color, trail=trail
        )
<commit_msg>Syntax correction<commit_after>""" Plotting utilities.

"""
from itertools import cycle

import numpy as np
import plotly.colors
from astropy import units as u
from plotly.graph_objects import Figure, Layout, Scatter, Scatter3d, Surface

from poliastro.frames import Planes
from poliastro.plotting._base import BaseOrbitPlotter, Mixin2D
from poliastro.plotting.util import generate_sphere

class _PlotlyOrbitPlotter(BaseOrbitPlotter):
    def __init__(self, figure=None, *, num_points=150, plane=None, unit=u.km):
        super().__init__(num_points=num_points, plane=plane)

        self._figure = figure or Figure()
        self._layout = None

        self._color_cycle = cycle(plotly.colors.DEFAULT_PLOTLY_COLORS)

        self._unit = unit

    def _clear_attractor(self):
        # FIXME: Implement
        pass

    def _get_colors(self, color, trail):
        # TODO: Support trail
        if color is None:
            color = next(self._color_cycle)

        return [color]

    def plot_trajectory(self, coordinates, *, label=None, color=None, trail=False):
        """Plots a precomputed trajectory.

        An attractor must be set first.

        Parameters
        ----------
        coordinates : ~astropy.coordinates.CartesianRepresentation
            Trajectory to plot.
        label : str, optional
            Label of the trajectory.
        color : str, optional
            Color of the trajectory.
        trail : bool, optional
            Fade the orbit trail, default to False.

        """

        super().plot_trajectory(coordinates, label=label, color=color, trail=trail)

        if not self._figure._in_batch_mode:
            return self.show()

    def plot(self, orbit, *, label=None, color=None, trail=False):
        """Plots state and osculating orbit in their plane.

        Parameters
        ----------
        orbit : ~poliastro.twobody.orbit.Orbit
            Orbit to plot.
        label : str, optional
            Label of the orbit.
        color : str, optional
            Color of the line and the position.
        trail : bool, optional
            Fade the orbit trail, default to False.

        """
        super().plot(orbit, label=label, color=color, trail=trail)

        if not self._figure._in_batch_mode:
            return self.show()

    def plot_body_orbit(
        self,
        body,
        epoch,
        *,
        label=None,
        color=None,
        trail=False,
    ):
        """Plots complete revolution of body and current position.

        Parameters
        ----------
        body : poliastro.bodies.SolarSystemPlanet
            Body.
        epoch : astropy.time.Time
            Epoch of current position.
        label : str, optional
            Label of the orbit, default to the name of the body.
        color : str, optional
            Color of the line and the position.
        trail : bool, optional
            Fade the orbit trail, default to False.

        """
        super().plot_body_orbit(body, epoch, label=label, color=color, trail=trail)

        if not self._figure._in_batch_mode:
            return self.show()

    def plot_ephem(self, ephem, epoch=None, *, label=None, color=None, trail=False):
        """Plots Ephem object over its sampling period.

        Parameters
        ----------
        ephem : ~poliastro.ephem.Ephem
            Ephemerides to plot.
        epoch : astropy.time.Time, optional
            Epoch of the current position, none will be used if not given.
        label : str, optional
            Label of the orbit, default to the name of the body.
        color : str, optional
            Color of the line and the position.
        trail : bool, optional
            Fade the orbit trail, default to False.

        """

        super().plot_ephem(ephem, epoch, label=label, color=color, trail=trail)

        if not self._figure._in_batch_mode:
            return self.show()

    def show(self):
        """Shows the plot in the Notebook.

        Updates the layout and returns the underlying figure.

        """
        if self._attractor is not None:
            self._redraw_attractor()

        self._figure.layout.update(self._layout)
        return self._figure

class OrbitPlotter3D(_PlotlyOrbitPlotter):
    """OrbitPlotter3D class."""

    def __init__(self, figure=None, dark=False, *, num_points=150, plane=None, unit=u.km):
        super().__init__(figure, num_points=num_points, plane=plane, unit=unit)
        self._layout = Layout(
            autosize=True,
            scene=dict(
                xaxis=dict(title= f"x ({self._unit})"),
                yaxis=dict(title= f"y({self._unit})"),
                zaxis=dict(title= f"z({self._unit})"),
                aspectmode="data",  # Important!
            ),
        )
        if dark:
            self._layout.template = "plotly_dark"

    def _draw_point(self, radius, color, name, center=[0, 0, 0] * u.km):
        # We use _plot_sphere here because it's not easy to specify the size of a marker
        # in data units instead of pixels, see
        # https://stackoverflow.com/q/47086547
        return self._draw_sphere(radius, color, name, center)

    def _draw_sphere(self, radius, color, name, center=[0, 0, 0] * u.km):
        xx, yy, zz = generate_sphere(radius, center)
        sphere = Surface(
            x=xx.to_value(self._unit),
            y=yy.to_value(self._unit),
            z=zz.to_value(self._unit),
            name=name,
            colorscale=[[0, color], [1, color]],
            cauto=False,
            cmin=1,
            cmax=1,
            showscale=False,
        )
        self._figure.add_trace(sphere)

        return sphere

    def _plot_coordinates(self, coordinates, label, colors, dashed):
        trace = Scatter3d(
            x=coordinates.x.to_value(self._unit),
            y=coordinates.y.to_value(self._unit),
            z=coordinates.z.to_value(self._unit),
            name=label,
            line=dict(color=colors[0], width=5, dash="dash" if dashed else "solid"),
            mode="lines",  # Boilerplate
        )
        self._figure.add_trace(trace)

        return trace, [trace.line.color]

    def plot(self, orbit, *, label=None, color=None, trail=False):
        """Plots state and osculating orbit in their plane.

        Parameters
        ----------
        orbit : ~poliastro.twobody.orbit.Orbit
            Orbit to plot.
        label : str, optional
            Label of the orbit.
        color : str, optional
            Color of the line and the position.
        trail : bool, optional
            Fade the orbit trail, default to False.

        """
        if trail:
            raise NotImplementedError("trail not supported yet")

        return super().plot(orbit, label=label, color=color, trail=trail)

    @u.quantity_input(elev=u.rad, azim=u.rad, distance=u.km)
    def set_view(self, elev, azim, distance=5 * u.km):
        """Changes 3D view."""
        x = distance * np.cos(elev) * np.cos(azim)
        y = distance * np.cos(elev) * np.sin(azim)
        z = distance * np.sin(elev)

        self._layout.update(
            {
                "scene": {
                    "camera": {
                        "eye": {
                            "x": x.to_value(self._unit),
                            "y": y.to_value(self._unit),
                            "z": z.to_value(self._unit),
                        }
                    }
                }
            }
        )

        if not self._figure._in_batch_mode:
            return self.show()

class OrbitPlotter2D(_PlotlyOrbitPlotter, Mixin2D):
    """OrbitPlotter2D class.

    .. versionadded:: 0.9.0
    """

    def __init__(self, figure=None, *, num_points=150, plane=None, unit=u.km):
        super().__init__(figure, num_points=num_points, plane=plane, unit=unit )
        self._layout = Layout(
            autosize=True,
            xaxis=dict(title = f" x ({self._unit})", constrain="domain"),
            yaxis=dict(title = f" y({self._unit})", scaleanchor="x"),
            shapes=[],
        )

        self._frame = None

    def _redraw(self):
        raise NotImplementedError("OrbitPlotter2D does not support reprojecting yet")

    def _draw_point(self, radius, color, name, center=[0, 0, 0] * u.km):
        x_center, y_center = self._project(
            center[None]
        )  # Indexing trick to add one extra dimension

        trace = Scatter(
            x=x_center.to_value(self._unit),
            y=y_center.to_value(self._unit),
            mode="markers",
            marker=dict(size=10, color=color),
            name=name,
        )
        self._figure.add_trace(trace)

        return trace

    def _draw_sphere(self, radius, color, name, center=[0, 0, 0] * u.km):
        x_center, y_center = self._project(
            center[None]
        )  # Indexing trick to add one extra dimension

        shape = {
            "type": "circle",
            "xref": "x",
            "yref": "y",
            "x0": (x_center[0] - radius).to_value(self._unit),
            "y0": (y_center[0] - radius).to_value(self._unit),
            "x1": (x_center[0] + radius).to_value(self._unit),
            "y1": (y_center[0] + radius).to_value(self._unit),
            "opacity": 1,
            "fillcolor": color,
            "line": {"color": color},
        }

        self._layout.shapes += (shape,)

        return shape

    def _plot_coordinates(self, coordinates, label, colors, dashed):
        if self._frame is None:
            raise ValueError(
                "A frame must be set up first, please use "
                "set_orbit_frame(orbit) or plot(orbit)"
            )

        rr = coordinates.xyz.transpose()
        x, y = self._project(rr)

        trace = Scatter(
            x=x.to_value(self._unit),
            y=y.to_value(self._unit),
            name=label,
            line=dict(color=colors[0], width=2, dash="dash" if dashed else "solid"),
            hoverinfo="none",  # TODO: Review
            mode="lines",  # Boilerplate
        )
        self._figure.add_trace(trace)

        return trace

    def plot_trajectory(self, coordinates, *, label=None, color=None, trail=False):
        """Plots a precomputed trajectory.

        An attractor must be set first.

        Parameters
        ----------
        coordinates : ~astropy.coordinates.CartesianRepresentation
            Trajectory to plot.
        label : str, optional
            Label of the trajectory.
        color : str, optional
            Color of the trajectory.
        trail : bool, optional
            Fade the orbit trail, default to False.

        """
        if self._frame is None:
            raise ValueError(
                "A frame must be set up first, please use "
                "set_orbit_frame(orbit) or plot(orbit)"
            )

        return super().plot_trajectory(
            coordinates, label=label, color=color, trail=trail
        )

    def plot_ephem(self, ephem, epoch=None, *, label=None, color=None, trail=False):
        """Plots Ephem object over its sampling period.

        Parameters
        ----------
        ephem : ~poliastro.ephem.Ephem
            Ephemerides to plot.
        epoch : astropy.time.Time, optional
            Epoch of the current position, none will be used if not given.
        label : str, optional
            Label of the orbit, default to the name of the body.
        color : str, optional
            Color of the line and the position.
        trail : bool, optional
            Fade the orbit trail, default to False.

        """
        if self._frame is None:
            raise ValueError(
                "A frame must be set up first, please use "
                "set_orbit_frame(orbit) or plot(orbit)"
            )
        super().plot_ephem(ephem, epoch, label=label, color=color, trail=trail)

    def plot(self, orbit, *, label=None, color=None, trail=False):
        """Plots state and osculating orbit in their plane.

        Parameters
        ----------
        orbit : ~poliastro.twobody.orbit.Orbit
            Orbit to plot.
        label : str, optional
            Label of the orbit.
        color : str, optional
            Color of the line and the position.
        trail : bool, optional
            Fade the orbit trail, default to False.

        """

        if trail:
            raise NotImplementedError("trail not supported yet")

        if not self._frame:
            self.set_orbit_frame(orbit)

        return super().plot(orbit, label=label, color=color, trail=trail)

    def plot_body_orbit(
        self,
        body,
        epoch,
        plane=Planes.EARTH_ECLIPTIC,
        *,
        label=None,
        color=None,
        trail=False,
    ):
        """Plots complete revolution of body and current position.

        Parameters
        ----------
        body : poliastro.bodies.SolarSystemPlanet
            Body.
        epoch : astropy.time.Time
            Epoch of current position.
        plane : ~poliastro.frames.enums.Planes
            Reference plane.
        label : str, optional
            Label of the orbit, default to the name of the body.
        color : str, optional
            Color of the line and the position.
        trail : bool, optional
            Fade the orbit trail, default to False.

        """
        if self._frame is None:
            self.set_body_frame(body, epoch)

        return super().plot_body_orbit(
            body, epoch, label=label, color=color, trail=trail
        )
<|endoftext|>


<commit_before>#!/usr/bin/env python3
"""
test for the numa module.
"""

import unittest

from pscheduler.numa import *

from base_test import PschedTestBase

class TestNuma(PschedTestBase):
    """
    NUMA tests.
    """

    def test_numa(self):

        # These may or may not work; we just don't want them to crash.

        for node in range(0,3):
            numa_node_ok(node)

        # One bad one.

        self.assertEqual(
            numa_node_ok("foo"),
            (False, "libnuma: Warning: unparseable node description `foo'")
            )

if __name__ == '__main__':
    unittest.main()
<commit_msg>Support building inside Docker.<commit_after>#!/usr/bin/env python3
"""
test for the numa module.
"""

import unittest

from pscheduler.numa import *

from base_test import PschedTestBase

class TestNuma(PschedTestBase):
    """
    NUMA tests.
    """

    def test_numa(self):

        # These may or may not work; we just don't want them to crash.

        for node in range(0,3):
            numa_node_ok(node)

        # One bad one.

        self.assertIn(
            numa_node_ok("foo"),
            [(False, "libnuma: Warning: unparseable node description `foo'"),
                (False, 'numactl: This system does not support NUMA policy')]
            )

if __name__ == '__main__':
    unittest.main()
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
"""
Presence analyzer unit tests.
"""
import os.path
import json
import datetime
import unittest
from mock import patch

from presence_analyzer import main, utils, views

TEST_DATA_CSV = os.path.join(
    os.path.dirname(__file__), '..', '..', 'runtime', 'data', 'test_data.csv'
)

# pylint: disable=E1103, R0904
class PresenceAnalyzerViewsTestCase(unittest.TestCase):
    """
    Views tests.
    """

    def setUp(self):
        """
        Before each test, set up a environment.
        """
        main.app.config.update({'DATA_CSV': TEST_DATA_CSV})
        self.client = main.app.test_client()

    def tearDown(self):
        """
        Get rid of unused objects after each test.
        """
        pass

    def test_mainpage(self):
        """
        Test main page redirect.
        """
        resp = self.client.get('/')
        self.assertEqual(resp.status_code, 302)
        assert resp.headers['Location'].endswith('/presence_weekday.html')

    def test_api_users(self):
        """
        Test users listing.
        """
        resp = self.client.get('/api/v1/users')
        self.assertEqual(resp.status_code, 200)
        self.assertEqual(resp.content_type, 'application/json')
        data = json.loads(resp.data)
        self.assertEqual(len(data), 2)
        self.assertDictEqual(data[0], {u'user_id': 10, u'name': u'User 10'})

    def test_mean_time_weekday_view(self):
        """
        Test mean time weekday view.
        """
        resp = self.client.get('/api/v1/mean_time_weekday/10')
        self.assertEqual(resp.status_code, 200)
        self.assertEqual(resp.content_type, 'application/json')
        data = json.loads(resp.data)
        self.assertEqual(len(data), 7)
        non_empty_data = [item for item in data if item[1] != 0]

        self.assertEqual(len(non_empty_data), 3)
        self.assertEqual(non_empty_data[0][0], 'Tue')

    @patch.object(views, 'log')
    def test_mean_time_weekday_user(self, mocked_log):
        """
        Test mean time weekday view with invalid user_id.
        """
        resp = self.client.get('/api/v1/mean_time_weekday/1')
        self.assertEqual(resp.status_code, 200)
        self.assertEqual(resp.content_type, 'application/json')
        mocked_log.debug.assert_called_with('User %s not found!', 1)

    def test_presence_weekday_view(self):
        """
        Test presence weekday view.
        """
        resp = self.client.get('/api/v1/presence_weekday/10')
        self.assertEqual(resp.status_code, 200)
        self.assertEqual(resp.content_type, 'application/json')
        data = json.loads(resp.data)
        self.assertEqual(len(data), 8)
        self.assertEqual(data[0], [u'Weekday', u'Presence (s)'])
        data.pop(0)
        non_empty_data = [item for item in data if item[1] != 0]
        self.assertEqual(len(non_empty_data), 3)
        self.assertEqual(non_empty_data[0][0], 'Tue')

    @patch.object(views, 'log')
    def test_presence_weekday_user(self, mocked_log):
        """
        Test presence weekday view with invalid user_id.
        """
        resp = self.client.get('/api/v1/presence_weekday/1')
        self.assertEqual(resp.status_code, 200)
        self.assertEqual(resp.content_type, 'application/json')
        mocked_log.debug.assert_called_with('User %s not found!', 1)

class PresenceAnalyzerUtilsTestCase(unittest.TestCase):
    """
    Utility functions tests.
    """

    def setUp(self):
        """
        Before each test, set up a environment.
        """
        main.app.config.update({'DATA_CSV': TEST_DATA_CSV})

    def tearDown(self):
        """
        Get rid of unused objects after each test.
        """
        pass

    def test_get_data(self):
        """
        Test parsing of CSV file.
        """
        data = utils.get_data()
        self.assertIsInstance(data, dict)
        self.assertItemsEqual(data.keys(), [10, 11])
        sample_date = datetime.date(2013, 9, 10)
        self.assertIn(sample_date, data[10])
        self.assertItemsEqual(data[10][sample_date].keys(), ['start', 'end'])
        self.assertEqual(data[10][sample_date]['start'],
                         datetime.time(9, 39, 5))
        self.assertEqual(len(data[11]), 5)

    def test_interval(self):
        """
        Test interval method
        """
        sample_date = {
            "start": datetime.time(9, 39, 5),
            "end": datetime.time(17, 59, 52)
        }
        interval = utils.interval(sample_date["start"], sample_date["end"])

        self.assertEqual(interval, 30047)

    def test_group_by_weekday(self):
        """
        Test grouping by weekday
        """
        data = utils.get_data()
        weekdays = utils.group_by_weekday(data[10])

        sample_date = {
            "start": datetime.time(9, 39, 5),
            "end": datetime.time(17, 59, 52)
        }
        presence = 0

        for day, interval in weekdays.items():  # pylint: disable=W0612
            if len(interval):
                presence += 1

        self.assertItemsEqual(weekdays, [0, 1, 2, 3, 4, 5, 6])
        self.assertEqual(presence, 3)
        self.assertEqual(
            weekdays[1][0],
            utils.interval(sample_date["start"], sample_date["end"])
        )

    def test_mean(self):
        """
        Test mean method
        """
        self.assertEqual(utils.mean([22999, 22969]), 22984)

def suite():
    """
    Default test suite.
    """
    test_suite = unittest.TestSuite()
    test_suite.addTest(unittest.makeSuite(PresenceAnalyzerViewsTestCase))
    test_suite.addTest(unittest.makeSuite(PresenceAnalyzerUtilsTestCase))
    return test_suite

if __name__ == '__main__':
    unittest.main()
<commit_msg>[#2164] Comparing data with static dict<commit_after># -*- coding: utf-8 -*-
"""
Presence analyzer unit tests.
"""
import os.path
import json
import datetime
import unittest
from mock import patch

from presence_analyzer import main, utils, views

TEST_DATA_CSV = os.path.join(
    os.path.dirname(__file__), '..', '..', 'runtime', 'data', 'test_data.csv'
)

# pylint: disable=E1103, R0904
class PresenceAnalyzerViewsTestCase(unittest.TestCase):
    """
    Views tests.
    """

    def setUp(self):
        """
        Before each test, set up a environment.
        """
        main.app.config.update({'DATA_CSV': TEST_DATA_CSV})
        self.client = main.app.test_client()

    def tearDown(self):
        """
        Get rid of unused objects after each test.
        """
        pass

    def test_mainpage(self):
        """
        Test main page redirect.
        """
        resp = self.client.get('/')
        self.assertEqual(resp.status_code, 302)
        assert resp.headers['Location'].endswith('/presence_weekday.html')

    def test_api_users(self):
        """
        Test users listing.
        """
        resp = self.client.get('/api/v1/users')
        self.assertEqual(resp.status_code, 200)
        self.assertEqual(resp.content_type, 'application/json')
        data = json.loads(resp.data)
        self.assertEqual(len(data), 2)
        self.assertDictEqual(data[0], {u'user_id': 10, u'name': u'User 10'})

    def test_mean_time_weekday_view(self):
        """
        Test mean time weekday view.
        """
        resp = self.client.get('/api/v1/mean_time_weekday/10')
        self.assertEqual(resp.status_code, 200)
        self.assertEqual(resp.content_type, 'application/json')
        data = json.loads(resp.data)
        self.assertEqual(len(data), 7)
        non_empty_data = [item for item in data if item[1] != 0]

        self.assertEqual(len(non_empty_data), 3)
        self.assertEqual(non_empty_data[0][0], 'Tue')

    @patch.object(views, 'log')
    def test_mean_time_weekday_user(self, mocked_log):
        """
        Test mean time weekday view with invalid user_id.
        """
        resp = self.client.get('/api/v1/mean_time_weekday/1')
        self.assertEqual(resp.status_code, 200)
        self.assertEqual(resp.content_type, 'application/json')
        mocked_log.debug.assert_called_with('User %s not found!', 1)

    def test_presence_weekday_view(self):
        """
        Test presence weekday view.
        """
        resp = self.client.get('/api/v1/presence_weekday/10')
        self.assertEqual(resp.status_code, 200)
        self.assertEqual(resp.content_type, 'application/json')
        data = json.loads(resp.data)
        expected_output = [[u'Weekday', u'Presence (s)'], [u'Mon', 0],
                           [u'Tue', 30047], [u'Wed', 24465], [u'Thu', 23705],
                           [u'Fri', 0], [u'Sat', 0], [u'Sun', 0]]
        self.assertEqual(data, expected_output)

    @patch.object(views, 'log')
    def test_presence_weekday_user(self, mocked_log):
        """
        Test presence weekday view with invalid user_id.
        """
        resp = self.client.get('/api/v1/presence_weekday/1')
        self.assertEqual(resp.status_code, 200)
        self.assertEqual(resp.content_type, 'application/json')
        mocked_log.debug.assert_called_with('User %s not found!', 1)

class PresenceAnalyzerUtilsTestCase(unittest.TestCase):
    """
    Utility functions tests.
    """

    def setUp(self):
        """
        Before each test, set up a environment.
        """
        main.app.config.update({'DATA_CSV': TEST_DATA_CSV})

    def tearDown(self):
        """
        Get rid of unused objects after each test.
        """
        pass

    def test_get_data(self):
        """
        Test parsing of CSV file.
        """
        data = utils.get_data()
        self.assertIsInstance(data, dict)
        self.assertItemsEqual(data.keys(), [10, 11])
        sample_date = datetime.date(2013, 9, 10)
        self.assertIn(sample_date, data[10])
        self.assertItemsEqual(data[10][sample_date].keys(), ['start', 'end'])
        self.assertEqual(data[10][sample_date]['start'],
                         datetime.time(9, 39, 5))
        self.assertEqual(len(data[11]), 5)

    def test_interval(self):
        """
        Test interval method
        """
        sample_date = {
            "start": datetime.time(9, 39, 5),
            "end": datetime.time(17, 59, 52)
        }
        interval = utils.interval(sample_date["start"], sample_date["end"])

        self.assertEqual(interval, 30047)

    def test_group_by_weekday(self):
        """
        Test grouping by weekday
        """
        data = utils.get_data()
        weekdays = utils.group_by_weekday(data[10])
        expected_output = {
            0: [],
            1: [30047],
            2: [24465],
            3: [23705],
            4: [],
            5: [],
            6: []
        }
        self.assertEqual(weekdays, expected_output)

    def test_mean(self):
        """
        Test mean method
        """
        self.assertEqual(utils.mean([22999, 22969]), 22984)

def suite():
    """
    Default test suite.
    """
    test_suite = unittest.TestSuite()
    test_suite.addTest(unittest.makeSuite(PresenceAnalyzerViewsTestCase))
    test_suite.addTest(unittest.makeSuite(PresenceAnalyzerUtilsTestCase))
    return test_suite

if __name__ == '__main__':
    unittest.main()
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
#
# The internetarchive module is a Python/CLI interface to Archive.org.
#
# Copyright (C) 2012-2017 Internet Archive
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

"""
internetarchive.session
~~~~~~~~~~~~~~~~~~~~~~~

This module provides an ArchiveSession object to manage and persist
settings across the internetarchive package.

:copyright: (C) 2012-2017 by Internet Archive.
:license: AGPL 3, see LICENSE for more details.
"""
from __future__ import absolute_import, unicode_literals

import os
import locale
import sys
import logging
import platform
import warnings

import requests.sessions
from requests.utils import default_headers
from requests.adapters import HTTPAdapter
from requests.packages.urllib3 import Retry

from internetarchive import __version__
from internetarchive.config import get_config
from internetarchive.item import Item, Collection
from internetarchive.search import Search
from internetarchive.catalog import Catalog

logger = logging.getLogger(__name__)

class ArchiveSession(requests.sessions.Session):
    """The :class:`ArchiveSession <internetarchive.ArchiveSession>`
    object collects together useful functionality from `internetarchive`
    as well as important data such as configuration information and
    credentials.  It is subclassed from
    :class:`requests.Session <requests.Session>`.

    Usage::

        >>> from internetarchive import ArchiveSession
        >>> s = ArchiveSession()
        >>> item = s.get_item('nasa')
        Collection(identifier='nasa', exists=True)
    """

    ITEM_MEDIATYPE_TABLE = {
        'collection': Collection,
    }

    def __init__(self,
                 config=None,
                 config_file=None,
                 debug=None,
                 http_adapter_kwargs=None):
        """Initialize :class:`ArchiveSession <ArchiveSession>` object with config.

        :type config: dict
        :param config: (optional) A config dict used for initializing the
                       :class:`ArchiveSession <ArchiveSession>` object.

        :type config_file: str
        :param config_file: (optional) Path to config file used for initializing the
                            :class:`ArchiveSession <ArchiveSession>` object.

        :type http_adapter_kwargs: dict
        :param http_adapter_kwargs: (optional) Keyword arguments used to initialize the
                                    :class:`requests.adapters.HTTPAdapter <HTTPAdapter>`
                                    object.

        :returns: :class:`ArchiveSession` object.
        """
        super(ArchiveSession, self).__init__()
        http_adapter_kwargs = {} if not http_adapter_kwargs else http_adapter_kwargs
        debug = False if not debug else True

        self.config = get_config(config, config_file)
        self.config_file = config_file
        self.cookies.update(self.config.get('cookies', {}))
        self.secure = self.config.get('general', {}).get('secure', True)
        self.protocol = 'https:' if self.secure else 'http:'
        self.access_key = self.config.get('s3', {}).get('access')
        self.secret_key = self.config.get('s3', {}).get('secret')
        self.http_adapter_kwargs = http_adapter_kwargs

        self.headers = default_headers()
        self.headers.update({'User-Agent': self._get_user_agent_string()})
        self.mount_http_adapter()

        logging_config = self.config.get('logging', {})
        if logging_config.get('level'):
            self.set_file_logger(logging_config.get('level', 'NOTSET'),
                                 logging_config.get('file', 'internetarchive.log'))
            if debug or (logger.level <= 10):
                self.set_file_logger(logging_config.get('level', 'NOTSET'),
                                     logging_config.get('file', 'internetarchive.log'),
                                     'requests.packages.urllib3')

    def _get_user_agent_string(self):
        """Generate a User-Agent string to be sent with every request."""
        uname = platform.uname()
        try:
            lang = locale.getlocale()[0][:2]
        except:
            lang = ''
        py_version = '{0}.{1}.{2}'.format(*sys.version_info)
        return 'internetarchive/{0} ({1} {2}; N; {3}; {4}) Python/{5}'.format(
            __version__, uname[0], uname[-1], lang, self.access_key, py_version)

    def mount_http_adapter(self, protocol=None, max_retries=None,
                            status_forcelist=None, host=None):
        """Mount an HTTP adapter to the
        :class:`ArchiveSession <ArchiveSession>` object.

        :type protocol: str
        :param protocol: HTTP protocol to mount your adapter to (e.g. 'https://').

        :type max_retries: int, object
        :param max_retries: The number of times to retry a failed request.
                            This can also be an `urllib3.Retry` object.

        :type status_forcelist: list
        :param status_forcelist: A list of status codes (as int's) to retry on.

        :type host: str
        :param host: The host to mount your adapter to.
        """
        protocol = protocol if protocol else self.protocol
        host = host if host else 'archive.org'
        if max_retries is None:
            max_retries = self.http_adapter_kwargs.get('max_retries', 3)

        if not status_forcelist:
            status_forcelist = [500, 501, 502, 503, 504]
        if max_retries and isinstance(max_retries, (int, float)):
            max_retries = Retry(total=max_retries,
                                connect=max_retries,
                                read=max_retries,
                                redirect=False,
                                method_whitelist=Retry.DEFAULT_METHOD_WHITELIST,
                                status_forcelist=status_forcelist,
                                backoff_factor=1)
        self.http_adapter_kwargs['max_retries'] = max_retries
        max_retries_adapter = HTTPAdapter(**self.http_adapter_kwargs)
        # Don't mount on s3.us.archive.org, only archive.org!
        # IA-S3 requires a more complicated retry workflow.
        self.mount('{0}//{1}'.format(protocol, host), max_retries_adapter)

    def set_file_logger(self, log_level, path, logger_name='internetarchive'):
        """Convenience function to quickly configure any level of
        logging to a file.

        :type log_level: str
        :param log_level: A log level as specified in the `logging` module.

        :type path: string
        :param path: Path to the log file. The file will be created if it doesn't already
                     exist.

        :type logger_name: str
        :param logger_name: (optional) The name of the logger.
        """
        _log_level = {
            'CRITICAL': 50,
            'ERROR': 40,
            'WARNING': 30,
            'INFO': 20,
            'DEBUG': 10,
            'NOTSET': 0,
        }

        log_format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'

        _log = logging.getLogger(logger_name)
        _log.setLevel(logging.DEBUG)

        fh = logging.FileHandler(path, encoding='utf-8')
        fh.setLevel(_log_level[log_level])

        formatter = logging.Formatter(log_format)
        fh.setFormatter(formatter)

        _log.addHandler(fh)

    def get_item(self, identifier, item_metadata=None, request_kwargs=None):
        """A method for creating :class:`internetarchive.Item <Item>` and
        :class:`internetarchive.Collection <Collection>` objects.

        :type identifier: str
        :param identifier: A globally unique Archive.org identifier.

        :type item_metadata: dict
        :param item_metadata: (optional) A metadata dict used to initialize the Item or
                              Collection object. Metadata will automatically be retrieved
                              from Archive.org if nothing is provided.

        :type request_kwargs: dict
        :param request_kwargs: (optional) Keyword arguments to be used in
                                    :meth:`requests.sessions.Session.get` request.
        """
        request_kwargs = {} if not request_kwargs else request_kwargs
        if not item_metadata:
            logger.debug('no metadata provided for "{0}", '
                         'retrieving now.'.format(identifier))
            item_metadata = self.get_metadata(identifier, request_kwargs)
        mediatype = item_metadata.get('metadata', {}).get('mediatype')
        try:
            item_class = self.ITEM_MEDIATYPE_TABLE.get(mediatype, Item)
        except TypeError:
            item_class = Item
        return item_class(self, identifier, item_metadata)

    def get_metadata(self, identifier, request_kwargs=None):
        """Get an item's metadata from the `Metadata API
        <http://blog.archive.org/2013/07/04/metadata-api/>`__

        :type identifier: str
        :param identifier: Globally unique Archive.org identifier.

        :rtype: dict
        :returns: Metadat API response.
        """
        request_kwargs = {} if not request_kwargs else request_kwargs
        url = '{0}//archive.org/metadata/{1}'.format(self.protocol, identifier)
        if 'timeout' not in request_kwargs:
            request_kwargs['timeout'] = 12
        try:
            resp = self.get(url, **request_kwargs)
            resp.raise_for_status()
        except Exception as exc:
            error_msg = 'Error retrieving metadata from {0}, {1}'.format(url, exc)
            logger.error(error_msg)
            raise type(exc)(error_msg)
        return resp.json()

    def search_items(self, query,
                     fields=None,
                     sorts=None,
                     params=None,
                     request_kwargs=None):
        """Search for items on Archive.org.

        :type query: str
        :param query: The Archive.org search query to yield results for. Refer to
                      https://archive.org/advancedsearch.php#raw for help formatting your
                      query.

        :type fields: bool
        :param fields: (optional) The metadata fields to return in the search results.

        :type params: dict
        :param params: (optional) The URL parameters to send with each request sent to the
                       Archive.org Advancedsearch Api.

        :returns: A :class:`Search` object, yielding search results.
        """
        request_kwargs = {} if not request_kwargs else request_kwargs
        return Search(self, query,
                      fields=fields,
                      sorts=sorts,
                      params=params,
                      request_kwargs=request_kwargs)

    def get_tasks(self,
                  identifier=None,
                  task_ids=None,
                  task_type=None,
                  params=None,
                  config=None,
                  verbose=None,
                  request_kwargs=None):
        """Get tasks from the Archive.org catalog. ``internetarchive`` must be configured
        with your logged-in-* cookies to use this function. If no arguments are provided,
        all queued tasks for the user will be returned.

        :type identifier: str
        :param identifier: (optional) The Archive.org identifier for which to retrieve
                           tasks for.

        :type task_ids: int or str
        :param task_ids: (optional) The task_ids to retrieve from the Archive.org catalog.

        :type task_type: str
        :param task_type: (optional) The type of tasks to retrieve from the Archive.org
                          catalog. The types can be either "red" for failed tasks, "blue"
                          for running tasks, "green" for pending tasks, "brown" for paused
                          tasks, or "purple" for completed tasks.

        :type params: dict
        :param params: (optional) The URL parameters to send with each request sent to the
                       Archive.org catalog API.

        :type config: dict
        :param secure: (optional) Configuration options for session.

        :type verbose: bool
        :param verbose: (optional) Set to ``True`` to retrieve verbose information for
                        each catalog task returned. verbose is set to ``True`` by default.

        :returns: A set of :class:`CatalogTask` objects.
        """
        request_kwargs = {} if not request_kwargs else request_kwargs
        _catalog = Catalog(self,
                           identifier=identifier,
                           task_ids=task_ids,
                           params=params,
                           config=config,
                           verbose=verbose,
                           request_kwargs=request_kwargs)
        if task_type:
            return eval('_catalog.{0}_rows'.format(task_type.lower()))
        else:
            return _catalog.tasks

    def s3_is_overloaded(self, identifier=None, access_key=None, request_kwargs=None):
        request_kwargs = {} if not request_kwargs else request_kwargs
        if 'timeout' not in request_kwargs:
            request_kwargs['timeout'] = 12

        u = '{protocol}//s3.us.archive.org'.format(protocol=self.protocol)
        p = dict(
            check_limit=1,
            accesskey=access_key,
            bucket=identifier,
        )
        try:
            r = self.get(u, params=p, **request_kwargs)
        except:
            return True
        try:
            j = r.json()
        except ValueError:
            return True
        if j.get('over_limit') == 0:
            return False
        else:
            return True

    def send(self, request, **kwargs):
        # Catch urllib3 warnings for HTTPS related errors.
        insecure = False
        with warnings.catch_warnings(record=True) as w:
            warnings.filterwarnings('always')
            r = super(ArchiveSession, self).send(request, **kwargs)
            if self.protocol == 'http:':
                return r
            insecure_warnings = ['SNIMissingWarning', 'InsecurePlatformWarning']
            if w:
                for e in w:
                    if any(x in str(e) for x in insecure_warnings):
                        insecure = True
                        break
        if insecure:
            from requests.exceptions import RequestException
            msg = ('You are attempting to make an HTTPS request on an insecure platform,'
                   ' please see:\n\n\thttps://internetarchive.readthedocs.org'
                   '/en/latest/troubleshooting.html#https-issues\n')
            raise RequestException(msg)
        return r
<commit_msg>forgot to add new kwarg<commit_after># -*- coding: utf-8 -*-
#
# The internetarchive module is a Python/CLI interface to Archive.org.
#
# Copyright (C) 2012-2017 Internet Archive
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

"""
internetarchive.session
~~~~~~~~~~~~~~~~~~~~~~~

This module provides an ArchiveSession object to manage and persist
settings across the internetarchive package.

:copyright: (C) 2012-2017 by Internet Archive.
:license: AGPL 3, see LICENSE for more details.
"""
from __future__ import absolute_import, unicode_literals

import os
import locale
import sys
import logging
import platform
import warnings

import requests.sessions
from requests.utils import default_headers
from requests.adapters import HTTPAdapter
from requests.packages.urllib3 import Retry

from internetarchive import __version__
from internetarchive.config import get_config
from internetarchive.item import Item, Collection
from internetarchive.search import Search
from internetarchive.catalog import Catalog

logger = logging.getLogger(__name__)

class ArchiveSession(requests.sessions.Session):
    """The :class:`ArchiveSession <internetarchive.ArchiveSession>`
    object collects together useful functionality from `internetarchive`
    as well as important data such as configuration information and
    credentials.  It is subclassed from
    :class:`requests.Session <requests.Session>`.

    Usage::

        >>> from internetarchive import ArchiveSession
        >>> s = ArchiveSession()
        >>> item = s.get_item('nasa')
        Collection(identifier='nasa', exists=True)
    """

    ITEM_MEDIATYPE_TABLE = {
        'collection': Collection,
    }

    def __init__(self,
                 config=None,
                 config_file=None,
                 debug=None,
                 http_adapter_kwargs=None):
        """Initialize :class:`ArchiveSession <ArchiveSession>` object with config.

        :type config: dict
        :param config: (optional) A config dict used for initializing the
                       :class:`ArchiveSession <ArchiveSession>` object.

        :type config_file: str
        :param config_file: (optional) Path to config file used for initializing the
                            :class:`ArchiveSession <ArchiveSession>` object.

        :type http_adapter_kwargs: dict
        :param http_adapter_kwargs: (optional) Keyword arguments used to initialize the
                                    :class:`requests.adapters.HTTPAdapter <HTTPAdapter>`
                                    object.

        :returns: :class:`ArchiveSession` object.
        """
        super(ArchiveSession, self).__init__()
        http_adapter_kwargs = {} if not http_adapter_kwargs else http_adapter_kwargs
        debug = False if not debug else True

        self.config = get_config(config, config_file)
        self.config_file = config_file
        self.cookies.update(self.config.get('cookies', {}))
        self.secure = self.config.get('general', {}).get('secure', True)
        self.protocol = 'https:' if self.secure else 'http:'
        self.access_key = self.config.get('s3', {}).get('access')
        self.secret_key = self.config.get('s3', {}).get('secret')
        self.http_adapter_kwargs = http_adapter_kwargs

        self.headers = default_headers()
        self.headers.update({'User-Agent': self._get_user_agent_string()})
        self.mount_http_adapter()

        logging_config = self.config.get('logging', {})
        if logging_config.get('level'):
            self.set_file_logger(logging_config.get('level', 'NOTSET'),
                                 logging_config.get('file', 'internetarchive.log'))
            if debug or (logger.level <= 10):
                self.set_file_logger(logging_config.get('level', 'NOTSET'),
                                     logging_config.get('file', 'internetarchive.log'),
                                     'requests.packages.urllib3')

    def _get_user_agent_string(self):
        """Generate a User-Agent string to be sent with every request."""
        uname = platform.uname()
        try:
            lang = locale.getlocale()[0][:2]
        except:
            lang = ''
        py_version = '{0}.{1}.{2}'.format(*sys.version_info)
        return 'internetarchive/{0} ({1} {2}; N; {3}; {4}) Python/{5}'.format(
            __version__, uname[0], uname[-1], lang, self.access_key, py_version)

    def mount_http_adapter(self, protocol=None, max_retries=None,
                            status_forcelist=None, host=None):
        """Mount an HTTP adapter to the
        :class:`ArchiveSession <ArchiveSession>` object.

        :type protocol: str
        :param protocol: HTTP protocol to mount your adapter to (e.g. 'https://').

        :type max_retries: int, object
        :param max_retries: The number of times to retry a failed request.
                            This can also be an `urllib3.Retry` object.

        :type status_forcelist: list
        :param status_forcelist: A list of status codes (as int's) to retry on.

        :type host: str
        :param host: The host to mount your adapter to.
        """
        protocol = protocol if protocol else self.protocol
        host = host if host else 'archive.org'
        if max_retries is None:
            max_retries = self.http_adapter_kwargs.get('max_retries', 3)

        if not status_forcelist:
            status_forcelist = [500, 501, 502, 503, 504]
        if max_retries and isinstance(max_retries, (int, float)):
            max_retries = Retry(total=max_retries,
                                connect=max_retries,
                                read=max_retries,
                                redirect=False,
                                method_whitelist=Retry.DEFAULT_METHOD_WHITELIST,
                                status_forcelist=status_forcelist,
                                backoff_factor=1)
        self.http_adapter_kwargs['max_retries'] = max_retries
        max_retries_adapter = HTTPAdapter(**self.http_adapter_kwargs)
        # Don't mount on s3.us.archive.org, only archive.org!
        # IA-S3 requires a more complicated retry workflow.
        self.mount('{0}//{1}'.format(protocol, host), max_retries_adapter)

    def set_file_logger(self, log_level, path, logger_name='internetarchive'):
        """Convenience function to quickly configure any level of
        logging to a file.

        :type log_level: str
        :param log_level: A log level as specified in the `logging` module.

        :type path: string
        :param path: Path to the log file. The file will be created if it doesn't already
                     exist.

        :type logger_name: str
        :param logger_name: (optional) The name of the logger.
        """
        _log_level = {
            'CRITICAL': 50,
            'ERROR': 40,
            'WARNING': 30,
            'INFO': 20,
            'DEBUG': 10,
            'NOTSET': 0,
        }

        log_format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'

        _log = logging.getLogger(logger_name)
        _log.setLevel(logging.DEBUG)

        fh = logging.FileHandler(path, encoding='utf-8')
        fh.setLevel(_log_level[log_level])

        formatter = logging.Formatter(log_format)
        fh.setFormatter(formatter)

        _log.addHandler(fh)

    def get_item(self, identifier, item_metadata=None, request_kwargs=None):
        """A method for creating :class:`internetarchive.Item <Item>` and
        :class:`internetarchive.Collection <Collection>` objects.

        :type identifier: str
        :param identifier: A globally unique Archive.org identifier.

        :type item_metadata: dict
        :param item_metadata: (optional) A metadata dict used to initialize the Item or
                              Collection object. Metadata will automatically be retrieved
                              from Archive.org if nothing is provided.

        :type request_kwargs: dict
        :param request_kwargs: (optional) Keyword arguments to be used in
                                    :meth:`requests.sessions.Session.get` request.
        """
        request_kwargs = {} if not request_kwargs else request_kwargs
        if not item_metadata:
            logger.debug('no metadata provided for "{0}", '
                         'retrieving now.'.format(identifier))
            item_metadata = self.get_metadata(identifier, request_kwargs)
        mediatype = item_metadata.get('metadata', {}).get('mediatype')
        try:
            item_class = self.ITEM_MEDIATYPE_TABLE.get(mediatype, Item)
        except TypeError:
            item_class = Item
        return item_class(self, identifier, item_metadata)

    def get_metadata(self, identifier, request_kwargs=None):
        """Get an item's metadata from the `Metadata API
        <http://blog.archive.org/2013/07/04/metadata-api/>`__

        :type identifier: str
        :param identifier: Globally unique Archive.org identifier.

        :rtype: dict
        :returns: Metadat API response.
        """
        request_kwargs = {} if not request_kwargs else request_kwargs
        url = '{0}//archive.org/metadata/{1}'.format(self.protocol, identifier)
        if 'timeout' not in request_kwargs:
            request_kwargs['timeout'] = 12
        try:
            resp = self.get(url, **request_kwargs)
            resp.raise_for_status()
        except Exception as exc:
            error_msg = 'Error retrieving metadata from {0}, {1}'.format(url, exc)
            logger.error(error_msg)
            raise type(exc)(error_msg)
        return resp.json()

    def search_items(self, query,
                     fields=None,
                     sorts=None,
                     params=None,
                     request_kwargs=None,
                     max_retries=None):
        """Search for items on Archive.org.

        :type query: str
        :param query: The Archive.org search query to yield results for. Refer to
                      https://archive.org/advancedsearch.php#raw for help formatting your
                      query.

        :type fields: bool
        :param fields: (optional) The metadata fields to return in the search results.

        :type params: dict
        :param params: (optional) The URL parameters to send with each request sent to the
                       Archive.org Advancedsearch Api.

        :returns: A :class:`Search` object, yielding search results.
        """
        request_kwargs = {} if not request_kwargs else request_kwargs
        return Search(self, query,
                      fields=fields,
                      sorts=sorts,
                      params=params,
                      request_kwargs=request_kwargs,
                      max_retries=None)

    def get_tasks(self,
                  identifier=None,
                  task_ids=None,
                  task_type=None,
                  params=None,
                  config=None,
                  verbose=None,
                  request_kwargs=None):
        """Get tasks from the Archive.org catalog. ``internetarchive`` must be configured
        with your logged-in-* cookies to use this function. If no arguments are provided,
        all queued tasks for the user will be returned.

        :type identifier: str
        :param identifier: (optional) The Archive.org identifier for which to retrieve
                           tasks for.

        :type task_ids: int or str
        :param task_ids: (optional) The task_ids to retrieve from the Archive.org catalog.

        :type task_type: str
        :param task_type: (optional) The type of tasks to retrieve from the Archive.org
                          catalog. The types can be either "red" for failed tasks, "blue"
                          for running tasks, "green" for pending tasks, "brown" for paused
                          tasks, or "purple" for completed tasks.

        :type params: dict
        :param params: (optional) The URL parameters to send with each request sent to the
                       Archive.org catalog API.

        :type config: dict
        :param secure: (optional) Configuration options for session.

        :type verbose: bool
        :param verbose: (optional) Set to ``True`` to retrieve verbose information for
                        each catalog task returned. verbose is set to ``True`` by default.

        :returns: A set of :class:`CatalogTask` objects.
        """
        request_kwargs = {} if not request_kwargs else request_kwargs
        _catalog = Catalog(self,
                           identifier=identifier,
                           task_ids=task_ids,
                           params=params,
                           config=config,
                           verbose=verbose,
                           request_kwargs=request_kwargs)
        if task_type:
            return eval('_catalog.{0}_rows'.format(task_type.lower()))
        else:
            return _catalog.tasks

    def s3_is_overloaded(self, identifier=None, access_key=None, request_kwargs=None):
        request_kwargs = {} if not request_kwargs else request_kwargs
        if 'timeout' not in request_kwargs:
            request_kwargs['timeout'] = 12

        u = '{protocol}//s3.us.archive.org'.format(protocol=self.protocol)
        p = dict(
            check_limit=1,
            accesskey=access_key,
            bucket=identifier,
        )
        try:
            r = self.get(u, params=p, **request_kwargs)
        except:
            return True
        try:
            j = r.json()
        except ValueError:
            return True
        if j.get('over_limit') == 0:
            return False
        else:
            return True

    def send(self, request, **kwargs):
        # Catch urllib3 warnings for HTTPS related errors.
        insecure = False
        with warnings.catch_warnings(record=True) as w:
            warnings.filterwarnings('always')
            r = super(ArchiveSession, self).send(request, **kwargs)
            if self.protocol == 'http:':
                return r
            insecure_warnings = ['SNIMissingWarning', 'InsecurePlatformWarning']
            if w:
                for e in w:
                    if any(x in str(e) for x in insecure_warnings):
                        insecure = True
                        break
        if insecure:
            from requests.exceptions import RequestException
            msg = ('You are attempting to make an HTTPS request on an insecure platform,'
                   ' please see:\n\n\thttps://internetarchive.readthedocs.org'
                   '/en/latest/troubleshooting.html#https-issues\n')
            raise RequestException(msg)
        return r
<|endoftext|>


<commit_before>from pushbullet import Pushbullet
from lxml import html
import requests
import time

def goGoalShop():
	try:
		page = requests.get('https://www.gogoalshop.com/flash-index')
		tree = html.fromstring(page.text)

		#//*[@id="gagaDealDiv"]/ul - entire list
		#//*[@id="gagaDealDiv"]/ul/li[1] - first of the list
		#//*[@id="gagaDealDiv"]/ul/li[12] - last of the list

		items = []

		for i in range(1, 13):
			xpathString = '//*[@id="gagaDealDiv"]/ul/li[' + str(i) + ']/div[2]/a/text()'
			items.append(tree.xpath(xpathString)[0])

		for elem in items:
			if "Bayern" in elem:
				print(time.strftime("%a %m/%d/%y %I:%M:%S") + " | GoGoalShop.com: Found Bayern jersey!")
				push = myPhone.push_link("GoGoalShop.com: " + elem, "https://www.gogoalshop.com/flash-index")
			if "Arsenal" in elem:
				print(time.strftime("%a %m/%d/%y %I:%M:%S") + " | GoGoalShop.com: Found Barcelona jersey!")
				push = myPhone.push_link("GoGoalShop.com: " + elem, "https://www.gogoalshop.com/flash-index")
			if "Barcelona" in elem:
				print(time.strftime("%a %m/%d/%y %I:%M:%S") + " | GoGoalShop.com: Found Barcelona jersey!")
				push = myPhone.push_link("GoGoalShop.com: " + elem, "https://www.gogoalshop.com/flash-index")

	except Exception as e:
		print(time.strftime("%a %m/%d/%y %I:%M:%S") + " | GoGoalShop.com: Oops! Something went wrong during scraping. Most likely items are not available yet.")
		print(time.strftime("%a %m/%d/%y %I:%M:%S") + " | " + e)
	else:
		print(time.strftime("%a %m/%d/%y %I:%M:%S") + " | GoGoalShop.com: Scraping ran successfully!")

def bestCheapSoccer():
	try:
		page = requests.get('http://www.bestcheapsoccer.com/flash-index')
		tree = html.fromstring(page.text)

		items = []

		for i in range(1, 13):
			xpathString = '//*[@id="gagaDealDiv"]/ul/li[' + str(i) + ']/div[2]/a/@title'
			items.append(tree.xpath(xpathString)[0])

		for elem in items:
			if "Bayern" in elem:
				print(time.strftime("%a %m/%d/%y %I:%M:%S") + " | BestCheapSoccer.com: Found Bayern jersey!")
				push = myPhone.push_link("BestCheapSoccer.com: " + elem, "http://www.bestcheapsoccer.com/flash-index")
			if "Arsenal" in elem:
				print(time.strftime("%a %m/%d/%y %I:%M:%S") + " | BestCheapSoccer.com: Found Barcelona jersey!")
				push = myPhone.push_link("BestCheapSoccer.com: " + elem, "http://www.bestcheapsoccer.com/flash-index")
			if "Barcelona" in elem:
				print(time.strftime("%a %m/%d/%y %I:%M:%S") + " | BestCheapSoccer.com: Found Barcelona jersey!")
				push = myPhone.push_link("BestCheapSoccer.com: " + elem, "http://www.bestcheapsoccer.com/flash-index")

	except Exception as e:
		print(time.strftime("%a %m/%d/%y %I:%M:%S") + " | BestCheapSoccer.com: Oops! Something went wrong during scraping. Most likely items are not available yet.")
		print(time.strftime("%a %m/%d/%y %I:%M:%S") + " | " + str(e))
	else:
		print(time.strftime("%a %m/%d/%y %I:%M:%S") + " | BestCheapSoccer.com: Scraping ran successfully!")

try:
	with open("api_key.txt", 'r') as fileIn:
		api_key = fileIn.read().strip()
		pb = Pushbullet(api_key)
		myPhone = pb.devices[0]
except Exception as e:
	print(time.strftime("%a %m/%d/%y %I:%M:%S") + " | Something went wrong with the Pushbullet.")
else:
	goGoalShop()
	bestCheapSoccer()
<commit_msg>Fixed exception to string error<commit_after>from pushbullet import Pushbullet
from lxml import html
import requests
import time

def goGoalShop():
	try:
		page = requests.get('https://www.gogoalshop.com/flash-index')
		tree = html.fromstring(page.text)

		#//*[@id="gagaDealDiv"]/ul - entire list
		#//*[@id="gagaDealDiv"]/ul/li[1] - first of the list
		#//*[@id="gagaDealDiv"]/ul/li[12] - last of the list

		items = []

		for i in range(1, 13):
			xpathString = '//*[@id="gagaDealDiv"]/ul/li[' + str(i) + ']/div[2]/a/text()'
			items.append(tree.xpath(xpathString)[0])

		for elem in items:
			if "Bayern" in elem:
				print(time.strftime("%a %m/%d/%y %I:%M:%S") + " | GoGoalShop.com: Found Bayern jersey!")
				push = myPhone.push_link("GoGoalShop.com: " + elem, "https://www.gogoalshop.com/flash-index")
			if "Arsenal" in elem:
				print(time.strftime("%a %m/%d/%y %I:%M:%S") + " | GoGoalShop.com: Found Barcelona jersey!")
				push = myPhone.push_link("GoGoalShop.com: " + elem, "https://www.gogoalshop.com/flash-index")
			if "Barcelona" in elem:
				print(time.strftime("%a %m/%d/%y %I:%M:%S") + " | GoGoalShop.com: Found Barcelona jersey!")
				push = myPhone.push_link("GoGoalShop.com: " + elem, "https://www.gogoalshop.com/flash-index")

	except Exception as e:
		print(time.strftime("%a %m/%d/%y %I:%M:%S") + " | GoGoalShop.com: Oops! Something went wrong during scraping. Most likely items are not available yet.")
		print(time.strftime("%a %m/%d/%y %I:%M:%S") + " | " + str(e))
	else:
		print(time.strftime("%a %m/%d/%y %I:%M:%S") + " | GoGoalShop.com: Scraping ran successfully!")

def bestCheapSoccer():
	try:
		page = requests.get('http://www.bestcheapsoccer.com/flash-index')
		tree = html.fromstring(page.text)

		items = []

		for i in range(1, 13):
			xpathString = '//*[@id="gagaDealDiv"]/ul/li[' + str(i) + ']/div[2]/a/@title'
			items.append(tree.xpath(xpathString)[0])

		for elem in items:
			if "Bayern" in elem:
				print(time.strftime("%a %m/%d/%y %I:%M:%S") + " | BestCheapSoccer.com: Found Bayern jersey!")
				push = myPhone.push_link("BestCheapSoccer.com: " + elem, "http://www.bestcheapsoccer.com/flash-index")
			if "Arsenal" in elem:
				print(time.strftime("%a %m/%d/%y %I:%M:%S") + " | BestCheapSoccer.com: Found Barcelona jersey!")
				push = myPhone.push_link("BestCheapSoccer.com: " + elem, "http://www.bestcheapsoccer.com/flash-index")
			if "Barcelona" in elem:
				print(time.strftime("%a %m/%d/%y %I:%M:%S") + " | BestCheapSoccer.com: Found Barcelona jersey!")
				push = myPhone.push_link("BestCheapSoccer.com: " + elem, "http://www.bestcheapsoccer.com/flash-index")

	except Exception as e:
		print(time.strftime("%a %m/%d/%y %I:%M:%S") + " | BestCheapSoccer.com: Oops! Something went wrong during scraping. Most likely items are not available yet.")
		print(time.strftime("%a %m/%d/%y %I:%M:%S") + " | " + str(e))
	else:
		print(time.strftime("%a %m/%d/%y %I:%M:%S") + " | BestCheapSoccer.com: Scraping ran successfully!")

try:
	with open("api_key.txt", 'r') as fileIn:
		api_key = fileIn.read().strip()
		pb = Pushbullet(api_key)
		myPhone = pb.devices[0]
except Exception as e:
	print(time.strftime("%a %m/%d/%y %I:%M:%S") + " | Something went wrong with the Pushbullet.")
	print(time.strftime("%a %m/%d/%y %I:%M:%S") + " | " + str(e))
else:
	goGoalShop()
	bestCheapSoccer()
<|endoftext|>


<commit_before>from sphinx.ext import autodoc
from sphinx.util.inspect import getargspec
from inspect import ArgSpec, formatargspec
from powerline.lib.threaded import ThreadedSegment, KwThreadedSegment
from itertools import count

try:
	from __builtin__ import unicode
except ImportError:
	unicode = lambda s, enc: s  # NOQA

def formatvalue(val):
	if type(val) is str:
		return '="' + unicode(val, 'utf-8').replace('"', '\\"').replace('\\', '\\\\') + '"'
	else:
		return '=' + repr(val)

class ThreadedDocumenter(autodoc.FunctionDocumenter):
	'''Specialized documenter subclass for ThreadedSegment subclasses.'''
	@classmethod
	def can_document_member(cls, member, membername, isattr, parent):
		return (isinstance(member, ThreadedSegment) or
			super(ThreadedDocumenter, cls).can_document_member(member, membername, isattr, parent))

	def format_args(self):
		if isinstance(self.object, ThreadedSegment):
			args = ['interval']
			defaults = [getattr(self.object, 'interval', 1)]
			if self.object.update_first:
				args.append('update_first')
				defaults.append(True)
			methods = ['render', 'set_state']
			if isinstance(self.object, KwThreadedSegment):
				methods += ['key', 'render_one']

			for method in methods:
				if hasattr(self.object, method):
					# Note: on <python-2.6 it may return simple tuple, not
					# ArgSpec instance.
					argspec = getargspec(getattr(self.object, method))
					for i, arg in zip(count(-1, -1), reversed(argspec.args)):
						if (arg == 'self' or
								(arg == 'segment_info' and
									getattr(self.object, 'powerline_requires_segment_info', None)) or
								(arg == 'pl') or
								(method.startswith('render') and 1-i == len(argspec.args)) or
								arg in args):
							continue
						if argspec.defaults and len(argspec.defaults) >= -i:
							default = argspec.defaults[i]
							defaults.append(default)
							args.append(arg)
						else:
							args.insert(0, arg)
			argspec = ArgSpec(args=args, varargs=None, keywords=None, defaults=tuple(defaults))
		else:
			if hasattr(self.object, 'powerline_origin'):
				obj = self.object.powerline_origin
			else:
				obj = self.object

			argspec = getargspec(obj)
			args = []
			defaults = []
			for i, arg in zip(count(-1, -1), reversed(argspec.args)):
				if ((arg == 'segment_info' and getattr(self.object, 'powerline_requires_segment_info', None)) or
					arg == 'pl'):
					continue
				if argspec.defaults and len(argspec.defaults) >= -i:
					default = argspec.defaults[i]
					defaults.append(default)
					args.append(arg)
				else:
					args.insert(0, arg)
			argspec = ArgSpec(args=args, varargs=argspec.varargs, keywords=argspec.keywords, defaults=tuple(defaults))

		return formatargspec(*argspec, formatvalue=formatvalue).replace('\\', '\\\\')

def setup(app):
	autodoc.setup(app)
	app.add_autodocumenter(ThreadedDocumenter)
<commit_msg>Fix documentation for ThreadedSegment classes with @staticmethod’s<commit_after>from sphinx.ext import autodoc
from sphinx.util.inspect import getargspec
from inspect import ArgSpec, formatargspec
from powerline.lib.threaded import ThreadedSegment, KwThreadedSegment
from itertools import count

try:
	from __builtin__ import unicode
except ImportError:
	unicode = lambda s, enc: s  # NOQA

def formatvalue(val):
	if type(val) is str:
		return '="' + unicode(val, 'utf-8').replace('"', '\\"').replace('\\', '\\\\') + '"'
	else:
		return '=' + repr(val)

class ThreadedDocumenter(autodoc.FunctionDocumenter):
	'''Specialized documenter subclass for ThreadedSegment subclasses.'''
	@classmethod
	def can_document_member(cls, member, membername, isattr, parent):
		return (isinstance(member, ThreadedSegment) or
			super(ThreadedDocumenter, cls).can_document_member(member, membername, isattr, parent))

	def format_args(self):
		if isinstance(self.object, ThreadedSegment):
			args = ['interval']
			defaults = [getattr(self.object, 'interval', 1)]
			if self.object.update_first:
				args.append('update_first')
				defaults.append(True)
			methods = ['render', 'set_state']
			if isinstance(self.object, KwThreadedSegment):
				methods += ['key', 'render_one']

			for method in methods:
				if hasattr(self.object, method):
					# Note: on <python-2.6 it may return simple tuple, not
					# ArgSpec instance.
					argspec = getargspec(getattr(self.object, method))
					for i, arg in zip(count(-1, -1), reversed(argspec.args)):
						if (arg == 'self' or
								(arg == 'segment_info' and
									getattr(self.object, 'powerline_requires_segment_info', None)) or
								(arg == 'pl') or
								(method.startswith('render') and (1 if argspec.args[0] == 'self' else 0) - i == len(argspec.args)) or
								arg in args):
							continue
						if argspec.defaults and len(argspec.defaults) >= -i:
							default = argspec.defaults[i]
							defaults.append(default)
							args.append(arg)
						else:
							args.insert(0, arg)
			argspec = ArgSpec(args=args, varargs=None, keywords=None, defaults=tuple(defaults))
		else:
			if hasattr(self.object, 'powerline_origin'):
				obj = self.object.powerline_origin
			else:
				obj = self.object

			argspec = getargspec(obj)
			args = []
			defaults = []
			for i, arg in zip(count(-1, -1), reversed(argspec.args)):
				if ((arg == 'segment_info' and getattr(self.object, 'powerline_requires_segment_info', None)) or
					arg == 'pl'):
					continue
				if argspec.defaults and len(argspec.defaults) >= -i:
					default = argspec.defaults[i]
					defaults.append(default)
					args.append(arg)
				else:
					args.insert(0, arg)
			argspec = ArgSpec(args=args, varargs=argspec.varargs, keywords=argspec.keywords, defaults=tuple(defaults))

		return formatargspec(*argspec, formatvalue=formatvalue).replace('\\', '\\\\')

def setup(app):
	autodoc.setup(app)
	app.add_autodocumenter(ThreadedDocumenter)
<|endoftext|>


<commit_before>"""
Utility functions for generating "lorem ipsum" Latin text.
"""

import random

COMMON_P = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'
WORDS = ('exercitationem', 'perferendis', 'perspiciatis', 'laborum', 'eveniet', 'sunt', 'iure', 'nam', 'nobis', 'eum', 'cum', 'officiis', 'excepturi', 'odio', 'consectetur', 'quasi', 'aut', 'quisquam', 'vel', 'eligendi', 'itaque', 'non', 'odit', 'tempore', 'quaerat', 'dignissimos', 'facilis', 'neque', 'nihil', 'expedita', 'vitae', 'vero', 'ipsum', 'nisi', 'animi', 'cumque', 'pariatur', 'velit', 'modi', 'natus', 'iusto', 'eaque', 'sequi', 'illo', 'sed', 'ex', 'et', 'voluptatibus', 'tempora', 'veritatis', 'ratione', 'assumenda', 'incidunt', 'nostrum', 'placeat', 'aliquid', 'fuga', 'provident', 'praesentium', 'rem', 'necessitatibus', 'suscipit', 'adipisci', 'quidem', 'possimus', 'voluptas', 'debitis', 'sint', 'accusantium', 'unde', 'sapiente', 'voluptate', 'qui', 'aspernatur', 'laudantium', 'soluta', 'amet', 'quo', 'aliquam', 'saepe', 'culpa', 'libero', 'ipsa', 'dicta', 'reiciendis', 'nesciunt', 'doloribus', 'autem', 'impedit', 'minima', 'maiores', 'repudiandae', 'ipsam', 'obcaecati', 'ullam', 'enim', 'totam', 'delectus', 'ducimus', 'quis', 'voluptates', 'dolores', 'molestiae', 'harum', 'dolorem', 'quia', 'voluptatem', 'molestias', 'magni', 'distinctio', 'omnis', 'illum', 'dolorum', 'voluptatum', 'ea', 'quas', 'quam', 'corporis', 'quae', 'blanditiis', 'atque', 'deserunt', 'laboriosam', 'earum', 'consequuntur', 'hic', 'cupiditate', 'quibusdam', 'accusamus', 'ut', 'rerum', 'error', 'minus', 'eius', 'ab', 'ad', 'nemo', 'fugit', 'officia', 'at', 'in', 'id', 'quos', 'reprehenderit', 'numquam', 'iste', 'fugiat', 'sit', 'inventore', 'beatae', 'repellendus', 'magnam', 'recusandae', 'quod', 'explicabo', 'doloremque', 'aperiam', 'consequatur', 'asperiores', 'commodi', 'optio', 'dolor', 'labore', 'temporibus', 'repellat', 'veniam', 'architecto', 'est', 'esse', 'mollitia', 'nulla', 'a', 'similique', 'eos', 'alias', 'dolore', 'tenetur', 'deleniti', 'porro', 'facere', 'maxime', 'corrupti')
COMMON_WORDS = ('lorem', 'ipsum', 'dolor', 'sit', 'amet', 'consectetur', 'adipisicing', 'elit', 'sed', 'do', 'eiusmod', 'tempor', 'incididunt', 'ut', 'labore', 'et', 'dolore', 'magna', 'aliqua')

def sentence():
    """
    Returns a randomly generated sentence of lorem ipsum text.

    The first word is capitalized, and the sentence ends in either a period or
    question mark. Commas are added at random.
    """
    # Determine the number of comma-separated sections and number of words in
    # each section for this sentence.
    sections = [' '.join(random.sample(WORDS, random.randint(3, 12))) for i in range(random.randint(1, 5))]
    s = ', '.join(sections)
    # Convert to sentence case and add end punctuation.
    return '%s%s%s' % (s[0].upper(), s[1:], random.choice('?.'))

def paragraph():
    """
    Returns a randomly generated paragraph of lorem ipsum text.

    The paragraph consists of between 1 and 4 sentences, inclusive.
    """
    return ' '.join([sentence() for i in range(random.randint(1, 4))])

def paragraphs(count, common=True):
    """
    Returns a list of paragraphs as returned by paragraph().

    If `common` is True, then the first paragraph will be the standard
    'lorem ipsum' paragraph. Otherwise, the first paragraph will be random
    Latin text. Either way, subsequent paragraphs will be random Latin text.
    """
    paras = []
    for i in range(count):
        if common and i == 0:
            paras.append(COMMON_P)
        else:
            paras.append(paragraph())
    return paras

def words(count, common=True):
    """
    Returns a string of `count` lorem ipsum words separated by a single space.

    If `common` is True, then the first 19 words will be the standard
    'lorem ipsum' words. Otherwise, all words will be selected randomly.
    """
    if common:
        word_list = list(COMMON_WORDS)
    else:
        word_list = []
    c = len(word_list)
    if count > c:
        count = min(count - c, len(WORDS))
        word_list += random.sample(WORDS, count - c)
    else:
        word_list = word_list[:count]
    return ' '.join(word_list)
<commit_msg>Added native eol-style settings to necessary files. Refs #4276.<commit_after>"""
Utility functions for generating "lorem ipsum" Latin text.
"""

import random

COMMON_P = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'
WORDS = ('exercitationem', 'perferendis', 'perspiciatis', 'laborum', 'eveniet', 'sunt', 'iure', 'nam', 'nobis', 'eum', 'cum', 'officiis', 'excepturi', 'odio', 'consectetur', 'quasi', 'aut', 'quisquam', 'vel', 'eligendi', 'itaque', 'non', 'odit', 'tempore', 'quaerat', 'dignissimos', 'facilis', 'neque', 'nihil', 'expedita', 'vitae', 'vero', 'ipsum', 'nisi', 'animi', 'cumque', 'pariatur', 'velit', 'modi', 'natus', 'iusto', 'eaque', 'sequi', 'illo', 'sed', 'ex', 'et', 'voluptatibus', 'tempora', 'veritatis', 'ratione', 'assumenda', 'incidunt', 'nostrum', 'placeat', 'aliquid', 'fuga', 'provident', 'praesentium', 'rem', 'necessitatibus', 'suscipit', 'adipisci', 'quidem', 'possimus', 'voluptas', 'debitis', 'sint', 'accusantium', 'unde', 'sapiente', 'voluptate', 'qui', 'aspernatur', 'laudantium', 'soluta', 'amet', 'quo', 'aliquam', 'saepe', 'culpa', 'libero', 'ipsa', 'dicta', 'reiciendis', 'nesciunt', 'doloribus', 'autem', 'impedit', 'minima', 'maiores', 'repudiandae', 'ipsam', 'obcaecati', 'ullam', 'enim', 'totam', 'delectus', 'ducimus', 'quis', 'voluptates', 'dolores', 'molestiae', 'harum', 'dolorem', 'quia', 'voluptatem', 'molestias', 'magni', 'distinctio', 'omnis', 'illum', 'dolorum', 'voluptatum', 'ea', 'quas', 'quam', 'corporis', 'quae', 'blanditiis', 'atque', 'deserunt', 'laboriosam', 'earum', 'consequuntur', 'hic', 'cupiditate', 'quibusdam', 'accusamus', 'ut', 'rerum', 'error', 'minus', 'eius', 'ab', 'ad', 'nemo', 'fugit', 'officia', 'at', 'in', 'id', 'quos', 'reprehenderit', 'numquam', 'iste', 'fugiat', 'sit', 'inventore', 'beatae', 'repellendus', 'magnam', 'recusandae', 'quod', 'explicabo', 'doloremque', 'aperiam', 'consequatur', 'asperiores', 'commodi', 'optio', 'dolor', 'labore', 'temporibus', 'repellat', 'veniam', 'architecto', 'est', 'esse', 'mollitia', 'nulla', 'a', 'similique', 'eos', 'alias', 'dolore', 'tenetur', 'deleniti', 'porro', 'facere', 'maxime', 'corrupti')
COMMON_WORDS = ('lorem', 'ipsum', 'dolor', 'sit', 'amet', 'consectetur', 'adipisicing', 'elit', 'sed', 'do', 'eiusmod', 'tempor', 'incididunt', 'ut', 'labore', 'et', 'dolore', 'magna', 'aliqua')

def sentence():
    """
    Returns a randomly generated sentence of lorem ipsum text.

    The first word is capitalized, and the sentence ends in either a period or
    question mark. Commas are added at random.
    """
    # Determine the number of comma-separated sections and number of words in
    # each section for this sentence.
    sections = [' '.join(random.sample(WORDS, random.randint(3, 12))) for i in range(random.randint(1, 5))]
    s = ', '.join(sections)
    # Convert to sentence case and add end punctuation.
    return '%s%s%s' % (s[0].upper(), s[1:], random.choice('?.'))

def paragraph():
    """
    Returns a randomly generated paragraph of lorem ipsum text.

    The paragraph consists of between 1 and 4 sentences, inclusive.
    """
    return ' '.join([sentence() for i in range(random.randint(1, 4))])

def paragraphs(count, common=True):
    """
    Returns a list of paragraphs as returned by paragraph().

    If `common` is True, then the first paragraph will be the standard
    'lorem ipsum' paragraph. Otherwise, the first paragraph will be random
    Latin text. Either way, subsequent paragraphs will be random Latin text.
    """
    paras = []
    for i in range(count):
        if common and i == 0:
            paras.append(COMMON_P)
        else:
            paras.append(paragraph())
    return paras

def words(count, common=True):
    """
    Returns a string of `count` lorem ipsum words separated by a single space.

    If `common` is True, then the first 19 words will be the standard
    'lorem ipsum' words. Otherwise, all words will be selected randomly.
    """
    if common:
        word_list = list(COMMON_WORDS)
    else:
        word_list = []
    c = len(word_list)
    if count > c:
        count = min(count - c, len(WORDS))
        word_list += random.sample(WORDS, count - c)
    else:
        word_list = word_list[:count]
    return ' '.join(word_list)
<|endoftext|>