<commit_before>#!/usr/bin/env python3
# Copyright (c) 2019-2020 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.

from test_framework.test_framework import SyscoinTestFramework
from test_framework.util import assert_equal, assert_raises_rpc_error
from test_framework.messages import COIN

class AssetNotaryTest(SyscoinTestFramework):
    def set_test_params(self):
        self.setup_clean_chain = True
        self.num_nodes = 5
        self.rpc_timeout = 240
        self.extra_args = [['-assetindex=1'],['-assetindex=1'],['-assetindex=1'],['-assetindex=1'],['-assetindex=1']]

    def run_test(self):
        self.nodes[0].generate(200)
        self.basic_notary()
        self.complex_notary()

    def basic_notary(self):
        self.basic_asset()
        self.nodes[0].assetsend(self.asset, self.nodes[0].getnewaddress(), 2)
        self.nodes[0].generate(1)
        # will give back hex because notarization doesn't happen in assetallocationsend
        hextx = self.nodes[0].assetallocationsend(self.asset, self.nodes[0].getnewaddress(), 0.4)['hex']
        notarysig = self.nodes[0].signhash(self.notary_address, self.nodes[0].getnotarysighash(hextx, self.asset))
        hextx_notarized = self.nodes[0].assettransactionnotarize(hextx, self.asset, notarysig)['hex']
        tx_resigned = self.nodes[0].signrawtransactionwithwallet(hextx_notarized)['hex']
        assert_equal(len(hextx), len(hextx_notarized))
        assert(hextx != hextx_notarized)
        assert(tx_resigned != hextx_notarized)
         # cannot send without notarization
        assert_raises_rpc_error(-26, 'assetallocation-notary-sig', self.nodes[0].sendrawtransaction, hextx)
        assert_raises_rpc_error(-26, 'non-mandatory-script-verify-flag', self.nodes[0].sendrawtransaction, hextx_notarized)
        self.nodes[0].sendrawtransaction(tx_resigned)
        self.nodes[0].generate(1)

    def basic_asset(self):
        self.notary_address = self.nodes[0].getnewaddress()
        notary = {'e': 'https://jsonplaceholder.typicode.com/posts/', 'it': True, 'rx': True}
        self.asset = self.nodes[0].assetnew('1', 'TST', 'asset description', '0x', 8, 1000, 10000, 31, self.notary_address, notary, {})['asset_guid']
        self.sync_mempools()
        self.nodes[0].generate(1)
        self.sync_blocks()
        assetInfo = self.nodes[0].assetinfo(self.asset)
        assert_equal(assetInfo['asset_guid'], self.asset)
        assetInfo = self.nodes[1].assetinfo(self.asset)
        assert_equal(assetInfo['asset_guid'], self.asset)

    def complex_notary(self):
        notary = {'e': 'https://jsonplaceholder.typicode.com/posts/', 'it': True, 'rx': True}
        self.notary_address0 = self.nodes[0].getnewaddress()
        self.notary_address1 = self.nodes[1].getnewaddress()
        self.notary_address2 = self.nodes[2].getnewaddress()
        self.notary_address3 = self.nodes[3].getnewaddress()
        self.notary_address4 = self.nodes[4].getnewaddress()
        self.asset0 = self.nodes[0].assetnew('1', 'TST0', 'asset description', '0x', 8, 1000, 10000, 31, self.notary_address0, notary, {})['asset_guid']
        self.asset1 = self.nodes[0].assetnew('1', 'TST1', 'asset description', '0x', 8, 1000, 10000, 31, self.notary_address1, notary, {})['asset_guid']
        self.asset2 = self.nodes[0].assetnew('1', 'TST2', 'asset description', '0x', 8, 1000, 10000, 31, self.notary_address2, notary, {})['asset_guid']
        self.asset3 = self.nodes[0].assetnew('1', 'TST3', 'asset description', '0x', 8, 1000, 10000, 31, self.notary_address3, notary, {})['asset_guid']
        self.asset4 = self.nodes[0].assetnew('1', 'TST4', 'asset description', '0x', 8, 1000, 10000, 31, self.notary_address4, notary, {})['asset_guid']
        self.asset5 = self.nodes[0].assetnew('1', 'TST4', 'asset description', '0x', 8, 1000, 10000, 31, '', {}, {})['asset_guid']
        self.nodes[0].generate(1)
        self.nodes[0].assetsend(self.asset0, self.nodes[0].getnewaddress(), 1)
        self.nodes[0].assetsend(self.asset1, self.nodes[0].getnewaddress(), 2)
        self.nodes[0].assetsend(self.asset2, self.nodes[0].getnewaddress(), 3)
        self.nodes[0].assetsend(self.asset3, self.nodes[0].getnewaddress(), 4)
        self.nodes[0].assetsend(self.asset4, self.nodes[0].getnewaddress(), 5)
        self.nodes[0].assetsend(self.asset5, self.nodes[0].getnewaddress(), 6)
        self.nodes[0].generate(1)
        sendobj = [{"asset_guid":self.asset0,"address":self.nodes[1].getnewaddress(),"amount":0.5},{"asset_guid":self.asset0,"address":self.nodes[1].getnewaddress(),"amount":0.5},{"asset_guid":self.asset1,"address":self.nodes[1].getnewaddress(),"amount":2},{"asset_guid":self.asset2,"address":self.nodes[1].getnewaddress(),"amount":2.5},{"asset_guid":self.asset3,"address":self.nodes[1].getnewaddress(),"amount":3},{"asset_guid":self.asset4,"address":self.nodes[1].getnewaddress(),"amount":3.5},{"asset_guid":self.asset5,"address":self.nodes[1].getnewaddress(),"amount":5}]
        hextx = self.nodes[0].assetallocationsendmany(sendobj)['hex']
        notarysig0 = self.nodes[0].signhash(self.notary_address0, self.nodes[0].getnotarysighash(hextx, self.asset0))
        notarysig1 = self.nodes[1].signhash(self.notary_address1, self.nodes[0].getnotarysighash(hextx, self.asset1))
        notarysig2 = self.nodes[2].signhash(self.notary_address2, self.nodes[0].getnotarysighash(hextx, self.asset2))
        notarysig3 = self.nodes[3].signhash(self.notary_address3, self.nodes[0].getnotarysighash(hextx, self.asset3))
        notarysig4 = self.nodes[4].signhash(self.notary_address4, self.nodes[0].getnotarysighash(hextx, self.asset4))
        hextx_notarized = self.nodes[0].assettransactionnotarize(hextx, self.asset0, notarysig0)['hex']
        hextx_notarized = self.nodes[0].assettransactionnotarize(hextx_notarized, self.asset1, notarysig1)['hex']
        hextx_notarized = self.nodes[0].assettransactionnotarize(hextx_notarized, self.asset2, notarysig2)['hex']
        hextx_notarized = self.nodes[0].assettransactionnotarize(hextx_notarized, self.asset3, notarysig3)['hex']
        # try without final signature
        tx_resigned = self.nodes[0].signrawtransactionwithwallet(hextx_notarized)['hex']
        assert_raises_rpc_error(-26, 'assetallocation-notary-sig', self.nodes[0].sendrawtransaction, tx_resigned)
        # try with wrong signature
        hextx_notarized = self.nodes[0].assettransactionnotarize(hextx_notarized, self.asset4, notarysig3)['hex']
        assert_raises_rpc_error(-26, 'assetallocation-notary-sig', self.nodes[0].sendrawtransaction, tx_resigned)
        hextx_notarized = self.nodes[0].assettransactionnotarize(hextx_notarized, self.asset4, notarysig4)['hex']
        tx_resigned = self.nodes[0].signrawtransactionwithwallet(hextx_notarized)['hex']
        assert_equal(len(hextx), len(hextx_notarized))
        assert(hextx != hextx_notarized)
        assert(tx_resigned != hextx_notarized)

        self.nodes[0].sendrawtransaction(tx_resigned)
        self.nodes[0].generate(1)
        self.sync_blocks()
        # check change on sender node
        out =  self.nodes[0].listunspent(query_options={'assetGuid': self.asset0})
        assert_equal(len(out), 1)
        assert_equal(out[0]['asset_guid'], self.asset0)
        assert_equal(out[0]['asset_amount'], 0)
        out =  self.nodes[0].listunspent(query_options={'assetGuid': self.asset1})
        assert_equal(len(out), 1)
        assert_equal(out[0]['asset_guid'], self.asset1)
        assert_equal(out[0]['asset_amount'], 0)
        out =  self.nodes[0].listunspent(query_options={'assetGuid': self.asset2})
        assert_equal(len(out), 2)
        assert(out[0]['asset_amount'] is int(0.5*COIN) or out[1]['asset_amount'] is int(0.5*COIN))
        out =  self.nodes[0].listunspent(query_options={'assetGuid': self.asset3})
        assert_equal(len(out), 2)
        assert(out[0]['asset_amount'] is int(1*COIN) or out[1]['asset_amount'] is int(1*COIN))
        out =  self.nodes[0].listunspent(query_options={'assetGuid': self.asset4})
        assert_equal(len(out), 2)
        assert(out[0]['asset_amount'] is int(1.5*COIN) or out[1]['asset_amount'] is int(1.5*COIN))
        out =  self.nodes[0].listunspent(query_options={'assetGuid': self.asset5})
        assert_equal(len(out), 2)
        assert(out[0]['asset_amount'] is int(1*COIN) or out[1]['asset_amount'] is int(1*COIN))
        # check receiver node
        out =  self.nodes[1].listunspent(query_options={'assetGuid': self.asset0})
        assert_equal(len(out), 1)
        assert_equal(out[0]['asset_guid'], self.asset0)
        assert_equal(out[0]['asset_amount'], int(1*COIN))
        out =  self.nodes[1].listunspent(query_options={'assetGuid': self.asset1})
        assert_equal(len(out), 1)
        assert_equal(out[0]['asset_guid'], self.asset1)
        assert_equal(out[0]['asset_amount'], int(2*COIN))
        out =  self.nodes[1].listunspent(query_options={'assetGuid': self.asset2})
        assert_equal(len(out), 1)
        assert_equal(out[0]['asset_guid'], self.asset2)
        assert_equal(out[0]['asset_amount'], int(2.5*COIN))
        out =  self.nodes[1].listunspent(query_options={'assetGuid': self.asset3})
        assert_equal(len(out), 1)
        assert_equal(out[0]['asset_guid'], self.asset3)
        assert_equal(out[0]['asset_amount'], int(3*COIN))
        out =  self.nodes[1].listunspent(query_options={'assetGuid': self.asset4})
        assert_equal(len(out), 1)
        assert_equal(out[0]['asset_guid'], self.asset4)
        assert_equal(out[0]['asset_amount'], int(3.5*COIN))
        out =  self.nodes[1].listunspent(query_options={'assetGuid': self.asset5})
        assert_equal(len(out), 1)
        assert_equal(out[0]['asset_guid'], self.asset5)
        assert_equal(out[0]['asset_amount'], int(5*COIN))
if __name__ == '__main__':
    AssetNotaryTest().main()
<commit_msg>fix test<commit_after>#!/usr/bin/env python3
# Copyright (c) 2019-2020 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.

from test_framework.test_framework import SyscoinTestFramework
from test_framework.util import assert_equal, assert_raises_rpc_error
from test_framework.messages import COIN

class AssetNotaryTest(SyscoinTestFramework):
    def set_test_params(self):
        self.setup_clean_chain = True
        self.num_nodes = 5
        self.rpc_timeout = 240
        self.extra_args = [['-assetindex=1'],['-assetindex=1'],['-assetindex=1'],['-assetindex=1'],['-assetindex=1']]

    def run_test(self):
        self.nodes[0].generate(200)
        self.basic_notary()
        self.complex_notary()

    def basic_notary(self):
        self.basic_asset()
        self.nodes[0].assetsend(self.asset, self.nodes[0].getnewaddress(), 2)
        self.nodes[0].generate(1)
        # will give back hex because notarization doesn't happen in assetallocationsend
        hextx = self.nodes[0].assetallocationsend(self.asset, self.nodes[0].getnewaddress(), 0.4)['hex']
        notarysig = self.nodes[0].signhash(self.notary_address, self.nodes[0].getnotarysighash(hextx, self.asset))
        hextx_notarized = self.nodes[0].assettransactionnotarize(hextx, self.asset, notarysig)['hex']
        tx_resigned = self.nodes[0].signrawtransactionwithwallet(hextx_notarized)['hex']
        assert_equal(len(hextx), len(hextx_notarized))
        assert(hextx != hextx_notarized)
        assert(tx_resigned != hextx_notarized)
         # cannot send without notarization
        assert_raises_rpc_error(-26, 'assetallocation-notary-sig', self.nodes[0].sendrawtransaction, hextx)
        assert_raises_rpc_error(-26, 'non-mandatory-script-verify-flag', self.nodes[0].sendrawtransaction, hextx_notarized)
        self.nodes[0].sendrawtransaction(tx_resigned)
        self.nodes[0].generate(1)

    def basic_asset(self):
        self.notary_address = self.nodes[0].getnewaddress()
        notary = {'e': 'https://jsonplaceholder.typicode.com/posts/', 'it': True, 'rx': True}
        self.asset = self.nodes[0].assetnew('1', 'TST', 'asset description', '0x', 8, 1000, 10000, 31, self.notary_address, notary, {})['asset_guid']
        self.sync_mempools()
        self.nodes[0].generate(1)
        self.sync_blocks()
        assetInfo = self.nodes[0].assetinfo(self.asset)
        assert_equal(assetInfo['asset_guid'], self.asset)
        assetInfo = self.nodes[1].assetinfo(self.asset)
        assert_equal(assetInfo['asset_guid'], self.asset)

    def complex_notary(self):
        notary = {'e': 'https://jsonplaceholder.typicode.com/posts/', 'it': True, 'rx': True}
        self.notary_address0 = self.nodes[0].getnewaddress()
        self.notary_address1 = self.nodes[1].getnewaddress()
        self.notary_address2 = self.nodes[2].getnewaddress()
        self.notary_address3 = self.nodes[3].getnewaddress()
        self.notary_address4 = self.nodes[4].getnewaddress()
        self.asset0 = self.nodes[0].assetnew('1', 'TST0', 'asset description', '0x', 8, 1000, 10000, 31, self.notary_address0, notary, {})['asset_guid']
        self.asset1 = self.nodes[0].assetnew('1', 'TST1', 'asset description', '0x', 8, 1000, 10000, 31, self.notary_address1, notary, {})['asset_guid']
        self.asset2 = self.nodes[0].assetnew('1', 'TST2', 'asset description', '0x', 8, 1000, 10000, 31, self.notary_address2, notary, {})['asset_guid']
        self.asset3 = self.nodes[0].assetnew('1', 'TST3', 'asset description', '0x', 8, 1000, 10000, 31, self.notary_address3, notary, {})['asset_guid']
        self.asset4 = self.nodes[0].assetnew('1', 'TST4', 'asset description', '0x', 8, 1000, 10000, 31, self.notary_address4, notary, {})['asset_guid']
        self.asset5 = self.nodes[0].assetnew('1', 'TST4', 'asset description', '0x', 8, 1000, 10000, 31, '', {}, {})['asset_guid']
        self.nodes[0].generate(1)
        self.nodes[0].assetsend(self.asset0, self.nodes[0].getnewaddress(), 1)
        self.nodes[0].assetsend(self.asset1, self.nodes[0].getnewaddress(), 2)
        self.nodes[0].assetsend(self.asset2, self.nodes[0].getnewaddress(), 3)
        self.nodes[0].assetsend(self.asset3, self.nodes[0].getnewaddress(), 4)
        self.nodes[0].assetsend(self.asset4, self.nodes[0].getnewaddress(), 5)
        self.nodes[0].assetsend(self.asset5, self.nodes[0].getnewaddress(), 6)
        self.nodes[0].generate(1)
        sendobj = [{"asset_guid":self.asset0,"address":self.nodes[1].getnewaddress(),"amount":0.5},{"asset_guid":self.asset0,"address":self.nodes[1].getnewaddress(),"amount":0.5},{"asset_guid":self.asset1,"address":self.nodes[1].getnewaddress(),"amount":2},{"asset_guid":self.asset2,"address":self.nodes[1].getnewaddress(),"amount":2.5},{"asset_guid":self.asset3,"address":self.nodes[1].getnewaddress(),"amount":3},{"asset_guid":self.asset4,"address":self.nodes[1].getnewaddress(),"amount":3.5},{"asset_guid":self.asset5,"address":self.nodes[1].getnewaddress(),"amount":5}]
        hextx = self.nodes[0].assetallocationsendmany(sendobj)['hex']
        notarysig0 = self.nodes[0].signhash(self.notary_address0, self.nodes[0].getnotarysighash(hextx, self.asset0))
        notarysig1 = self.nodes[1].signhash(self.notary_address1, self.nodes[0].getnotarysighash(hextx, self.asset1))
        notarysig2 = self.nodes[2].signhash(self.notary_address2, self.nodes[0].getnotarysighash(hextx, self.asset2))
        notarysig3 = self.nodes[3].signhash(self.notary_address3, self.nodes[0].getnotarysighash(hextx, self.asset3))
        notarysig4 = self.nodes[4].signhash(self.notary_address4, self.nodes[0].getnotarysighash(hextx, self.asset4))
        hextx_notarized = self.nodes[0].assettransactionnotarize(hextx, self.asset0, notarysig0)['hex']
        hextx_notarized = self.nodes[0].assettransactionnotarize(hextx_notarized, self.asset1, notarysig1)['hex']
        hextx_notarized = self.nodes[0].assettransactionnotarize(hextx_notarized, self.asset2, notarysig2)['hex']
        hextx_notarized = self.nodes[0].assettransactionnotarize(hextx_notarized, self.asset3, notarysig3)['hex']
        # try without final signature
        tx_resigned = self.nodes[0].signrawtransactionwithwallet(hextx_notarized)['hex']
        assert_raises_rpc_error(-26, 'assetallocation-notary-sig', self.nodes[0].sendrawtransaction, tx_resigned)
        # try with wrong signature
        hextx_notarized = self.nodes[0].assettransactionnotarize(hextx_notarized, self.asset4, notarysig3)['hex']
        assert_raises_rpc_error(-26, 'assetallocation-notary-sig', self.nodes[0].sendrawtransaction, tx_resigned)
        hextx_notarized = self.nodes[0].assettransactionnotarize(hextx_notarized, self.asset4, notarysig4)['hex']
        tx_resigned = self.nodes[0].signrawtransactionwithwallet(hextx_notarized)['hex']
        assert_equal(len(hextx), len(hextx_notarized))
        assert(hextx != hextx_notarized)
        assert(tx_resigned != hextx_notarized)

        self.nodes[0].sendrawtransaction(tx_resigned)
        self.nodes[0].generate(1)
        self.sync_blocks()
        # check change on sender node
        out =  self.nodes[0].listunspent(query_options={'assetGuid': self.asset0})
        assert_equal(len(out), 1)
        assert_equal(out[0]['asset_guid'], self.asset0)
        assert_equal(out[0]['asset_amount'], 0)
        out =  self.nodes[0].listunspent(query_options={'assetGuid': self.asset1})
        assert_equal(len(out), 1)
        assert_equal(out[0]['asset_guid'], self.asset1)
        assert_equal(out[0]['asset_amount'], 0)
        out =  self.nodes[0].listunspent(query_options={'assetGuid': self.asset2})
        assert_equal(len(out), 2)
        assert(out[0]['asset_amount'] == int(0.5*COIN) or out[1]['asset_amount'] == int(0.5*COIN))
        out =  self.nodes[0].listunspent(query_options={'assetGuid': self.asset3})
        assert_equal(len(out), 2)
        assert(out[0]['asset_amount'] == int(1*COIN) or out[1]['asset_amount'] == int(1*COIN))
        out =  self.nodes[0].listunspent(query_options={'assetGuid': self.asset4})
        assert_equal(len(out), 2)
        assert(out[0]['asset_amount'] == int(1.5*COIN) or out[1]['asset_amount'] == int(1.5*COIN))
        out =  self.nodes[0].listunspent(query_options={'assetGuid': self.asset5})
        assert_equal(len(out), 2)
        assert(out[0]['asset_amount'] == int(1*COIN) or out[1]['asset_amount'] == int(1*COIN))
        # check receiver node
        out =  self.nodes[1].listunspent(query_options={'assetGuid': self.asset0})
        assert_equal(len(out), 1)
        assert_equal(out[0]['asset_guid'], self.asset0)
        assert_equal(out[0]['asset_amount'], int(1*COIN))
        out =  self.nodes[1].listunspent(query_options={'assetGuid': self.asset1})
        assert_equal(len(out), 1)
        assert_equal(out[0]['asset_guid'], self.asset1)
        assert_equal(out[0]['asset_amount'], int(2*COIN))
        out =  self.nodes[1].listunspent(query_options={'assetGuid': self.asset2})
        assert_equal(len(out), 1)
        assert_equal(out[0]['asset_guid'], self.asset2)
        assert_equal(out[0]['asset_amount'], int(2.5*COIN))
        out =  self.nodes[1].listunspent(query_options={'assetGuid': self.asset3})
        assert_equal(len(out), 1)
        assert_equal(out[0]['asset_guid'], self.asset3)
        assert_equal(out[0]['asset_amount'], int(3*COIN))
        out =  self.nodes[1].listunspent(query_options={'assetGuid': self.asset4})
        assert_equal(len(out), 1)
        assert_equal(out[0]['asset_guid'], self.asset4)
        assert_equal(out[0]['asset_amount'], int(3.5*COIN))
        out =  self.nodes[1].listunspent(query_options={'assetGuid': self.asset5})
        assert_equal(len(out), 1)
        assert_equal(out[0]['asset_guid'], self.asset5)
        assert_equal(out[0]['asset_amount'], int(5*COIN))
if __name__ == '__main__':
    AssetNotaryTest().main()
<|endoftext|>


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

from . import Mapping

NoneType = type(None)

class PrimitiveType:

    def bind(self, obj):
        return obj

class Array(PrimitiveType):
    __name__ = 'array'

    def __init__(self,
                 items=None, additional_items=True,
                 max_items=None, min_items=None, unique_items=False):
        assert isinstance(items, ())
        assert isinstance(additional_items, bool)
        assert isinstance(max_items, (int, NoneType))
        assert isinstance(min_items, (int, NoneType))
        assert isinstance(unique_items, bool)

        self.items = items
        self.additional_items = additional_items
        self.max_items = max_items
        self.min_items = min_items
        self.unique_items = unique_items

class Boolean(PrimitiveType):
    __name__ = 'boolean'

class Numeric(PrimitiveType):

    def __init__(self,
                 multiple_of=None, maximum=None, exclusive_maximum=False,
                 minimum=None, exclusive_minimum=False):
        assert isinstance(multiple_of, (int, NoneType))
        assert isinstance(maximum, (int, NoneType))
        assert isinstance(exclusive_maximum, bool)
        assert isinstance(minimum, (int, NoneType))
        assert isinstance(exclusive_minimum, (int, NoneType))

        self.multiple_of = multiple_of
        self.maximum = maximum
        self.exclusive_maximum = exclusive_maximum
        self.minimum = minimum
        self.exclusive_minimum = exclusive_minimum

class Integer(Numeric):
    __name__ = 'integer'

class Number(Numeric):
    __name__ = 'number'

class Null(PrimitiveType):
    __name__ = 'null'

class Object(PrimitiveType):
    __name__ = 'object'

    def __init__(self,
                 max_properties=None, min_properties=None, required=[],
                 additional_properties=True, properties={},
                 pattern_properties={}, dependencies={}):
        assert isinstance(max_properties, (int, NoneType))
        assert isinstance(min_properties, (int, NoneType))
        assert isinstance(required, list)
        assert isinstance(additional_properties, bool)
        assert isinstance(properties, dict) or issubclass(properties, Mapping)
        assert isinstance(pattern_properties, dict)
        assert isinstance(dependencies, dict)

        self.max_properties = max_properties
        self.min_properties = min_properties
        self.required = required
        self.additional_properties = additional_properties
        self.properties = properties
        self.pattern_properties = pattern_properties
        self.dependencies = dependencies

    def bind(self, obj):
        if isinstance(self.properties, (dict, NoneType)):
            return super().bind(obj)

        return self.properties._bind(obj)

class String(PrimitiveType):
    __name__ = 'string'

    def __init__(self, max_length=None, min_length=None, pattern=None):
        assert isinstance(max_length, (int, NoneType))
        assert isinstance(min_length, (int, NoneType))
        assert isinstance(pattern, (str, NoneType))

        self.max_length = max_length
        self.min_length = min_length
        self.pattern = pattern
<commit_msg>fix condition<commit_after># -*- coding: utf-8 -*-

from . import Mapping

NoneType = type(None)

class PrimitiveType:

    def bind(self, obj):
        return obj

class Array(PrimitiveType):
    __name__ = 'array'

    def __init__(self,
                 items=None, additional_items=True,
                 max_items=None, min_items=None, unique_items=False):
        assert isinstance(items, (list, NoneType))
        assert isinstance(additional_items, bool)
        assert isinstance(max_items, (int, NoneType))
        assert isinstance(min_items, (int, NoneType))
        assert isinstance(unique_items, bool)

        self.items = items
        self.additional_items = additional_items
        self.max_items = max_items
        self.min_items = min_items
        self.unique_items = unique_items

class Boolean(PrimitiveType):
    __name__ = 'boolean'

class Numeric(PrimitiveType):

    def __init__(self,
                 multiple_of=None, maximum=None, exclusive_maximum=False,
                 minimum=None, exclusive_minimum=False):
        assert isinstance(multiple_of, (int, NoneType))
        assert isinstance(maximum, (int, NoneType))
        assert isinstance(exclusive_maximum, bool)
        assert isinstance(minimum, (int, NoneType))
        assert isinstance(exclusive_minimum, (int, NoneType))

        self.multiple_of = multiple_of
        self.maximum = maximum
        self.exclusive_maximum = exclusive_maximum
        self.minimum = minimum
        self.exclusive_minimum = exclusive_minimum

class Integer(Numeric):
    __name__ = 'integer'

class Number(Numeric):
    __name__ = 'number'

class Null(PrimitiveType):
    __name__ = 'null'

class Object(PrimitiveType):
    __name__ = 'object'

    def __init__(self,
                 max_properties=None, min_properties=None, required=[],
                 additional_properties=True, properties={},
                 pattern_properties={}, dependencies={}):
        assert isinstance(max_properties, (int, NoneType))
        assert isinstance(min_properties, (int, NoneType))
        assert isinstance(required, list)
        assert isinstance(additional_properties, bool)
        assert isinstance(properties, dict) or issubclass(properties, Mapping)
        assert isinstance(pattern_properties, dict)
        assert isinstance(dependencies, dict)

        self.max_properties = max_properties
        self.min_properties = min_properties
        self.required = required
        self.additional_properties = additional_properties
        self.properties = properties
        self.pattern_properties = pattern_properties
        self.dependencies = dependencies

    def bind(self, obj):
        if isinstance(self.properties, (dict, NoneType)):
            return super().bind(obj)

        return self.properties._bind(obj)

class String(PrimitiveType):
    __name__ = 'string'

    def __init__(self, max_length=None, min_length=None, pattern=None):
        assert isinstance(max_length, (int, NoneType))
        assert isinstance(min_length, (int, NoneType))
        assert isinstance(pattern, (str, NoneType))

        self.max_length = max_length
        self.min_length = min_length
        self.pattern = pattern
<|endoftext|>


<commit_before>from copy import copy

import json
import six
from django.db import models
from django.core import exceptions
from django.utils.text import capfirst
from django.forms.widgets import Select
from django.forms.fields import CallableChoiceIterator

import kobo.django.forms
from kobo.types import StateEnum
from kobo.django.compat import gettext_lazy as _

'''
StateEnumField
==============

encapsulates StateEnum from kobo.types for use with django db and forms
layer.

Simply create model containing these fields and supply state engine instance
as parameter:

class MyModel(models.Model):
    state = StateEnumField(state_engine, default="NEW")

You can use such field as normal StateEnum. If model.save() is called, then
StateEnumFields will call change_state(None, True) if new state is prepared.

JSONField
=========

creates field which contains any JSON-codable object (via json.dumps). On
db level it is saved as a TextField.

There is boolean option "human_readable" which uses indent and sorting of
keys when saving to db. It is better for inspection, but can take significant
amount of space in some cases due to additional spaces and newlines. Also it
can slow down saving process, as keys are being sorted. From these reasons is
default value set to False.
'''

class StateEnumField(models.IntegerField):
    '''StateEnum DB encapsulation'''
    widget = Select

    def __init__(self, state_machine, *args, **kwargs):
        super(StateEnumField, self).__init__(*args, **kwargs)
        self.state_machine = state_machine
        self.widget = Select
        if self.has_default:
            self.state_machine.set_state(self.default)

    def _get_val_from_obj(self, obj):
        if obj:
            return getattr(obj, self.attname)
        else:
            return self.get_default()

    def from_db_value(self, value, expression, connection, context=None):
        if value is None:
            return None

        if isinstance(value, (str, six.text_type)) and not value.isdigit():
            value = self.state_machine.get_num(value)

        try:
            value = int(value)
            if value < 0:
                raise ValueError
        except (TypeError, ValueError):
            raise exceptions.ValidationError(_("This value must be a positive integer."))

        state_machine = copy(self.state_machine)
        state_machine.set_state(state_machine.get_value(value))
        return state_machine

    def to_python(self, value):
        if value is None:
            return None

        if isinstance(value, StateEnum):
            return value

        if isinstance(value, (str, six.text_type)) and not value.isdigit():
            value = self.state_machine.get_num(value)

        try:
            value = int(value)
            if value < 0:
                raise ValueError
        except (TypeError, ValueError):
            raise exceptions.ValidationError(_("This value must be a positive integer."))

        state_machine = copy(self.state_machine)
        state_machine.set_state(state_machine.get_value(value))
        return state_machine

    def _get_choices(self):
        return tuple(self.state_machine.get_next_states_mapping(current=self.state_machine.get_state_id()))

    def _set_choices(self, value):
        # Setting choices also sets the choices on the widget.
        # choices can be any iterable, but we call list() on it because
        # it will be consumed more than once.
        if callable(value):
            value = CallableChoiceIterator(value)
        elif value is not None:
            value = list(value)
        else:
            value = []

        self._choices = self.widget.choices = value

    choices = property(_get_choices, _set_choices)

    def get_db_prep_value(self, value, connection, prepared=False):
        if value is not None:
            try:
                value = self.state_machine.get_value(value)
            except:
                value = str(value._current_state)

#        self.state_machine.change_state(value, commit=False)
        if value is None:
            return None
        return self.state_machine.get_num(value)

    def get_db_prep_save(self, value, connection):
        return self.get_db_prep_value(value, connection=connection)

    def pre_save(self, instance, add):
        state = getattr(instance, self.attname)
        if state._to is not None:
            state.change_state(None, commit=True)
        return state

    def formfield(self, form_class=kobo.django.forms.StateChoiceFormField, **kwargs):
        # after fix of http://code.djangoproject.com/ticket/9245 could be
        # simplified
        defaults = {'required': not self.blank, 'label': capfirst(self.verbose_name), 'help_text': self.help_text}
        if self.has_default():
            defaults['initial'] = self.get_default()
            if callable(self.default):
                defaults['show_hidden_initial'] = True
        # Fields with choices get special treatment.
        include_blank = self.blank or not (self.has_default() or 'initial' in kwargs)
        defaults['choices'] = self.get_choices(include_blank=include_blank)
        defaults['coerce'] = self.to_python
        if self.null:
            defaults['empty_value'] = None
        # Many of the subclass-specific formfield arguments (min_value,
        # max_value) don't apply for choice fields, so be sure to only pass
        # the values that TypedChoiceField will understand.
        for k in kwargs.keys():
            if k not in ('coerce', 'empty_value', 'choices', 'required',
                         'widget', 'label', 'initial', 'help_text',
                         'error_messages'):
                del kwargs[k]
        defaults.update(kwargs)
        return form_class(**defaults)

class JSONField(models.TextField):
    """JSON field for storing a serialized dictionary or list."""

    def __init__(self, *args, **kwargs):
        self.human_readable = kwargs.pop('human_readable', False)
        return super(JSONField, self).__init__(*args, **kwargs)

    def from_db_value(self, value, expression, connection):
        if not isinstance(value, six.string_types):
            return value

        try:
            return json.loads(value)
        except ValueError:
            raise exceptions.ValidationError(_("Cannot deserialize JSON data. '%s'") % value)

    def to_python(self, value):
        if value is None:
            return None

        if not isinstance(value, six.string_types):
            return value

        try:
            return json.loads(value)
        except ValueError:
            raise exceptions.ValidationError(_("Cannot deserialize JSON data. '%s'") % value)

    def get_db_prep_value(self, value, *args, **kwargs):
        if value is None or value == "null":
            return None
        try:
            if self.human_readable:
                return json.dumps(value, indent=2, sort_keys=True)
            else:
                return json.dumps(value)
        except Exception:
            raise exceptions.ValidationError(_("Cannot serialize JSON data."))

    def value_to_string(self, obj):
        value = self._get_val_from_obj(obj)
        return self.get_db_prep_value(value)

    def value_from_object(self, obj):
        if self.human_readable:
            return json.dumps(super(JSONField, self).value_from_object(obj), indent=2, sort_keys=True)
        else:
            return json.dumps(super(JSONField, self).value_from_object(obj))

    def formfield(self, form_class=kobo.django.forms.JSONFormField, **kwargs):
        kwargs["form_class"] = form_class
        return super(JSONField, self).formfield(**kwargs)

# HACK:
import django.contrib.admin.options
django.contrib.admin.options.FORMFIELD_FOR_DBFIELD_DEFAULTS[JSONField] = {"widget": kobo.django.forms.JSONWidget}
<commit_msg>Make Django's manage.py dumpdata command work on version 2.0+<commit_after>from copy import copy

import json
import six
from django.db import models
from django.core import exceptions
from django.utils.text import capfirst
from django.forms.widgets import Select
from django.forms.fields import CallableChoiceIterator

import kobo.django.forms
from kobo.types import StateEnum
from kobo.django.compat import gettext_lazy as _
from kobo.django.django_version import django_version_ge

'''
StateEnumField
==============

encapsulates StateEnum from kobo.types for use with django db and forms
layer.

Simply create model containing these fields and supply state engine instance
as parameter:

class MyModel(models.Model):
    state = StateEnumField(state_engine, default="NEW")

You can use such field as normal StateEnum. If model.save() is called, then
StateEnumFields will call change_state(None, True) if new state is prepared.

JSONField
=========

creates field which contains any JSON-codable object (via json.dumps). On
db level it is saved as a TextField.

There is boolean option "human_readable" which uses indent and sorting of
keys when saving to db. It is better for inspection, but can take significant
amount of space in some cases due to additional spaces and newlines. Also it
can slow down saving process, as keys are being sorted. From these reasons is
default value set to False.
'''

class StateEnumField(models.IntegerField):
    '''StateEnum DB encapsulation'''
    widget = Select

    def __init__(self, state_machine, *args, **kwargs):
        super(StateEnumField, self).__init__(*args, **kwargs)
        self.state_machine = state_machine
        self.widget = Select
        if self.has_default:
            self.state_machine.set_state(self.default)

    def _get_val_from_obj(self, obj):
        if obj:
            return getattr(obj, self.attname)
        else:
            return self.get_default()

    def from_db_value(self, value, expression, connection, context=None):
        if value is None:
            return None

        if isinstance(value, (str, six.text_type)) and not value.isdigit():
            value = self.state_machine.get_num(value)

        try:
            value = int(value)
            if value < 0:
                raise ValueError
        except (TypeError, ValueError):
            raise exceptions.ValidationError(_("This value must be a positive integer."))

        state_machine = copy(self.state_machine)
        state_machine.set_state(state_machine.get_value(value))
        return state_machine

    def to_python(self, value):
        if value is None:
            return None

        if isinstance(value, StateEnum):
            return value

        if isinstance(value, (str, six.text_type)) and not value.isdigit():
            value = self.state_machine.get_num(value)

        try:
            value = int(value)
            if value < 0:
                raise ValueError
        except (TypeError, ValueError):
            raise exceptions.ValidationError(_("This value must be a positive integer."))

        state_machine = copy(self.state_machine)
        state_machine.set_state(state_machine.get_value(value))
        return state_machine

    def _get_choices(self):
        return tuple(self.state_machine.get_next_states_mapping(current=self.state_machine.get_state_id()))

    def _set_choices(self, value):
        # Setting choices also sets the choices on the widget.
        # choices can be any iterable, but we call list() on it because
        # it will be consumed more than once.
        if callable(value):
            value = CallableChoiceIterator(value)
        elif value is not None:
            value = list(value)
        else:
            value = []

        self._choices = self.widget.choices = value

    choices = property(_get_choices, _set_choices)

    def get_db_prep_value(self, value, connection, prepared=False):
        if value is not None:
            try:
                value = self.state_machine.get_value(value)
            except:
                value = str(value._current_state)

#        self.state_machine.change_state(value, commit=False)
        if value is None:
            return None
        return self.state_machine.get_num(value)

    def get_db_prep_save(self, value, connection):
        return self.get_db_prep_value(value, connection=connection)

    def pre_save(self, instance, add):
        state = getattr(instance, self.attname)
        if state._to is not None:
            state.change_state(None, commit=True)
        return state

    def formfield(self, form_class=kobo.django.forms.StateChoiceFormField, **kwargs):
        # after fix of http://code.djangoproject.com/ticket/9245 could be
        # simplified
        defaults = {'required': not self.blank, 'label': capfirst(self.verbose_name), 'help_text': self.help_text}
        if self.has_default():
            defaults['initial'] = self.get_default()
            if callable(self.default):
                defaults['show_hidden_initial'] = True
        # Fields with choices get special treatment.
        include_blank = self.blank or not (self.has_default() or 'initial' in kwargs)
        defaults['choices'] = self.get_choices(include_blank=include_blank)
        defaults['coerce'] = self.to_python
        if self.null:
            defaults['empty_value'] = None
        # Many of the subclass-specific formfield arguments (min_value,
        # max_value) don't apply for choice fields, so be sure to only pass
        # the values that TypedChoiceField will understand.
        for k in kwargs.keys():
            if k not in ('coerce', 'empty_value', 'choices', 'required',
                         'widget', 'label', 'initial', 'help_text',
                         'error_messages'):
                del kwargs[k]
        defaults.update(kwargs)
        return form_class(**defaults)

class JSONField(models.TextField):
    """JSON field for storing a serialized dictionary or list."""

    def __init__(self, *args, **kwargs):
        self.human_readable = kwargs.pop('human_readable', False)
        return super(JSONField, self).__init__(*args, **kwargs)

    def from_db_value(self, value, expression, connection):
        if not isinstance(value, six.string_types):
            return value

        try:
            return json.loads(value)
        except ValueError:
            raise exceptions.ValidationError(_("Cannot deserialize JSON data. '%s'") % value)

    def to_python(self, value):
        if value is None:
            return None

        if not isinstance(value, six.string_types):
            return value

        try:
            return json.loads(value)
        except ValueError:
            raise exceptions.ValidationError(_("Cannot deserialize JSON data. '%s'") % value)

    def get_db_prep_value(self, value, *args, **kwargs):
        if value is None or value == "null":
            return None
        try:
            if self.human_readable:
                return json.dumps(value, indent=2, sort_keys=True)
            else:
                return json.dumps(value)
        except Exception:
            raise exceptions.ValidationError(_("Cannot serialize JSON data."))

    def value_to_string(self, obj):
        if django_version_ge('2.0'):
            value = self.value_from_object(obj)
        else:
            value = self._get_val_from_obj(obj)
        return self.get_db_prep_value(value)

    def value_from_object(self, obj):
        if self.human_readable:
            return json.dumps(super(JSONField, self).value_from_object(obj), indent=2, sort_keys=True)
        else:
            return json.dumps(super(JSONField, self).value_from_object(obj))

    def formfield(self, form_class=kobo.django.forms.JSONFormField, **kwargs):
        kwargs["form_class"] = form_class
        return super(JSONField, self).formfield(**kwargs)

# HACK:
import django.contrib.admin.options
django.contrib.admin.options.FORMFIELD_FOR_DBFIELD_DEFAULTS[JSONField] = {"widget": kobo.django.forms.JSONWidget}
<|endoftext|>


<commit_before>#!/usr/bin/python3
import boto3
import time
import yaml
import argparse
import os
import amazonia.amz as amz

"""
This Script will take a cloud formation template file and upload it to create a cloud formation stack in aws using boto3
http://boto3.readthedocs.org/en/latest/reference/services/cloudformation.html#CloudFormation.Client.create_stack
"""

def read_yaml(user_yaml):
    """
    Ingest user YAML
    :param user_yaml: yaml file location
    :return: Json serialised version of Yaml
    """
    with open(user_yaml, 'r') as stack_yaml:
        return yaml.safe_load(stack_yaml)

def create_template(yaml_data, default_data, schema_data, template_path):
    """
    Creates stack template from amazonia and places it inhte template path
    :param yaml_data: User stack data from application's yaml file
    :param default_data: Default data to be used if not specified in applications yaml file
    :param schema_data: Cerburus schema data used for validation
    :param template_path: path to place template file (inc template file name)
    """
    template_data = amz.generate_template(yaml_data, default_data, schema_data)

    with open(template_path, 'w') as template_file:
        template_file.write(template_data)
        template_file.close()

def upload_s3(s3_client, template_path, s3_bucket, s3_key):
    """
    Upload to s3
    :param s3_client: Boto S3 client API
    :param template_path: Path where output template file was saved to
    :param s3_bucket: S3 bucket where to upload template to
    :param s3_key: Folder and file path key where to upload template to
    """
    s3_client.upload_file(template_path, s3_bucket, s3_key)

    print('File Successfully Uploaded to S3')

def create_and_delete_stack(cf_client, stack_name, s3_bucket, s3_key):
    """
    This Script will take a cloud formation template file and upload it to create a cloud formation stack in aws using boto3
    http://boto3.readthedocs.org/en/latest/reference/services/cloudformation.html#CloudFormation.Client.create_stack
    :param cf_client: Boto Cloudformation client API
    :param stack_name: name of stack to create and delete
    :param s3_bucket: S3 bucket where to read template from
    :param s3_key: Folder and file path key where to read template from
    """
    template_url = \
        'https://s3-ap-southeast-2.amazonaws.com/' + s3_bucket + '/' + s3_key
    time_delay = 11

    create_response = cf_client.create_stack(
        StackName=stack_name,
        TemplateURL=template_url,
        TimeoutInMinutes=123,
        ResourceTypes=['AWS::*'],
        OnFailure='ROLLBACK',
        Tags=[
            {
                'Key': 'Stack Name',
                'Value': stack_name
            }

        ]
    )

    stack_id = create_response['StackId']
    print('\nStack Creating...\n{0}\n'.format(stack_id))

    # Script to return an AWS Cloudformation Stack_ID or Stack_Name stack status every 10 seconds using boto3.
    # If the status returns CREATE_COMPLETE then exit with success message
    # If the status returns ROLLBACK_IN_PROGRESS or ROLLBACK_COMPLETE then exit with failure message
    # http://boto3.readthedocs.org/en/latest/reference/services/cloudformation.html#CloudFormation.Client.describe_stacks

    while stack_id:
        confirm_response = cf_client.describe_stacks(StackName=stack_id)
        stack_status = confirm_response['Stacks'][0]['StackStatus']

        if stack_status == 'CREATE_COMPLETE':
            print('\nStack Successfully Created...\nStack Status: {0}'.format(stack_status))
            break
        elif stack_status in ('ROLLBACK_IN_PROGRESS', 'ROLLBACK_COMPLETE'):
            print('Error occurred creating AWS CloudFormation stack and returned status code {0}.'.format(stack_status))
            exit(1)
        else:
            print('Stack Status: {0}'.format(stack_status))
        time.sleep(time_delay)

    # This script will delete a stack in AWS
    # http://boto3.readthedocs.org/en/latest/reference/services/cloudformation.html#CloudFormation.Client.delete_stack

    cf_client.delete_stack(StackName=stack_name)

    print('\nStack {0} Deletion Commencing...\n'.format(stack_name))

    # Script to return an AWS Cloudformation Stack_ID or Stack_Name stack status every 10 seconds using boto3.
    # If the status returns CREATE_COMPLETE then exit with success message
    # If the status returns ROLLBACK_IN_PROGRESS or ROLLBACK_COMPLETE then exit with failure message
    # http://boto3.readthedocs.org/en/latest/reference/services/cloudformation.html#CloudFormation.Client.describe_stack_events

    while stack_id:
        confirm_response = cf_client.describe_stacks(StackName=stack_id)
        stack_status = confirm_response['Stacks'][0]['StackStatus']

        if stack_status == 'DELETE_COMPLETE':
            print('\nStack Successfully Deleted...\nStack Status: {0}\n'.format(stack_status))
            break
        elif stack_status in ('ROLLBACK_IN_PROGRESS', 'ROLLBACK_COMPLETE'):
            print('Error occurred creating AWS CloudFormation stack and returned status code {0}.'.format(stack_status))
            exit(1)
        else:
            print('Stack Status: {0}'.format(stack_status))
        time.sleep(time_delay)

def main():
    """
    Accepts arguments
    Reads data
    Creates template
    Uploads template to S3
    Creates and delets stack
    """
    cf_client = boto3.client('cloudformation')
    s3_client = boto3.resource('s3').meta.client

    __location__ = os.path.realpath(
        os.path.join(os.getcwd(), os.path.dirname(__file__)))

    parser = argparse.ArgumentParser()
    parser.add_argument('-y', '--yaml',
                        default=os.path.join(__location__, './application.yaml'),
                        help="Path to the applications amazonia yaml file")
    parser.add_argument('-d', '--default',
                        default=os.path.join(__location__, './defaults.yaml'),
                        help='Path to the environmental defaults yaml file')
    parser.add_argument('-s', '--schema',
                        default=os.path.join(__location__, './schema.yaml'),
                        help='Path to the schema to validate the provided yaml values against')
    parser.add_argument('-t', '--template',
                        default='stack.template',
                        help='Path for amazonia to place template file')
    parser.add_argument('-b', '--s3_bucket',
                        default='smallest-bucket-in-history',
                        help='s3 bucket to place template file')
    parser.add_argument('-st', '--stack_name',
                        default='testSysStack',
                        help='Title of stack')
    parser.add_argument('-o', '--out',
                        action='store_true',
                        help='Output template to stdout rather than a file.')
    args = parser.parse_args()

    # YAML ingestion
    yaml_data = read_yaml(args.yaml)
    default_data = read_yaml(args.default)
    schema_data = read_yaml(args.schema)
    template_path = os.path.join(__location__, args.template)
    s3_key = 'amazonia/' + args.template
    s3_bucket = args.s3_bucket
    stack_name = args.stack_name

    # Create template, upload to s3 then create and delete stack
    create_template(yaml_data, default_data, schema_data, template_path)
    upload_s3(s3_client, template_path, s3_bucket, s3_key)
    create_and_delete_stack(cf_client, stack_name, s3_bucket, s3_key)

if __name__ == '__main__':
    main()
<commit_msg>updating s3.py For lowercase name and output<commit_after><|endoftext|>


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

Created on Wed Mar 28 15:34:18 2012

Author: Josef Perktold
"""

from statsmodels.compatnp.py3k import BytesIO, asbytes
import numpy as np
from numpy.testing import assert_almost_equal, assert_equal

from statsmodels.stats.libqsturng import qsturng

ss = '''\
  43.9  1   1
  39.0  1   2
  46.7  1   3
  43.8  1   4
  44.2  1   5
  47.7  1   6
  43.6  1   7
  38.9  1   8
  43.6  1   9
  40.0  1  10
  89.8  2   1
  87.1  2   2
  92.7  2   3
  90.6  2   4
  87.7  2   5
  92.4  2   6
  86.1  2   7
  88.1  2   8
  90.8  2   9
  89.1  2  10
  68.4  3   1
  69.3  3   2
  68.5  3   3
  66.4  3   4
  70.0  3   5
  68.1  3   6
  70.6  3   7
  65.2  3   8
  63.8  3   9
  69.2  3  10
  36.2  4   1
  45.2  4   2
  40.7  4   3
  40.5  4   4
  39.3  4   5
  40.3  4   6
  43.2  4   7
  38.7  4   8
  40.9  4   9
  39.7  4  10'''

#idx   Treatment StressReduction
ss2 = '''\
1     mental               2
2     mental               2
3     mental               3
4     mental               4
5     mental               4
6     mental               5
7     mental               3
8     mental               4
9     mental               4
10    mental               4
11  physical               4
12  physical               4
13  physical               3
14  physical               5
15  physical               4
16  physical               1
17  physical               1
18  physical               2
19  physical               3
20  physical               3
21   medical               1
22   medical               2
23   medical               2
24   medical               2
25   medical               3
26   medical               2
27   medical               3
28   medical               1
29   medical               3
30   medical               1'''

ss3 = '''\
1 24.5
1 23.5
1 26.4
1 27.1
1 29.9
2 28.4
2 34.2
2 29.5
2 32.2
2 30.1
3 26.1
3 28.3
3 24.3
3 26.2
3 27.8'''

ss5 = '''\
2 - 3	4.340	0.691	7.989	***
2 - 1	4.600	0.951	8.249	***
3 - 2	-4.340	-7.989	-0.691	***
3 - 1	0.260	-3.389	3.909	 -
1 - 2	-4.600	-8.249	-0.951	***
1 - 3	-0.260	-3.909	3.389	'''

#accommodate recfromtxt for python 3.2, requires bytes
ss = asbytes(ss)
ss2 = asbytes(ss2)
ss3 = asbytes(ss3)
ss5 = asbytes(ss5)

dta = np.recfromtxt(BytesIO(ss), names=("Rust","Brand","Replication"))
dta2 = np.recfromtxt(BytesIO(ss2), names = ("idx", "Treatment", "StressReduction"))
dta3 = np.recfromtxt(BytesIO(ss3), names = ("Brand", "Relief"))
dta5 = np.recfromtxt(BytesIO(ss5), names = ('pair', 'mean', 'lower', 'upper', 'sig'), delimiter='\t')
sas_ = dta5[[1,3,2]]

from statsmodels.stats.multicomp import (tukeyhsd, pairwise_tukeyhsd,
                                         MultiComparison)
#import statsmodels.sandbox.stats.multicomp as multi
#print tukeyhsd(dta['Brand'], dta['Rust'])

def get_thsd(mci, alpha=0.05):
    var_ = np.var(mci.groupstats.groupdemean(), ddof=len(mci.groupsunique))
    means = mci.groupstats.groupmean
    nobs = mci.groupstats.groupnobs
    resi = tukeyhsd(means, nobs, var_, df=None, alpha=alpha,
                    q_crit=qsturng(1-alpha, len(means), (nobs-1).sum()))
    #print resi[4]
    var2 = (mci.groupstats.groupvarwithin() * (nobs - 1)).sum() \
                                                        / (nobs - 1).sum()
    assert_almost_equal(var_, var2, decimal=14)
    return resi

class CheckTuckeyHSD(object):

    @classmethod
    def setup_class_(self):
        self.mc = MultiComparison(self.endog, self.groups)
        self.res = self.mc.tukeyhsd(alpha=self.alpha)

    def test_multicomptukey(self):
        meandiff1 = self.res[1][2]
        assert_almost_equal(meandiff1, self.meandiff2, decimal=14)

        confint1 = self.res[1][4]
        assert_almost_equal(confint1, self.confint2, decimal=2)

        reject1 = self.res[1][1]
        assert_equal(reject1, self.reject2)

    def test_group_tukey(self):
        res_t = get_thsd(self.mc,alpha=self.alpha)
        assert_almost_equal(res_t[4], self.confint2, decimal=2)

    def test_shortcut_function(self):
        #check wrapper function
        res = pairwise_tukeyhsd(self.endog, self.groups, alpha=self.alpha)
        assert_almost_equal(res[1][4], self.res[1][4], decimal=14)

class TestTuckeyHSD2(CheckTuckeyHSD):

    @classmethod
    def setup_class(self):
        #balanced case
        self.endog = dta2['StressReduction']
        self.groups = dta2['Treatment']
        self.alpha = 0.05
        self.setup_class_() #in super

        #from R
        tukeyhsd2s = tukeyhsd = np.array([1.5,1,-0.5,0.3214915,-0.1785085,-1.678509,2.678509,2.178509,0.6785085,0.01056279,0.1079035,0.5513904]).reshape(3,4, order='F')
        self.meandiff2 = tukeyhsd2s[:, 0]
        self.confint2 = tukeyhsd2s[:, 1:3]
        pvals = tukeyhsd2s[:, 3]
        self.reject2 = pvals < 0.05

class TestTuckeyHSD2s(CheckTuckeyHSD):

    @classmethod
    def setup_class(self):
        #unbalanced case
        self.endog = dta2['StressReduction'][3:29]
        self.groups = dta2['Treatment'][3:29]
        self.alpha = 0.01
        self.setup_class_()

        #from R
        tukeyhsd2s = np.array([1.8888888888888889,0.888888888888889,-1,0.2658549,-0.5908785,
                               -2.587133,3.511923,2.368656,0.5871331,
                               0.002837638,0.150456,0.1266072]
                               ).reshape(3,4, order='F')
        self.meandiff2 = tukeyhsd2s[:, 0]
        self.confint2 = tukeyhsd2s[:, 1:3]
        pvals = tukeyhsd2s[:, 3]
        self.reject2 = pvals < 0.01

class TestTuckeyHSD3(CheckTuckeyHSD):

    @classmethod
    def setup_class(self):
        #SAS case
        self.endog = dta3['Relief']
        self.groups = dta3['Brand']
        self.alpha = 0.05
        self.setup_class_()
        #super(self, self).setup_class_()
        #CheckTuckeyHSD.setup_class_()

        self.meandiff2 = sas_['mean']
        self.confint2 = sas_[['lower','upper']].view(float).reshape((3,2))
        self.reject2 = sas_['sig'] == '***'

if __name__ == '__main__':
    import statsmodels.sandbox.stats.multicomp as multi #incomplete refactoring

    mc = multi.MultiComparison(dta['Rust'], dta['Brand'])
    res = mc.tukeyhsd()
    print res[0]

    mc2 = multi.MultiComparison(dta2['StressReduction'], dta2['Treatment'])
    res2 = mc2.tukeyhsd()
    print res2[0]

    mc2s = multi.MultiComparison(dta2['StressReduction'][3:29], dta2['Treatment'][3:29])
    res2s = mc2s.tukeyhsd()
    print res2s[0]
    res2s_001 = mc2s.tukeyhsd(alpha=0.01)
    #R result
    tukeyhsd2s = np.array([1.888889,0.8888889,-1,0.2658549,-0.5908785,-2.587133,3.511923,2.368656,0.5871331,0.002837638,0.150456,0.1266072]).reshape(3,4, order='F')
    assert_almost_equal(res2s_001[1][4], tukeyhsd2s[:,1:3], decimal=3)

    mc3 = multi.MultiComparison(dta3['Relief'], dta3['Brand'])
    res3 = mc3.tukeyhsd()
    print res3[0]

    for mci in [mc, mc2, mc3]:
        get_thsd(mci)

    from scipy import stats
    print mc2.allpairtest(stats.ttest_ind, method='b')[0]

    '''same as SAS:
    >>> np.var(mci.groupstats.groupdemean(), ddof=3)
    4.6773333333333351
    >>> var_ = np.var(mci.groupstats.groupdemean(), ddof=3)
    >>> tukeyhsd(means, nobs, var_, df=None, alpha=0.05, q_crit=qsturng(0.95, 3, 12))[4]
    array([[ 0.95263648,  8.24736352],
           [-3.38736352,  3.90736352],
           [-7.98736352, -0.69263648]])
    >>> tukeyhsd(means, nobs, var_, df=None, alpha=0.05, q_crit=3.77278)[4]
    array([[ 0.95098508,  8.24901492],
           [-3.38901492,  3.90901492],
           [-7.98901492, -0.69098508]])
    '''

    ss5 = '''\
    Comparisons significant at the 0.05 level are indicated by ***.
    BRAND
    Comparison	Difference
    Between
    Means	Simultaneous 95% Confidence Limits	 Sign.
    2 - 3	4.340	0.691	7.989	***
    2 - 1	4.600	0.951	8.249	***
    3 - 2	-4.340	-7.989	-0.691	***
    3 - 1	0.260	-3.389	3.909	 -
    1 - 2	-4.600	-8.249	-0.951	***
    1 - 3	-0.260	-3.909	3.389	'''

    ss5 = '''\
    2 - 3	4.340	0.691	7.989	***
    2 - 1	4.600	0.951	8.249	***
    3 - 2	-4.340	-7.989	-0.691	***
    3 - 1	0.260	-3.389	3.909	 -
    1 - 2	-4.600	-8.249	-0.951	***
    1 - 3	-0.260	-3.909	3.389	'''

    dta5 = np.recfromtxt(StringIO.StringIO(ss5), names = ('pair', 'mean', 'lower', 'upper', 'sig'), delimiter='\t')

    sas_ = dta5[[1,3,2]]
    confint1 = res3[1][4]
    confint2 = sas_[['lower','upper']].view(float).reshape((3,2))
    assert_almost_equal(confint1, confint2, decimal=2)
    reject1 = res3[1][1]
    reject2 = sas_['sig'] == '***'
    assert_equal(reject1, reject2)
    meandiff1 = res3[1][2]
    meandiff2 = sas_['mean']
    assert_almost_equal(meandiff1, meandiff2, decimal=14)
<commit_msg>BUG: py32 compatibility in test<commit_after># -*- coding: utf-8 -*-
"""

Created on Wed Mar 28 15:34:18 2012

Author: Josef Perktold
"""

from statsmodels.compatnp.py3k import BytesIO, asbytes
import numpy as np
from numpy.testing import assert_almost_equal, assert_equal

from statsmodels.stats.libqsturng import qsturng

ss = '''\
  43.9  1   1
  39.0  1   2
  46.7  1   3
  43.8  1   4
  44.2  1   5
  47.7  1   6
  43.6  1   7
  38.9  1   8
  43.6  1   9
  40.0  1  10
  89.8  2   1
  87.1  2   2
  92.7  2   3
  90.6  2   4
  87.7  2   5
  92.4  2   6
  86.1  2   7
  88.1  2   8
  90.8  2   9
  89.1  2  10
  68.4  3   1
  69.3  3   2
  68.5  3   3
  66.4  3   4
  70.0  3   5
  68.1  3   6
  70.6  3   7
  65.2  3   8
  63.8  3   9
  69.2  3  10
  36.2  4   1
  45.2  4   2
  40.7  4   3
  40.5  4   4
  39.3  4   5
  40.3  4   6
  43.2  4   7
  38.7  4   8
  40.9  4   9
  39.7  4  10'''

#idx   Treatment StressReduction
ss2 = '''\
1     mental               2
2     mental               2
3     mental               3
4     mental               4
5     mental               4
6     mental               5
7     mental               3
8     mental               4
9     mental               4
10    mental               4
11  physical               4
12  physical               4
13  physical               3
14  physical               5
15  physical               4
16  physical               1
17  physical               1
18  physical               2
19  physical               3
20  physical               3
21   medical               1
22   medical               2
23   medical               2
24   medical               2
25   medical               3
26   medical               2
27   medical               3
28   medical               1
29   medical               3
30   medical               1'''

ss3 = '''\
1 24.5
1 23.5
1 26.4
1 27.1
1 29.9
2 28.4
2 34.2
2 29.5
2 32.2
2 30.1
3 26.1
3 28.3
3 24.3
3 26.2
3 27.8'''

ss5 = '''\
2 - 3	4.340	0.691	7.989	***
2 - 1	4.600	0.951	8.249	***
3 - 2	-4.340	-7.989	-0.691	***
3 - 1	0.260	-3.389	3.909	 -
1 - 2	-4.600	-8.249	-0.951	***
1 - 3	-0.260	-3.909	3.389	'''

#accommodate recfromtxt for python 3.2, requires bytes
ss = asbytes(ss)
ss2 = asbytes(ss2)
ss3 = asbytes(ss3)
ss5 = asbytes(ss5)

dta = np.recfromtxt(BytesIO(ss), names=("Rust","Brand","Replication"))
dta2 = np.recfromtxt(BytesIO(ss2), names = ("idx", "Treatment", "StressReduction"))
dta3 = np.recfromtxt(BytesIO(ss3), names = ("Brand", "Relief"))
dta5 = np.recfromtxt(BytesIO(ss5), names = ('pair', 'mean', 'lower', 'upper', 'sig'), delimiter='\t')
sas_ = dta5[[1,3,2]]

from statsmodels.stats.multicomp import (tukeyhsd, pairwise_tukeyhsd,
                                         MultiComparison)
#import statsmodels.sandbox.stats.multicomp as multi
#print tukeyhsd(dta['Brand'], dta['Rust'])

def get_thsd(mci, alpha=0.05):
    var_ = np.var(mci.groupstats.groupdemean(), ddof=len(mci.groupsunique))
    means = mci.groupstats.groupmean
    nobs = mci.groupstats.groupnobs
    resi = tukeyhsd(means, nobs, var_, df=None, alpha=alpha,
                    q_crit=qsturng(1-alpha, len(means), (nobs-1).sum()))
    #print resi[4]
    var2 = (mci.groupstats.groupvarwithin() * (nobs - 1)).sum() \
                                                        / (nobs - 1).sum()
    assert_almost_equal(var_, var2, decimal=14)
    return resi

class CheckTuckeyHSD(object):

    @classmethod
    def setup_class_(self):
        self.mc = MultiComparison(self.endog, self.groups)
        self.res = self.mc.tukeyhsd(alpha=self.alpha)

    def test_multicomptukey(self):
        meandiff1 = self.res[1][2]
        assert_almost_equal(meandiff1, self.meandiff2, decimal=14)

        confint1 = self.res[1][4]
        assert_almost_equal(confint1, self.confint2, decimal=2)

        reject1 = self.res[1][1]
        assert_equal(reject1, self.reject2)

    def test_group_tukey(self):
        res_t = get_thsd(self.mc,alpha=self.alpha)
        assert_almost_equal(res_t[4], self.confint2, decimal=2)

    def test_shortcut_function(self):
        #check wrapper function
        res = pairwise_tukeyhsd(self.endog, self.groups, alpha=self.alpha)
        assert_almost_equal(res[1][4], self.res[1][4], decimal=14)

class TestTuckeyHSD2(CheckTuckeyHSD):

    @classmethod
    def setup_class(self):
        #balanced case
        self.endog = dta2['StressReduction']
        self.groups = dta2['Treatment']
        self.alpha = 0.05
        self.setup_class_() #in super

        #from R
        tukeyhsd2s = tukeyhsd = np.array([1.5,1,-0.5,0.3214915,-0.1785085,-1.678509,2.678509,2.178509,0.6785085,0.01056279,0.1079035,0.5513904]).reshape(3,4, order='F')
        self.meandiff2 = tukeyhsd2s[:, 0]
        self.confint2 = tukeyhsd2s[:, 1:3]
        pvals = tukeyhsd2s[:, 3]
        self.reject2 = pvals < 0.05

class TestTuckeyHSD2s(CheckTuckeyHSD):

    @classmethod
    def setup_class(self):
        #unbalanced case
        self.endog = dta2['StressReduction'][3:29]
        self.groups = dta2['Treatment'][3:29]
        self.alpha = 0.01
        self.setup_class_()

        #from R
        tukeyhsd2s = np.array([1.8888888888888889,0.888888888888889,-1,0.2658549,-0.5908785,
                               -2.587133,3.511923,2.368656,0.5871331,
                               0.002837638,0.150456,0.1266072]
                               ).reshape(3,4, order='F')
        self.meandiff2 = tukeyhsd2s[:, 0]
        self.confint2 = tukeyhsd2s[:, 1:3]
        pvals = tukeyhsd2s[:, 3]
        self.reject2 = pvals < 0.01

class TestTuckeyHSD3(CheckTuckeyHSD):

    @classmethod
    def setup_class(self):
        #SAS case
        self.endog = dta3['Relief']
        self.groups = dta3['Brand']
        self.alpha = 0.05
        self.setup_class_()
        #super(self, self).setup_class_()
        #CheckTuckeyHSD.setup_class_()

        self.meandiff2 = sas_['mean']
        self.confint2 = sas_[['lower','upper']].view(float).reshape((3,2))
        self.reject2 = sas_['sig'] == asbytes('***')

if __name__ == '__main__':
    import statsmodels.sandbox.stats.multicomp as multi #incomplete refactoring

    mc = multi.MultiComparison(dta['Rust'], dta['Brand'])
    res = mc.tukeyhsd()
    print res[0]

    mc2 = multi.MultiComparison(dta2['StressReduction'], dta2['Treatment'])
    res2 = mc2.tukeyhsd()
    print res2[0]

    mc2s = multi.MultiComparison(dta2['StressReduction'][3:29], dta2['Treatment'][3:29])
    res2s = mc2s.tukeyhsd()
    print res2s[0]
    res2s_001 = mc2s.tukeyhsd(alpha=0.01)
    #R result
    tukeyhsd2s = np.array([1.888889,0.8888889,-1,0.2658549,-0.5908785,-2.587133,3.511923,2.368656,0.5871331,0.002837638,0.150456,0.1266072]).reshape(3,4, order='F')
    assert_almost_equal(res2s_001[1][4], tukeyhsd2s[:,1:3], decimal=3)

    mc3 = multi.MultiComparison(dta3['Relief'], dta3['Brand'])
    res3 = mc3.tukeyhsd()
    print res3[0]

    for mci in [mc, mc2, mc3]:
        get_thsd(mci)

    from scipy import stats
    print mc2.allpairtest(stats.ttest_ind, method='b')[0]

    '''same as SAS:
    >>> np.var(mci.groupstats.groupdemean(), ddof=3)
    4.6773333333333351
    >>> var_ = np.var(mci.groupstats.groupdemean(), ddof=3)
    >>> tukeyhsd(means, nobs, var_, df=None, alpha=0.05, q_crit=qsturng(0.95, 3, 12))[4]
    array([[ 0.95263648,  8.24736352],
           [-3.38736352,  3.90736352],
           [-7.98736352, -0.69263648]])
    >>> tukeyhsd(means, nobs, var_, df=None, alpha=0.05, q_crit=3.77278)[4]
    array([[ 0.95098508,  8.24901492],
           [-3.38901492,  3.90901492],
           [-7.98901492, -0.69098508]])
    '''

    ss5 = '''\
    Comparisons significant at the 0.05 level are indicated by ***.
    BRAND
    Comparison	Difference
    Between
    Means	Simultaneous 95% Confidence Limits	 Sign.
    2 - 3	4.340	0.691	7.989	***
    2 - 1	4.600	0.951	8.249	***
    3 - 2	-4.340	-7.989	-0.691	***
    3 - 1	0.260	-3.389	3.909	 -
    1 - 2	-4.600	-8.249	-0.951	***
    1 - 3	-0.260	-3.909	3.389	'''

    ss5 = '''\
    2 - 3	4.340	0.691	7.989	***
    2 - 1	4.600	0.951	8.249	***
    3 - 2	-4.340	-7.989	-0.691	***
    3 - 1	0.260	-3.389	3.909	 -
    1 - 2	-4.600	-8.249	-0.951	***
    1 - 3	-0.260	-3.909	3.389	'''

    dta5 = np.recfromtxt(StringIO.StringIO(ss5), names = ('pair', 'mean', 'lower', 'upper', 'sig'), delimiter='\t')

    sas_ = dta5[[1,3,2]]
    confint1 = res3[1][4]
    confint2 = sas_[['lower','upper']].view(float).reshape((3,2))
    assert_almost_equal(confint1, confint2, decimal=2)
    reject1 = res3[1][1]
    reject2 = sas_['sig'] == '***'
    assert_equal(reject1, reject2)
    meandiff1 = res3[1][2]
    meandiff2 = sas_['mean']
    assert_almost_equal(meandiff1, meandiff2, decimal=14)
<|endoftext|>


<commit_before>from sympy import Integer, Rational, symbols, Function
from sympy.calculus.finite_diff import (apply_finite_diff,
                                        finite_diff_weights, as_finite_diff)

def test_apply_finite_diff():
    x, h = symbols('x h')
    f = Function('f')
    assert (apply_finite_diff(1, [x-h, x+h], [f(x-h), f(x+h)], x) -
            (f(x+h)-f(x-h))/(2*h)).simplify() == 0

    assert (apply_finite_diff(1, [5, 6, 7], [f(5), f(6), f(7)], 5) -
            (-Rational(3, 2)*f(5) + 2*f(6) - Rational(1, 2)*f(7))).simplify() == 0

def test_finite_diff_weights():

    d = finite_diff_weights(1, [5, 6, 7], 5)
    assert d[1][2] == [-Rational(3, 2), 2, -Rational(1, 2)]

    # Table 1, p. 702 in doi:10.1090/S0025-5718-1988-0935077-0
    # --------------------------------------------------------
    xl = [0, 1, -1, 2, -2, 3, -3, 4, -4]

    # d holds all coefficients
    d = finite_diff_weights(4, xl, Integer(0))

    # Zeroeth derivative
    for i in range(5):
        assert d[0][i] == [Integer(1)] + [Integer(0)]*8

    # First derivative
    assert d[1][0] == [Integer(0)]*9
    assert d[1][2] == [Integer(0), Rational(1, 2), -Rational(1, 2)] + [Integer(0)]*6
    assert d[1][4] == [Integer(0), Rational(2, 3), -Rational(2, 3), -Rational(1, 12), Rational(1, 12)] + [Integer(0)]*4
    assert d[1][6] == [Integer(0), Rational(3, 4), -Rational(3, 4), -Rational(3, 20), Rational(3, 20),
                       Rational(1, 60), -Rational(1, 60)] + [Integer(0)]*2
    assert d[1][8] == [Integer(0), Rational(4, 5), -Rational(4, 5), -Rational(1, 5), Rational(1, 5),
                       Rational(4, 105), -Rational(4, 105), -Rational(1, 280), Rational(1, 280)]

    # Second derivative
    for i in range(2):
        assert d[2][i] == [Integer(0)]*9
    assert d[2][2] == [-Integer(2), Integer(1), Integer(1)] + [Integer(0)]*6
    assert d[2][4] == [-Rational(5, 2), Rational(4, 3), Rational(4, 3), -Rational(1, 12), -Rational(1, 12)] + [Integer(0)]*4
    assert d[2][6] == [-Rational(49, 18), Rational(3, 2), Rational(3, 2), -Rational(3, 20), -Rational(3, 20),
                       Rational(1, 90), Rational(1, 90)] + [Integer(0)]*2
    assert d[2][8] == [-Rational(205, 72), Rational(8, 5), Rational(8, 5), -Rational(1, 5), -Rational(1, 5),
                       Rational(8, 315), Rational(8, 315), -Rational(1, 560), -Rational(1, 560)]

    # Third derivative
    for i in range(3):
        assert d[3][i] == [Integer(0)]*9
    assert d[3][4] == [Integer(0), -Integer(1), Integer(1), Rational(1, 2), -Rational(1, 2)] + [Integer(0)]*4
    assert d[3][6] == [Integer(0), -Rational(13, 8), Rational(13, 8), Integer(1), -Integer(1),
                       -Rational(1, 8), Rational(1, 8)] + [Integer(0)]*2
    assert d[3][8] == [Integer(0), -Rational(61, 30), Rational(61, 30), Rational(169, 120), -Rational(169, 120),
                       -Rational(3, 10), Rational(3, 10), Rational(7, 240), -Rational(7, 240)]

    # Fourth derivative
    for i in range(4):
        assert d[4][i] == [Integer(0)]*9
    assert d[4][4] == [Integer(6), -Integer(4), -Integer(4), Integer(1), Integer(1)] + [Integer(0)]*4
    assert d[4][6] == [Rational(28, 3), -Rational(13, 2), -Rational(13, 2), Integer(2), Integer(2),
                       -Rational(1, 6), -Rational(1, 6)] + [Integer(0)]*2
    assert d[4][8] == [Rational(91, 8), -Rational(122, 15), -Rational(122, 15), Rational(169, 60), Rational(169, 60),
                       -Rational(2, 5), -Rational(2, 5), Rational(7, 240), Rational(7, 240)]

    # Table 2, p. 703 in doi:10.1090/S0025-5718-1988-0935077-0
    # --------------------------------------------------------
    xl = [[j/Integer(2) for j in list(range(-i*2+1, 0, 2))+list(range(1, i*2+1, 2))]
          for i in range(1, 5)]

    # d holds all coefficients
    d = [finite_diff_weights({0: 1, 1: 2, 2: 4, 3: 4}[i], xl[i], 0) for
         i in range(4)]

    # Zeroth derivative
    assert d[0][0][1] == [Rational(1, 2), Rational(1, 2)]
    assert d[1][0][3] == [-Rational(1, 16), Rational(9, 16), Rational(9, 16), -Rational(1, 16)]
    assert d[2][0][5] == [Rational(3, 256), -Rational(25, 256), Rational(75, 128), Rational(75, 128),
                          -Rational(25, 256), Rational(3, 256)]
    assert d[3][0][7] == [-Rational(5, 2048), Rational(49, 2048), -Rational(245, 2048), Rational(1225, 2048),
                          Rational(1225, 2048), -Rational(245, 2048), Rational(49, 2048), -Rational(5, 2048)]

    # First derivative
    assert d[0][1][1] == [-Integer(1), Integer(1)]
    assert d[1][1][3] == [Rational(1, 24), -Rational(9, 8), Rational(9, 8), -Rational(1, 24)]
    assert d[2][1][5] == [-Rational(3, 640), Rational(25, 384), -Rational(75, 64), Rational(75, 64),
                          -Rational(25, 384), Rational(3, 640)]
    assert d[3][1][7] == [Rational(5, 7168), -Rational(49, 5120),  Rational(245, 3072), Rational(-1225, 1024),
                          Rational(1225, 1024), -Rational(245, 3072), Rational(49, 5120), -Rational(5, 7168)]

    # Reasonably the rest of the table is also correct... (testing of that
    # deemed excessive at the moment)

def test_as_finite_diff():
    x, h = symbols('x h')
    f = Function('f')

    # Central 1st derivative at gridpoint
    assert (as_finite_diff(f(x).diff(x), [x-2, x-1, x, x+1, x+2]) -
            (Rational(1, 12)*(f(x-2)-f(x+2)) + Rational(2, 3)*(f(x+1)-f(x-1)))).simplify() == 0

    # Central 1st derivative "half-way"
    assert (as_finite_diff(f(x).diff(x)) -
            (f(x + Rational(1, 2))-f(x - Rational(1, 2)))).simplify() == 0
    assert (as_finite_diff(f(x).diff(x), h) -
            (f(x + h/Integer(2))-f(x - h/Integer(2)))/h).simplify() == 0
    assert (as_finite_diff(f(x).diff(x), [x - 3*h, x-h, x+h, x + 3*h]) -
            (Integer(9)/(8*2*h)*(f(x+h) - f(x-h)) +
             Integer(1)/(24*2*h)*(f(x - 3*h) - f(x + 3*h)))).simplify() == 0

    # One sided 1st derivative at gridpoint
    assert (as_finite_diff(f(x).diff(x), [0, 1, 2], 0) -
            (-Rational(3, 2)*f(0) + 2*f(1) - f(2)/2)).simplify() == 0
    assert (as_finite_diff(f(x).diff(x), [x, x+h], x) -
            (f(x+h) - f(x))/h).simplify() == 0
    assert (as_finite_diff(f(x).diff(x), [x-h, x, x+h], x-h) -
            (-Integer(3)/(2*h)*f(x-h) + 2/h*f(x) -
             Integer(1)/(2*h)*f(x+h))).simplify() == 0

    # One sided 1st derivative "half-way"
    assert (as_finite_diff(f(x).diff(x), [x-h, x+h, x + 3*h, x + 5*h, x + 7*h])
            - 1/(2*h)*(-Integer(11)/(12)*f(x-h) + Integer(17)/(24)*f(x+h)
                       + Rational(3, 8)*f(x + 3*h) - Rational(5, 24)*f(x + 5*h)
                       + Rational(1, 24)*f(x + 7*h))).simplify() == 0

    # Central 2nd derivative at gridpoint
    assert (as_finite_diff(f(x).diff(x, 2), [x-h, x, x+h]) -
            h**-2 * (f(x-h) + f(x+h) - 2*f(x))).simplify() == 0

    assert (as_finite_diff(f(x).diff(x, 2), [x - 2*h, x-h, x, x+h, x + 2*h]) -
            h**-2 * (-Rational(1, 12)*(f(x - 2*h) + f(x + 2*h)) +
                     Rational(4, 3)*(f(x+h) + f(x-h)) - Rational(5, 2)*f(x))).simplify() == 0

    # Central 2nd derivative "half-way"
    assert (as_finite_diff(f(x).diff(x, 2), [x - 3*h, x-h, x+h, x + 3*h]) -
            (2*h)**-2 * (Rational(1, 2)*(f(x - 3*h) + f(x + 3*h)) -
                         Rational(1, 2)*(f(x+h) + f(x-h)))).simplify() == 0

    # One sided 2nd derivative at gridpoint
    assert (as_finite_diff(f(x).diff(x, 2), [x, x+h, x + 2*h, x + 3*h]) -
            h**-2 * (2*f(x) - 5*f(x+h) +
                     4*f(x+2*h) - f(x+3*h))).simplify() == 0

    # One sided 2nd derivative at "half-way"
    assert (as_finite_diff(f(x).diff(x, 2), [x-h, x+h, x + 3*h, x + 5*h]) -
            (2*h)**-2 * (Rational(3, 2)*f(x-h) - Rational(7, 2)*f(x+h) + Rational(5, 2)*f(x + 3*h) -
                         Rational(1, 2)*f(x + 5*h))).simplify() == 0

    # Central 3rd derivative at gridpoint
    assert (as_finite_diff(f(x).diff(x, 3)) -
            (-f(x - 3/Integer(2)) + 3*f(x - 1/Integer(2)) -
             3*f(x + 1/Integer(2)) + f(x + 3/Integer(2)))).simplify() == 0

    assert (as_finite_diff(
        f(x).diff(x, 3), [x - 3*h, x - 2*h, x-h, x, x+h, x + 2*h, x + 3*h]) -
        h**-3 * (Rational(1, 8)*(f(x - 3*h) - f(x + 3*h)) - f(x - 2*h) +
                 f(x + 2*h) + Rational(13, 8)*(f(x-h) - f(x+h)))).simplify() == 0

    # Central 3rd derivative at "half-way"
    assert (as_finite_diff(f(x).diff(x, 3), [x - 3*h, x-h, x+h, x + 3*h]) -
            (2*h)**-3 * (f(x + 3*h)-f(x - 3*h) +
                         3*(f(x-h)-f(x+h)))).simplify() == 0

    # One sided 3rd derivative at gridpoint
    assert (as_finite_diff(f(x).diff(x, 3), [x, x+h, x + 2*h, x + 3*h]) -
            h**-3 * (f(x + 3*h)-f(x) + 3*(f(x+h)-f(x + 2*h)))).simplify() == 0

    # One sided 3rd derivative at "half-way"
    assert (as_finite_diff(f(x).diff(x, 3), [x-h, x+h, x + 3*h, x + 5*h]) -
            (2*h)**-3 * (f(x + 5*h)-f(x-h) +
                         3*(f(x+h)-f(x + 3*h)))).simplify() == 0
<commit_msg>100% coverage for finite_diff.py<commit_after>import pytest

from sympy import Integer, Rational, symbols, Function
from sympy.calculus.finite_diff import (apply_finite_diff,
                                        finite_diff_weights, as_finite_diff)

from sympy.abc import x, y, h

def test_apply_finite_diff():
    pytest.raises(ValueError, lambda: apply_finite_diff(1, [1, 2], [3], x))

    f = Function('f')
    assert (apply_finite_diff(1, [x-h, x+h], [f(x-h), f(x+h)], x) -
            (f(x+h)-f(x-h))/(2*h)).simplify() == 0

    assert (apply_finite_diff(1, [5, 6, 7], [f(5), f(6), f(7)], 5) -
            (-Rational(3, 2)*f(5) + 2*f(6) - Rational(1, 2)*f(7))).simplify() == 0

def test_finite_diff_weights():
    pytest.raises(ValueError, lambda: finite_diff_weights(-1, [5, 6], 5))
    pytest.raises(ValueError, lambda: finite_diff_weights(Rational(1, 3),
                                                          [5, 6], 5))

    d = finite_diff_weights(1, [5, 6, 7], 5)
    assert d[1][2] == [-Rational(3, 2), 2, -Rational(1, 2)]

    # Table 1, p. 702 in doi:10.1090/S0025-5718-1988-0935077-0
    # --------------------------------------------------------
    xl = [0, 1, -1, 2, -2, 3, -3, 4, -4]

    # d holds all coefficients
    d = finite_diff_weights(4, xl, Integer(0))

    # Zeroeth derivative
    for i in range(5):
        assert d[0][i] == [Integer(1)] + [Integer(0)]*8

    # First derivative
    assert d[1][0] == [Integer(0)]*9
    assert d[1][2] == [Integer(0), Rational(1, 2), -Rational(1, 2)] + [Integer(0)]*6
    assert d[1][4] == [Integer(0), Rational(2, 3), -Rational(2, 3), -Rational(1, 12), Rational(1, 12)] + [Integer(0)]*4
    assert d[1][6] == [Integer(0), Rational(3, 4), -Rational(3, 4), -Rational(3, 20), Rational(3, 20),
                       Rational(1, 60), -Rational(1, 60)] + [Integer(0)]*2
    assert d[1][8] == [Integer(0), Rational(4, 5), -Rational(4, 5), -Rational(1, 5), Rational(1, 5),
                       Rational(4, 105), -Rational(4, 105), -Rational(1, 280), Rational(1, 280)]

    # Second derivative
    for i in range(2):
        assert d[2][i] == [Integer(0)]*9
    assert d[2][2] == [-Integer(2), Integer(1), Integer(1)] + [Integer(0)]*6
    assert d[2][4] == [-Rational(5, 2), Rational(4, 3), Rational(4, 3), -Rational(1, 12), -Rational(1, 12)] + [Integer(0)]*4
    assert d[2][6] == [-Rational(49, 18), Rational(3, 2), Rational(3, 2), -Rational(3, 20), -Rational(3, 20),
                       Rational(1, 90), Rational(1, 90)] + [Integer(0)]*2
    assert d[2][8] == [-Rational(205, 72), Rational(8, 5), Rational(8, 5), -Rational(1, 5), -Rational(1, 5),
                       Rational(8, 315), Rational(8, 315), -Rational(1, 560), -Rational(1, 560)]

    # Third derivative
    for i in range(3):
        assert d[3][i] == [Integer(0)]*9
    assert d[3][4] == [Integer(0), -Integer(1), Integer(1), Rational(1, 2), -Rational(1, 2)] + [Integer(0)]*4
    assert d[3][6] == [Integer(0), -Rational(13, 8), Rational(13, 8), Integer(1), -Integer(1),
                       -Rational(1, 8), Rational(1, 8)] + [Integer(0)]*2
    assert d[3][8] == [Integer(0), -Rational(61, 30), Rational(61, 30), Rational(169, 120), -Rational(169, 120),
                       -Rational(3, 10), Rational(3, 10), Rational(7, 240), -Rational(7, 240)]

    # Fourth derivative
    for i in range(4):
        assert d[4][i] == [Integer(0)]*9
    assert d[4][4] == [Integer(6), -Integer(4), -Integer(4), Integer(1), Integer(1)] + [Integer(0)]*4
    assert d[4][6] == [Rational(28, 3), -Rational(13, 2), -Rational(13, 2), Integer(2), Integer(2),
                       -Rational(1, 6), -Rational(1, 6)] + [Integer(0)]*2
    assert d[4][8] == [Rational(91, 8), -Rational(122, 15), -Rational(122, 15), Rational(169, 60), Rational(169, 60),
                       -Rational(2, 5), -Rational(2, 5), Rational(7, 240), Rational(7, 240)]

    # Table 2, p. 703 in doi:10.1090/S0025-5718-1988-0935077-0
    # --------------------------------------------------------
    xl = [[j/Integer(2) for j in list(range(-i*2+1, 0, 2))+list(range(1, i*2+1, 2))]
          for i in range(1, 5)]

    # d holds all coefficients
    d = [finite_diff_weights({0: 1, 1: 2, 2: 4, 3: 4}[i], xl[i], 0) for
         i in range(4)]

    # Zeroth derivative
    assert d[0][0][1] == [Rational(1, 2), Rational(1, 2)]
    assert d[1][0][3] == [-Rational(1, 16), Rational(9, 16), Rational(9, 16), -Rational(1, 16)]
    assert d[2][0][5] == [Rational(3, 256), -Rational(25, 256), Rational(75, 128), Rational(75, 128),
                          -Rational(25, 256), Rational(3, 256)]
    assert d[3][0][7] == [-Rational(5, 2048), Rational(49, 2048), -Rational(245, 2048), Rational(1225, 2048),
                          Rational(1225, 2048), -Rational(245, 2048), Rational(49, 2048), -Rational(5, 2048)]

    # First derivative
    assert d[0][1][1] == [-Integer(1), Integer(1)]
    assert d[1][1][3] == [Rational(1, 24), -Rational(9, 8), Rational(9, 8), -Rational(1, 24)]
    assert d[2][1][5] == [-Rational(3, 640), Rational(25, 384), -Rational(75, 64), Rational(75, 64),
                          -Rational(25, 384), Rational(3, 640)]
    assert d[3][1][7] == [Rational(5, 7168), -Rational(49, 5120),  Rational(245, 3072), Rational(-1225, 1024),
                          Rational(1225, 1024), -Rational(245, 3072), Rational(49, 5120), -Rational(5, 7168)]

    # Reasonably the rest of the table is also correct... (testing of that
    # deemed excessive at the moment)

def test_as_finite_diff():
    f = Function('f')

    # Central 1st derivative at gridpoint
    assert (as_finite_diff(f(x).diff(x), [x-2, x-1, x, x+1, x+2]) -
            (Rational(1, 12)*(f(x-2)-f(x+2)) + Rational(2, 3)*(f(x+1)-f(x-1)))).simplify() == 0

    # Central 1st derivative "half-way"
    assert (as_finite_diff(f(x).diff(x)) -
            (f(x + Rational(1, 2))-f(x - Rational(1, 2)))).simplify() == 0
    assert (as_finite_diff(f(x).diff(x), h) -
            (f(x + h/Integer(2))-f(x - h/Integer(2)))/h).simplify() == 0
    assert (as_finite_diff(f(x).diff(x), [x - 3*h, x-h, x+h, x + 3*h]) -
            (Integer(9)/(8*2*h)*(f(x+h) - f(x-h)) +
             Integer(1)/(24*2*h)*(f(x - 3*h) - f(x + 3*h)))).simplify() == 0

    # One sided 1st derivative at gridpoint
    assert (as_finite_diff(f(x).diff(x), [0, 1, 2], 0) -
            (-Rational(3, 2)*f(0) + 2*f(1) - f(2)/2)).simplify() == 0
    assert (as_finite_diff(f(x).diff(x), [x, x+h], x) -
            (f(x+h) - f(x))/h).simplify() == 0
    assert (as_finite_diff(f(x).diff(x), [x-h, x, x+h], x-h) -
            (-Integer(3)/(2*h)*f(x-h) + 2/h*f(x) -
             Integer(1)/(2*h)*f(x+h))).simplify() == 0

    # One sided 1st derivative "half-way"
    assert (as_finite_diff(f(x).diff(x), [x-h, x+h, x + 3*h, x + 5*h, x + 7*h])
            - 1/(2*h)*(-Integer(11)/(12)*f(x-h) + Integer(17)/(24)*f(x+h)
                       + Rational(3, 8)*f(x + 3*h) - Rational(5, 24)*f(x + 5*h)
                       + Rational(1, 24)*f(x + 7*h))).simplify() == 0

    # Central 2nd derivative at gridpoint
    assert (as_finite_diff(f(x).diff(x, 2), [x-h, x, x+h]) -
            h**-2 * (f(x-h) + f(x+h) - 2*f(x))).simplify() == 0

    assert (as_finite_diff(f(x).diff(x, 2), [x - 2*h, x-h, x, x+h, x + 2*h]) -
            h**-2 * (-Rational(1, 12)*(f(x - 2*h) + f(x + 2*h)) +
                     Rational(4, 3)*(f(x+h) + f(x-h)) - Rational(5, 2)*f(x))).simplify() == 0

    # Central 2nd derivative "half-way"
    assert (as_finite_diff(f(x).diff(x, 2), [x - 3*h, x-h, x+h, x + 3*h]) -
            (2*h)**-2 * (Rational(1, 2)*(f(x - 3*h) + f(x + 3*h)) -
                         Rational(1, 2)*(f(x+h) + f(x-h)))).simplify() == 0

    # One sided 2nd derivative at gridpoint
    assert (as_finite_diff(f(x).diff(x, 2), [x, x+h, x + 2*h, x + 3*h]) -
            h**-2 * (2*f(x) - 5*f(x+h) +
                     4*f(x+2*h) - f(x+3*h))).simplify() == 0

    # One sided 2nd derivative at "half-way"
    assert (as_finite_diff(f(x).diff(x, 2), [x-h, x+h, x + 3*h, x + 5*h]) -
            (2*h)**-2 * (Rational(3, 2)*f(x-h) - Rational(7, 2)*f(x+h) + Rational(5, 2)*f(x + 3*h) -
                         Rational(1, 2)*f(x + 5*h))).simplify() == 0

    # Central 3rd derivative at gridpoint
    assert (as_finite_diff(f(x).diff(x, 3)) -
            (-f(x - 3/Integer(2)) + 3*f(x - 1/Integer(2)) -
             3*f(x + 1/Integer(2)) + f(x + 3/Integer(2)))).simplify() == 0

    assert (as_finite_diff(
        f(x).diff(x, 3), [x - 3*h, x - 2*h, x-h, x, x+h, x + 2*h, x + 3*h]) -
        h**-3 * (Rational(1, 8)*(f(x - 3*h) - f(x + 3*h)) - f(x - 2*h) +
                 f(x + 2*h) + Rational(13, 8)*(f(x-h) - f(x+h)))).simplify() == 0

    # Central 3rd derivative at "half-way"
    assert (as_finite_diff(f(x).diff(x, 3), [x - 3*h, x-h, x+h, x + 3*h]) -
            (2*h)**-3 * (f(x + 3*h)-f(x - 3*h) +
                         3*(f(x-h)-f(x+h)))).simplify() == 0

    # One sided 3rd derivative at gridpoint
    assert (as_finite_diff(f(x).diff(x, 3), [x, x+h, x + 2*h, x + 3*h]) -
            h**-3 * (f(x + 3*h)-f(x) + 3*(f(x+h)-f(x + 2*h)))).simplify() == 0

    # One sided 3rd derivative at "half-way"
    assert (as_finite_diff(f(x).diff(x, 3), [x-h, x+h, x + 3*h, x + 5*h]) -
            (2*h)**-3 * (f(x + 5*h)-f(x-h) +
                         3*(f(x+h)-f(x + 3*h)))).simplify() == 0

    assert as_finite_diff(f(x).diff(x, 2)) == -2*f(x) + f(x - 1) + f(x + 1)

    d2fdxdy = f(x, y).diff(x, y)
    assert as_finite_diff(d2fdxdy, wrt=x) == (-f(x - Rational(1, 2), y) +
                                              f(x + Rational(1, 2), y))
    pytest.raises(ValueError, lambda: as_finite_diff(d2fdxdy))
    pytest.raises(ValueError, lambda: as_finite_diff(f(x).diff(x, 2),
                                                     [x, x + h]))
<|endoftext|>