<commit_before>from src.rules.integrals import indef, choose_constant, solve_integral, \
        match_solve_indef, solve_indef, match_integrate_variable_power, \
        integrate_variable_root, integrate_variable_exponent, \
        match_constant_integral, constant_integral, single_variable_integral, \
        match_factor_out_constant, split_negation_to_constant, \
        factor_out_constant, match_division_integral, division_integral, \
        extend_division_integral, match_function_integral, \
        logarithm_integral, sinus_integral, cosinus_integral, \
        match_sum_rule_integral, sum_rule_integral, \
        match_remove_indef_constant, remove_indef_constant
from src.node import Scope
from src.possibilities import Possibility as P
from tests.rulestestcase import RulesTestCase, tree

class TestRulesIntegrals(RulesTestCase):

    def test_choose_constant(self):
        a, b, c = tree('a, b, c')
        self.assertEqual(choose_constant(tree('int x ^ n')), c)
        self.assertEqual(choose_constant(tree('int x ^ c')), a)
        self.assertEqual(choose_constant(tree('int a ^ c da')), b)

    def test_match_solve_indef(self):
        root = tree('[x ^ 2]_a^b')
        self.assertEqualPos(match_solve_indef(root), [P(root, solve_indef)])

    def test_solve_integral(self):
        root, F, Fc = tree('int x ^ 2 dx, 1 / 3 x ^ 3, 1 / 3 x ^ 3 + c')
        self.assertEqual(solve_integral(root, F), Fc)
        x2, x, a, b = root = tree('int_a^b x ^ 2 dx')
        self.assertEqual(solve_integral(root, F), indef(Fc, a, b))

    def test_solve_integral_skip_indef(self):
        root, x, c, l1 = tree('int_a^b y ^ x dy, x, c, 1')
        F = tree('1 / (x + 1)y ^ (x + 1)')
        y, a, b = root[1:4]
        Fx = lambda y: l1 / (x + 1) * y ** (x + 1) + c
        self.assertEqual(solve_integral(root, F), Fx(b) - Fx(a))

    def test_solve_indef(self):
        root, expect = tree('[x ^ 2]_a^b, b ^ 2 - a ^ 2')
        self.assertEqual(solve_indef(root, ()), expect)

    def test_match_integrate_variable_power(self):
        root = tree('int x ^ n')
        self.assertEqualPos(match_integrate_variable_power(root),
                [P(root, integrate_variable_root)])

        root = tree('int x ^ n')
        self.assertEqualPos(match_integrate_variable_power(root),
                [P(root, integrate_variable_root)])

        root = tree('int -x ^ n')
        self.assertEqualPos(match_integrate_variable_power(root), [])

        for root in tree('int g ^ x, int g ^ x'):
            self.assertEqualPos(match_integrate_variable_power(root),
                    [P(root, integrate_variable_exponent)])

    def test_integrate_variable_root(self):
        root, expect = tree('int x ^ n, 1 / (n + 1) * x ^ (n + 1) + c')
        self.assertEqual(integrate_variable_root(root, ()), expect)

    def test_integrate_variable_exponent(self):
        root, expect = tree('int g ^ x, g ^ x / ln(g) + c')
        self.assertEqual(integrate_variable_exponent(root, ()), expect)

    def test_match_constant_integral(self):
        root = tree('int x dx')
        self.assertEqualPos(match_constant_integral(root),
                [P(root, single_variable_integral)])

        root = tree('int 2')
        self.assertEqualPos(match_constant_integral(root),
                [P(root, constant_integral)])

        root = tree('int c dx')
        self.assertEqualPos(match_constant_integral(root),
                [P(root, constant_integral)])

    def test_single_variable_integral(self):
        root, expect = tree('int x, int x ^ 1')
        self.assertEqual(single_variable_integral(root, ()), expect)

    def test_constant_integral(self):
        root, expect = tree('int 2, 2x + c')
        self.assertEqual(constant_integral(root, ()), expect)

        root, expect = tree('int_0^4 2, [2x + c]_0^4')
        self.assertEqual(constant_integral(root, ()), expect)

    def test_match_factor_out_constant(self):
        root, c, cx = tree('int cx dx, c, cx')
        self.assertEqualPos(match_factor_out_constant(root),
                [P(root, factor_out_constant, (Scope(cx), c))])

        root = tree('int -x2 dx')
        self.assertEqualPos(match_factor_out_constant(root),
                [P(root, split_negation_to_constant)])

    def test_split_negation_to_constant(self):
        root, expect = tree('int -x ^ 2 dx, int (-1)x ^ 2 dx')
        self.assertEqual(split_negation_to_constant(root, ()), expect)

    def test_factor_out_constant(self):
        root, expect = tree('int cx dx, c int x dx')
        c, x2 = cx2 = root[0]
        self.assertEqual(factor_out_constant(root, (Scope(cx2), c)), expect)

    def test_match_division_integral(self):
        root0, root1 = tree('int 1 / x, int 2 / x')
        self.assertEqualPos(match_division_integral(root0),
                [P(root0, division_integral)])
        self.assertEqualPos(match_division_integral(root1),
                [P(root1, extend_division_integral)])

    def test_division_integral(self):
        root, expect = tree('int 1 / x dx, ln|x| + c')
        self.assertEqual(division_integral(root, ()), expect)

    def test_extend_division_integral(self):
        root, expect = tree('int a / x dx, int a(1 / x) dx')
        self.assertEqual(extend_division_integral(root, ()), expect)

    def test_match_division_integral_chain(self):
        self.assertRewrite([
            'int a / x',
            'int a * 1 / x dx',
            'aint 1 / x dx',
            'a(ln|x| + c)',
            'aln|x| + ac',
            # FIXME: 'aln|x| + c',  # ac -> c
        ])

    def test_match_function_integral(self):
        root = tree('int ln x')
        self.assertEqualPos(match_function_integral(root),
                [P(root, logarithm_integral)])

        root = tree('int sin x')
        self.assertEqualPos(match_function_integral(root),
                [P(root, sinus_integral)])

        root = tree('int cos x')
        self.assertEqualPos(match_function_integral(root),
                [P(root, cosinus_integral)])

        root = tree('int sqrt x')
        self.assertEqualPos(match_function_integral(root), [])

    def test_logarithm_integral(self):
        root, expect = tree('int ln x, (xlnx - x) / ln e + c')
        self.assertEqual(logarithm_integral(root, ()), expect)

    def test_sinus_integral(self):
        root, expect = tree('int sin x, -cos x + c')
        self.assertEqual(sinus_integral(root, ()), expect)

    def test_cosinus_integral(self):
        root, expect = tree('int cos x, sin x + c')
        self.assertEqual(cosinus_integral(root, ()), expect)

    def test_match_sum_rule_integral(self):
        (f, g), x = root = tree('int 2x + 3x dx')
        self.assertEqualPos(match_sum_rule_integral(root),
                [P(root, sum_rule_integral, (Scope(root[0]), f))])

        ((f, g), h), x = root = tree('int 2x + 3x + 4x dx')
        self.assertEqualPos(match_sum_rule_integral(root),
                [P(root, sum_rule_integral, (Scope(root[0]), f)),
                 P(root, sum_rule_integral, (Scope(root[0]), g)),
                 P(root, sum_rule_integral, (Scope(root[0]), h))])

    def test_sum_rule_integral(self):
        ((f, g), h), x = root = tree('int 2x + 3x + 4x dx')
        self.assertEqual(sum_rule_integral(root, (Scope(root[0]), f)),
                         tree('int 2x dx + int 3x + 4x dx'))
        self.assertEqual(sum_rule_integral(root, (Scope(root[0]), g)),
                         tree('int 3x dx + int 2x + 4x dx'))
        self.assertEqual(sum_rule_integral(root, (Scope(root[0]), h)),
                         tree('int 4x dx + int 2x + 3x dx'))

    def test_match_remove_indef_constant(self):
        Fx, a, b = root = tree('[2x + c]_a^b')
        self.assertEqualPos(match_remove_indef_constant(root),
                [P(root, remove_indef_constant, (Scope(Fx), Fx[1]))])

        Fx, a, b = root = tree('[2x + x]_a^b')
        self.assertEqualPos(match_remove_indef_constant(root), [])

        Fx, a, b = root = tree('[2x]_a^b')
        self.assertEqualPos(match_remove_indef_constant(root), [])

    def test_remove_indef_constant(self):
        root, e = tree('[2x + c]_a^b, [2x]_a^b')
        Fx = root[0]
        self.assertEqual(remove_indef_constant(root, (Scope(Fx), Fx[1])), e)
<commit_msg>Intergrals now use uppercase constant variable names.<commit_after>from src.rules.integrals import indef, choose_constant, solve_integral, \
        match_solve_indef, solve_indef, match_integrate_variable_power, \
        integrate_variable_root, integrate_variable_exponent, \
        match_constant_integral, constant_integral, single_variable_integral, \
        match_factor_out_constant, split_negation_to_constant, \
        factor_out_constant, match_division_integral, division_integral, \
        extend_division_integral, match_function_integral, \
        logarithm_integral, sinus_integral, cosinus_integral, \
        match_sum_rule_integral, sum_rule_integral, \
        match_remove_indef_constant, remove_indef_constant
from src.node import Scope
from src.possibilities import Possibility as P
from tests.rulestestcase import RulesTestCase, tree

class TestRulesIntegrals(RulesTestCase):

    def test_choose_constant(self):
        a, b, c = tree('A, B, C')
        self.assertEqual(choose_constant(tree('int x ^ n')), c)
        self.assertEqual(choose_constant(tree('int x ^ c')), a)
        self.assertEqual(choose_constant(tree('int a ^ c da')), b)

    def test_match_solve_indef(self):
        root = tree('[x ^ 2]_a^b')
        self.assertEqualPos(match_solve_indef(root), [P(root, solve_indef)])

    def test_solve_integral(self):
        root, F, Fc = tree('int x ^ 2 dx, 1 / 3 x ^ 3, 1 / 3 x ^ 3 + C')
        self.assertEqual(solve_integral(root, F), Fc)
        x2, x, a, b = root = tree('int_a^b x ^ 2 dx')
        self.assertEqual(solve_integral(root, F), indef(Fc, a, b))

    def test_solve_integral_skip_indef(self):
        root, x, C, l1 = tree('int_a^b y ^ x dy, x, C, 1')
        F = tree('1 / (x + 1)y ^ (x + 1)')
        y, a, b = root[1:4]
        Fx = lambda y: l1 / (x + 1) * y ** (x + 1) + C
        self.assertEqual(solve_integral(root, F), Fx(b) - Fx(a))

    def test_solve_indef(self):
        root, expect = tree('[x ^ 2]_a^b, b ^ 2 - a ^ 2')
        self.assertEqual(solve_indef(root, ()), expect)

    def test_match_integrate_variable_power(self):
        root = tree('int x ^ n')
        self.assertEqualPos(match_integrate_variable_power(root),
                [P(root, integrate_variable_root)])

        root = tree('int x ^ n')
        self.assertEqualPos(match_integrate_variable_power(root),
                [P(root, integrate_variable_root)])

        root = tree('int -x ^ n')
        self.assertEqualPos(match_integrate_variable_power(root), [])

        for root in tree('int g ^ x, int g ^ x'):
            self.assertEqualPos(match_integrate_variable_power(root),
                    [P(root, integrate_variable_exponent)])

    def test_integrate_variable_root(self):
        root, expect = tree('int x ^ n, 1 / (n + 1) * x ^ (n + 1) + C')
        self.assertEqual(integrate_variable_root(root, ()), expect)

    def test_integrate_variable_exponent(self):
        root, expect = tree('int g ^ x, g ^ x / ln(g) + C')
        self.assertEqual(integrate_variable_exponent(root, ()), expect)

    def test_match_constant_integral(self):
        root = tree('int x dx')
        self.assertEqualPos(match_constant_integral(root),
                [P(root, single_variable_integral)])

        root = tree('int 2')
        self.assertEqualPos(match_constant_integral(root),
                [P(root, constant_integral)])

        root = tree('int c dx')
        self.assertEqualPos(match_constant_integral(root),
                [P(root, constant_integral)])

    def test_single_variable_integral(self):
        root, expect = tree('int x, int x ^ 1')
        self.assertEqual(single_variable_integral(root, ()), expect)

    def test_constant_integral(self):
        root, expect = tree('int 2, 2x + C')
        self.assertEqual(constant_integral(root, ()), expect)

        root, expect = tree('int_0^4 2, [2x + C]_0^4')
        self.assertEqual(constant_integral(root, ()), expect)

    def test_match_factor_out_constant(self):
        root, c, cx = tree('int cx dx, c, cx')
        self.assertEqualPos(match_factor_out_constant(root),
                [P(root, factor_out_constant, (Scope(cx), c))])

        root = tree('int -x2 dx')
        self.assertEqualPos(match_factor_out_constant(root),
                [P(root, split_negation_to_constant)])

    def test_split_negation_to_constant(self):
        root, expect = tree('int -x ^ 2 dx, int (-1)x ^ 2 dx')
        self.assertEqual(split_negation_to_constant(root, ()), expect)

    def test_factor_out_constant(self):
        root, expect = tree('int cx dx, c int x dx')
        c, x2 = cx2 = root[0]
        self.assertEqual(factor_out_constant(root, (Scope(cx2), c)), expect)

    def test_match_division_integral(self):
        root0, root1 = tree('int 1 / x, int 2 / x')
        self.assertEqualPos(match_division_integral(root0),
                [P(root0, division_integral)])
        self.assertEqualPos(match_division_integral(root1),
                [P(root1, extend_division_integral)])

    def test_division_integral(self):
        root, expect = tree('int 1 / x dx, ln|x| + C')
        self.assertEqual(division_integral(root, ()), expect)

    def test_extend_division_integral(self):
        root, expect = tree('int a / x dx, int a(1 / x) dx')
        self.assertEqual(extend_division_integral(root, ()), expect)

    def test_match_division_integral_chain(self):
        self.assertRewrite([
            'int a / x',
            'int a * 1 / x dx',
            'aint 1 / x dx',
            'a(ln|x| + C)',
            'aln|x| + aC',
            # FIXME: 'aln|x| + C',  # ac -> C
        ])

    def test_match_function_integral(self):
        root = tree('int ln x')
        self.assertEqualPos(match_function_integral(root),
                [P(root, logarithm_integral)])

        root = tree('int sin x')
        self.assertEqualPos(match_function_integral(root),
                [P(root, sinus_integral)])

        root = tree('int cos x')
        self.assertEqualPos(match_function_integral(root),
                [P(root, cosinus_integral)])

        root = tree('int sqrt x')
        self.assertEqualPos(match_function_integral(root), [])

    def test_logarithm_integral(self):
        root, expect = tree('int ln x, (xlnx - x) / ln e + C')
        self.assertEqual(logarithm_integral(root, ()), expect)

    def test_sinus_integral(self):
        root, expect = tree('int sin x, -cos x + C')
        self.assertEqual(sinus_integral(root, ()), expect)

    def test_cosinus_integral(self):
        root, expect = tree('int cos x, sin x + C')
        self.assertEqual(cosinus_integral(root, ()), expect)

    def test_match_sum_rule_integral(self):
        (f, g), x = root = tree('int 2x + 3x dx')
        self.assertEqualPos(match_sum_rule_integral(root),
                [P(root, sum_rule_integral, (Scope(root[0]), f))])

        ((f, g), h), x = root = tree('int 2x + 3x + 4x dx')
        self.assertEqualPos(match_sum_rule_integral(root),
                [P(root, sum_rule_integral, (Scope(root[0]), f)),
                 P(root, sum_rule_integral, (Scope(root[0]), g)),
                 P(root, sum_rule_integral, (Scope(root[0]), h))])

    def test_sum_rule_integral(self):
        ((f, g), h), x = root = tree('int 2x + 3x + 4x dx')
        self.assertEqual(sum_rule_integral(root, (Scope(root[0]), f)),
                         tree('int 2x dx + int 3x + 4x dx'))
        self.assertEqual(sum_rule_integral(root, (Scope(root[0]), g)),
                         tree('int 3x dx + int 2x + 4x dx'))
        self.assertEqual(sum_rule_integral(root, (Scope(root[0]), h)),
                         tree('int 4x dx + int 2x + 3x dx'))

    def test_match_remove_indef_constant(self):
        Fx, a, b = root = tree('[2x + C]_a^b')
        self.assertEqualPos(match_remove_indef_constant(root),
                [P(root, remove_indef_constant, (Scope(Fx), Fx[1]))])

        Fx, a, b = root = tree('[2x + x]_a^b')
        self.assertEqualPos(match_remove_indef_constant(root), [])

        Fx, a, b = root = tree('[2x]_a^b')
        self.assertEqualPos(match_remove_indef_constant(root), [])

    def test_remove_indef_constant(self):
        root, e = tree('[2x + C]_a^b, [2x]_a^b')
        Fx = root[0]
        self.assertEqual(remove_indef_constant(root, (Scope(Fx), Fx[1])), e)
<|endoftext|>


<commit_before>from ppb_vector import Vector2
from pytest import raises # type: ignore
from utils import units, lengths, vectors
from hypothesis import assume, event, given, note, example
from hypothesis.strategies import floats

@given(x=vectors(), abs_tol=floats(min_value=0), rel_tol=floats(min_value=0))
def test_isclose_to_self(x, abs_tol, rel_tol):
    assert x.isclose(x, abs_tol=abs_tol, rel_tol=rel_tol)

@given(x=vectors(), direction=units(), abs_tol=lengths())
def test_isclose_abs_error(x, direction, abs_tol):
    """Test x.isclose(rel_tol=0) near the boundary between “close” and “not close”

    - x + (1 - EPSILON) * abs_tol * direction should always be close
    - x + (1 + EPSILON) * abs_tol * direction should not be close
      assuming it isn't equal to x (because of rounding, or because x is null)
    """
    error = abs_tol * direction
    note(f"error = {error}")

    EPSILON = 1e-12
    positive = x + (1 - EPSILON) * error
    note(f"positive example: {positive} = x + {positive - x}")
    assert x.isclose(positive, abs_tol=abs_tol, rel_tol=0)

    if abs_tol > EPSILON * x.length:
        negative = x + (1 + EPSILON) * error
        event("Negative example generated (abs_tol > ε * |x|)")
        note(f"negative example: {negative} = x + {negative - x}")
        assert not x.isclose(negative, abs_tol=abs_tol, rel_tol=0)

EPSILON = 1e-8
@given(x=vectors(), direction=units(),
       rel_tol=floats(min_value=EPSILON, max_value=1-EPSILON))
def test_isclose_rel_error(x, direction, rel_tol):
    """Test x.isclose(abs_tol=0) near the boundary between “close” and “not close”

    - x + rel_tol * |x| * direction should always be close
    """
    error = rel_tol * x.length * direction
    note(f"error = {error}")

    positive = x + (1 - EPSILON) * error
    note(f"positive example: {positive} = x + {positive - x}")
    if x.length > EPSILON:
        note(f"x + |x| * {(positive - x) / x.length}")

    assert x.isclose(positive, abs_tol=0, rel_tol=rel_tol)

def test_isclose_negative_tolerances():
    zero = Vector2(0, 0)

    with raises(ValueError):
        zero.isclose(zero, abs_tol=-1)

    with raises(ValueError):
        zero.isclose(zero, rel_tol=-1)
<commit_msg>tests/isclose: Add a negative example for relative tolerance<commit_after>from ppb_vector import Vector2
from pytest import raises # type: ignore
from utils import units, lengths, vectors
from hypothesis import assume, event, given, note, example
from hypothesis.strategies import floats

@given(x=vectors(), abs_tol=floats(min_value=0), rel_tol=floats(min_value=0))
def test_isclose_to_self(x, abs_tol, rel_tol):
    assert x.isclose(x, abs_tol=abs_tol, rel_tol=rel_tol)

@given(x=vectors(), direction=units(), abs_tol=lengths())
def test_isclose_abs_error(x, direction, abs_tol):
    """Test x.isclose(rel_tol=0) near the boundary between “close” and “not close”

    - x + (1 - EPSILON) * abs_tol * direction should always be close
    - x + (1 + EPSILON) * abs_tol * direction should not be close
      assuming it isn't equal to x (because of rounding, or because x is null)
    """
    error = abs_tol * direction
    note(f"error = {error}")

    EPSILON = 1e-12
    positive = x + (1 - EPSILON) * error
    note(f"positive example: {positive} = x + {positive - x}")
    assert x.isclose(positive, abs_tol=abs_tol, rel_tol=0)

    if abs_tol > EPSILON * x.length:
        negative = x + (1 + EPSILON) * error
        event("Negative example generated (abs_tol > ε * |x|)")
        note(f"negative example: {negative} = x + {negative - x}")
        assert not x.isclose(negative, abs_tol=abs_tol, rel_tol=0)

EPSILON = 1e-8
@given(x=vectors(), direction=units(),
       rel_tol=floats(min_value=EPSILON, max_value=1-EPSILON))
def test_isclose_rel_error(x, direction, rel_tol):
    """Test x.isclose(abs_tol=0) near the boundary between “close” and “not close”

    - x + rel_tol * |x| * direction should always be close
    - x + (1 + EPSILON) * rel_tol * |x| * direction should not be close
      assuming it isn't equal to x (because of rounding, or because x is null)
    """
    error = rel_tol * x.length * direction
    note(f"error = {error}")

    positive = x + (1 - EPSILON) * error
    note(f"positive example: {positive} = x + {positive - x}")
    if x.length > EPSILON:
        note(f"x + |x| * {(positive - x) / x.length}")

    assert x.isclose(positive, abs_tol=0, rel_tol=rel_tol)

    if x.length > EPSILON:
        # In x.isclose(negative), the allowed relative error is relative to |x|
        # and |negative|, so the acceptable errors grow larger as negative does.
        #
        # The choice of negative accounts for this, with the (1 - rel_tol) term:
        # we have negative = x + Δ, and we want to pick Δ such that
        # δ = |x - negative| > rel_tol * max(|x|, |negative|)
        #
        # Since r * (|x| + δ) > rel_tol * max(|x|, |negative|), any choice where
        # δ > rel_tol * (|x| + δ) is suitable. The smallest is
        # rel_tol |x| / (1 - rel_tol), as such, we take
        # Δ = r * |x| * direction / (1 - rel_tol), and an ε safety margin.
        negative = x + (1 + EPSILON) / (1 - rel_tol) * error
        note(f"negative example: {negative} = x + {negative - x} = "
             f"x + {(negative - x).length / x.length} * |x| * {(negative - x).normalize()}")

        assert not x.isclose(negative, abs_tol=0, rel_tol=rel_tol)

def test_isclose_negative_tolerances():
    zero = Vector2(0, 0)

    with raises(ValueError):
        zero.isclose(zero, abs_tol=-1)

    with raises(ValueError):
        zero.isclose(zero, rel_tol=-1)
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
import os
import shutil
from depot.middleware import _FileIter
from nose import SkipTest
import uuid
from depot.manager import DepotManager
from tg import expose, TGController, AppConfig
from webtest import TestApp
from depot._compat import u_, unquote

FILE_CONTENT = b'HELLO WORLD'

class RootController(TGController):
    UPLOADED_FILES = []

    @expose('json')
    def index(self):
        return dict(files=self.UPLOADED_FILES)

    @expose('json')
    def clear_files(self):
        self.UPLOADED_FILES = []
        return dict(files=self.UPLOADED_FILES)

    @expose('json')
    def depotskipped(self):
        return dict(ok=True)

    @expose('json')
    def depot(self):
        # this should never be called
        return dict(ok=False)

    @expose('json')
    def create_file(self, lang='en'):
        fname = {'en': 'hello.txt',
                 'ru': u_('Крупный'),
                 'it': u_('àèìòù')}.get(lang, 'unknown')

        self.UPLOADED_FILES += [DepotManager.get().create(FILE_CONTENT,
                                                          filename=fname)]
        return dict(files=self.UPLOADED_FILES,
                    uploaded_to=DepotManager.get_default(),
                    last=self.UPLOADED_FILES[-1])

class BaseWSGITests(object):
    @classmethod
    def setup_class(cls):
        config = AppConfig(minimal=True, root_controller=RootController())
        cls.wsgi_app = config.make_wsgi_app()

    def make_app(self, **options):
        wsgi_app = DepotManager.make_middleware(self.wsgi_app, **options)
        return TestApp(wsgi_app)

class TestWSGIMiddleware(BaseWSGITests):
    def setup(self):
        DepotManager._clear()
        DepotManager.configure('default', {'depot.storage_path': './lfs'})

    def teardown(cls):
        shutil.rmtree('./lfs', ignore_errors=True)

    def test_invalid_mountpoint(self):
        try:
            DepotManager.make_middleware(self.wsgi_app, mountpoint='hello')
        except ValueError as err:
            assert 'mountpoint must be an absolute path' in str(err)
        else:
            assert False, 'Should have raised ValueError'

    def test_serving_files(self):
        app = self.make_app()
        new_file = app.post('/create_file').json

        uploaded_file = app.get(DepotManager.url_for('%(uploaded_to)s/%(last)s' % new_file))
        assert uploaded_file.body == FILE_CONTENT

    def test_headers_are_there(self):
        app = self.make_app()
        new_file = app.post('/create_file').json

        uploaded_file = app.get(DepotManager.url_for('%(uploaded_to)s/%(last)s' % new_file))
        assert uploaded_file.headers['Content-Type'] == 'text/plain'
        assert 'ETag' in uploaded_file.headers
        assert 'Last-Modified' in uploaded_file.headers
        assert 'Expires' in uploaded_file.headers

    def test_caching_unmodified(self):
        app = self.make_app()
        new_file = app.post('/create_file').json

        uploaded_file = app.get(DepotManager.url_for('%(uploaded_to)s/%(last)s' % new_file))
        last_modified = uploaded_file.headers['Last-Modified']

        unmodified_file = app.get('/depot/default/%(last)s' % new_file,
                                  headers=[('If-Modified-Since', last_modified)],
                                  status=304)
        assert 'Not Modified' in unmodified_file.status, unmodified_file

    def test_caching_etag(self):
        app = self.make_app()
        new_file = app.post('/create_file').json

        uploaded_file = app.get(DepotManager.url_for('%(uploaded_to)s/%(last)s' % new_file))
        etag = uploaded_file.headers['ETag']

        unmodified_file = app.get('/depot/default/%(last)s' % new_file,
                                  headers=[('If-None-Match', etag)],
                                  status=304)
        assert 'Not Modified' in unmodified_file.status, unmodified_file

    def test_post_is_forwarded_to_app(self):
        app = self.make_app()
        new_file = app.post('/create_file').json

        file_path = DepotManager.url_for('%(uploaded_to)s/%(last)s' % new_file)
        uploaded_file = app.post(file_path, status=404)
        assert 'Not Found' in uploaded_file.status, uploaded_file

    def test_forwards_to_app(self):
        app = self.make_app()
        new_file = app.post('/create_file').json

        files = app.get('/').json
        assert new_file['last'] in files['files'], (new_file, files)

    def test_forwards_to_app_begins_with_endpoint(self):
        app = self.make_app()

        resp = app.get('/depotskipped').json
        assert resp['ok'] == True

    def test_404_on_nofile(self):
        app = self.make_app()

        missing = app.get('/depot', status=404)
        assert 'Not Found' in missing.status

    def test_404_on_missing_file(self):
        app = self.make_app()
        missing = app.get('/depot/default/hello', status=404)
        assert 'Not Found' in missing.status
        missing = app.get('/depot/nodepot', status=404)
        assert 'Not Found' in missing.status
        missing = app.get('/depot/nodepot/hello', status=404)
        assert 'Not Found' in missing.status

    def test_invalid_unmodified_header(self):
        app = self.make_app()
        new_file = app.post('/create_file').json

        uploaded_file = app.get(DepotManager.url_for('%(uploaded_to)s/%(last)s' % new_file))

        unmodified_file = app.get('/depot/default/%(last)s' % new_file,
                                  headers=[('If-Modified-Since', 'HELLO WORLD')],
                                  status=400)
        assert 'Bad Request' in unmodified_file.status, unmodified_file

    def test_serving_files_with_wsgifilewrapper(self):
        app = self.make_app(replace_wsgi_filewrapper=True)
        new_file = app.post('/create_file').json

        uploaded_file = app.get(DepotManager.url_for('%(uploaded_to)s/%(last)s' % new_file))
        assert uploaded_file.body == FILE_CONTENT
        assert uploaded_file.request.environ['wsgi.file_wrapper'] is _FileIter

    def test_serving_files_content_disposition(self):
        app = self.make_app()
        new_file = app.post('/create_file', params={'lang': 'ru'}).json

        uploaded_file = app.get(DepotManager.url_for('%(uploaded_to)s/%(last)s' % new_file))
        content_disposition = uploaded_file.headers['Content-Disposition']
        assert content_disposition == "inline;filename=\"Krupnyi\";filename*=utf-8''%D0%9A%D1%80%D1%83%D0%BF%D0%BD%D1%8B%D0%B9", content_disposition

        new_file = app.post('/create_file', params={'lang': 'it'}).json
        uploaded_file = app.get(DepotManager.url_for('%(uploaded_to)s/%(last)s' % new_file))
        content_disposition = uploaded_file.headers['Content-Disposition']
        _, asciiname, uniname = content_disposition.split(';')
        assert asciiname == 'filename="aeiou"', asciiname
        assert u_(unquote(uniname[17:])) == u_('àèìòù'), unquote(uniname[17:])

class TestS3TestWSGIMiddleware(BaseWSGITests):
    def setup(self):
        try:
            global S3Storage
            from depot.io.awss3 import S3Storage
        except ImportError:
            raise SkipTest('Boto not installed')

        env = os.environ
        access_key_id = env.get('AWS_ACCESS_KEY_ID')
        secret_access_key = env.get('AWS_SECRET_ACCESS_KEY')
        if access_key_id is None or secret_access_key is None:
            raise SkipTest('Amazon S3 credentials not available')

        PID = os.getpid()
        NODE = str(uuid.uuid1()).rsplit('-', 1)[-1]  # Travis runs multiple tests concurrently
        default_bucket_name = 'filedepot-%s' % (access_key_id.lower(), )
        cred = (access_key_id, secret_access_key)
        bucket_name = 'filedepot-testfs-%s-%s-%s' % (access_key_id.lower(), NODE, PID)

        DepotManager.configure('awss3', {'depot.backend': 'depot.io.awss3.S3Storage',
                                         'depot.access_key_id': access_key_id,
                                         'depot.secret_access_key': secret_access_key,
                                         'depot.bucket': bucket_name})
        DepotManager.set_default('awss3')

    def teardown(self):
        store = DepotManager.get('awss3')
        if not store._conn.lookup(store._bucket_driver.bucket.name):
            return

        keys = [key.name for key in store._bucket_driver.bucket]
        if keys:
            store._bucket_driver.bucket.delete_keys(keys)

        try:
            store._conn.delete_bucket(store._bucket_driver.bucket.name)
            while store._conn.lookup(store._bucket_driver.bucket.name):
                # Wait for bucket to be deleted, to avoid flaky tests...
                time.sleep(0.5)
        except:
            pass

    def test_public_url_gets_redirect(self):
        app = self.make_app()
        new_file = app.post('/create_file').json

        file_path = DepotManager.url_for('%(uploaded_to)s/%(last)s' % new_file)
        uploaded_file = app.get(file_path, status=301)
        location = uploaded_file.headers['Location']
        assert 'https://filedepot-testfs-' in location
        assert 's3.amazonaws.com' in location<commit_msg>Fix for multiple cals<commit_after># -*- coding: utf-8 -*-
import os
import shutil
from depot.middleware import _FileIter
from nose import SkipTest
import uuid
from depot.manager import DepotManager
from tg import expose, TGController, AppConfig
from webtest import TestApp
from depot._compat import u_, unquote

FILE_CONTENT = b'HELLO WORLD'

class RootController(TGController):
    UPLOADED_FILES = []

    @expose('json')
    def index(self):
        return dict(files=self.UPLOADED_FILES)

    @expose('json')
    def clear_files(self):
        self.UPLOADED_FILES = []
        return dict(files=self.UPLOADED_FILES)

    @expose('json')
    def depotskipped(self):
        return dict(ok=True)

    @expose('json')
    def depot(self):
        # this should never be called
        return dict(ok=False)

    @expose('json')
    def create_file(self, lang='en'):
        fname = {'en': 'hello.txt',
                 'ru': u_('Крупный'),
                 'it': u_('àèìòù')}.get(lang, 'unknown')

        self.UPLOADED_FILES += [DepotManager.get().create(FILE_CONTENT,
                                                          filename=fname)]
        return dict(files=self.UPLOADED_FILES,
                    uploaded_to=DepotManager.get_default(),
                    last=self.UPLOADED_FILES[-1])

class BaseWSGITests(object):
    @classmethod
    def setup_class(cls):
        config = AppConfig(minimal=True, root_controller=RootController())
        cls.wsgi_app = config.make_wsgi_app()

    def make_app(self, **options):
        wsgi_app = DepotManager.make_middleware(self.wsgi_app, **options)
        return TestApp(wsgi_app)

class TestWSGIMiddleware(BaseWSGITests):
    def setup(self):
        DepotManager._clear()
        DepotManager.configure('default', {'depot.storage_path': './lfs'})

    def teardown(cls):
        shutil.rmtree('./lfs', ignore_errors=True)

    def test_invalid_mountpoint(self):
        try:
            DepotManager.make_middleware(self.wsgi_app, mountpoint='hello')
        except ValueError as err:
            assert 'mountpoint must be an absolute path' in str(err)
        else:
            assert False, 'Should have raised ValueError'

    def test_serving_files(self):
        app = self.make_app()
        new_file = app.post('/create_file').json

        uploaded_file = app.get(DepotManager.url_for('%(uploaded_to)s/%(last)s' % new_file))
        assert uploaded_file.body == FILE_CONTENT

    def test_headers_are_there(self):
        app = self.make_app()
        new_file = app.post('/create_file').json

        uploaded_file = app.get(DepotManager.url_for('%(uploaded_to)s/%(last)s' % new_file))
        assert uploaded_file.headers['Content-Type'] == 'text/plain'
        assert 'ETag' in uploaded_file.headers
        assert 'Last-Modified' in uploaded_file.headers
        assert 'Expires' in uploaded_file.headers

    def test_caching_unmodified(self):
        app = self.make_app()
        new_file = app.post('/create_file').json

        uploaded_file = app.get(DepotManager.url_for('%(uploaded_to)s/%(last)s' % new_file))
        last_modified = uploaded_file.headers['Last-Modified']

        unmodified_file = app.get('/depot/default/%(last)s' % new_file,
                                  headers=[('If-Modified-Since', last_modified)],
                                  status=304)
        assert 'Not Modified' in unmodified_file.status, unmodified_file

    def test_caching_etag(self):
        app = self.make_app()
        new_file = app.post('/create_file').json

        uploaded_file = app.get(DepotManager.url_for('%(uploaded_to)s/%(last)s' % new_file))
        etag = uploaded_file.headers['ETag']

        unmodified_file = app.get('/depot/default/%(last)s' % new_file,
                                  headers=[('If-None-Match', etag)],
                                  status=304)
        assert 'Not Modified' in unmodified_file.status, unmodified_file

    def test_post_is_forwarded_to_app(self):
        app = self.make_app()
        new_file = app.post('/create_file').json

        file_path = DepotManager.url_for('%(uploaded_to)s/%(last)s' % new_file)
        uploaded_file = app.post(file_path, status=404)
        assert 'Not Found' in uploaded_file.status, uploaded_file

    def test_forwards_to_app(self):
        app = self.make_app()
        new_file = app.post('/create_file').json

        files = app.get('/').json
        assert new_file['last'] in files['files'], (new_file, files)

    def test_forwards_to_app_begins_with_endpoint(self):
        app = self.make_app()

        resp = app.get('/depotskipped').json
        assert resp['ok'] == True

    def test_404_on_nofile(self):
        app = self.make_app()

        missing = app.get('/depot', status=404)
        assert 'Not Found' in missing.status

    def test_404_on_missing_file(self):
        app = self.make_app()
        missing = app.get('/depot/default/hello', status=404)
        assert 'Not Found' in missing.status
        missing = app.get('/depot/nodepot', status=404)
        assert 'Not Found' in missing.status
        missing = app.get('/depot/nodepot/hello', status=404)
        assert 'Not Found' in missing.status

    def test_invalid_unmodified_header(self):
        app = self.make_app()
        new_file = app.post('/create_file').json

        uploaded_file = app.get(DepotManager.url_for('%(uploaded_to)s/%(last)s' % new_file))

        unmodified_file = app.get('/depot/default/%(last)s' % new_file,
                                  headers=[('If-Modified-Since', 'HELLO WORLD')],
                                  status=400)
        assert 'Bad Request' in unmodified_file.status, unmodified_file

    def test_serving_files_with_wsgifilewrapper(self):
        app = self.make_app(replace_wsgi_filewrapper=True)
        new_file = app.post('/create_file').json

        uploaded_file = app.get(DepotManager.url_for('%(uploaded_to)s/%(last)s' % new_file))
        assert uploaded_file.body == FILE_CONTENT
        assert uploaded_file.request.environ['wsgi.file_wrapper'] is _FileIter

    def test_serving_files_content_disposition(self):
        app = self.make_app()
        new_file = app.post('/create_file', params={'lang': 'ru'}).json

        uploaded_file = app.get(DepotManager.url_for('%(uploaded_to)s/%(last)s' % new_file))
        content_disposition = uploaded_file.headers['Content-Disposition']
        assert content_disposition == "inline;filename=\"Krupnyi\";filename*=utf-8''%D0%9A%D1%80%D1%83%D0%BF%D0%BD%D1%8B%D0%B9", content_disposition

        new_file = app.post('/create_file', params={'lang': 'it'}).json
        uploaded_file = app.get(DepotManager.url_for('%(uploaded_to)s/%(last)s' % new_file))
        content_disposition = uploaded_file.headers['Content-Disposition']
        _, asciiname, uniname = content_disposition.split(';')
        assert asciiname == 'filename="aeiou"', asciiname
        assert u_(unquote(uniname[17:])) == u_('àèìòù'), unquote(uniname[17:])

class TestS3TestWSGIMiddleware(BaseWSGITests):
    @classmethod
    def setup_class(cls):
        super(TestS3TestWSGIMiddleware, cls).setup_class()

        try:
            global S3Storage
            from depot.io.awss3 import S3Storage
        except ImportError:
            raise SkipTest('Boto not installed')

        env = os.environ
        access_key_id = env.get('AWS_ACCESS_KEY_ID')
        secret_access_key = env.get('AWS_SECRET_ACCESS_KEY')
        if access_key_id is None or secret_access_key is None:
            raise SkipTest('Amazon S3 credentials not available')

        PID = os.getpid()
        NODE = str(uuid.uuid1()).rsplit('-', 1)[-1]  # Travis runs multiple tests concurrently
        default_bucket_name = 'filedepot-%s' % (access_key_id.lower(), )
        cred = (access_key_id, secret_access_key)
        bucket_name = 'filedepot-testfs-%s-%s-%s' % (access_key_id.lower(), NODE, PID)

        DepotManager.configure('awss3', {'depot.backend': 'depot.io.awss3.S3Storage',
                                         'depot.access_key_id': access_key_id,
                                         'depot.secret_access_key': secret_access_key,
                                         'depot.bucket': bucket_name})
        DepotManager.set_default('awss3')

    def teardown(self):
        store = DepotManager.get('awss3')
        if not store._conn.lookup(store._bucket_driver.bucket.name):
            return

        keys = [key.name for key in store._bucket_driver.bucket]
        if keys:
            store._bucket_driver.bucket.delete_keys(keys)

        try:
            store._conn.delete_bucket(store._bucket_driver.bucket.name)
            while store._conn.lookup(store._bucket_driver.bucket.name):
                # Wait for bucket to be deleted, to avoid flaky tests...
                time.sleep(0.5)
        except:
            pass

    def test_public_url_gets_redirect(self):
        app = self.make_app()
        new_file = app.post('/create_file').json

        file_path = DepotManager.url_for('%(uploaded_to)s/%(last)s' % new_file)
        uploaded_file = app.get(file_path, status=301)
        location = uploaded_file.headers['Location']
        assert 'https://filedepot-testfs-' in location
        assert 's3.amazonaws.com' in location<|endoftext|>


<commit_before>"""
1. Bare-bones model

This is a basic model with only two non-primary-key fields.
"""

from django.core import meta

class Article(meta.Model):
    fields = (
        meta.CharField('headline', maxlength=100, default='Default headline'),
        meta.DateTimeField('pub_date'),
    )

API_TESTS = """
# No articles are in the system yet.
>>> articles.get_list()
[]

# Create an Article.
>>> from datetime import datetime
>>> a = articles.Article(id=None, headline='Area man programs in Python',
...     pub_date=datetime(2005, 7, 28))

# Save it into the database. You have to call save() explicitly.
>>> a.save()

# Now it has an ID. Note it's a long integer, as designated by the trailing "L".
>>> a.id
1L

# Access database columns via Python attributes.
>>> a.headline
'Area man programs in Python'
>>> a.pub_date
datetime.datetime(2005, 7, 28, 0, 0)

# Change values by changing the attributes, then calling save().
>>> a.headline = 'Area woman programs in Python'
>>> a.save()

# get_list() displays all the articles in the database. Note that the article
# is represented by "<Article object>", because we haven't given the Article
# model a __repr__() method.
>>> articles.get_list()
[<Article object>]

# Django provides a rich database lookup API that's entirely driven by
# keyword arguments.
>>> articles.get_object(id__exact=1)
<Article object>
>>> articles.get_object(headline__startswith='Area woman')
<Article object>
>>> articles.get_object(pub_date__year=2005)
<Article object>

# Django raises an ArticleDoesNotExist exception for get_object()
>>> articles.get_object(id__exact=2)
Traceback (most recent call last):
    ...
ArticleDoesNotExist: Article does not exist for {'id__exact': 2}

# Lookup by a primary key is the most common case, so Django provides a
# shortcut for primary-key exact lookups.
# The following is identical to articles.get_object(id__exact=1).
>>> articles.get_object(pk=1)
<Article object>

# Model instances of the same type and same ID are considered equal.
>>> a = articles.get_object(pk=1)
>>> b = articles.get_object(pk=1)
>>> a == b
True

# You can initialize a model instance using positional arguments, which should
# match the field order as defined in the model...
>>> a2 = articles.Article(None, 'Second article', datetime(2005, 7, 29))
>>> a2.save()
>>> a2.id
2L
>>> a2.headline
'Second article'
>>> a2.pub_date
datetime.datetime(2005, 7, 29, 0, 0)

# ...or, you can use keyword arguments.
>>> a3 = articles.Article(id=None, headline='Third article',
...    pub_date=datetime(2005, 7, 30))
>>> a3.save()
>>> a3.id
3L
>>> a3.headline
'Third article'
>>> a3.pub_date
datetime.datetime(2005, 7, 30, 0, 0)

# You can also mix and match position and keyword arguments, but be sure not to
# duplicate field information.
>>> a4 = articles.Article(None, 'Fourth article', pub_date=datetime(2005, 7, 31))
>>> a4.save()
>>> a4.headline
'Fourth article'

# Don't use invalid keyword arguments.
>>> a5 = articles.Article(id=None, headline='Invalid', pub_date=datetime(2005, 7, 31), foo='bar')
Traceback (most recent call last):
    ...
TypeError: 'foo' is an invalid keyword argument for this function

# You can leave off the ID.
>>> a5 = articles.Article(headline='Article 6', pub_date=datetime(2005, 7, 31))
>>> a5.save()
>>> a5.id
5L
>>> a5.headline
'Article 6'

# If you leave off a field with "default" set, Django will use the default.
>>> a6 = articles.Article(pub_date=datetime(2005, 7, 31))
>>> a6.save()
>>> a6.headline
'Default headline'

# For DateTimeFields, Django saves as much precision (in seconds) as you
# give it.
>>> a7 = articles.Article(headline='Article 7', pub_date=datetime(2005, 7, 31, 12, 30))
>>> a7.save()
>>> articles.get_object(id__exact=7).pub_date
datetime.datetime(2005, 7, 31, 12, 30)

>>> a8 = articles.Article(headline='Article 8', pub_date=datetime(2005, 7, 31, 12, 30, 45))
>>> a8.save()
>>> articles.get_object(id__exact=8).pub_date
datetime.datetime(2005, 7, 31, 12, 30, 45)
"""

from django.conf import settings

building_docs = getattr(settings, 'BUILDING_DOCS', False)

if building_docs or settings.DATABASE_ENGINE == 'postgresql':
    API_TESTS += """
# In PostgreSQL, microsecond-level precision is available.
>>> a9 = articles.Article(headline='Article 9', pub_date=datetime(2005, 7, 31, 12, 30, 45, 180))
>>> a9.save()
>>> articles.get_object(id__exact=9).pub_date
datetime.datetime(2005, 7, 31, 12, 30, 45, 180)
"""

if building_docs or settings.DATABASE_ENGINE == 'mysql':
    API_TESTS += """
# In MySQL, microsecond-level precision isn't available. You'll lose
# microsecond-level precision once the data is saved.
>>> a9 = articles.Article(headline='Article 9', pub_date=datetime(2005, 7, 31, 12, 30, 45, 180))
>>> a9.save()
>>> articles.get_object(id__exact=9).pub_date
datetime.datetime(2005, 7, 31, 12, 30, 45)
"""
<commit_msg>Added unit test that tests #323 -- currently fails for MySQL and passes for PostgreSQL<commit_after>"""
1. Bare-bones model

This is a basic model with only two non-primary-key fields.
"""

from django.core import meta

class Article(meta.Model):
    fields = (
        meta.CharField('headline', maxlength=100, default='Default headline'),
        meta.DateTimeField('pub_date'),
    )

API_TESTS = """
# No articles are in the system yet.
>>> articles.get_list()
[]

# Create an Article.
>>> from datetime import datetime
>>> a = articles.Article(id=None, headline='Area man programs in Python',
...     pub_date=datetime(2005, 7, 28))

# Save it into the database. You have to call save() explicitly.
>>> a.save()

# Now it has an ID. Note it's a long integer, as designated by the trailing "L".
>>> a.id
1L

# Access database columns via Python attributes.
>>> a.headline
'Area man programs in Python'
>>> a.pub_date
datetime.datetime(2005, 7, 28, 0, 0)

# Change values by changing the attributes, then calling save().
>>> a.headline = 'Area woman programs in Python'
>>> a.save()

# get_list() displays all the articles in the database. Note that the article
# is represented by "<Article object>", because we haven't given the Article
# model a __repr__() method.
>>> articles.get_list()
[<Article object>]

# Django provides a rich database lookup API that's entirely driven by
# keyword arguments.
>>> articles.get_object(id__exact=1)
<Article object>
>>> articles.get_object(headline__startswith='Area woman')
<Article object>
>>> articles.get_object(pub_date__year=2005)
<Article object>

# Django raises an ArticleDoesNotExist exception for get_object()
>>> articles.get_object(id__exact=2)
Traceback (most recent call last):
    ...
ArticleDoesNotExist: Article does not exist for {'id__exact': 2}

# Lookup by a primary key is the most common case, so Django provides a
# shortcut for primary-key exact lookups.
# The following is identical to articles.get_object(id__exact=1).
>>> articles.get_object(pk=1)
<Article object>

# Model instances of the same type and same ID are considered equal.
>>> a = articles.get_object(pk=1)
>>> b = articles.get_object(pk=1)
>>> a == b
True

# You can initialize a model instance using positional arguments, which should
# match the field order as defined in the model...
>>> a2 = articles.Article(None, 'Second article', datetime(2005, 7, 29))
>>> a2.save()
>>> a2.id
2L
>>> a2.headline
'Second article'
>>> a2.pub_date
datetime.datetime(2005, 7, 29, 0, 0)

# ...or, you can use keyword arguments.
>>> a3 = articles.Article(id=None, headline='Third article',
...    pub_date=datetime(2005, 7, 30))
>>> a3.save()
>>> a3.id
3L
>>> a3.headline
'Third article'
>>> a3.pub_date
datetime.datetime(2005, 7, 30, 0, 0)

# You can also mix and match position and keyword arguments, but be sure not to
# duplicate field information.
>>> a4 = articles.Article(None, 'Fourth article', pub_date=datetime(2005, 7, 31))
>>> a4.save()
>>> a4.headline
'Fourth article'

# Don't use invalid keyword arguments.
>>> a5 = articles.Article(id=None, headline='Invalid', pub_date=datetime(2005, 7, 31), foo='bar')
Traceback (most recent call last):
    ...
TypeError: 'foo' is an invalid keyword argument for this function

# You can leave off the ID.
>>> a5 = articles.Article(headline='Article 6', pub_date=datetime(2005, 7, 31))
>>> a5.save()
>>> a5.id
5L
>>> a5.headline
'Article 6'

# If you leave off a field with "default" set, Django will use the default.
>>> a6 = articles.Article(pub_date=datetime(2005, 7, 31))
>>> a6.save()
>>> a6.headline
'Default headline'

# For DateTimeFields, Django saves as much precision (in seconds) as you
# give it.
>>> a7 = articles.Article(headline='Article 7', pub_date=datetime(2005, 7, 31, 12, 30))
>>> a7.save()
>>> articles.get_object(id__exact=7).pub_date
datetime.datetime(2005, 7, 31, 12, 30)

>>> a8 = articles.Article(headline='Article 8', pub_date=datetime(2005, 7, 31, 12, 30, 45))
>>> a8.save()
>>> articles.get_object(id__exact=8).pub_date
datetime.datetime(2005, 7, 31, 12, 30, 45)
>>> a8.id
8L

# Saving an object again shouldn't create a new object -- it just saves the old one.
>>> a8.save()
>>> a8.id
8L
>>> a8.headline = 'Updated article 8'
>>> a8.save()
>>> a8.id
8L
"""

from django.conf import settings

building_docs = getattr(settings, 'BUILDING_DOCS', False)

if building_docs or settings.DATABASE_ENGINE == 'postgresql':
    API_TESTS += """
# In PostgreSQL, microsecond-level precision is available.
>>> a9 = articles.Article(headline='Article 9', pub_date=datetime(2005, 7, 31, 12, 30, 45, 180))
>>> a9.save()
>>> articles.get_object(id__exact=9).pub_date
datetime.datetime(2005, 7, 31, 12, 30, 45, 180)
"""

if building_docs or settings.DATABASE_ENGINE == 'mysql':
    API_TESTS += """
# In MySQL, microsecond-level precision isn't available. You'll lose
# microsecond-level precision once the data is saved.
>>> a9 = articles.Article(headline='Article 9', pub_date=datetime(2005, 7, 31, 12, 30, 45, 180))
>>> a9.save()
>>> articles.get_object(id__exact=9).pub_date
datetime.datetime(2005, 7, 31, 12, 30, 45)
"""
<|endoftext|>


<commit_before>"""
1. Bare-bones model

This is a basic model with only two non-primary-key fields.
"""

from django.core import meta

class Article(meta.Model):
    headline = meta.CharField(maxlength=100, default='Default headline')
    pub_date = meta.DateTimeField()

API_TESTS = """
# No articles are in the system yet.
>>> articles.get_list()
[]

# Create an Article.
>>> from datetime import datetime
>>> a = articles.Article(id=None, headline='Area man programs in Python',
...     pub_date=datetime(2005, 7, 28))

# Save it into the database. You have to call save() explicitly.
>>> a.save()

# Now it has an ID. Note it's a long integer, as designated by the trailing "L".
>>> a.id
1L

# Access database columns via Python attributes.
>>> a.headline
'Area man programs in Python'
>>> a.pub_date
datetime.datetime(2005, 7, 28, 0, 0)

# Change values by changing the attributes, then calling save().
>>> a.headline = 'Area woman programs in Python'
>>> a.save()

# get_list() displays all the articles in the database. Note that the article
# is represented by "<Article object>", because we haven't given the Article
# model a __repr__() method.
>>> articles.get_list()
[<Article object>]

# Django provides a rich database lookup API that's entirely driven by
# keyword arguments.
>>> articles.get_object(id__exact=1)
<Article object>
>>> articles.get_object(headline__startswith='Area woman')
<Article object>
>>> articles.get_object(pub_date__year=2005)
<Article object>

# Django raises an ArticleDoesNotExist exception for get_object()
>>> articles.get_object(id__exact=2)
Traceback (most recent call last):
    ...
ArticleDoesNotExist: Article does not exist for {'id__exact': 2}

# Lookup by a primary key is the most common case, so Django provides a
# shortcut for primary-key exact lookups.
# The following is identical to articles.get_object(id__exact=1).
>>> articles.get_object(pk=1)
<Article object>

# Model instances of the same type and same ID are considered equal.
>>> a = articles.get_object(pk=1)
>>> b = articles.get_object(pk=1)
>>> a == b
True

# You can initialize a model instance using positional arguments, which should
# match the field order as defined in the model...
>>> a2 = articles.Article(None, 'Second article', datetime(2005, 7, 29))
>>> a2.save()
>>> a2.id
2L
>>> a2.headline
'Second article'
>>> a2.pub_date
datetime.datetime(2005, 7, 29, 0, 0)

# ...or, you can use keyword arguments.
>>> a3 = articles.Article(id=None, headline='Third article',
...    pub_date=datetime(2005, 7, 30))
>>> a3.save()
>>> a3.id
3L
>>> a3.headline
'Third article'
>>> a3.pub_date
datetime.datetime(2005, 7, 30, 0, 0)

# You can also mix and match position and keyword arguments, but be sure not to
# duplicate field information.
>>> a4 = articles.Article(None, 'Fourth article', pub_date=datetime(2005, 7, 31))
>>> a4.save()
>>> a4.headline
'Fourth article'

# Don't use invalid keyword arguments.
>>> a5 = articles.Article(id=None, headline='Invalid', pub_date=datetime(2005, 7, 31), foo='bar')
Traceback (most recent call last):
    ...
TypeError: 'foo' is an invalid keyword argument for this function

# You can leave off the ID.
>>> a5 = articles.Article(headline='Article 6', pub_date=datetime(2005, 7, 31))
>>> a5.save()
>>> a5.id
5L
>>> a5.headline
'Article 6'

# If you leave off a field with "default" set, Django will use the default.
>>> a6 = articles.Article(pub_date=datetime(2005, 7, 31))
>>> a6.save()
>>> a6.headline
'Default headline'

# For DateTimeFields, Django saves as much precision (in seconds) as you
# give it.
>>> a7 = articles.Article(headline='Article 7', pub_date=datetime(2005, 7, 31, 12, 30))
>>> a7.save()
>>> articles.get_object(id__exact=7).pub_date
datetime.datetime(2005, 7, 31, 12, 30)

>>> a8 = articles.Article(headline='Article 8', pub_date=datetime(2005, 7, 31, 12, 30, 45))
>>> a8.save()
>>> articles.get_object(id__exact=8).pub_date
datetime.datetime(2005, 7, 31, 12, 30, 45)
>>> a8.id
8L

# Saving an object again shouldn't create a new object -- it just saves the old one.
>>> a8.save()
>>> a8.id
8L
>>> a8.headline = 'Updated article 8'
>>> a8.save()
>>> a8.id
8L
"""

from django.conf import settings

building_docs = getattr(settings, 'BUILDING_DOCS', False)

if building_docs or settings.DATABASE_ENGINE == 'postgresql':
    API_TESTS += """
# In PostgreSQL, microsecond-level precision is available.
>>> a9 = articles.Article(headline='Article 9', pub_date=datetime(2005, 7, 31, 12, 30, 45, 180))
>>> a9.save()
>>> articles.get_object(id__exact=9).pub_date
datetime.datetime(2005, 7, 31, 12, 30, 45, 180)
"""

if building_docs or settings.DATABASE_ENGINE == 'mysql':
    API_TESTS += """
# In MySQL, microsecond-level precision isn't available. You'll lose
# microsecond-level precision once the data is saved.
>>> a9 = articles.Article(headline='Article 9', pub_date=datetime(2005, 7, 31, 12, 30, 45, 180))
>>> a9.save()
>>> articles.get_object(id__exact=9).pub_date
datetime.datetime(2005, 7, 31, 12, 30, 45)
"""
<commit_msg>Added model unit tests for year, month and day lookup. Refs #659<commit_after>"""
1. Bare-bones model

This is a basic model with only two non-primary-key fields.
"""

from django.core import meta

class Article(meta.Model):
    headline = meta.CharField(maxlength=100, default='Default headline')
    pub_date = meta.DateTimeField()

API_TESTS = """
# No articles are in the system yet.
>>> articles.get_list()
[]

# Create an Article.
>>> from datetime import datetime
>>> a = articles.Article(id=None, headline='Area man programs in Python',
...     pub_date=datetime(2005, 7, 28))

# Save it into the database. You have to call save() explicitly.
>>> a.save()

# Now it has an ID. Note it's a long integer, as designated by the trailing "L".
>>> a.id
1L

# Access database columns via Python attributes.
>>> a.headline
'Area man programs in Python'
>>> a.pub_date
datetime.datetime(2005, 7, 28, 0, 0)

# Change values by changing the attributes, then calling save().
>>> a.headline = 'Area woman programs in Python'
>>> a.save()

# get_list() displays all the articles in the database. Note that the article
# is represented by "<Article object>", because we haven't given the Article
# model a __repr__() method.
>>> articles.get_list()
[<Article object>]

# Django provides a rich database lookup API that's entirely driven by
# keyword arguments.
>>> articles.get_object(id__exact=1)
<Article object>
>>> articles.get_object(headline__startswith='Area woman')
<Article object>
>>> articles.get_object(pub_date__year=2005)
<Article object>
>>> articles.get_object(pub_date__year=2005, pub_date__month=7)
<Article object>
>>> articles.get_object(pub_date__year=2005, pub_date__month=7, pub_date__day=28)
<Article object>

>>> articles.get_list(pub_date__year=2005)
[<Article object>]
>>> articles.get_list(pub_date__year=2004)
[]
>>> articles.get_list(pub_date__year=2005, pub_date__month=7)
[<Article object>]

# Django raises an ArticleDoesNotExist exception for get_object()
>>> articles.get_object(id__exact=2)
Traceback (most recent call last):
    ...
ArticleDoesNotExist: Article does not exist for {'id__exact': 2}

>>> articles.get_object(pub_date__year=2005, pub_date__month=8)
Traceback (most recent call last):
    ...
ArticleDoesNotExist: Article does not exist for ...

# Lookup by a primary key is the most common case, so Django provides a
# shortcut for primary-key exact lookups.
# The following is identical to articles.get_object(id__exact=1).
>>> articles.get_object(pk=1)
<Article object>

# Model instances of the same type and same ID are considered equal.
>>> a = articles.get_object(pk=1)
>>> b = articles.get_object(pk=1)
>>> a == b
True

# You can initialize a model instance using positional arguments, which should
# match the field order as defined in the model...
>>> a2 = articles.Article(None, 'Second article', datetime(2005, 7, 29))
>>> a2.save()
>>> a2.id
2L
>>> a2.headline
'Second article'
>>> a2.pub_date
datetime.datetime(2005, 7, 29, 0, 0)

# ...or, you can use keyword arguments.
>>> a3 = articles.Article(id=None, headline='Third article',
...    pub_date=datetime(2005, 7, 30))
>>> a3.save()
>>> a3.id
3L
>>> a3.headline
'Third article'
>>> a3.pub_date
datetime.datetime(2005, 7, 30, 0, 0)

# You can also mix and match position and keyword arguments, but be sure not to
# duplicate field information.
>>> a4 = articles.Article(None, 'Fourth article', pub_date=datetime(2005, 7, 31))
>>> a4.save()
>>> a4.headline
'Fourth article'

# Don't use invalid keyword arguments.
>>> a5 = articles.Article(id=None, headline='Invalid', pub_date=datetime(2005, 7, 31), foo='bar')
Traceback (most recent call last):
    ...
TypeError: 'foo' is an invalid keyword argument for this function

# You can leave off the ID.
>>> a5 = articles.Article(headline='Article 6', pub_date=datetime(2005, 7, 31))
>>> a5.save()
>>> a5.id
5L
>>> a5.headline
'Article 6'

# If you leave off a field with "default" set, Django will use the default.
>>> a6 = articles.Article(pub_date=datetime(2005, 7, 31))
>>> a6.save()
>>> a6.headline
'Default headline'

# For DateTimeFields, Django saves as much precision (in seconds) as you
# give it.
>>> a7 = articles.Article(headline='Article 7', pub_date=datetime(2005, 7, 31, 12, 30))
>>> a7.save()
>>> articles.get_object(id__exact=7).pub_date
datetime.datetime(2005, 7, 31, 12, 30)

>>> a8 = articles.Article(headline='Article 8', pub_date=datetime(2005, 7, 31, 12, 30, 45))
>>> a8.save()
>>> articles.get_object(id__exact=8).pub_date
datetime.datetime(2005, 7, 31, 12, 30, 45)
>>> a8.id
8L

# Saving an object again shouldn't create a new object -- it just saves the old one.
>>> a8.save()
>>> a8.id
8L
>>> a8.headline = 'Updated article 8'
>>> a8.save()
>>> a8.id
8L
"""

from django.conf import settings

building_docs = getattr(settings, 'BUILDING_DOCS', False)

if building_docs or settings.DATABASE_ENGINE == 'postgresql':
    API_TESTS += """
# In PostgreSQL, microsecond-level precision is available.
>>> a9 = articles.Article(headline='Article 9', pub_date=datetime(2005, 7, 31, 12, 30, 45, 180))
>>> a9.save()
>>> articles.get_object(id__exact=9).pub_date
datetime.datetime(2005, 7, 31, 12, 30, 45, 180)
"""

if building_docs or settings.DATABASE_ENGINE == 'mysql':
    API_TESTS += """
# In MySQL, microsecond-level precision isn't available. You'll lose
# microsecond-level precision once the data is saved.
>>> a9 = articles.Article(headline='Article 9', pub_date=datetime(2005, 7, 31, 12, 30, 45, 180))
>>> a9.save()
>>> articles.get_object(id__exact=9).pub_date
datetime.datetime(2005, 7, 31, 12, 30, 45)
"""
<|endoftext|>


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

# Import python libs
from __future__ import absolute_import

# Import Salt Libs
from salt import acl

# Import Salt Testing Libs
from salttesting import TestCase, skipIf
from salttesting.mock import (
    NO_MOCK,
    NO_MOCK_REASON,
)
from salttesting.helpers import ensure_in_syspath

ensure_in_syspath('../../')

@skipIf(NO_MOCK, NO_MOCK_REASON)
class ClientACLTestCase(TestCase):
    '''
    Unit tests for salt.acl.ClientACL
    '''
    def setUp(self):
        self.blacklist = {
            'users': ['joker', 'penguin', '*bad_*', 'blocked_.*', '^Homer$'],
            'modules': ['cmd.run', 'test.fib', 'rm-rf.*'],
        }

    def test_user_is_blacklisted(self):
        '''
        test user_is_blacklisted
        '''
        client_acl = acl.PublisherACL(self.blacklist)

        self.assertTrue(client_acl.user_is_blacklisted('joker'))
        self.assertTrue(client_acl.user_is_blacklisted('penguin'))
        self.assertTrue(client_acl.user_is_blacklisted('bad_'))
        self.assertTrue(client_acl.user_is_blacklisted('bad_user'))
        self.assertTrue(client_acl.user_is_blacklisted('bad_*'))
        self.assertTrue(client_acl.user_is_blacklisted('user_bad_'))
        self.assertTrue(client_acl.user_is_blacklisted('blocked_'))
        self.assertTrue(client_acl.user_is_blacklisted('blocked_user'))
        self.assertTrue(client_acl.user_is_blacklisted('blocked_.*'))
        self.assertTrue(client_acl.user_is_blacklisted('Homer'))

        self.assertFalse(client_acl.user_is_blacklisted('batman'))
        self.assertFalse(client_acl.user_is_blacklisted('robin'))
        self.assertFalse(client_acl.user_is_blacklisted('bad'))
        self.assertFalse(client_acl.user_is_blacklisted('blocked'))
        self.assertFalse(client_acl.user_is_blacklisted('NotHomer'))
        self.assertFalse(client_acl.user_is_blacklisted('HomerSimpson'))

    def test_cmd_is_blacklisted(self):
        '''
        test cmd_is_blacklisted
        '''
        client_acl = acl.PublisherACL(self.blacklist)

        self.assertTrue(client_acl.cmd_is_blacklisted('cmd.run'))
        self.assertTrue(client_acl.cmd_is_blacklisted('test.fib'))
        self.assertTrue(client_acl.cmd_is_blacklisted('rm-rf.root'))

        self.assertFalse(client_acl.cmd_is_blacklisted('cmd.shell'))
        self.assertFalse(client_acl.cmd_is_blacklisted('test.versions'))
        self.assertFalse(client_acl.cmd_is_blacklisted('arm-rf.root'))

        self.assertTrue(client_acl.cmd_is_blacklisted(['cmd.run', 'state.sls']))
        self.assertFalse(client_acl.cmd_is_blacklisted(['state.highstate', 'state.sls']))

if __name__ == '__main__':
    from integration import run_tests
    run_tests(ClientACLTestCase, needs_daemon=False)
<commit_msg>Code cleanup. We aren't even using mock!<commit_after># -*- coding: utf-8 -*-

# Import python libs
from __future__ import absolute_import

# Import Salt Libs
from salt import acl

# Import Salt Testing Libs
from salttesting import TestCase

class ClientACLTestCase(TestCase):
    '''
    Unit tests for salt.acl.ClientACL
    '''
    def setUp(self):
        self.blacklist = {
            'users': ['joker', 'penguin', '*bad_*', 'blocked_.*', '^Homer$'],
            'modules': ['cmd.run', 'test.fib', 'rm-rf.*'],
        }

    def test_user_is_blacklisted(self):
        '''
        test user_is_blacklisted
        '''
        client_acl = acl.PublisherACL(self.blacklist)

        self.assertTrue(client_acl.user_is_blacklisted('joker'))
        self.assertTrue(client_acl.user_is_blacklisted('penguin'))
        self.assertTrue(client_acl.user_is_blacklisted('bad_'))
        self.assertTrue(client_acl.user_is_blacklisted('bad_user'))
        self.assertTrue(client_acl.user_is_blacklisted('bad_*'))
        self.assertTrue(client_acl.user_is_blacklisted('user_bad_'))
        self.assertTrue(client_acl.user_is_blacklisted('blocked_'))
        self.assertTrue(client_acl.user_is_blacklisted('blocked_user'))
        self.assertTrue(client_acl.user_is_blacklisted('blocked_.*'))
        self.assertTrue(client_acl.user_is_blacklisted('Homer'))

        self.assertFalse(client_acl.user_is_blacklisted('batman'))
        self.assertFalse(client_acl.user_is_blacklisted('robin'))
        self.assertFalse(client_acl.user_is_blacklisted('bad'))
        self.assertFalse(client_acl.user_is_blacklisted('blocked'))
        self.assertFalse(client_acl.user_is_blacklisted('NotHomer'))
        self.assertFalse(client_acl.user_is_blacklisted('HomerSimpson'))

    def test_cmd_is_blacklisted(self):
        '''
        test cmd_is_blacklisted
        '''
        client_acl = acl.PublisherACL(self.blacklist)

        self.assertTrue(client_acl.cmd_is_blacklisted('cmd.run'))
        self.assertTrue(client_acl.cmd_is_blacklisted('test.fib'))
        self.assertTrue(client_acl.cmd_is_blacklisted('rm-rf.root'))

        self.assertFalse(client_acl.cmd_is_blacklisted('cmd.shell'))
        self.assertFalse(client_acl.cmd_is_blacklisted('test.versions'))
        self.assertFalse(client_acl.cmd_is_blacklisted('arm-rf.root'))

        self.assertTrue(client_acl.cmd_is_blacklisted(['cmd.run', 'state.sls']))
        self.assertFalse(client_acl.cmd_is_blacklisted(['state.highstate', 'state.sls']))
<|endoftext|>


<commit_before>from contextlib import contextmanager
import os
import sys

from jinja2 import ChoiceLoader, FileSystemLoader
from mock import MagicMock, patch, call
from nose.tools import istest

from provy.core.roles import Role, UsingRole
from tests.unit.tools.helpers import PROJECT_ROOT, ProvyTestCase

class RoleTest(ProvyTestCase):
    def setUp(self):
        loader = ChoiceLoader([
            FileSystemLoader(os.path.join(PROJECT_ROOT, 'files'))
        ])
        context = {
            'owner': 'foo',
            'registered_loaders': [],
            'loader': loader,
            'cleanup': [],
        }
        self.role = Role(prov=None, context=context)

    @istest
    def checks_if_a_remote_directory_exists(self):
        with self.execute_mock() as execute:
            execute.return_value = '0'
            self.assertTrue(self.role.remote_exists_dir('/some_path'))

            execute.assert_called_with('test -d /some_path; echo $?', stdout=False, sudo=True)

    @istest
    def checks_if_a_remote_directory_doesnt_exist(self):
        with self.execute_mock() as execute:
            execute.return_value = '1'
            self.assertFalse(self.role.remote_exists_dir('/some_path'))

            execute.assert_called_with('test -d /some_path; echo $?', stdout=False, sudo=True)

    @istest
    def doesnt_create_directory_if_it_already_exists(self):
        with self.mock_role_method('remote_exists_dir') as remote_exists_dir, self.execute_mock() as execute:
            remote_exists_dir.return_value = True
            self.role.ensure_dir('/some_path')
            self.assertFalse(execute.called)

    @istest
    def creates_the_directory_if_it_doesnt_exist(self):
        with self.mock_role_method('remote_exists_dir') as remote_exists_dir, self.execute_mock() as execute:
            remote_exists_dir.return_value = False
            self.role.ensure_dir('/some_path')
            execute.assert_called_with('mkdir -p /some_path', stdout=False, sudo=False)

    @istest
    def gets_distro_info_for_debian(self):
        with self.execute_mock() as execute:
            execute.return_value = 'No LSB modules are available.\nDistributor ID:\tDebian\nDescription:\tDebian GNU/Linux 6.0.5 (squeeze)\nRelease:\t6.0.5\nCodename:\tsqueeze'
            distro_info = self.role.get_distro_info()
            execute.assert_called_with('lsb_release -a')
            self.assertEqual(distro_info.distributor_id, 'Debian')
            self.assertEqual(distro_info.description, 'Debian GNU/Linux 6.0.5 (squeeze)')
            self.assertEqual(distro_info.release, '6.0.5')
            self.assertEqual(distro_info.codename, 'squeeze')

    @istest
    def gets_distro_info_for_ubuntu(self):
        with self.execute_mock() as execute:
            execute.return_value = 'No LSB modules are available.\r\nDistributor ID:\tUbuntu\r\nDescription:\tUbuntu 12.04.1 LTS\r\nRelease:\t12.04\r\nCodename:\tprecise'
            distro_info = self.role.get_distro_info()
            execute.assert_called_with('lsb_release -a')
            self.assertEqual(distro_info.distributor_id, 'Ubuntu')
            self.assertEqual(distro_info.description, 'Ubuntu 12.04.1 LTS')
            self.assertEqual(distro_info.release, '12.04')
            self.assertEqual(distro_info.codename, 'precise')

    @istest
    def gets_distro_info_for_centos(self):
        with self.execute_mock() as execute:
            execute.return_value = 'LSB Version:\t:core-4.0-ia32:core-4.0-noarch:graphics-4.0-ia32:graphics-4.0-noarch:printing-4.0-ia32:printing-4.0-noarch\nDistributor ID:\tCentOS\nDescription:\tCentOS release 5.8 (Final)\nRelease:\t5.8\nCodename:\tFinal'
            distro_info = self.role.get_distro_info()
            execute.assert_called_with('lsb_release -a')
            self.assertEqual(distro_info.lsb_version, ':core-4.0-ia32:core-4.0-noarch:graphics-4.0-ia32:graphics-4.0-noarch:printing-4.0-ia32:printing-4.0-noarch')
            self.assertEqual(distro_info.distributor_id, 'CentOS')
            self.assertEqual(distro_info.description, 'CentOS release 5.8 (Final)')
            self.assertEqual(distro_info.release, '5.8')
            self.assertEqual(distro_info.codename, 'Final')

    @istest
    def ignores_line_if_already_exists_in_file(self):
        with self.mock_role_method('has_line') as has_line, self.execute_mock() as execute:
            has_line.return_value = True
            self.role.ensure_line('this line in', '/some/file')
            self.assertFalse(execute.called)

    @istest
    def inserts_line_if_it_doesnt_exist_yet(self):
        with self.mock_role_method('has_line') as has_line, self.execute_mock() as execute:
            has_line.return_value = False
            self.role.ensure_line('this line in', '/some/file')
            execute.assert_called_with('echo "this line in" >> /some/file', stdout=False, sudo=False, user=None)

    @istest
    def inserts_line_with_sudo(self):
        with self.mock_role_method('has_line') as has_line, self.execute_mock() as execute:
            has_line.return_value = False
            self.role.ensure_line('this line in', '/some/file', sudo=True)
            execute.assert_called_with('echo "this line in" >> /some/file', stdout=False, sudo=True, user=None)

    @istest
    def inserts_line_with_specific_user(self):
        with self.mock_role_method('has_line') as has_line, self.execute_mock() as execute:
            has_line.return_value = False
            self.role.ensure_line('this line in', '/some/file', owner='foo')
            execute.assert_called_with('echo "this line in" >> /some/file', stdout=False, sudo=False, user='foo')

    @istest
    def registers_a_template_loader(self):
        package_name = 'provy.more.debian.monitoring'

        self.assertNotIn(package_name, self.role.context['registered_loaders'])
        self.role.register_template_loader(package_name)
        self.assertIn(package_name, self.role.context['registered_loaders'])

        choice_loader = self.role.context['loader']
        package_loader = choice_loader.loaders[1]
        self.assertIn('monitoring', package_loader.provider.module_path)

    @istest
    def appends_role_instance_to_cleanup_list_when_scheduling_cleanup(self):
        self.assertEqual(self.role.context['cleanup'], [])
        self.role.schedule_cleanup()
        self.assertEqual(self.role.context['cleanup'], [self.role])

    @istest
    def doesnt_append_again_if_role_is_already_in_cleanup_list(self):
        same_class_instance = Role(None, {})
        self.role.context['cleanup'] = [same_class_instance]
        self.role.schedule_cleanup()
        self.assertEqual(self.role.context['cleanup'], [same_class_instance])

    @istest
    def provisions_role(self):
        role_instance = MagicMock()
        def StubRole(prov, context):
            return role_instance

        self.role.provision_role(StubRole)

        role_instance.provision.assert_called_with()

    @istest
    def schedules_cleanup_when_provisioning(self):
        role_instance = MagicMock()
        def StubRole(prov, context):
            return role_instance

        self.role.provision_role(StubRole)

        role_instance.schedule_cleanup.assert_called_with()

    @istest
    def can_call_cleanup_safely(self):
        self.role.cleanup()

    @istest
    def executes_command_with_stdout_and_same_user(self):
        with patch('fabric.api.run') as run:
            self.role.execute('some command', stdout=True)

            run.assert_called_with('some command')

    @istest
    def executes_command_with_stdout_and_sudo(self):
        with patch('fabric.api.sudo') as sudo:
            self.role.execute('some command', stdout=True, sudo=True)

            sudo.assert_called_with('some command', user=None)

    @istest
    def executes_command_with_stdout_and_another_user(self):
        with patch('fabric.api.sudo') as sudo:
            self.role.execute('some command', stdout=True, user='foo')

            sudo.assert_called_with('some command', user='foo')

    @istest
    def executes_command_without_stdout_but_same_user(self):
        with patch('fabric.api.run') as run, patch('fabric.api.hide') as hide:
            self.role.execute('some command', stdout=False)

            run.assert_called_with('some command')
            hide.assert_called_with('warnings', 'running', 'stdout', 'stderr')

    @istest
    def executes_command_without_stdout_but_sudo(self):
        with patch('fabric.api.sudo') as sudo, patch('fabric.api.hide') as hide:
            self.role.execute('some command', stdout=False, sudo=True)

            sudo.assert_called_with('some command', user=None)
            hide.assert_called_with('warnings', 'running', 'stdout', 'stderr')

    @istest
    def executes_command_without_stdout_but_another_user(self):
        with patch('fabric.api.sudo') as sudo, patch('fabric.api.hide') as hide:
            self.role.execute('some command', stdout=False, user='foo')

            sudo.assert_called_with('some command', user='foo')
            hide.assert_called_with('warnings', 'running', 'stdout', 'stderr')

    @istest
    def executes_a_python_command(self):
        with self.execute_mock() as execute:
            self.role.execute_python('some command', stdout='is stdout?', sudo='is sudo?')

            execute.assert_called_with('python -c "some command"', stdout='is stdout?', sudo='is sudo?')

    @istest
    def gets_logged_user(self):
        with self.execute_mock() as execute:
            execute.return_value = 'some user'
            user = self.role.get_logged_user()

            self.assertEqual(user, 'some user')
            execute.assert_called_with('whoami', stdout=False)

    @istest
    def verifies_that_remote_file_exists(self):
        with self.execute_mock() as execute:
            execute.return_value = '0'

            self.assertTrue(self.role.remote_exists('/some.path'))
            execute.assert_called_with('test -f /some.path; echo $?', stdout=False, sudo=True)

    @istest
    def verifies_that_remote_file_doesnt_exist(self):
        with self.execute_mock() as execute:
            execute.return_value = '1'

            self.assertFalse(self.role.remote_exists('/some.path'))
            execute.assert_called_with('test -f /some.path; echo $?', stdout=False, sudo=True)

    @istest
    def verifies_that_a_local_file_exists(self):
        file_to_verify = os.path.abspath(__file__)
        self.assertTrue(self.role.local_exists(file_to_verify))

    @istest
    def verifies_that_a_local_file_doesnt_exist(self):
        file_to_verify = '/some/sneaky.file'
        self.assertFalse(self.role.local_exists(file_to_verify))

    @istest
    def creates_a_local_temp_dir(self):
        self.assertTrue(self.role.local_temp_dir().startswith('/tmp'))

class UsingRoleTest(ProvyTestCase):
    def any_context(self):
        return {'used_roles': {},}

    @istest
    def returns_role_instance_for_with_block(self):
        class DummyRole(Role):
            def schedule_cleanup(self):
                pass

        with UsingRole(DummyRole, None, self.any_context()) as role:
            self.assertIsInstance(role, DummyRole)

    @istest
    def provisions_role_when_entering_with_block(self):
        sentinel = MagicMock()

        class DummyRole(Role):
            def schedule_cleanup(self):
                pass

            def provision(self):
                sentinel()

        with UsingRole(DummyRole, None, self.any_context()) as role:
            self.assertTrue(sentinel.called)

    @istest
    def triggers_schedule_cleanup_when_exiting_with_block(self):
        sentinel = MagicMock()

        class DummyRole(Role):
            def schedule_cleanup(self):
                sentinel()

        with UsingRole(DummyRole, None, self.any_context()) as role:
            self.assertFalse(sentinel.called)
        self.assertTrue(sentinel.called)

    @istest
    def reuses_role_if_already_in_use(self):
        class DummyRole(Role):
            def schedule_cleanup(self):
                pass
        context = self.any_context()
        instance = DummyRole(None, context)
        context['used_roles'][DummyRole] = instance

        using = UsingRole(DummyRole, None, context)

        with using as role:
            self.assertEqual(using.role_instance, instance)
<commit_msg>Covering remote_temp_dir<commit_after>from contextlib import contextmanager
import os
import sys

from jinja2 import ChoiceLoader, FileSystemLoader
from mock import MagicMock, patch, call
from nose.tools import istest

from provy.core.roles import Role, UsingRole
from tests.unit.tools.helpers import PROJECT_ROOT, ProvyTestCase

class RoleTest(ProvyTestCase):
    def setUp(self):
        loader = ChoiceLoader([
            FileSystemLoader(os.path.join(PROJECT_ROOT, 'files'))
        ])
        context = {
            'owner': 'foo',
            'registered_loaders': [],
            'loader': loader,
            'cleanup': [],
        }
        self.role = Role(prov=None, context=context)

    @istest
    def checks_if_a_remote_directory_exists(self):
        with self.execute_mock() as execute:
            execute.return_value = '0'
            self.assertTrue(self.role.remote_exists_dir('/some_path'))

            execute.assert_called_with('test -d /some_path; echo $?', stdout=False, sudo=True)

    @istest
    def checks_if_a_remote_directory_doesnt_exist(self):
        with self.execute_mock() as execute:
            execute.return_value = '1'
            self.assertFalse(self.role.remote_exists_dir('/some_path'))

            execute.assert_called_with('test -d /some_path; echo $?', stdout=False, sudo=True)

    @istest
    def doesnt_create_directory_if_it_already_exists(self):
        with self.mock_role_method('remote_exists_dir') as remote_exists_dir, self.execute_mock() as execute:
            remote_exists_dir.return_value = True
            self.role.ensure_dir('/some_path')
            self.assertFalse(execute.called)

    @istest
    def creates_the_directory_if_it_doesnt_exist(self):
        with self.mock_role_method('remote_exists_dir') as remote_exists_dir, self.execute_mock() as execute:
            remote_exists_dir.return_value = False
            self.role.ensure_dir('/some_path')
            execute.assert_called_with('mkdir -p /some_path', stdout=False, sudo=False)

    @istest
    def gets_distro_info_for_debian(self):
        with self.execute_mock() as execute:
            execute.return_value = 'No LSB modules are available.\nDistributor ID:\tDebian\nDescription:\tDebian GNU/Linux 6.0.5 (squeeze)\nRelease:\t6.0.5\nCodename:\tsqueeze'
            distro_info = self.role.get_distro_info()
            execute.assert_called_with('lsb_release -a')
            self.assertEqual(distro_info.distributor_id, 'Debian')
            self.assertEqual(distro_info.description, 'Debian GNU/Linux 6.0.5 (squeeze)')
            self.assertEqual(distro_info.release, '6.0.5')
            self.assertEqual(distro_info.codename, 'squeeze')

    @istest
    def gets_distro_info_for_ubuntu(self):
        with self.execute_mock() as execute:
            execute.return_value = 'No LSB modules are available.\r\nDistributor ID:\tUbuntu\r\nDescription:\tUbuntu 12.04.1 LTS\r\nRelease:\t12.04\r\nCodename:\tprecise'
            distro_info = self.role.get_distro_info()
            execute.assert_called_with('lsb_release -a')
            self.assertEqual(distro_info.distributor_id, 'Ubuntu')
            self.assertEqual(distro_info.description, 'Ubuntu 12.04.1 LTS')
            self.assertEqual(distro_info.release, '12.04')
            self.assertEqual(distro_info.codename, 'precise')

    @istest
    def gets_distro_info_for_centos(self):
        with self.execute_mock() as execute:
            execute.return_value = 'LSB Version:\t:core-4.0-ia32:core-4.0-noarch:graphics-4.0-ia32:graphics-4.0-noarch:printing-4.0-ia32:printing-4.0-noarch\nDistributor ID:\tCentOS\nDescription:\tCentOS release 5.8 (Final)\nRelease:\t5.8\nCodename:\tFinal'
            distro_info = self.role.get_distro_info()
            execute.assert_called_with('lsb_release -a')
            self.assertEqual(distro_info.lsb_version, ':core-4.0-ia32:core-4.0-noarch:graphics-4.0-ia32:graphics-4.0-noarch:printing-4.0-ia32:printing-4.0-noarch')
            self.assertEqual(distro_info.distributor_id, 'CentOS')
            self.assertEqual(distro_info.description, 'CentOS release 5.8 (Final)')
            self.assertEqual(distro_info.release, '5.8')
            self.assertEqual(distro_info.codename, 'Final')

    @istest
    def ignores_line_if_already_exists_in_file(self):
        with self.mock_role_method('has_line') as has_line, self.execute_mock() as execute:
            has_line.return_value = True
            self.role.ensure_line('this line in', '/some/file')
            self.assertFalse(execute.called)

    @istest
    def inserts_line_if_it_doesnt_exist_yet(self):
        with self.mock_role_method('has_line') as has_line, self.execute_mock() as execute:
            has_line.return_value = False
            self.role.ensure_line('this line in', '/some/file')
            execute.assert_called_with('echo "this line in" >> /some/file', stdout=False, sudo=False, user=None)

    @istest
    def inserts_line_with_sudo(self):
        with self.mock_role_method('has_line') as has_line, self.execute_mock() as execute:
            has_line.return_value = False
            self.role.ensure_line('this line in', '/some/file', sudo=True)
            execute.assert_called_with('echo "this line in" >> /some/file', stdout=False, sudo=True, user=None)

    @istest
    def inserts_line_with_specific_user(self):
        with self.mock_role_method('has_line') as has_line, self.execute_mock() as execute:
            has_line.return_value = False
            self.role.ensure_line('this line in', '/some/file', owner='foo')
            execute.assert_called_with('echo "this line in" >> /some/file', stdout=False, sudo=False, user='foo')

    @istest
    def registers_a_template_loader(self):
        package_name = 'provy.more.debian.monitoring'

        self.assertNotIn(package_name, self.role.context['registered_loaders'])
        self.role.register_template_loader(package_name)
        self.assertIn(package_name, self.role.context['registered_loaders'])

        choice_loader = self.role.context['loader']
        package_loader = choice_loader.loaders[1]
        self.assertIn('monitoring', package_loader.provider.module_path)

    @istest
    def appends_role_instance_to_cleanup_list_when_scheduling_cleanup(self):
        self.assertEqual(self.role.context['cleanup'], [])
        self.role.schedule_cleanup()
        self.assertEqual(self.role.context['cleanup'], [self.role])

    @istest
    def doesnt_append_again_if_role_is_already_in_cleanup_list(self):
        same_class_instance = Role(None, {})
        self.role.context['cleanup'] = [same_class_instance]
        self.role.schedule_cleanup()
        self.assertEqual(self.role.context['cleanup'], [same_class_instance])

    @istest
    def provisions_role(self):
        role_instance = MagicMock()
        def StubRole(prov, context):
            return role_instance

        self.role.provision_role(StubRole)

        role_instance.provision.assert_called_with()

    @istest
    def schedules_cleanup_when_provisioning(self):
        role_instance = MagicMock()
        def StubRole(prov, context):
            return role_instance

        self.role.provision_role(StubRole)

        role_instance.schedule_cleanup.assert_called_with()

    @istest
    def can_call_cleanup_safely(self):
        self.role.cleanup()

    @istest
    def executes_command_with_stdout_and_same_user(self):
        with patch('fabric.api.run') as run:
            self.role.execute('some command', stdout=True)

            run.assert_called_with('some command')

    @istest
    def executes_command_with_stdout_and_sudo(self):
        with patch('fabric.api.sudo') as sudo:
            self.role.execute('some command', stdout=True, sudo=True)

            sudo.assert_called_with('some command', user=None)

    @istest
    def executes_command_with_stdout_and_another_user(self):
        with patch('fabric.api.sudo') as sudo:
            self.role.execute('some command', stdout=True, user='foo')

            sudo.assert_called_with('some command', user='foo')

    @istest
    def executes_command_without_stdout_but_same_user(self):
        with patch('fabric.api.run') as run, patch('fabric.api.hide') as hide:
            self.role.execute('some command', stdout=False)

            run.assert_called_with('some command')
            hide.assert_called_with('warnings', 'running', 'stdout', 'stderr')

    @istest
    def executes_command_without_stdout_but_sudo(self):
        with patch('fabric.api.sudo') as sudo, patch('fabric.api.hide') as hide:
            self.role.execute('some command', stdout=False, sudo=True)

            sudo.assert_called_with('some command', user=None)
            hide.assert_called_with('warnings', 'running', 'stdout', 'stderr')

    @istest
    def executes_command_without_stdout_but_another_user(self):
        with patch('fabric.api.sudo') as sudo, patch('fabric.api.hide') as hide:
            self.role.execute('some command', stdout=False, user='foo')

            sudo.assert_called_with('some command', user='foo')
            hide.assert_called_with('warnings', 'running', 'stdout', 'stderr')

    @istest
    def executes_a_python_command(self):
        with self.execute_mock() as execute:
            self.role.execute_python('some command', stdout='is stdout?', sudo='is sudo?')

            execute.assert_called_with('python -c "some command"', stdout='is stdout?', sudo='is sudo?')

    @istest
    def gets_logged_user(self):
        with self.execute_mock() as execute:
            execute.return_value = 'some user'
            user = self.role.get_logged_user()

            self.assertEqual(user, 'some user')
            execute.assert_called_with('whoami', stdout=False)

    @istest
    def verifies_that_remote_file_exists(self):
        with self.execute_mock() as execute:
            execute.return_value = '0'

            self.assertTrue(self.role.remote_exists('/some.path'))
            execute.assert_called_with('test -f /some.path; echo $?', stdout=False, sudo=True)

    @istest
    def verifies_that_remote_file_doesnt_exist(self):
        with self.execute_mock() as execute:
            execute.return_value = '1'

            self.assertFalse(self.role.remote_exists('/some.path'))
            execute.assert_called_with('test -f /some.path; echo $?', stdout=False, sudo=True)

    @istest
    def verifies_that_a_local_file_exists(self):
        file_to_verify = os.path.abspath(__file__)
        self.assertTrue(self.role.local_exists(file_to_verify))

    @istest
    def verifies_that_a_local_file_doesnt_exist(self):
        file_to_verify = '/some/sneaky.file'
        self.assertFalse(self.role.local_exists(file_to_verify))

    @istest
    def creates_a_local_temp_dir(self):
        self.assertTrue(self.role.local_temp_dir().startswith('/tmp'))

    @istest
    def creates_a_remote_temp_dir(self):
        with self.mock_role_method('execute_python') as execute_python:
            execute_python.return_value = '/some/remote/temp/dir'
            directory = self.role.remote_temp_dir()
            self.assertEqual(directory, '/some/remote/temp/dir')
            execute_python.assert_called_with('from tempfile import gettempdir; print gettempdir()', stdout=False)

class UsingRoleTest(ProvyTestCase):
    def any_context(self):
        return {'used_roles': {},}

    @istest
    def returns_role_instance_for_with_block(self):
        class DummyRole(Role):
            def schedule_cleanup(self):
                pass

        with UsingRole(DummyRole, None, self.any_context()) as role:
            self.assertIsInstance(role, DummyRole)

    @istest
    def provisions_role_when_entering_with_block(self):
        sentinel = MagicMock()

        class DummyRole(Role):
            def schedule_cleanup(self):
                pass

            def provision(self):
                sentinel()

        with UsingRole(DummyRole, None, self.any_context()) as role:
            self.assertTrue(sentinel.called)

    @istest
    def triggers_schedule_cleanup_when_exiting_with_block(self):
        sentinel = MagicMock()

        class DummyRole(Role):
            def schedule_cleanup(self):
                sentinel()

        with UsingRole(DummyRole, None, self.any_context()) as role:
            self.assertFalse(sentinel.called)
        self.assertTrue(sentinel.called)

    @istest
    def reuses_role_if_already_in_use(self):
        class DummyRole(Role):
            def schedule_cleanup(self):
                pass
        context = self.any_context()
        instance = DummyRole(None, context)
        context['used_roles'][DummyRole] = instance

        using = UsingRole(DummyRole, None, context)

        with using as role:
            self.assertEqual(using.role_instance, instance)
<|endoftext|>