<commit_before>#!/usr/bin/env python3
"""Classes and functions for testing the behavior of NFAs."""

import types
from unittest.mock import patch

import nose.tools as nose

import automata.base.exceptions as exceptions
import tests.test_fa as test_fa
from automata.fa.nfa import NFA

class TestNFA(test_fa.TestFA):
    """A test class for testing nondeterministic finite automata."""

    def test_init_nfa(self):
        """Should copy NFA if passed into NFA constructor."""
        new_nfa = NFA.copy(self.nfa)
        self.assert_is_copy(new_nfa, self.nfa)

    def test_init_nfa_missing_formal_params(self):
        """Should raise an error if formal NFA parameters are missing."""
        with nose.assert_raises(TypeError):
            NFA(
                states={'q0', 'q1'},
                input_symbols={'0', '1'},
                initial_state='q0',
                final_states={'q1'}
            )

    def test_copy_nfa(self):
        """Should create exact copy of NFA if copy() method is called."""
        new_nfa = self.nfa.copy()
        self.assert_is_copy(new_nfa, self.nfa)

    def test_init_dfa(self):
        """Should convert DFA to NFA if passed into NFA constructor."""
        nfa = NFA.from_dfa(self.dfa)
        nose.assert_equal(nfa.states, {'q0', 'q1', 'q2'})
        nose.assert_equal(nfa.input_symbols, {'0', '1'})
        nose.assert_equal(nfa.transitions, {
            'q0': {'0': {'q0'}, '1': {'q1'}},
            'q1': {'0': {'q0'}, '1': {'q2'}},
            'q2': {'0': {'q2'}, '1': {'q1'}}
        })
        nose.assert_equal(nfa.initial_state, 'q0')

    @patch('automata.fa.nfa.NFA.validate')
    def test_init_validation(self, validate):
        """Should validate NFA when initialized."""
        NFA.copy(self.nfa)
        validate.assert_called_once_with()

    def test_nfa_equal(self):
        """Should correctly determine if two NFAs are equal."""
        new_nfa = self.nfa.copy()
        nose.assert_true(self.nfa == new_nfa, 'NFAs are not equal')

    def test_nfa_not_equal(self):
        """Should correctly determine if two NFAs are not equal."""
        new_nfa = self.nfa.copy()
        new_nfa.final_states.add('q2')
        nose.assert_true(self.nfa != new_nfa, 'NFAs are equal')

    def test_validate_invalid_symbol(self):
        """Should raise error if a transition references an invalid symbol."""
        with nose.assert_raises(exceptions.InvalidSymbolError):
            self.nfa.transitions['q1']['c'] = {'q2'}
            self.nfa.validate()

    def test_validate_invalid_state(self):
        """Should raise error if a transition references an invalid state."""
        with nose.assert_raises(exceptions.InvalidStateError):
            self.nfa.transitions['q1']['a'] = {'q3'}
            self.nfa.validate()

    def test_validate_invalid_initial_state(self):
        """Should raise error if the initial state is invalid."""
        with nose.assert_raises(exceptions.InvalidStateError):
            self.nfa.initial_state = 'q3'
            self.nfa.validate()

    def test_validate_initial_state_transitions(self):
        """Should raise error if the initial state has no transitions."""
        with nose.assert_raises(exceptions.MissingStateError):
            del self.nfa.transitions[self.nfa.initial_state]
            self.nfa.validate()

    def test_validate_invalid_final_state(self):
        """Should raise error if the final state is invalid."""
        with nose.assert_raises(exceptions.InvalidStateError):
            self.nfa.final_states = {'q3'}
            self.nfa.validate()

    def test_validate_invalid_final_state_non_str(self):
        """Should raise InvalidStateError even for non-string final states."""
        with nose.assert_raises(exceptions.InvalidStateError):
            self.nfa.final_states = {3}
            self.nfa.validate()

    def test_read_input_accepted(self):
        """Should return correct states if acceptable NFA input is given."""
        nose.assert_equal(self.nfa.read_input('aba'), {'q1', 'q2'})

    def test_validate_missing_state(self):
        """Should silently ignore states without transitions defined."""
        self.nfa.states.add('q3')
        self.nfa.transitions['q0']['a'].add('q3')
        nose.assert_equal(self.nfa.validate(), True)

    def test_read_input_rejection(self):
        """Should raise error if the stop state is not a final state."""
        with nose.assert_raises(exceptions.RejectionException):
            self.nfa.read_input('abba')

    def test_read_input_rejection_invalid_symbol(self):
        """Should raise error if an invalid symbol is read."""
        with nose.assert_raises(exceptions.RejectionException):
            self.nfa.read_input('abc')

    def test_read_input_step(self):
        """Should return validation generator if step flag is supplied."""
        validation_generator = self.nfa.read_input_stepwise('aba')
        nose.assert_is_instance(validation_generator, types.GeneratorType)
        nose.assert_equal(list(validation_generator), [
            {'q0'}, {'q1', 'q2'}, {'q0'}, {'q1', 'q2'}
        ])

    def test_accepts_input_true(self):
        """Should return True if NFA input is accepted."""
        nose.assert_equal(self.nfa.accepts_input('aba'), True)

    def test_accepts_input_false(self):
        """Should return False if NFA input is rejected."""
        nose.assert_equal(self.nfa.accepts_input('abba'), False)

    def test_cyclic_lambda_transitions(self):
        """Should traverse NFA containing cyclic lambda transitions."""
        # NFA which matches zero or more occurrences of 'a'
        nfa = NFA(
            states={'q0', 'q1', 'q2', 'q3'},
            input_symbols={'a'},
            transitions={
                'q0': {'': {'q1', 'q3'}},
                'q1': {'a': {'q2'}},
                'q2': {'': {'q3'}},
                'q3': {'': {'q0'}}
            },
            initial_state='q0',
            final_states={'q3'}
        )
        nose.assert_equal(nfa.read_input(''), {'q0', 'q1', 'q3'})
        nose.assert_equal(nfa.read_input('a'), {'q0', 'q1', 'q2', 'q3'})

    def test_non_str_states(self):
        """should handle non-string state names"""
        nfa = NFA(
            states={0},
            input_symbols={0},
            transitions={0: {}},
            initial_state=0,
            final_states=set())
        # We don't care what the output is, just as long as no exception is
        # raised
        nose.assert_not_equal(nfa.accepts_input(''), None)

    def test_operations_other_type(self):
        """Should raise NotImplementedError for concatenate."""
        nfa = NFA(
                states={'q1', 'q2', 'q3', 'q4'},
                input_symbols={'0', '1'},
                transitions={'q1': {'0': {'q1'}, '1': {'q1', 'q2'}},
                             'q2': {'': {'q2'}, '0': {'q2'}},
                             'q3': {'1': {'q4'}},
                             'q4': {'0': {'q4'}, '1': {'q4'}}},
                initial_state='q1',
                final_states={'q2', 'q4'})
        other = 42
        with nose.assert_raises(NotImplementedError):
            nfa + other

    def test_concatenate(self):
        nfa_a = NFA(
                states={'q1', 'q2', 'q3', 'q4'},
                input_symbols={'0', '1'},
                transitions={'q1': {'0': {'q1'}, '1': {'q1', 'q2'}},
                             'q2': {'': {'q2'}, '0': {'q2'}},
                             'q3': {'1': {'q4'}},
                             'q4': {'0': {'q4'}, '1': {'q4'}}},
                initial_state='q1',
                final_states={'q2', 'q4'})

        nfa_b = NFA(
                states={'r1', 'r2', 'r3'},
                input_symbols={'0', '1'},
                transitions={'r1': {'': {'r3'}, '1': {'r2'}},
                             'r2': {'0': {'r2', 'r3'}, '1': {'r3'}},
                             'r3': {'0': {'r1'}}},
                initial_state='r1',
                final_states={'r1'})

        concat_nfa = nfa_a + nfa_b

        nose.assert_equal(concat_nfa.accepts_input(''), False)
        nose.assert_equal(concat_nfa.accepts_input('0'), False)
        nose.assert_equal(concat_nfa.accepts_input('1'), True)
        nose.assert_equal(concat_nfa.accepts_input('00'), False)
        nose.assert_equal(concat_nfa.accepts_input('01'), True)
        nose.assert_equal(concat_nfa.accepts_input('10'), True)
        nose.assert_equal(concat_nfa.accepts_input('11'), True)
        nose.assert_equal(concat_nfa.accepts_input('101'), True)
        nose.assert_equal(concat_nfa.accepts_input('101100'), True)
        nose.assert_equal(concat_nfa.accepts_input('1010'), True)

    def test_kleene_star(self):
        # This NFA accepts aa and ab
        nfa = NFA(
                states={0,1,2,3,4,6},
                input_symbols={'a', 'b'},
                transitions={0: {'a': {1, 3}},
                             1: {'b': {2}},
                             2: {},
                             3: {'a': {4}},
                             4: {'':{6}},
                             6: {}},
                initial_state=0,
                final_states={2,4,6})

        # This NFA should then accept any number of repetitions
        # of aa or ab concatenated together.
        kleene_nfa = nfa.kleene_star()

        nose.assert_equal(kleene_nfa.accepts_input(''), True)
        nose.assert_equal(kleene_nfa.accepts_input('a'), False)
        nose.assert_equal(kleene_nfa.accepts_input('b'), False)
        nose.assert_equal(kleene_nfa.accepts_input('aa'), True)
        nose.assert_equal(kleene_nfa.accepts_input('ab'), True)
        nose.assert_equal(kleene_nfa.accepts_input('ba'), False)
        nose.assert_equal(kleene_nfa.accepts_input('bb'), False)
        nose.assert_equal(kleene_nfa.accepts_input('aaa'), False)
        nose.assert_equal(kleene_nfa.accepts_input('aba'), False)
        nose.assert_equal(kleene_nfa.accepts_input('abaa'), True)
        nose.assert_equal(kleene_nfa.accepts_input('abba'), False)
        nose.assert_equal(kleene_nfa.accepts_input('aaabababaaaaa'), False)
        nose.assert_equal(kleene_nfa.accepts_input('aaabababaaaaab'), True)
        nose.assert_equal(kleene_nfa.accepts_input('aaabababaaaaba'), False)

    def test_reverse(self):
        nfa = NFA(
                states={0,1,2,4},
                input_symbols={'a', 'b'},
                transitions={0: {'a': {1}},
                             1: {'a': {2}, 'b': {1, 2}},
                             2: {},
                             3: {'a': {2}, 'b': {2}}
                            },
                initial_state=0,
                final_states={2})

        reverse_nfa = reversed(nfa)
        nose.assert_equal(reverse_nfa.accepts_input('a'), False)
        nose.assert_equal(reverse_nfa.accepts_input('ab'), False)
        nose.assert_equal(reverse_nfa.accepts_input('ba'), True)
        nose.assert_equal(reverse_nfa.accepts_input('bba'), True)
        nose.assert_equal(reverse_nfa.accepts_input('bbba'), True)
<commit_msg>Make PEP 8 style corrections in NFA test file<commit_after>#!/usr/bin/env python3
"""Classes and functions for testing the behavior of NFAs."""

import types
from unittest.mock import patch

import nose.tools as nose

import automata.base.exceptions as exceptions
import tests.test_fa as test_fa
from automata.fa.nfa import NFA

class TestNFA(test_fa.TestFA):
    """A test class for testing nondeterministic finite automata."""

    def test_init_nfa(self):
        """Should copy NFA if passed into NFA constructor."""
        new_nfa = NFA.copy(self.nfa)
        self.assert_is_copy(new_nfa, self.nfa)

    def test_init_nfa_missing_formal_params(self):
        """Should raise an error if formal NFA parameters are missing."""
        with nose.assert_raises(TypeError):
            NFA(
                states={'q0', 'q1'},
                input_symbols={'0', '1'},
                initial_state='q0',
                final_states={'q1'}
            )

    def test_copy_nfa(self):
        """Should create exact copy of NFA if copy() method is called."""
        new_nfa = self.nfa.copy()
        self.assert_is_copy(new_nfa, self.nfa)

    def test_init_dfa(self):
        """Should convert DFA to NFA if passed into NFA constructor."""
        nfa = NFA.from_dfa(self.dfa)
        nose.assert_equal(nfa.states, {'q0', 'q1', 'q2'})
        nose.assert_equal(nfa.input_symbols, {'0', '1'})
        nose.assert_equal(nfa.transitions, {
            'q0': {'0': {'q0'}, '1': {'q1'}},
            'q1': {'0': {'q0'}, '1': {'q2'}},
            'q2': {'0': {'q2'}, '1': {'q1'}}
        })
        nose.assert_equal(nfa.initial_state, 'q0')

    @patch('automata.fa.nfa.NFA.validate')
    def test_init_validation(self, validate):
        """Should validate NFA when initialized."""
        NFA.copy(self.nfa)
        validate.assert_called_once_with()

    def test_nfa_equal(self):
        """Should correctly determine if two NFAs are equal."""
        new_nfa = self.nfa.copy()
        nose.assert_true(self.nfa == new_nfa, 'NFAs are not equal')

    def test_nfa_not_equal(self):
        """Should correctly determine if two NFAs are not equal."""
        new_nfa = self.nfa.copy()
        new_nfa.final_states.add('q2')
        nose.assert_true(self.nfa != new_nfa, 'NFAs are equal')

    def test_validate_invalid_symbol(self):
        """Should raise error if a transition references an invalid symbol."""
        with nose.assert_raises(exceptions.InvalidSymbolError):
            self.nfa.transitions['q1']['c'] = {'q2'}
            self.nfa.validate()

    def test_validate_invalid_state(self):
        """Should raise error if a transition references an invalid state."""
        with nose.assert_raises(exceptions.InvalidStateError):
            self.nfa.transitions['q1']['a'] = {'q3'}
            self.nfa.validate()

    def test_validate_invalid_initial_state(self):
        """Should raise error if the initial state is invalid."""
        with nose.assert_raises(exceptions.InvalidStateError):
            self.nfa.initial_state = 'q3'
            self.nfa.validate()

    def test_validate_initial_state_transitions(self):
        """Should raise error if the initial state has no transitions."""
        with nose.assert_raises(exceptions.MissingStateError):
            del self.nfa.transitions[self.nfa.initial_state]
            self.nfa.validate()

    def test_validate_invalid_final_state(self):
        """Should raise error if the final state is invalid."""
        with nose.assert_raises(exceptions.InvalidStateError):
            self.nfa.final_states = {'q3'}
            self.nfa.validate()

    def test_validate_invalid_final_state_non_str(self):
        """Should raise InvalidStateError even for non-string final states."""
        with nose.assert_raises(exceptions.InvalidStateError):
            self.nfa.final_states = {3}
            self.nfa.validate()

    def test_read_input_accepted(self):
        """Should return correct states if acceptable NFA input is given."""
        nose.assert_equal(self.nfa.read_input('aba'), {'q1', 'q2'})

    def test_validate_missing_state(self):
        """Should silently ignore states without transitions defined."""
        self.nfa.states.add('q3')
        self.nfa.transitions['q0']['a'].add('q3')
        nose.assert_equal(self.nfa.validate(), True)

    def test_read_input_rejection(self):
        """Should raise error if the stop state is not a final state."""
        with nose.assert_raises(exceptions.RejectionException):
            self.nfa.read_input('abba')

    def test_read_input_rejection_invalid_symbol(self):
        """Should raise error if an invalid symbol is read."""
        with nose.assert_raises(exceptions.RejectionException):
            self.nfa.read_input('abc')

    def test_read_input_step(self):
        """Should return validation generator if step flag is supplied."""
        validation_generator = self.nfa.read_input_stepwise('aba')
        nose.assert_is_instance(validation_generator, types.GeneratorType)
        nose.assert_equal(list(validation_generator), [
            {'q0'}, {'q1', 'q2'}, {'q0'}, {'q1', 'q2'}
        ])

    def test_accepts_input_true(self):
        """Should return True if NFA input is accepted."""
        nose.assert_equal(self.nfa.accepts_input('aba'), True)

    def test_accepts_input_false(self):
        """Should return False if NFA input is rejected."""
        nose.assert_equal(self.nfa.accepts_input('abba'), False)

    def test_cyclic_lambda_transitions(self):
        """Should traverse NFA containing cyclic lambda transitions."""
        # NFA which matches zero or more occurrences of 'a'
        nfa = NFA(
            states={'q0', 'q1', 'q2', 'q3'},
            input_symbols={'a'},
            transitions={
                'q0': {'': {'q1', 'q3'}},
                'q1': {'a': {'q2'}},
                'q2': {'': {'q3'}},
                'q3': {'': {'q0'}}
            },
            initial_state='q0',
            final_states={'q3'}
        )
        nose.assert_equal(nfa.read_input(''), {'q0', 'q1', 'q3'})
        nose.assert_equal(nfa.read_input('a'), {'q0', 'q1', 'q2', 'q3'})

    def test_non_str_states(self):
        """should handle non-string state names"""
        nfa = NFA(
            states={0},
            input_symbols={0},
            transitions={0: {}},
            initial_state=0,
            final_states=set())
        # We don't care what the output is, just as long as no exception is
        # raised
        nose.assert_not_equal(nfa.accepts_input(''), None)

    def test_operations_other_type(self):
        """Should raise NotImplementedError for concatenate."""
        nfa = NFA(
                states={'q1', 'q2', 'q3', 'q4'},
                input_symbols={'0', '1'},
                transitions={'q1': {'0': {'q1'}, '1': {'q1', 'q2'}},
                             'q2': {'': {'q2'}, '0': {'q2'}},
                             'q3': {'1': {'q4'}},
                             'q4': {'0': {'q4'}, '1': {'q4'}}},
                initial_state='q1',
                final_states={'q2', 'q4'})
        other = 42
        with nose.assert_raises(NotImplementedError):
            nfa + other

    def test_concatenate(self):
        nfa_a = NFA(
            states={'q1', 'q2', 'q3', 'q4'},
            input_symbols={'0', '1'},
            transitions={
                'q1': {'0': {'q1'}, '1': {'q1', 'q2'}},
                'q2': {'': {'q2'}, '0': {'q2'}},
                'q3': {'1': {'q4'}},
                'q4': {'0': {'q4'}, '1': {'q4'}}
            },
            initial_state='q1',
            final_states={'q2', 'q4'}
        )

        nfa_b = NFA(
            states={'r1', 'r2', 'r3'},
            input_symbols={'0', '1'},
            transitions={
                'r1': {'': {'r3'}, '1': {'r2'}},
                'r2': {'0': {'r2', 'r3'}, '1': {'r3'}},
                'r3': {'0': {'r1'}}
            },
            initial_state='r1',
            final_states={'r1'}
        )

        concat_nfa = nfa_a + nfa_b

        nose.assert_equal(concat_nfa.accepts_input(''), False)
        nose.assert_equal(concat_nfa.accepts_input('0'), False)
        nose.assert_equal(concat_nfa.accepts_input('1'), True)
        nose.assert_equal(concat_nfa.accepts_input('00'), False)
        nose.assert_equal(concat_nfa.accepts_input('01'), True)
        nose.assert_equal(concat_nfa.accepts_input('10'), True)
        nose.assert_equal(concat_nfa.accepts_input('11'), True)
        nose.assert_equal(concat_nfa.accepts_input('101'), True)
        nose.assert_equal(concat_nfa.accepts_input('101100'), True)
        nose.assert_equal(concat_nfa.accepts_input('1010'), True)

    def test_kleene_star(self):
        # This NFA accepts aa and ab
        nfa = NFA(
            states={0, 1, 2, 3, 4, 6},
            input_symbols={'a', 'b'},
            transitions={
                0: {'a': {1, 3}},
                1: {'b': {2}},
                2: {},
                3: {'a': {4}},
                4: {'': {6}},
                6: {}
            },
            initial_state=0,
            final_states={2, 4, 6}
        )
        # This NFA should then accept any number of repetitions
        # of aa or ab concatenated together.
        kleene_nfa = nfa.kleene_star()
        nose.assert_equal(kleene_nfa.accepts_input(''), True)
        nose.assert_equal(kleene_nfa.accepts_input('a'), False)
        nose.assert_equal(kleene_nfa.accepts_input('b'), False)
        nose.assert_equal(kleene_nfa.accepts_input('aa'), True)
        nose.assert_equal(kleene_nfa.accepts_input('ab'), True)
        nose.assert_equal(kleene_nfa.accepts_input('ba'), False)
        nose.assert_equal(kleene_nfa.accepts_input('bb'), False)
        nose.assert_equal(kleene_nfa.accepts_input('aaa'), False)
        nose.assert_equal(kleene_nfa.accepts_input('aba'), False)
        nose.assert_equal(kleene_nfa.accepts_input('abaa'), True)
        nose.assert_equal(kleene_nfa.accepts_input('abba'), False)
        nose.assert_equal(kleene_nfa.accepts_input('aaabababaaaaa'), False)
        nose.assert_equal(kleene_nfa.accepts_input('aaabababaaaaab'), True)
        nose.assert_equal(kleene_nfa.accepts_input('aaabababaaaaba'), False)

    def test_reverse(self):
        nfa = NFA(
            states={0, 1, 2, 4},
            input_symbols={'a', 'b'},
            transitions={
                0: {'a': {1}},
                1: {'a': {2}, 'b': {1, 2}},
                2: {},
                3: {'a': {2}, 'b': {2}}
            },
            initial_state=0,
            final_states={2}
        )
        reverse_nfa = reversed(nfa)
        nose.assert_equal(reverse_nfa.accepts_input('a'), False)
        nose.assert_equal(reverse_nfa.accepts_input('ab'), False)
        nose.assert_equal(reverse_nfa.accepts_input('ba'), True)
        nose.assert_equal(reverse_nfa.accepts_input('bba'), True)
        nose.assert_equal(reverse_nfa.accepts_input('bbba'), True)
<|endoftext|>


<commit_before>import pandas as pd
import bioframe
import pyranges as pr
import numpy as np
from io import StringIO

def bioframe_to_pyranges(df):
    pydf = df.copy()
    pydf.rename(
        {"chrom": "Chromosome", "start": "Start", "end": "End"},
        axis="columns",
        inplace=True,
    )
    return pr.PyRanges(pydf)

def pyranges_to_bioframe(pydf):
    df = pydf.df
    df.rename(
        {"Chromosome": "chrom", "Start": "start", "End": "end", "Count": "n_intervals"},
        axis="columns",
        inplace=True,
    )
    return df

def pyranges_overlap_to_bioframe(pydf):
    ## convert the df output by pyranges join into a bioframe-compatible format
    df = pydf.df.copy()
    df.rename(
        {
            "Chromosome": "chrom_1",
            "Start": "start_1",
            "End": "end_1",
            "Start_b": "start_2",
            "End_b": "end_2",
        },
        axis="columns",
        inplace=True,
    )
    df["chrom_1"] = df["chrom_1"].values.astype("object")  # to remove categories
    df["chrom_2"] = df["chrom_1"].values
    return df

chroms = ["chr12", "chrX"]

def mock_bioframe(num_entries=100):
    pos = np.random.randint(1, 1e7, size=(num_entries, 2))
    df = pd.DataFrame()
    df["chrom"] = np.random.choice(chroms, num_entries)
    df["start"] = np.min(pos, axis=1)
    df["end"] = np.max(pos, axis=1)
    df.sort_values(["chrom", "start"], inplace=True)
    return df

############# tests #####################

def test_expand():
    fake_bioframe = pd.DataFrame(
        {"chrom": ["chr1", "chr1", "chr2"], "start": [1, 50, 100], "end": [5, 55, 200]}
    )
    fake_chromsizes = {"chr1": 60, "chr2": 300}
    expand_bp = 10
    fake_expanded = bioframe.expand(fake_bioframe.copy(), expand_bp, fake_chromsizes)
    print(fake_expanded)
    assert fake_expanded.iloc[0].start == 0  # don't expand below zero
    assert (
        fake_expanded.iloc[1].end == fake_chromsizes["chr1"]
    )  # don't expand above chromsize
    assert (
        fake_expanded.iloc[2].end == fake_bioframe.iloc[2].end + expand_bp
    )  # expand end normally
    assert (
        fake_expanded.iloc[2].start == fake_bioframe.iloc[2].start - expand_bp
    )  # expand start normally

def test_overlap():
    ### note does not test overlap_start or overlap_end columns of bioframe.overlap
    df1 = mock_bioframe()
    df2 = mock_bioframe()
    assert df1.equals(df2) == False
    p1 = bioframe_to_pyranges(df1)
    p2 = bioframe_to_pyranges(df2)
    pp = pyranges_overlap_to_bioframe(p1.join(p2))[
        ["chrom_1", "start_1", "end_1", "chrom_2", "start_2", "end_2"]
    ]
    bb = bioframe.overlap(df1, df2)[
        ["chrom_1", "start_1", "end_1", "chrom_2", "start_2", "end_2"]
    ]
    pd.testing.assert_frame_equal(bb, pp, check_dtype=False, check_exact=True)
    print("overlap elements agree")

def test_cluster():
    df1 = pd.DataFrame(
        [["chr1", 1, 5], ["chr1", 3, 8], ["chr1", 8, 10], ["chr1", 12, 14],],
        columns=["chrom", "start", "end"],
    )
    df_annotated = bioframe.cluster(df1)
    assert (
        df_annotated["cluster"].values == np.array([0, 0, 0, 1])
    ).all()  # the last interval does not overlap the first three
    df_annotated = bioframe.cluster(df1, min_dist=2)
    assert (
        df_annotated["cluster"].values == np.array([0, 0, 0, 0])
    ).all()  # all intervals part of the same cluster

    df_annotated = bioframe.cluster(df1, min_dist=None)
    assert (
        df_annotated["cluster"].values == np.array([0, 0, 1, 2])
    ).all()  # adjacent intervals not clustered

    df1.iloc[0, 0] = "chrX"
    df_annotated = bioframe.cluster(df1)
    assert (
        df_annotated["cluster"].values == np.array([2, 0, 0, 1])
    ).all()  # do not cluster intervals across chromosomes

    # test consistency with pyranges (which automatically sorts df upon creation and uses 1-based indexing for clusters)
    assert (
        (bioframe_to_pyranges(df1).cluster(count=True).df["Cluster"].values - 1)
        == bioframe.cluster(df1.sort_values(["chrom", "start"]))["cluster"].values
    ).all()

def test_merge():
    df1 = pd.DataFrame(
        [["chr1", 1, 5], ["chr1", 3, 8], ["chr1", 8, 10], ["chr1", 12, 14],],
        columns=["chrom", "start", "end"],
    )

    # the last interval does not overlap the first three with default min_dist=0
    assert (bioframe.merge(df1)["n_intervals"].values == np.array([3, 1])).all()

    # adjacent intervals are not clustered with min_dist=none
    assert (
        bioframe.merge(df1, min_dist=None)["n_intervals"].values == np.array([2, 1, 1])
    ).all()

    # all intervals part of one cluster
    assert (
        bioframe.merge(df1, min_dist=2)["n_intervals"].values == np.array([4])
    ).all()

    df1.iloc[0, 0] = "chrX"
    assert (
        bioframe.merge(df1, min_dist=None)["n_intervals"].values
        == np.array([1, 1, 1, 1])
    ).all()
    assert (
        bioframe.merge(df1, min_dist=0)["n_intervals"].values == np.array([2, 1, 1])
    ).all()

    # total number of intervals should equal length of original dataframe
    mock_df = mock_bioframe()
    assert np.sum(bioframe.merge(mock_df, min_dist=0)["n_intervals"].values) == len(
        mock_df
    )

    # test consistency with pyranges
    pd.testing.assert_frame_equal(
        pyranges_to_bioframe(bioframe_to_pyranges(df1).merge(count=True)),
        bioframe.merge(df1),
        check_dtype=False,
        check_exact=True,
    )

def test_complement():
    df1 = pd.DataFrame(
        [["chr1", 1, 5], ["chr1", 3, 8], ["chr1", 8, 10], ["chr1", 12, 14]],
        columns=["chrom", "start", "end"],
    )
    df1_chromsizes = {"chr1": 100, "chrX": 100}

    df1_complement = pd.DataFrame(
        [["chr1", 0, 1], ["chr1", 10, 12], ["chr1", 14, 100]],
        columns=["chrom", "start", "end"],
    )

    pd.testing.assert_frame_equal(
        bioframe.complement(df1, chromsizes=df1_chromsizes), df1_complement
    )

    ### test complement with two chromosomes ###
    df1.iloc[0, 0] = "chrX"
    df1_complement = pd.DataFrame(
        [
            ["chr1", 0, 3],
            ["chr1", 10, 12],
            ["chr1", 14, 100],
            ["chrX", 0, 1],
            ["chrX", 5, 100],
        ],
        columns=["chrom", "start", "end"],
    )
    pd.testing.assert_frame_equal(
        bioframe.complement(df1, chromsizes=df1_chromsizes), df1_complement
    )

############# TODO #############

def test_closest():
    df1 = pd.DataFrame([
        ['chr1', 1, 5],
        ],
        columns=['chrom', 'start', 'end']
    )

    df2 = pd.DataFrame([
        ['chr1', 4, 8],
        ['chr1', 10, 11]],
        columns=['chrom', 'start', 'end']
    )

    ### closest(df1,df2,k=1) ###
    d =  '''chrom_1  start_1  end_1 chrom_2  start_2  end_2  distance
        0    chr1        1      5    chr1        4      8         0'''
    df = pd.read_csv(StringIO(d), sep=r'\s+')
    pd.testing.assert_frame_equal(df,bioframe.closest(df1,df2,k=1))

    ### closest(df1,df2, ignore_overlaps=True)) ###
    d = '''chrom_1 start_1 end_1   chrom_2 start_2 end_2   distance
        0   chr1    1   5   chr1    10  11  5'''
    df = pd.read_csv(StringIO(d), sep=r'\s+')
    pd.testing.assert_frame_equal(df, bioframe.closest(df1,df2, ignore_overlaps=True))

    ### closest(df1,df2,k=2) ###
    d =  '''chrom_1 start_1 end_1   chrom_2 start_2 end_2   distance
            0   chr1    1   5   chr1    4   8   0
            1   chr1    1   5   chr1    10  11  5'''
    df = pd.read_csv(StringIO(d), sep=r'\s+')
    pd.testing.assert_frame_equal(df, bioframe.closest(df1,df2,k=2))

    ### closest(df2,df1) ###
    d = '''chrom_1  start_1 end_1   chrom_2 start_2 end_2   distance
            0   chr1    4   8   chr1    1   5   0
            1   chr1    10  11  chr1    1   5   5 '''
    df = pd.read_csv(StringIO(d), sep=r'\s+')
    pd.testing.assert_frame_equal(df,bioframe.closest(df2,df1))

    ### change first interval to new chrom ###
    df2.iloc[0,0] = 'chrA'
    d = '''chrom_1 start_1 end_1   chrom_2 start_2 end_2   distance
              0   chr1    1   5   chr1    10  11  5'''
    df = pd.read_csv(StringIO(d), sep=r'\s+')
    pd.testing.assert_frame_equal(df,bioframe.closest(df1,df2,k=1))

# def test_coverage():

<commit_msg>add-test_coverage<commit_after>import pandas as pd
import bioframe
import pyranges as pr
import numpy as np
from io import StringIO

def bioframe_to_pyranges(df):
    pydf = df.copy()
    pydf.rename(
        {"chrom": "Chromosome", "start": "Start", "end": "End"},
        axis="columns",
        inplace=True,
    )
    return pr.PyRanges(pydf)

def pyranges_to_bioframe(pydf):
    df = pydf.df
    df.rename(
        {"Chromosome": "chrom", "Start": "start", "End": "end", "Count": "n_intervals"},
        axis="columns",
        inplace=True,
    )
    return df

def pyranges_overlap_to_bioframe(pydf):
    ## convert the df output by pyranges join into a bioframe-compatible format
    df = pydf.df.copy()
    df.rename(
        {
            "Chromosome": "chrom_1",
            "Start": "start_1",
            "End": "end_1",
            "Start_b": "start_2",
            "End_b": "end_2",
        },
        axis="columns",
        inplace=True,
    )
    df["chrom_1"] = df["chrom_1"].values.astype("object")  # to remove categories
    df["chrom_2"] = df["chrom_1"].values
    return df

chroms = ["chr12", "chrX"]

def mock_bioframe(num_entries=100):
    pos = np.random.randint(1, 1e7, size=(num_entries, 2))
    df = pd.DataFrame()
    df["chrom"] = np.random.choice(chroms, num_entries)
    df["start"] = np.min(pos, axis=1)
    df["end"] = np.max(pos, axis=1)
    df.sort_values(["chrom", "start"], inplace=True)
    return df

############# tests #####################

def test_expand():
    fake_bioframe = pd.DataFrame(
        {"chrom": ["chr1", "chr1", "chr2"], "start": [1, 50, 100], "end": [5, 55, 200]}
    )
    fake_chromsizes = {"chr1": 60, "chr2": 300}
    expand_bp = 10
    fake_expanded = bioframe.expand(fake_bioframe.copy(), expand_bp, fake_chromsizes)
    print(fake_expanded)
    assert fake_expanded.iloc[0].start == 0  # don't expand below zero
    assert (
        fake_expanded.iloc[1].end == fake_chromsizes["chr1"]
    )  # don't expand above chromsize
    assert (
        fake_expanded.iloc[2].end == fake_bioframe.iloc[2].end + expand_bp
    )  # expand end normally
    assert (
        fake_expanded.iloc[2].start == fake_bioframe.iloc[2].start - expand_bp
    )  # expand start normally

def test_overlap():
    ### note does not test overlap_start or overlap_end columns of bioframe.overlap
    df1 = mock_bioframe()
    df2 = mock_bioframe()
    assert df1.equals(df2) == False
    p1 = bioframe_to_pyranges(df1)
    p2 = bioframe_to_pyranges(df2)
    pp = pyranges_overlap_to_bioframe(p1.join(p2))[
        ["chrom_1", "start_1", "end_1", "chrom_2", "start_2", "end_2"]
    ]
    bb = bioframe.overlap(df1, df2)[
        ["chrom_1", "start_1", "end_1", "chrom_2", "start_2", "end_2"]
    ]
    pd.testing.assert_frame_equal(bb, pp, check_dtype=False, check_exact=True)
    print("overlap elements agree")

def test_cluster():
    df1 = pd.DataFrame(
        [["chr1", 1, 5], ["chr1", 3, 8], ["chr1", 8, 10], ["chr1", 12, 14],],
        columns=["chrom", "start", "end"],
    )
    df_annotated = bioframe.cluster(df1)
    assert (
        df_annotated["cluster"].values == np.array([0, 0, 0, 1])
    ).all()  # the last interval does not overlap the first three
    df_annotated = bioframe.cluster(df1, min_dist=2)
    assert (
        df_annotated["cluster"].values == np.array([0, 0, 0, 0])
    ).all()  # all intervals part of the same cluster

    df_annotated = bioframe.cluster(df1, min_dist=None)
    assert (
        df_annotated["cluster"].values == np.array([0, 0, 1, 2])
    ).all()  # adjacent intervals not clustered

    df1.iloc[0, 0] = "chrX"
    df_annotated = bioframe.cluster(df1)
    assert (
        df_annotated["cluster"].values == np.array([2, 0, 0, 1])
    ).all()  # do not cluster intervals across chromosomes

    # test consistency with pyranges (which automatically sorts df upon creation and uses 1-based indexing for clusters)
    assert (
        (bioframe_to_pyranges(df1).cluster(count=True).df["Cluster"].values - 1)
        == bioframe.cluster(df1.sort_values(["chrom", "start"]))["cluster"].values
    ).all()

def test_merge():
    df1 = pd.DataFrame(
        [["chr1", 1, 5], ["chr1", 3, 8], ["chr1", 8, 10], ["chr1", 12, 14],],
        columns=["chrom", "start", "end"],
    )

    # the last interval does not overlap the first three with default min_dist=0
    assert (bioframe.merge(df1)["n_intervals"].values == np.array([3, 1])).all()

    # adjacent intervals are not clustered with min_dist=none
    assert (
        bioframe.merge(df1, min_dist=None)["n_intervals"].values == np.array([2, 1, 1])
    ).all()

    # all intervals part of one cluster
    assert (
        bioframe.merge(df1, min_dist=2)["n_intervals"].values == np.array([4])
    ).all()

    df1.iloc[0, 0] = "chrX"
    assert (
        bioframe.merge(df1, min_dist=None)["n_intervals"].values
        == np.array([1, 1, 1, 1])
    ).all()
    assert (
        bioframe.merge(df1, min_dist=0)["n_intervals"].values == np.array([2, 1, 1])
    ).all()

    # total number of intervals should equal length of original dataframe
    mock_df = mock_bioframe()
    assert np.sum(bioframe.merge(mock_df, min_dist=0)["n_intervals"].values) == len(
        mock_df
    )

    # test consistency with pyranges
    pd.testing.assert_frame_equal(
        pyranges_to_bioframe(bioframe_to_pyranges(df1).merge(count=True)),
        bioframe.merge(df1),
        check_dtype=False,
        check_exact=True,
    )

def test_complement():
    df1 = pd.DataFrame(
        [["chr1", 1, 5], ["chr1", 3, 8], ["chr1", 8, 10], ["chr1", 12, 14]],
        columns=["chrom", "start", "end"],
    )
    df1_chromsizes = {"chr1": 100, "chrX": 100}

    df1_complement = pd.DataFrame(
        [["chr1", 0, 1], ["chr1", 10, 12], ["chr1", 14, 100]],
        columns=["chrom", "start", "end"],
    )

    pd.testing.assert_frame_equal(
        bioframe.complement(df1, chromsizes=df1_chromsizes), df1_complement
    )

    ### test complement with two chromosomes ###
    df1.iloc[0, 0] = "chrX"
    df1_complement = pd.DataFrame(
        [
            ["chr1", 0, 3],
            ["chr1", 10, 12],
            ["chr1", 14, 100],
            ["chrX", 0, 1],
            ["chrX", 5, 100],
        ],
        columns=["chrom", "start", "end"],
    )
    pd.testing.assert_frame_equal(
        bioframe.complement(df1, chromsizes=df1_chromsizes), df1_complement
    )

def test_closest():
    df1 = pd.DataFrame([["chr1", 1, 5],], columns=["chrom", "start", "end"])

    df2 = pd.DataFrame(
        [["chr1", 4, 8], ["chr1", 10, 11]], columns=["chrom", "start", "end"]
    )

    ### closest(df1,df2,k=1) ###
    d = """chrom_1  start_1  end_1 chrom_2  start_2  end_2  distance
        0    chr1        1      5    chr1        4      8         0"""
    df = pd.read_csv(StringIO(d), sep=r"\s+")
    pd.testing.assert_frame_equal(df, bioframe.closest(df1, df2, k=1))

    ### closest(df1,df2, ignore_overlaps=True)) ###
    d = """chrom_1 start_1 end_1   chrom_2 start_2 end_2   distance
        0   chr1    1   5   chr1    10  11  5"""
    df = pd.read_csv(StringIO(d), sep=r"\s+")
    pd.testing.assert_frame_equal(df, bioframe.closest(df1, df2, ignore_overlaps=True))

    ### closest(df1,df2,k=2) ###
    d = """chrom_1 start_1 end_1   chrom_2 start_2 end_2   distance
            0   chr1    1   5   chr1    4   8   0
            1   chr1    1   5   chr1    10  11  5"""
    df = pd.read_csv(StringIO(d), sep=r"\s+")
    pd.testing.assert_frame_equal(df, bioframe.closest(df1, df2, k=2))

    ### closest(df2,df1) ###
    d = """chrom_1  start_1 end_1   chrom_2 start_2 end_2   distance
            0   chr1    4   8   chr1    1   5   0
            1   chr1    10  11  chr1    1   5   5 """
    df = pd.read_csv(StringIO(d), sep=r"\s+")
    pd.testing.assert_frame_equal(df, bioframe.closest(df2, df1))

    ### change first interval to new chrom ###
    df2.iloc[0, 0] = "chrA"
    d = """chrom_1 start_1 end_1   chrom_2 start_2 end_2   distance
              0   chr1    1   5   chr1    10  11  5"""
    df = pd.read_csv(StringIO(d), sep=r"\s+")
    pd.testing.assert_frame_equal(df, bioframe.closest(df1, df2, k=1))

def test_coverage():

    #### coverage does not exceed length of original interval
    df1 = pd.DataFrame([
        ['chr1', 3, 8]],
        columns=['chrom', 'start', 'end']
    )
    df2 = pd.DataFrame([
        ['chr1', 2, 10] ],
        columns=['chrom', 'start', 'end']
    )
    d = """chrom    start   end coverage    n_overlaps
         0  chr1    3   8   5   1"""
    df = pd.read_csv(StringIO(d), sep=r"\s+")
    pd.testing.assert_frame_equal(df, bioframe.coverage(df1, df2))

    ### coverage of interval on different chrom returns zero for coverage and n_overlaps
    df1 = pd.DataFrame([
        ['chr1', 3, 8]],
        columns=['chrom', 'start', 'end']
    )
    df2 = pd.DataFrame([
        ['chrX', 3, 8] ],
        columns=['chrom', 'start', 'end']
    )
    d = """chrom    start   end coverage    n_overlaps
         0  chr1    3   8   0   0"""
    df = pd.read_csv(StringIO(d), sep=r"\s+")
    pd.testing.assert_frame_equal(df, bioframe.coverage(df1, df2))

    # ### currently does not pass, as n_overlaps not calculated correctly
    # ### when a second overlap starts within the first
    # df1 = pd.DataFrame([["chr1", 3, 8]], columns=["chrom", "start", "end"])
    # df2 = pd.DataFrame(
    #     [["chr1", 3, 5], ["chr1", 5, 8]], columns=["chrom", "start", "end"]
    # )

    # d = """chrom    start   end coverage    n_overlaps
    #      0  chr1    3   8   5   2"""
    # df = pd.read_csv(StringIO(d), sep=r"\s+")
    # pd.testing.assert_frame_equal(df, bioframe.coverage(df1, df2))

<|endoftext|>


<commit_before>import redis
from porm.model import Model
from porm.validators import StringValidator, LengthValidator, RegexValidator, ValidatorException, EmailValidator, EqualToValidator, NumberRangeValidator, IPAddressValidator
from porm.fields import StringField, NumberField
from unittest import TestCase
import pytest

class TestCache(TestCase):

    def test_basic_saving(self):
        class User(Model):
            name = StringField(index=True)
            surname = StringField()

        user = User()
        user.name = 'Peter'
        user.surname = 'Pan'
        user.save()

        connection = redis.StrictRedis(host='127.0.0.1', port=6379, db=0)
        assert connection.hget('User:Peter', 'surname') == 'Pan'

    def test_basic_validation(self):
        class User(Model):
            name = StringField(
                               index=True,
                               validators= [
                                            StringValidator(),
                                            LengthValidator(min_length=0, max_length=20),
                                            RegexValidator('^A')
                                            ])
            surname = StringField()

        with pytest.raises(ValidatorException):
            user = User()
            user.name = 'Peter2'
            user.surname = 'Pan2'

    def test_lenght_validation(self):
        class User(Model):
            name = StringField(
                               index=True,
                               validators= [
                                            StringValidator(),
                                            LengthValidator(min_length=0, max_length=20),
                                            ])
            surname = StringField()

        user = User()
        user.name = 'Peter2'
        user.surname = 'Pan2'
        with pytest.raises(ValidatorException):
            user.name = 'Peter2Peter2Peter2Peter2Peter2Peter2'

    def test_range_validation(self):
        class User(Model):
            name = StringField(index=True)
            age = NumberField(validators=[NumberRangeValidator(min=0, max=10)])

        user = User()
        user.name = 'Peter2'
        user.age = 5
        with pytest.raises(ValidatorException):
            user.age = 11

    def test_email_validation(self):
        class User(Model):
            name = StringField(
                               index=True,
                               validators= [
                                            LengthValidator(min_length=0, max_length=20),
                                            RegexValidator('^A')
                                            ])
            surname = StringField()
            email = StringField(
                                validators= [
                                            EmailValidator()
                                ])

        with pytest.raises(ValidatorException):
            user = User()
            user.name = 'Peter2'
            user.surname = 'Pan2'
            user.email = 'test|test.com'

    def test_equalto_validation(self):
        class User(Model):
            name = StringField(
                               index=True,
                               validators= [
                                            LengthValidator(min_length=0, max_length=20),
                                            EqualToValidator('Peter2')
                                            ])
            surname = StringField()

        user = User()
        user.name = 'Peter2'
        user.surname = 'Pan2'
        with pytest.raises(ValidatorException):
            user.name = 'Peter3'

    def test_prefix(self):
        class User(Model):
            name = StringField(index=True)
            age = NumberField()

        user = User(prefix='my_partition')
        user.name = 'Peter4'
        user.age = 15
        user.save()

        assert user.exists() == True
        connection = redis.StrictRedis(host='127.0.0.1', port=6379, db=0)
        assert connection.hget('my_partition:User:Peter4', 'age') == str(15)

    def test_exists_key(self):
        class User(Model):
            name = StringField(
                               index=True,
                               validators= [
                                            LengthValidator(min_length=0, max_length=20)
                                            ])
            surname = StringField()

        user = User()
        user.name = 'Peter2'
        user.surname = 'Pan2'
        user.save()

        assert user.exists() == True

    def test_free_key(self):
        class User(Model):
            name = StringField(
                               index=True,
                               validators= [
                                            LengthValidator(min_length=0, max_length=20)
                                            ])
            surname = StringField()

        user = User()
        user.name = 'Peter3'
        user.surname = 'Pan3'
        user.save()
        assert user.exists() == True
        user.free()
        assert user.exists() == False

    def test_ip_validation(self):
        class User(Model):
            name = StringField(
                               index=True,
                               validators= [
                                            LengthValidator(min_length=0, max_length=20),
                                            EqualToValidator('Peter2')
                                            ])
            ip = StringField(validators =[
                                            StringValidator(),
                                            IPAddressValidator()
                                        ])

        user = User()
        user.name = 'Peter2'
        user.ip = '127.0.0.1'
        with pytest.raises(ValidatorException):
            user.ip = '1234.456.12.12'

    def test_finding(self):
        class User(Model):
            name = StringField(index=True)
            surname = StringField()

        user = User()
        user.name = 'Peter7'
        user.surname = 'Pan'
        user.save()

        found_user = User.find('Peter7')
        assert found_user.surname.get() == 'Pan'

    def test_finding_with_numeric_parameter(self):
        class User(Model):
            name = StringField(index=True)
            surname = StringField()
            age = NumberField()

        user = User()
        user.name = 'Peter8'
        user.surname = 'Pan'
        user.age = 15
        user.save()

        found_user = User.find('Peter8')
        assert found_user.age.get() == 15

    def test_non_finding(self):
        class User(Model):
            name = StringField(index=True)
            surname = StringField()

        found_user = User.find('NonExist')
        assert found_user.surname.get() == found_user.name.get() == None
<commit_msg>Added test for string representation<commit_after>import redis
from porm.model import Model
from porm.validators import StringValidator, LengthValidator, RegexValidator, ValidatorException, EmailValidator, EqualToValidator, NumberRangeValidator, IPAddressValidator
from porm.fields import StringField, NumberField
from unittest import TestCase
from StringIO import StringIO
import sys
import pytest

class TestORM(TestCase):

    def test_basic_saving(self):
        class User(Model):
            name = StringField(index=True)
            surname = StringField()

        user = User()
        user.name = 'Peter'
        user.surname = 'Pan'
        user.save()

        connection = redis.StrictRedis(host='127.0.0.1', port=6379, db=0)
        assert connection.hget('User:Peter', 'surname') == 'Pan'

    def test_basic_validation(self):
        class User(Model):
            name = StringField(
                               index=True,
                               validators= [
                                            StringValidator(),
                                            LengthValidator(min_length=0, max_length=20),
                                            RegexValidator('^A')
                                            ])
            surname = StringField()

        with pytest.raises(ValidatorException):
            user = User()
            user.name = 'Peter2'
            user.surname = 'Pan2'

    def test_lenght_validation(self):
        class User(Model):
            name = StringField(
                               index=True,
                               validators= [
                                            StringValidator(),
                                            LengthValidator(min_length=0, max_length=20),
                                            ])
            surname = StringField()

        user = User()
        user.name = 'Peter2'
        user.surname = 'Pan2'
        with pytest.raises(ValidatorException):
            user.name = 'Peter2Peter2Peter2Peter2Peter2Peter2'

    def test_range_validation(self):
        class User(Model):
            name = StringField(index=True)
            age = NumberField(validators=[NumberRangeValidator(min=0, max=10)])

        user = User()
        user.name = 'Peter2'
        user.age = 5
        with pytest.raises(ValidatorException):
            user.age = 11

    def test_email_validation(self):
        class User(Model):
            name = StringField(
                               index=True,
                               validators= [
                                            LengthValidator(min_length=0, max_length=20),
                                            RegexValidator('^A')
                                            ])
            surname = StringField()
            email = StringField(
                                validators= [
                                            EmailValidator()
                                ])

        with pytest.raises(ValidatorException):
            user = User()
            user.name = 'Peter2'
            user.surname = 'Pan2'
            user.email = 'test|test.com'

    def test_equalto_validation(self):
        class User(Model):
            name = StringField(
                               index=True,
                               validators= [
                                            LengthValidator(min_length=0, max_length=20),
                                            EqualToValidator('Peter2')
                                            ])
            surname = StringField()

        user = User()
        user.name = 'Peter2'
        user.surname = 'Pan2'
        with pytest.raises(ValidatorException):
            user.name = 'Peter3'

    def test_prefix(self):
        class User(Model):
            name = StringField(index=True)
            age = NumberField()

        user = User(prefix='my_partition')
        user.name = 'Peter4'
        user.age = 15
        user.save()

        assert user.exists() == True
        connection = redis.StrictRedis(host='127.0.0.1', port=6379, db=0)
        assert connection.hget('my_partition:User:Peter4', 'age') == str(15)

    def test_exists_key(self):
        class User(Model):
            name = StringField(
                               index=True,
                               validators= [
                                            LengthValidator(min_length=0, max_length=20)
                                            ])
            surname = StringField()

        user = User()
        user.name = 'Peter2'
        user.surname = 'Pan2'
        user.save()

        assert user.exists() == True

    def test_free_key(self):
        class User(Model):
            name = StringField(
                               index=True,
                               validators= [
                                            LengthValidator(min_length=0, max_length=20)
                                            ])
            surname = StringField()

        user = User()
        user.name = 'Peter3'
        user.surname = 'Pan3'
        user.save()
        assert user.exists() == True
        user.free()
        assert user.exists() == False

    def test_ip_validation(self):
        class User(Model):
            name = StringField(
                               index=True,
                               validators= [
                                            LengthValidator(min_length=0, max_length=20),
                                            EqualToValidator('Peter2')
                                            ])
            ip = StringField(validators =[
                                            StringValidator(),
                                            IPAddressValidator()
                                        ])

        user = User()
        user.name = 'Peter2'
        user.ip = '127.0.0.1'
        with pytest.raises(ValidatorException):
            user.ip = '1234.456.12.12'

    def test_finding(self):
        class User(Model):
            name = StringField(index=True)
            surname = StringField()

        user = User()
        user.name = 'Peter7'
        user.surname = 'Pan'
        user.save()

        found_user = User.find('Peter7')
        assert found_user.surname.get() == 'Pan'

    def test_finding_with_numeric_parameter(self):
        class User(Model):
            name = StringField(index=True)
            surname = StringField()
            age = NumberField()

        user = User()
        user.name = 'Peter8'
        user.surname = 'Pan'
        user.age = 15
        user.save()

        found_user = User.find('Peter8')
        assert found_user.age.get() == 15

    def test_non_finding(self):
        class User(Model):
            name = StringField(index=True)
            surname = StringField()

        found_user = User.find('NonExist')
        assert found_user.surname.get() == found_user.name.get() == None

    def test_str_output(self):
        class User(Model):
            name = StringField(index=True)
            surname = StringField()
            age = NumberField()

        user = User()
        user.name = 'Peter'
        user.surname = 'Pan'
        user.age = 15
        stdout = sys.stdout
        sys.stdout = reportSIO = StringIO()

        print user
        out = reportSIO.getvalue()
        sys.stdout = stdout
        assert out == "{'age': 15, 'surname': 'Pan', 'name': 'Peter'}\n"
<|endoftext|>


<commit_before>import os
import os.path
import sys
import signal
import pytest
from contextlib import contextmanager
try:
    from unittest.mock import patch
except ImportError:
    from mock import patch

try:
    from subprocess import run
except ImportError:
    # python2 support
    from subprocess import call as run

import pid

pid.DEFAULT_PID_DIR = "/tmp"

# https://code.google.com/p/python-nose/issues/detail?id=175
@contextmanager
def raising(*exc_types):
    """
    A context manager to ensure that an exception of a given list of
    types is thrown.

    Instead of::

      @nose.tools.raises(ValueError)
      def test_that_raises():
        # ... lengthy setup
        raise ValueError

    you can write::

      def test_that_raises_at_the_end():
        # ... lengthy setup
        with raising(ValueError):
          raise ValueError

    to make the scope for catching exceptions as small as possible.
    """
    try:
        yield
    except exc_types:
        pass
    except Exception:
        raise
    else:
        raise AssertionError("Failed to throw exception of type(s) %s." % (", ".join(exc_type.__name__ for exc_type in exc_types),))

def test_pid_class():
    pidfile = pid.PidFile()
    pidfile.create()
    pidfile.close()
    assert not os.path.exists(pidfile.filename)

def test_pid_context_manager():
    with pid.PidFile() as pidfile:
        pass

    assert not os.path.exists(pidfile.filename)

def test_pid_pid():
    with pid.PidFile() as pidfile:
        pidnr = int(open(pidfile.filename, "r").readline().strip())
        assert pidnr == os.getpid(), "%s != %s" % (pidnr, os.getpid())
    assert not os.path.exists(pidfile.filename)

def test_pid_custom_name():
    with pid.PidFile(pidname="testpidfile") as pidfile:
        pass
    assert not os.path.exists(pidfile.filename)

def test_pid_enforce_dotpid_postfix():
    with pid.PidFile(pidname="testpidfile", enforce_dotpid_postfix=False) as pidfile:
        assert not pidfile.filename.endswith(".pid")
    assert not os.path.exists(pidfile.filename)

def test_pid_force_tmpdir():
    with pid.PidFile(force_tmpdir=True) as pidfile:
        pass
    assert not os.path.exists(pidfile.filename)

def test_pid_custom_dir():
    with pid.PidFile(piddir="/tmp/testpidfile.dir/") as pidfile:
        pass
    assert not os.path.exists(pidfile.filename)

def test_pid_no_term_signal():
    def _noop(*args, **kwargs):
        pass

    signal.signal(signal.SIGTERM, _noop)
    with pid.PidFile(register_term_signal_handler=False) as pidfile:
        assert signal.getsignal(signal.SIGTERM) is _noop
    assert not os.path.exists(pidfile.filename)

def test_pid_term_signal():
    def _noop(*args, **kwargs):
        pass

    signal.signal(signal.SIGTERM, _noop)
    with pid.PidFile(register_term_signal_handler=True) as pidfile:
        assert signal.getsignal(signal.SIGTERM) is not _noop
    assert not os.path.exists(pidfile.filename)

def test_pid_force_register_term_signal_handler():
    def _noop(*args, **kwargs):
        pass

    def _custom_signal_func(*args, **kwargs):
        pass

    signal.signal(signal.SIGTERM, _custom_signal_func)
    assert signal.getsignal(signal.SIGTERM) is _custom_signal_func
    with pid.PidFile(register_term_signal_handler=True) as pidfile:
        assert signal.getsignal(signal.SIGTERM) is not _custom_signal_func
    assert not os.path.exists(pidfile.filename)

def test_pid_supply_term_signal_handler():
    def _noop(*args, **kwargs):
        pass

    signal.signal(signal.SIGTERM, signal.SIG_IGN)

    with pid.PidFile(register_term_signal_handler=_noop) as pidfile:
        assert signal.getsignal(signal.SIGTERM) is _noop
    assert not os.path.exists(pidfile.filename)

def test_pid_chmod():
    with pid.PidFile(chmod=0o600) as pidfile:
        pass
    assert not os.path.exists(pidfile.filename)

def test_pid_already_locked():
    with pid.PidFile() as _pid:
        with raising(pid.PidFileAlreadyLockedError):
            with pid.PidFile():
                pass
        assert os.path.exists(_pid.filename)
    assert not os.path.exists(_pid.filename)

def test_pid_already_locked_custom_name():
    with pid.PidFile(pidname="testpidfile") as _pid:
        with raising(pid.PidFileAlreadyLockedError):
            with pid.PidFile(pidname="testpidfile"):
                pass
        assert os.path.exists(_pid.filename)
    assert not os.path.exists(_pid.filename)

def test_pid_already_locked_multi_process():
    with pid.PidFile() as _pid:
        s = '''
import pid
with pid.PidFile(os.path.basename(sys.argv[0]), piddir="/tmp"):
    pass
'''
        result = run(['python', '-c', s])
        returncode = result if isinstance(result, int) else result.returncode
        assert returncode == 1
        assert os.path.exists(_pid.filename)
    assert not os.path.exists(_pid.filename)

def test_pid_two_locks_multi_process():
    with pid.PidFile() as _pid:
        s = '''
import os, pid
with pid.PidFile("pytest2", piddir="/tmp") as _pid:
    assert os.path.exists(_pid.filename)
assert not os.path.exists(_pid.filename)
'''
        result = run(['python', '-c', s])
        returncode = result if isinstance(result, int) else result.returncode
        assert returncode == 0
        assert os.path.exists(_pid.filename)
    assert not os.path.exists(_pid.filename)

def test_pid_already_running():
    with pid.PidFile(lock_pidfile=False) as _pid:
        with raising(pid.PidFileAlreadyRunningError):
            with pid.PidFile(lock_pidfile=False):
                pass
        assert os.path.exists(_pid.filename)
    assert not os.path.exists(_pid.filename)

def test_pid_already_running_custom_name():
    with pid.PidFile(lock_pidfile=False, pidname="testpidfile") as _pid:
        with raising(pid.PidFileAlreadyRunningError):
            with pid.PidFile(lock_pidfile=False, pidname="testpidfile"):
                pass
        assert os.path.exists(_pid.filename)
    assert not os.path.exists(_pid.filename)

def test_pid_decorator():
    from pid.decorator import pidfile

    @pidfile()
    def test_decorator():
        pass

    test_decorator()

def test_pid_decorator_already_locked():
    from pid.decorator import pidfile

    @pidfile("testpiddecorator")
    def test_decorator():
        with raising(pid.PidFileAlreadyLockedError):
            @pidfile("testpiddecorator")
            def test_decorator2():
                pass
            test_decorator2()

    test_decorator()

def test_pid_already_closed():
    pidfile = pid.PidFile()
    pidfile.create()
    try:
        pidfile.fh.close()
    finally:
        pidfile.close()
    assert not os.path.exists(pidfile.filename)

def test_pid_multiplecreate():
    pidfile = pid.PidFile()
    pidfile.create()
    try:
        with raising(pid.PidFileAlreadyRunningError, pid.PidFileAlreadyLockedError):
            pidfile.create()
    finally:
        pidfile.close()
    assert not os.path.exists(pidfile.filename)

def test_pid_gid():
    gid = os.getgid()
    with pid.PidFile(gid=gid) as pidfile:
        pass
    assert not os.path.exists(pidfile.filename)

def test_pid_check_const_empty():
    pidfile = pid.PidFile()
    pidfile.setup()
    try:
        with open(pidfile.filename, "w") as f:
            f.write("\n")
        assert pidfile.check() == pid.PID_CHECK_EMPTY
    finally:
        pidfile.close(cleanup=True)
    assert not os.path.exists(pidfile.filename)

def test_pid_check_const_nofile():
    pidfile = pid.PidFile()
    assert pidfile.check() == pid.PID_CHECK_NOFILE

def test_pid_check_const_samepid():
    with pid.PidFile(allow_samepid=True) as pidfile:
        assert pidfile.check() == pid.PID_CHECK_SAMEPID
    assert not os.path.exists(pidfile.filename)

def test_pid_check_const_notrunning():
    with pid.PidFile() as pidfile:
        with open(pidfile.filename, "w") as f:
            # hope this does not clash
            f.write("999999999\n")
        assert pidfile.check() == pid.PID_CHECK_NOTRUNNING
    assert not os.path.exists(pidfile.filename)

def test_pid_check_already_running():
    with pid.PidFile() as pidfile:
        pidfile2 = pid.PidFile()
        with raising(pid.PidFileAlreadyRunningError):
            pidfile2.check()
    assert not os.path.exists(pidfile.filename)

def test_pid_check_samepid_with_blocks():
    with pid.PidFile(allow_samepid=True):
        with pid.PidFile(allow_samepid=True):
            pass

    pidfile = pid.PidFile(allow_samepid=True)
    with pidfile:
        with pidfile:
            pass

    assert not os.path.exists(pidfile.filename)

def test_pid_check_samepid():
    pidfile = pid.PidFile(allow_samepid=True)

    try:
        pidfile.create()
        pidfile.create()
    finally:
        pidfile.close()

    assert not os.path.exists(pidfile.filename)

@patch("os.getpid")
@patch("os.kill")
def test_pid_raises_already_running_when_samepid_and_two_different_pids(mock_getpid, mock_kill):
    pidfile_proc1 = pid.PidFile()
    pidfile_proc2 = pid.PidFile(allow_samepid=True)

    try:
        mock_getpid.return_value = 1
        pidfile_proc1.create()

        mock_getpid.return_value = 2
        with raising(pid.PidFileAlreadyRunningError):
            pidfile_proc2.create()

    finally:
        pidfile_proc1.close()
        pidfile_proc2.close()

    assert not os.path.exists(pidfile_proc1.filename)
    assert not os.path.exists(pidfile_proc2.filename)

def test_pid_default_term_signal():
    signal.signal(signal.SIGTERM, signal.SIG_DFL)

    with pid.PidFile() as pidfile:
        assert callable(signal.getsignal(signal.SIGTERM)) is True

    assert not os.path.exists(pidfile.filename)

def test_pid_ignore_term_signal():
    signal.signal(signal.SIGTERM, signal.SIG_IGN)

    with pid.PidFile() as pidfile:
        assert signal.getsignal(signal.SIGTERM) == signal.SIG_IGN

    assert not os.path.exists(pidfile.filename)

def test_pid_custom_term_signal():
    def _noop(*args, **kwargs):
        pass

    signal.signal(signal.SIGTERM, _noop)

    with pid.PidFile() as pidfile:
        assert signal.getsignal(signal.SIGTERM) == _noop

    assert not os.path.exists(pidfile.filename)

# def test_pid_unknown_term_signal():
#     # Not sure how to properly test this when signal.getsignal returns None
#     #  - perhaps by writing a C extension which might get ugly
#     #
#     with pid.PidFile():
#         assert signal.getsignal(signal.SIGTERM) == None

def test_double_close_race_condition():
    # https://github.com/trbs/pid/issues/22
    pidfile1 = pid.PidFile()
    pidfile2 = pid.PidFile()

    try:
        pidfile1.create()
        assert os.path.exists(pidfile1.filename)
    finally:
        pidfile1.close()
        assert not os.path.exists(pidfile1.filename)

    try:
        pidfile2.create()
        assert os.path.exists(pidfile2.filename)

        # simulate calling atexit in process of pidfile1
        pidfile1.close()

        assert os.path.exists(pidfile2.filename)
    finally:
        pidfile2.close()

    assert not os.path.exists(pidfile1.filename)
    assert not os.path.exists(pidfile2.filename)

@pytest.mark.skipif(sys.version_info < (3, 5), reason="requires python3.5 or higher")
@patch('atexit.register', autospec=True)
def test_register_atexit_false(mock_atexit_register):
    with pid.PidFile(register_atexit=False):
        mock_atexit_register.assert_not_called()

@patch('atexit.register', autospec=True)
def test_register_atexit_true(mock_atexit_register):
    with pid.PidFile(register_atexit=True) as pidfile:
        mock_atexit_register.assert_called_once_with(pidfile.close)
<commit_msg>tests: Do not hardcode Python executable to "python"<commit_after>import os
import os.path
import sys
import signal
import pytest
from contextlib import contextmanager
try:
    from unittest.mock import patch
except ImportError:
    from mock import patch

try:
    from subprocess import run
except ImportError:
    # python2 support
    from subprocess import call as run

import pid

pid.DEFAULT_PID_DIR = "/tmp"

# https://code.google.com/p/python-nose/issues/detail?id=175
@contextmanager
def raising(*exc_types):
    """
    A context manager to ensure that an exception of a given list of
    types is thrown.

    Instead of::

      @nose.tools.raises(ValueError)
      def test_that_raises():
        # ... lengthy setup
        raise ValueError

    you can write::

      def test_that_raises_at_the_end():
        # ... lengthy setup
        with raising(ValueError):
          raise ValueError

    to make the scope for catching exceptions as small as possible.
    """
    try:
        yield
    except exc_types:
        pass
    except Exception:
        raise
    else:
        raise AssertionError("Failed to throw exception of type(s) %s." % (", ".join(exc_type.__name__ for exc_type in exc_types),))

def test_pid_class():
    pidfile = pid.PidFile()
    pidfile.create()
    pidfile.close()
    assert not os.path.exists(pidfile.filename)

def test_pid_context_manager():
    with pid.PidFile() as pidfile:
        pass

    assert not os.path.exists(pidfile.filename)

def test_pid_pid():
    with pid.PidFile() as pidfile:
        pidnr = int(open(pidfile.filename, "r").readline().strip())
        assert pidnr == os.getpid(), "%s != %s" % (pidnr, os.getpid())
    assert not os.path.exists(pidfile.filename)

def test_pid_custom_name():
    with pid.PidFile(pidname="testpidfile") as pidfile:
        pass
    assert not os.path.exists(pidfile.filename)

def test_pid_enforce_dotpid_postfix():
    with pid.PidFile(pidname="testpidfile", enforce_dotpid_postfix=False) as pidfile:
        assert not pidfile.filename.endswith(".pid")
    assert not os.path.exists(pidfile.filename)

def test_pid_force_tmpdir():
    with pid.PidFile(force_tmpdir=True) as pidfile:
        pass
    assert not os.path.exists(pidfile.filename)

def test_pid_custom_dir():
    with pid.PidFile(piddir="/tmp/testpidfile.dir/") as pidfile:
        pass
    assert not os.path.exists(pidfile.filename)

def test_pid_no_term_signal():
    def _noop(*args, **kwargs):
        pass

    signal.signal(signal.SIGTERM, _noop)
    with pid.PidFile(register_term_signal_handler=False) as pidfile:
        assert signal.getsignal(signal.SIGTERM) is _noop
    assert not os.path.exists(pidfile.filename)

def test_pid_term_signal():
    def _noop(*args, **kwargs):
        pass

    signal.signal(signal.SIGTERM, _noop)
    with pid.PidFile(register_term_signal_handler=True) as pidfile:
        assert signal.getsignal(signal.SIGTERM) is not _noop
    assert not os.path.exists(pidfile.filename)

def test_pid_force_register_term_signal_handler():
    def _noop(*args, **kwargs):
        pass

    def _custom_signal_func(*args, **kwargs):
        pass

    signal.signal(signal.SIGTERM, _custom_signal_func)
    assert signal.getsignal(signal.SIGTERM) is _custom_signal_func
    with pid.PidFile(register_term_signal_handler=True) as pidfile:
        assert signal.getsignal(signal.SIGTERM) is not _custom_signal_func
    assert not os.path.exists(pidfile.filename)

def test_pid_supply_term_signal_handler():
    def _noop(*args, **kwargs):
        pass

    signal.signal(signal.SIGTERM, signal.SIG_IGN)

    with pid.PidFile(register_term_signal_handler=_noop) as pidfile:
        assert signal.getsignal(signal.SIGTERM) is _noop
    assert not os.path.exists(pidfile.filename)

def test_pid_chmod():
    with pid.PidFile(chmod=0o600) as pidfile:
        pass
    assert not os.path.exists(pidfile.filename)

def test_pid_already_locked():
    with pid.PidFile() as _pid:
        with raising(pid.PidFileAlreadyLockedError):
            with pid.PidFile():
                pass
        assert os.path.exists(_pid.filename)
    assert not os.path.exists(_pid.filename)

def test_pid_already_locked_custom_name():
    with pid.PidFile(pidname="testpidfile") as _pid:
        with raising(pid.PidFileAlreadyLockedError):
            with pid.PidFile(pidname="testpidfile"):
                pass
        assert os.path.exists(_pid.filename)
    assert not os.path.exists(_pid.filename)

def test_pid_already_locked_multi_process():
    with pid.PidFile() as _pid:
        s = '''
import pid
with pid.PidFile(os.path.basename(sys.argv[0]), piddir="/tmp"):
    pass
'''
        result = run([sys.executable, '-c', s])
        returncode = result if isinstance(result, int) else result.returncode
        assert returncode == 1
        assert os.path.exists(_pid.filename)
    assert not os.path.exists(_pid.filename)

def test_pid_two_locks_multi_process():
    with pid.PidFile() as _pid:
        s = '''
import os, pid
with pid.PidFile("pytest2", piddir="/tmp") as _pid:
    assert os.path.exists(_pid.filename)
assert not os.path.exists(_pid.filename)
'''
        result = run([sys.executable, '-c', s])
        returncode = result if isinstance(result, int) else result.returncode
        assert returncode == 0
        assert os.path.exists(_pid.filename)
    assert not os.path.exists(_pid.filename)

def test_pid_already_running():
    with pid.PidFile(lock_pidfile=False) as _pid:
        with raising(pid.PidFileAlreadyRunningError):
            with pid.PidFile(lock_pidfile=False):
                pass
        assert os.path.exists(_pid.filename)
    assert not os.path.exists(_pid.filename)

def test_pid_already_running_custom_name():
    with pid.PidFile(lock_pidfile=False, pidname="testpidfile") as _pid:
        with raising(pid.PidFileAlreadyRunningError):
            with pid.PidFile(lock_pidfile=False, pidname="testpidfile"):
                pass
        assert os.path.exists(_pid.filename)
    assert not os.path.exists(_pid.filename)

def test_pid_decorator():
    from pid.decorator import pidfile

    @pidfile()
    def test_decorator():
        pass

    test_decorator()

def test_pid_decorator_already_locked():
    from pid.decorator import pidfile

    @pidfile("testpiddecorator")
    def test_decorator():
        with raising(pid.PidFileAlreadyLockedError):
            @pidfile("testpiddecorator")
            def test_decorator2():
                pass
            test_decorator2()

    test_decorator()

def test_pid_already_closed():
    pidfile = pid.PidFile()
    pidfile.create()
    try:
        pidfile.fh.close()
    finally:
        pidfile.close()
    assert not os.path.exists(pidfile.filename)

def test_pid_multiplecreate():
    pidfile = pid.PidFile()
    pidfile.create()
    try:
        with raising(pid.PidFileAlreadyRunningError, pid.PidFileAlreadyLockedError):
            pidfile.create()
    finally:
        pidfile.close()
    assert not os.path.exists(pidfile.filename)

def test_pid_gid():
    gid = os.getgid()
    with pid.PidFile(gid=gid) as pidfile:
        pass
    assert not os.path.exists(pidfile.filename)

def test_pid_check_const_empty():
    pidfile = pid.PidFile()
    pidfile.setup()
    try:
        with open(pidfile.filename, "w") as f:
            f.write("\n")
        assert pidfile.check() == pid.PID_CHECK_EMPTY
    finally:
        pidfile.close(cleanup=True)
    assert not os.path.exists(pidfile.filename)

def test_pid_check_const_nofile():
    pidfile = pid.PidFile()
    assert pidfile.check() == pid.PID_CHECK_NOFILE

def test_pid_check_const_samepid():
    with pid.PidFile(allow_samepid=True) as pidfile:
        assert pidfile.check() == pid.PID_CHECK_SAMEPID
    assert not os.path.exists(pidfile.filename)

def test_pid_check_const_notrunning():
    with pid.PidFile() as pidfile:
        with open(pidfile.filename, "w") as f:
            # hope this does not clash
            f.write("999999999\n")
        assert pidfile.check() == pid.PID_CHECK_NOTRUNNING
    assert not os.path.exists(pidfile.filename)

def test_pid_check_already_running():
    with pid.PidFile() as pidfile:
        pidfile2 = pid.PidFile()
        with raising(pid.PidFileAlreadyRunningError):
            pidfile2.check()
    assert not os.path.exists(pidfile.filename)

def test_pid_check_samepid_with_blocks():
    with pid.PidFile(allow_samepid=True):
        with pid.PidFile(allow_samepid=True):
            pass

    pidfile = pid.PidFile(allow_samepid=True)
    with pidfile:
        with pidfile:
            pass

    assert not os.path.exists(pidfile.filename)

def test_pid_check_samepid():
    pidfile = pid.PidFile(allow_samepid=True)

    try:
        pidfile.create()
        pidfile.create()
    finally:
        pidfile.close()

    assert not os.path.exists(pidfile.filename)

@patch("os.getpid")
@patch("os.kill")
def test_pid_raises_already_running_when_samepid_and_two_different_pids(mock_getpid, mock_kill):
    pidfile_proc1 = pid.PidFile()
    pidfile_proc2 = pid.PidFile(allow_samepid=True)

    try:
        mock_getpid.return_value = 1
        pidfile_proc1.create()

        mock_getpid.return_value = 2
        with raising(pid.PidFileAlreadyRunningError):
            pidfile_proc2.create()

    finally:
        pidfile_proc1.close()
        pidfile_proc2.close()

    assert not os.path.exists(pidfile_proc1.filename)
    assert not os.path.exists(pidfile_proc2.filename)

def test_pid_default_term_signal():
    signal.signal(signal.SIGTERM, signal.SIG_DFL)

    with pid.PidFile() as pidfile:
        assert callable(signal.getsignal(signal.SIGTERM)) is True

    assert not os.path.exists(pidfile.filename)

def test_pid_ignore_term_signal():
    signal.signal(signal.SIGTERM, signal.SIG_IGN)

    with pid.PidFile() as pidfile:
        assert signal.getsignal(signal.SIGTERM) == signal.SIG_IGN

    assert not os.path.exists(pidfile.filename)

def test_pid_custom_term_signal():
    def _noop(*args, **kwargs):
        pass

    signal.signal(signal.SIGTERM, _noop)

    with pid.PidFile() as pidfile:
        assert signal.getsignal(signal.SIGTERM) == _noop

    assert not os.path.exists(pidfile.filename)

# def test_pid_unknown_term_signal():
#     # Not sure how to properly test this when signal.getsignal returns None
#     #  - perhaps by writing a C extension which might get ugly
#     #
#     with pid.PidFile():
#         assert signal.getsignal(signal.SIGTERM) == None

def test_double_close_race_condition():
    # https://github.com/trbs/pid/issues/22
    pidfile1 = pid.PidFile()
    pidfile2 = pid.PidFile()

    try:
        pidfile1.create()
        assert os.path.exists(pidfile1.filename)
    finally:
        pidfile1.close()
        assert not os.path.exists(pidfile1.filename)

    try:
        pidfile2.create()
        assert os.path.exists(pidfile2.filename)

        # simulate calling atexit in process of pidfile1
        pidfile1.close()

        assert os.path.exists(pidfile2.filename)
    finally:
        pidfile2.close()

    assert not os.path.exists(pidfile1.filename)
    assert not os.path.exists(pidfile2.filename)

@pytest.mark.skipif(sys.version_info < (3, 5), reason="requires python3.5 or higher")
@patch('atexit.register', autospec=True)
def test_register_atexit_false(mock_atexit_register):
    with pid.PidFile(register_atexit=False):
        mock_atexit_register.assert_not_called()

@patch('atexit.register', autospec=True)
def test_register_atexit_true(mock_atexit_register):
    with pid.PidFile(register_atexit=True) as pidfile:
        mock_atexit_register.assert_called_once_with(pidfile.close)
<|endoftext|>


<commit_before>'Test of special function unit'

import numpy as np

from videocore.assembler import qpu
from videocore.driver import Driver

@qpu
def sfu(asm):
    setup_dma_load(nrows=1)
    start_dma_load(uniform)
    wait_dma_load()
    setup_vpm_read(nrows=1)
    setup_vpm_write()

    mov(r0, vpm)
    for unit in [sfu_recip, sfu_recipsqrt, sfu_exp2, sfu_log2]:
        mov(unit, r0)
        nop()
        nop()
        mov(vpm, r4)

    setup_dma_store(nrows=4)
    start_dma_store(uniform)
    wait_dma_store()
    exit()

def test_sfu():
    with Driver() as drv:
        X = np.random.uniform(0, 1, 16).astype('float32')
        X = drv.copy(X)
        Y = drv.alloc((4, 16), dtype='float32')
        drv.execute(
                num_threads=1,
                program=drv.program(sfu),
                uniforms=[X.address, Y.address]
                )

        assert np.allclose(1/X, Y[0], rtol=1e-3)
        assert np.allclose(1/np.sqrt(X), Y[1], rtol=1e-3)
        assert np.allclose(np.exp2(X), Y[2], rtol=1e-3)
        assert np.allclose(np.log2(X), Y[3], rtol=1e-3)
<commit_msg>Add tests.<commit_after>'Test of special function unit'

import numpy as np

from videocore.assembler import qpu
from videocore.driver import Driver

@qpu
def boilerplate(asm, f, nout):
    setup_dma_load(nrows=1)
    start_dma_load(uniform)
    wait_dma_load()
    setup_vpm_read(nrows=1)
    setup_vpm_write()

    f(asm)

    setup_dma_store(nrows=nout)
    start_dma_store(uniform)
    wait_dma_store()
    exit()

def run_code(code, X, nout):
    with Driver() as drv:
        X = drv.copy(X)
        Y = drv.alloc((nout, 16), dtype='float32')
        drv.execute(
                num_threads=1,
                program=drv.program(boilerplate, code, nout),
                uniforms=[X.address, Y.address]
                )
        return np.copy(Y)

@qpu
def sfu(asm):
    mov(r0, vpm)
    for unit in [sfu_recip, sfu_recipsqrt, sfu_exp2, sfu_log2]:
        mov(unit, r0)
        nop()
        nop()
        mov(vpm, r4)

def test_sfu():
    X = np.random.uniform(0, 1, 16).astype('float32')
    Y = run_code(sfu, X, 4)
    assert np.allclose(1/X, Y[0], rtol=1e-4)
    assert np.allclose(1/np.sqrt(X), Y[1], rtol=1e-4)
    assert np.allclose(np.exp2(X), Y[2], rtol=1e-4)
    assert np.allclose(np.log2(X), Y[3], rtol=1e-2)

@qpu
def zero_division(asm):
    mov(r0, vpm)
    for unit in [sfu_recip, sfu_recipsqrt]:
        mov(unit, r0)
        nop()
        nop()
        mov(vpm, r4)

def test_zero_division():
    X = np.zeros(16).astype('float32')
    Y = run_code(zero_division, X, 2)
    assert np.all(np.isinf(Y[0]))
    assert np.all(np.isinf(Y[1]))

@qpu
def sqrt_of_negative(asm):
    mov(sfu_recipsqrt, vpm)
    nop()
    nop()
    mov(vpm, r4)

def test_sqrt_of_negative():
    X = np.random.uniform(-1, 0, 16).astype('float32')
    Y = run_code(sqrt_of_negative, X, 1)
    assert np.allclose(1/np.sqrt(np.abs(X)), Y[0], rtol=1e-4)

@qpu
def log_of_negative(asm):
    mov(sfu_log2, vpm)
    nop()
    nop()
    mov(vpm, r4)

def test_log_of_negative():
    X = np.random.uniform(-1, 0, 16).astype('float32')
    Y = run_code(log_of_negative, X, 1)
    assert np.allclose(np.log2(np.abs(X)), Y[0], rtol=1e-2)
<|endoftext|>


<commit_before>"""
<Program>
  initialize.py

<Date Started>
  July 5th, 2014

<Author>
  Chintan Choksi

<Purpose>
  This script does a git check-out of all the dependent repositories
  to the current directory.

<Usage>
  * Clone the repository you would like to build on your machine, e.g. using
      ``git clone https://github.com/SeattleTestbed/seash''
  * Change into the ``scripts'' subdirectory
  * Run this script:
      ``python initialize.py''
  * The dependencies will be checked out into the current directory.

"""

import subprocess
import os
import sys

config_file = open("config_initialize.txt")

for line in config_file.readlines():
  # Ignore comments and blank lines
  if line.startswith("#") or line.strip == '':
    continue

  # If we end up here, the line contains a Git URL (+options?) for us to clone
  print "Checking out repo from", line.split()[0], "..."
  git_process = subprocess.Popen("git clone " + line, cwd = os.getcwd(), shell = True,
     stdout = subprocess.PIPE, stderr = subprocess.PIPE )
  (stdout_data, stderr_data) = git_process.communicate()

  # Git prints all status messages to stderr (!). We check its retval
  # to see if it performed correctly, and halt the program (giving debug
  # output) if not.
  if git_process.returncode == 0:
     print "Done!"
  else:
    print "*** Error checking out repo. Git returned status code", git_process.returncode
    print "*** Git messages on stdout: '" + stdout_data + "'."
    print "*** Git messages on stderr: '" + stderr_data + "'."
    print
    print """These errors need to be fixed before the build process can proceed. In
doubt, please contact the Seattle development team at

   seattle-devel@googlegroups.com

and supply all of the above information. Thank you!

"""
    sys.exit(1)

# If there is a readme file, show it to the user.
try:
  readme_file = open('readme.txt', 'r')
  for line in readme_file.readlines():
    print line
  readme_file.close()
except IOError:
  # There is no readme file, or we can't access it.
  pass

<commit_msg>Change "readme.txt" ref to use upper-case file name<commit_after>"""
<Program>
  initialize.py

<Date Started>
  July 5th, 2014

<Author>
  Chintan Choksi

<Purpose>
  This script does a git check-out of all the dependent repositories
  to the current directory.

<Usage>
  * Clone the repository you would like to build on your machine, e.g. using
      ``git clone https://github.com/SeattleTestbed/seash''
  * Change into the ``scripts'' subdirectory
  * Run this script:
      ``python initialize.py''
  * The dependencies will be checked out into the current directory.

"""

import subprocess
import os
import sys

config_file = open("config_initialize.txt")

for line in config_file.readlines():
  # Ignore comments and blank lines
  if line.startswith("#") or line.strip == '':
    continue

  # If we end up here, the line contains a Git URL (+options?) for us to clone
  print "Checking out repo from", line.split()[0], "..."
  git_process = subprocess.Popen("git clone " + line, cwd = os.getcwd(), shell = True,
     stdout = subprocess.PIPE, stderr = subprocess.PIPE )
  (stdout_data, stderr_data) = git_process.communicate()

  # Git prints all status messages to stderr (!). We check its retval
  # to see if it performed correctly, and halt the program (giving debug
  # output) if not.
  if git_process.returncode == 0:
     print "Done!"
  else:
    print "*** Error checking out repo. Git returned status code", git_process.returncode
    print "*** Git messages on stdout: '" + stdout_data + "'."
    print "*** Git messages on stderr: '" + stderr_data + "'."
    print
    print """These errors need to be fixed before the build process can proceed. In
doubt, please contact the Seattle development team at

   seattle-devel@googlegroups.com

and supply all of the above information. Thank you!

"""
    sys.exit(1)

# If there is a readme file, show it to the user.
try:
  readme_file = open('README.txt', 'r')
  for line in readme_file.readlines():
    print line
  readme_file.close()
except IOError:
  # There is no readme file, or we can't access it.
  pass

<|endoftext|>


<commit_before>import networkx
from pyscipopt import Model, Conshdlr, quicksum,  \
  SCIP_RESULT, SCIP_PRESOLTIMING, SCIP_PROPTIMING

class TSPconshdlr(Conshdlr):

  def findSubtours(self, checkonly, solution):
    edges = []
    x = self.model.data
    for (i,j) in x:
      if self.model.getSolVal(solution, x[i,j]) > 1.e-6:
        edges.append((i,j))

    G = networkx.Graph()
    G.add_edges_from(edges)
    Components = list(networkx.connected_components(G))

    if len(Components) == 1:
      return False
    elif checkonly:
      return True

    for S in Components:
      self.model.addCons(quicksum(x[i,j]
        for i in S for j in S if j > i) <= len(S) - 1)
      print("cut: len(%s) <= %s" % (S, len(S) - 1))

    return True

  def conscheck(self, constraints, solution, checkintegrality,
                checklprows, printreason):
    if self.findSubtours(checkonly = True, solution = solution):
      return {"result": SCIP_RESULT.INFEASIBLE}
    else:
      return {"result": SCIP_RESULT.FEASIBLE}

  def consenfolp(self, constraints, nusefulconss, solinfeasible):
    if self.findSubtours(checkonly = False, solution = None):
      return {"result": SCIP_RESULT.CONSADDED}
    else:
      return {"result": SCIP_RESULT.FEASIBLE}

  def conslock(self, constraint, nlockspos, nlocksneg):
    pass

def create_tsp(V,c):
  model = Model("TSP")

  x = {}
  for i in V:
    for j in V:
      if j > i:
        x[i,j] = model.addVar(vtype = "B",name = "x(%s,%s)" % (i,j))

  for i in V:
    model.addCons(
      quicksum(x[j,i] for j in V if j < i) +
      quicksum(x[i,j] for j in V if j > i) == 2, "Degree(%s)" % i)

  model.setObjective(
    quicksum(c[i,j] * x[i,j] for i in V for j in V if j > i),
    "minimize")

  model.data = x
  return model

def solve_tsp(V,c):
  model = create_tsp(V,c)
  conshdlr = TSPconshdlr()
  model.includeConshdlr(conshdlr, "TSP", "TSP subtour eliminator",
    sepapriority = 0, enfopriority = -1, chckpriority = -1,
    sepafreq = -1, propfreq = -1, eagerfreq = -1, maxprerounds = 0,
    delaysepa = False, delayprop = False, needscons = False,
    presoltiming = SCIP_PRESOLTIMING.FAST,
    proptiming = SCIP_PROPTIMING.BEFORELP)
  model.setBoolParam("misc/allowdualreds", 0)
  model.optimize()
  x = model.data
  edges = []
  for (i,j) in x:
    if model.getVal(x[i,j]) > 1.e-6:
      edges.append((i,j))
  return model.getObjVal(), edges

def test_main():
  V = [1, 2, 3, 4, 5, 6]
  c = {(u,v):1 for u in V for v in V if u < v}
  for u in [1, 2, 3]:
    for v in [4, 5, 6]:
      c[u,v] = 10

  obj, edges = solve_tsp(V, c)

  print("Optimal tour:", edges)
  print("Optimal cost:", obj)

if __name__ == "__main__":
  test_main()
<commit_msg>test_tsp: use default values in conshdlr<commit_after>import networkx
from pyscipopt import Model, Conshdlr, quicksum,  \
  SCIP_RESULT, SCIP_PRESOLTIMING, SCIP_PROPTIMING

class TSPconshdlr(Conshdlr):

  def findSubtours(self, checkonly, solution):
    edges = []
    x = self.model.data
    for (i,j) in x:
      if self.model.getSolVal(solution, x[i,j]) > 1.e-6:
        edges.append((i,j))

    G = networkx.Graph()
    G.add_edges_from(edges)
    Components = list(networkx.connected_components(G))

    if len(Components) == 1:
      return False
    elif checkonly:
      return True

    for S in Components:
      self.model.addCons(quicksum(x[i,j]
        for i in S for j in S if j > i) <= len(S) - 1)
      print("cut: len(%s) <= %s" % (S, len(S) - 1))

    return True

  def conscheck(self, constraints, solution, checkintegrality,
                checklprows, printreason):
    if self.findSubtours(checkonly = True, solution = solution):
      return {"result": SCIP_RESULT.INFEASIBLE}
    else:
      return {"result": SCIP_RESULT.FEASIBLE}

  def consenfolp(self, constraints, nusefulconss, solinfeasible):
    if self.findSubtours(checkonly = False, solution = None):
      return {"result": SCIP_RESULT.CONSADDED}
    else:
      return {"result": SCIP_RESULT.FEASIBLE}

  def conslock(self, constraint, nlockspos, nlocksneg):
    pass

def create_tsp(V,c):
  model = Model("TSP")

  x = {}
  for i in V:
    for j in V:
      if j > i:
        x[i,j] = model.addVar(vtype = "B",name = "x(%s,%s)" % (i,j))

  for i in V:
    model.addCons(
      quicksum(x[j,i] for j in V if j < i) +
      quicksum(x[i,j] for j in V if j > i) == 2, "Degree(%s)" % i)

  model.setObjective(
    quicksum(c[i,j] * x[i,j] for i in V for j in V if j > i),
    "minimize")

  model.data = x
  return model

def solve_tsp(V,c):
  model = create_tsp(V,c)
  conshdlr = TSPconshdlr()
  model.includeConshdlr(conshdlr, "TSP", "TSP subtour eliminator",
                        needscons=False)
  model.setBoolParam("misc/allowdualreds", False)
  model.optimize()
  x = model.data
  edges = []
  for (i,j) in x:
    if model.getVal(x[i,j]) > 1.e-6:
      edges.append((i,j))
  return model.getObjVal(), edges

def test_main():
  V = [1, 2, 3, 4, 5, 6]
  c = {(u,v):1 for u in V for v in V if u < v}
  for u in [1, 2, 3]:
    for v in [4, 5, 6]:
      c[u,v] = 10

  obj, edges = solve_tsp(V, c)

  print("Optimal tour:", edges)
  print("Optimal cost:", obj)

if __name__ == "__main__":
  test_main()
<|endoftext|>