<commit_before># run with:
# python -m unittest discover

import unittest
import logging
import json
import server
from flask_api import status    # HTTP Status Codes

# Status Codes
HTTP_200_OK = status.HTTP_200_OK
HTTP_201_CREATED = status.HTTP_201_CREATED
HTTP_204_NO_CONTENT = status.HTTP_204_NO_CONTENT
HTTP_400_BAD_REQUEST = status.HTTP_400_BAD_REQUEST
HTTP_404_NOT_FOUND = status.HTTP_404_NOT_FOUND
HTTP_409_CONFLICT = status.HTTP_409_CONFLICT

######################################################################
#  T E S T   C A S E S
######################################################################
class TestRecommendationServer(unittest.TestCase):
    @classmethod
    def setUpClass(self):
        server.initialize_mysql(test=True)

    @classmethod
    def tearDownClass(self):
        server.conn.close()

    def setUp(self):
        server.app.debug = True
        self.app = server.app.test_client()
        server.conn.execute("TRUNCATE TABLE recommendations")
        server.conn.execute("INSERT INTO `recommendations` VALUES (1,1,2,'x-sell',5),(2,1,3,'up-sell',5),(3,2,4,'up-sell',5)")

    def test_index(self):
        resp = self.app.get('/')
        self.assertTrue ('Recommendations REST API Service' in resp.data)
        self.assertTrue( resp.status_code == HTTP_200_OK )

    def test_get_recommendation_list(self):
        resp = self.app.get('/recommendations')
        self.assertTrue( resp.status_code == HTTP_200_OK )
        self.assertTrue( len(resp.data) > 0 )

    def test_get_recommendation(self):
        resp = self.app.get('/recommendations/3')
        self.assertEqual( resp.status_code, HTTP_200_OK )
        data = json.loads(resp.data)
        self.assertEqual (data['parent_product_id'], 2)

    def test_get_recommendation_not_found(self):
        resp = self.app.get('/recommendations/0')
        self.assertEqual( resp.status_code, HTTP_404_NOT_FOUND )

    def test_delete_recommendation_pass(self):
        # save the current number of recommendations for later comparison
        recommendation_count = self.get_recommendation_count()
        # delete a recommendation that doesn't exist
        resp = self.app.delete('/recommendations/1', content_type='application/json')
        self.assertTrue( resp.status_code == HTTP_204_NO_CONTENT )
        self.assertTrue( len(resp.data) == 0 )
        new_count = self.get_recommendation_count()
        self.assertTrue ( new_count == recommendation_count - 1)

    def test_delete_recommendation_fail(self):
        resp_get = self.app.get('/recommendations/2')
        self.assertTrue ( resp_get.status_code == HTTP_200_OK )
        resp_delete = self.app.delete('/recommendations/2', content_type='application/json')
        self.assertTrue( resp_delete.status_code == HTTP_204_NO_CONTENT )
        resp_get_deleted = self.app.get('recommendations/2')
        self.assertTrue ( resp_get_deleted.status_code == HTTP_404_NOT_FOUND )

    def test_get_recommendation_by_type(self):
        log = logging.getLogger("Test GET recommendations by type")
        resp = self.app.get('/recommendations?type=x-sell')
        self.assertTrue(resp.status_code == HTTP_200_OK)
        data = json.loads(resp.data)
        for data_point in data:
            log.debug(data_point)
            self.assertTrue(data_point["type"] == "x-sell",
                            msg=data_point["type"])

    def test_clicked_recommendation_pass(self):
        resp = self.app.get('/recommendations/3')
        data = json.loads(resp.data)
        old_priority = data['priority']
        resp = self.app.put('/recommendations/3/clicked', content_type='application/json')
        self.assertTrue( resp.status_code == HTTP_200_OK )
        resp = self.app.get('/recommendations/3')
        data = json.loads(resp.data)
        new_priority = data['priority']
        if (old_priority == 1):
            self.assertTrue( new_priority == old_priority )
        else:
            self.assertTrue( new_priority == old_priority - 1 )

    def test_clicked_recommendation_id_not_found(self):
        resp = self.app.put('/recommendations/0/clicked', content_type='application/json')
        self.assertEqual( resp.status_code, HTTP_404_NOT_FOUND )

    def test_get_recommendation_by_non_existent_type(self):
        resp = self.app.get('/recommendations?type=foo')
        self.assertTrue(resp.status_code == HTTP_200_OK)
        data = json.loads(resp.data)
        self.assertFalse(data)

    def test_get_recommendation_by_parent_id(self):
        log = logging.getLogger("Test GET recommendations by parent_product_id")

        resp = self.app.get('/recommendations?product-id=1')
        data = json.loads(resp.data)
        self.assertTrue(resp.status_code == HTTP_200_OK, msg=data)
        test_result = all(data_point["parent_product_id"] == 1 for data_point in data)
        self.assertTrue(test_result)

    def test_get_recommendation_by_non_existent_parent_id(self):
        resp = self.app.get('/recommendations?product-id=foo')
        data = json.loads(resp.data)
        self.assertTrue(resp.status_code == HTTP_200_OK, msg=data)
        self.assertFalse(data)

    def test_get_recommendation_by_type_and_parent_id(self):
        log = logging.getLogger("Test GET recommendations by parent_product_id and type")
        log.warning("result with spaces between queries are errorneous.")

        resp = self.app.get('/recommendations?product-id=1&type=up-sell')
        data = json.loads(resp.data)
        self.assertTrue(resp.status_code == HTTP_200_OK, msg=data)
        self.assertFalse(data)

    def test_get_recommendation_by_type_and_non_existent_parent_id(self):
        resp = self.app.get('/recommendations?product-id=foo&type=up-sell')
        data = json.loads(resp.data)
        self.assertTrue(resp.status_code == HTTP_200_OK, msg=data)
        self.assertFalse(data)

    def test_get_recommendation_by_parent_id_and_non_existent_type(self):
        resp = self.app.get('/recommendations?product-id=1&type=bar')
        data = json.loads(resp.data)
        self.assertTrue(resp.status_code == HTTP_200_OK, msg=data)
        self.assertFalse(data)

    def test_get_recommendation_by_non_existent_parent_id_and_non_existent_type(self):
        resp = self.app.get('/recommendations?product-id=foo&type=bar')
        data = json.loads(resp.data)
        self.assertTrue(resp.status_code == HTTP_200_OK, msg=data)
        self.assertFalse(data)

    def test_create_recommendation(self):
        recommendation_count = self.get_recommendation_count()
        new_recommendation = {'parent_product_id': '2', 'priority': '5', 'related_product_id':'2', 'type': 'x-sell'}
        data = json.dumps(new_recommendation)
        resp = self.app.post('/recommendations', data=data, content_type='application/json')
        self.assertTrue( resp.status_code == HTTP_201_CREATED )
        new_json = json.loads(resp.data)
        self.assertEqual (new_json['parent_product_id'], 2)
        self.assertEqual (new_json['priority'], 5)
        self.assertEqual (new_json['related_product_id'], 2)
        self.assertEqual (new_json['type'], 'x-sell')
        resp = self.app.get('/recommendations')
        data = json.loads(resp.data)
        self.assertEqual( resp.status_code, HTTP_200_OK )
        self.assertEqual( len(data), recommendation_count + 1 )
        self.assertIn( new_json, data )

    def test_create_recommendation_with_no_data(self):
        resp = self.app.post('/recommendations', content_type='application/json')
        data = json.loads(resp.data)
        self.assertTrue( resp.status_code == HTTP_400_BAD_REQUEST )

    def test_create_recommendation_with_no_parent_product_id(self):
        new_recommendation = {'priority': '5', 'related_product_id':'2', 'type': 'x-sell'}
        data = json.dumps(new_recommendation)
        resp = self.app.post('/recommendations', data=data, content_type='application/json')
        self.assertEqual( resp.status_code, HTTP_400_BAD_REQUEST )

    def test_create_recommendation_with_no_related_product_id(self):
        new_recommendation = {'parent_product_id': '2', 'priority': '5', 'type': 'x-sell'}
        data = json.dumps(new_recommendation)
        resp = self.app.post('/recommendations', data=data, content_type='application/json')
        self.assertEqual( resp.status_code, HTTP_400_BAD_REQUEST )

    def test_create_recommendation_with_no_priority(self):
        new_recommendation = {'parent_product_id': '2', 'related_product_id':'2', 'type': 'x-sell'}
        data = json.dumps(new_recommendation)
        resp = self.app.post('/recommendations', data=data, content_type='application/json')
        self.assertEqual( resp.status_code, HTTP_400_BAD_REQUEST )

    def test_create_recommendation_with_no_type(self):
        new_recommendation = {'parent_product_id': '2', 'priority': '5', 'related_product_id':'2'}
        data = json.dumps(new_recommendation)
        resp = self.app.post('/recommendations', data=data, content_type='application/json')
        self.assertEqual( resp.status_code, HTTP_400_BAD_REQUEST )

    def test_create_recommendation_with_no_parent_product_id_and_related_product_id(self):
        new_recommendation = {'priority': '5', 'type': 'x-sell'}
        data = json.dumps(new_recommendation)
        resp = self.app.post('/recommendations', data=data, content_type='application/json')
        self.assertEqual( resp.status_code, HTTP_400_BAD_REQUEST )

    def test_create_recommendation_with_no_parent_product_id_and_priority(self):
        new_recommendation = {'related_product_id':'2', 'type': 'x-sell'}
        data = json.dumps(new_recommendation)
        resp = self.app.post('/recommendations', data=data, content_type='application/json')
        self.assertEqual( resp.status_code, HTTP_400_BAD_REQUEST )

    def test_create_recommendation_with_no_priority_and_related_product_id(self):
        new_recommendation = {'parent_product_id': '2', 'type': 'x-sell'}
        data = json.dumps(new_recommendation)
        resp = self.app.post('/recommendations', data=data, content_type='application/json')
        self.assertEqual( resp.status_code, HTTP_400_BAD_REQUEST )

    def test_create_recommendation_with_no_priority_and_type(self):
        new_recommendation = {'parent_product_id': '2', 'related_product_id':'2'}
        data = json.dumps(new_recommendation)
        resp = self.app.post('/recommendations', data=data, content_type='application/json')
        self.assertEqual( resp.status_code, HTTP_400_BAD_REQUEST )

    def test_create_recommendation_with_no_related_product_id_and_type(self):
        new_recommendation = {'parent_product_id': '2', 'priority': '5'}
        data = json.dumps(new_recommendation)
        resp = self.app.post('/recommendations', data=data, content_type='application/json')
        self.assertEqual( resp.status_code, HTTP_400_BAD_REQUEST )

    def test_update_recommendation(self):
        new_recommendation = {'parent_product_id': '2', 'priority': '5', 'related_product_id':'4', 'type': 'x-sell'}
        data = json.dumps(new_recommendation)
        resp = self.app.put('/recommendations/3', data=data, content_type='application/json')
        self.assertEqual( resp.status_code, HTTP_200_OK )
        new_json = json.loads(resp.data)
        self.assertEqual (new_json['type'], 'x-sell')

    def test_update_recommendation_with_no_data(self):
        resp = self.app.put('/recommendations/3', data=None, content_type='application/json')
        self.assertEqual( resp.status_code, HTTP_400_BAD_REQUEST )

    def test_update_recommendation_with_no_parent_product_id(self):
        new_recommendation = {'priority': '5', 'related_product_id':'4', 'type': 'x-sell'}
        data = json.dumps(new_recommendation)
        resp = self.app.put('/recommendations/2', data=data, content_type='application/json')
        self.assertEqual( resp.status_code, HTTP_400_BAD_REQUEST )

    def test_update_recommendation_not_found(self):
        new_recommendation = {'parent_product_id': '2', 'priority': '5', 'related_product_id':'4', 'type': 'up-sell'}
        data = json.dumps(new_recommendation)
        resp = self.app.put('/recommendations/0', data=data, content_type='application/json')
        self.assertEquals( resp.status_code, HTTP_404_NOT_FOUND )

    def test_update_recommendation_idempotency(self):
        new_recommendation = {'parent_product_id': '1', 'priority': '3', 'related_product_id':'3', 'type': 'up-sell'}
        data = json.dumps(new_recommendation)
        resp = self.app.put('/recommendations/1', data=data, content_type='application/json')
        self.assertEquals( resp.status_code, HTTP_200_OK )
        new_json = json.loads(resp.data)
        self.assertEqual (new_json['type'], 'x-sell')
        self.assertEqual (new_json['priority'], 5)
        self.assertEqual (new_json['related_product_id'], 2)

    def test_initialize_db(self):
        server.initialize_mysql()
        self.assertTrue(server.conn != None)

    def test_is_valid_errors_valueerror(self):
        new_recommendation = {'parent_product_id': 'a', 'priority': '3', 'related_product_id':'3', 'type': 'up-sell'}
        data = json.dumps(new_recommendation)
        (message, status) = server.is_valid(data)
        self.assertEqual(status, False)
        data = json.dumps(message)
        self.assertTrue('Data value error' in data)

    def test_is_valid_errors_typeerror(self):
        new_recommendation = {'parent_product_id': [1], 'priority': '3', 'related_product_id':'3', 'type': 'up-sell'}
        data = json.dumps(new_recommendation)
        (message, status) = server.is_valid(data)
        self.assertEqual(status, False)
        data = json.dumps(message)
        self.assertTrue('Data type error' in data)

######################################################################
# Utility functions
######################################################################

    def get_recommendation_count(self):
        # save the current number of recommendations
        resp = self.app.get('/recommendations')
        self.assertTrue( resp.status_code == HTTP_200_OK )
        data = json.loads(resp.data)
        return len(data)

######################################################################
#   M A I N
######################################################################
if __name__ == '__main__':
    unittest.main()
<commit_msg>removing only test rows instead of truncate table<commit_after># run with:
# python -m unittest discover

import unittest
import logging
import json
import server
from flask_api import status    # HTTP Status Codes

# Status Codes
HTTP_200_OK = status.HTTP_200_OK
HTTP_201_CREATED = status.HTTP_201_CREATED
HTTP_204_NO_CONTENT = status.HTTP_204_NO_CONTENT
HTTP_400_BAD_REQUEST = status.HTTP_400_BAD_REQUEST
HTTP_404_NOT_FOUND = status.HTTP_404_NOT_FOUND
HTTP_409_CONFLICT = status.HTTP_409_CONFLICT

######################################################################
#  T E S T   C A S E S
######################################################################
class TestRecommendationServer(unittest.TestCase):
    @classmethod
    def setUpClass(self):
        server.initialize_mysql(test=True)

    @classmethod
    def tearDownClass(self):
        server.conn.close()

    def setUp(self):
        server.app.debug = True
        self.app = server.app.test_client()
        server.conn.execute("DELETE FROM `recommendations` WHERE id in (1,2,3)")
        server.conn.execute("INSERT INTO `recommendations` VALUES (1,1,2,'x-sell',5),(2,1,3,'up-sell',5),(3,2,4,'up-sell',5)")

    def test_index(self):
        resp = self.app.get('/')
        self.assertTrue ('Recommendations REST API Service' in resp.data)
        self.assertTrue( resp.status_code == HTTP_200_OK )

    def test_get_recommendation_list(self):
        resp = self.app.get('/recommendations')
        self.assertTrue( resp.status_code == HTTP_200_OK )
        self.assertTrue( len(resp.data) > 0 )

    def test_get_recommendation(self):
        resp = self.app.get('/recommendations/3')
        self.assertEqual( resp.status_code, HTTP_200_OK )
        data = json.loads(resp.data)
        self.assertEqual (data['parent_product_id'], 2)

    def test_get_recommendation_not_found(self):
        resp = self.app.get('/recommendations/0')
        self.assertEqual( resp.status_code, HTTP_404_NOT_FOUND )

    def test_delete_recommendation_pass(self):
        # save the current number of recommendations for later comparison
        recommendation_count = self.get_recommendation_count()
        # delete a recommendation that doesn't exist
        resp = self.app.delete('/recommendations/1', content_type='application/json')
        self.assertTrue( resp.status_code == HTTP_204_NO_CONTENT )
        self.assertTrue( len(resp.data) == 0 )
        new_count = self.get_recommendation_count()
        self.assertTrue ( new_count == recommendation_count - 1)

    def test_delete_recommendation_fail(self):
        resp_get = self.app.get('/recommendations/2')
        self.assertTrue ( resp_get.status_code == HTTP_200_OK )
        resp_delete = self.app.delete('/recommendations/2', content_type='application/json')
        self.assertTrue( resp_delete.status_code == HTTP_204_NO_CONTENT )
        resp_get_deleted = self.app.get('recommendations/2')
        self.assertTrue ( resp_get_deleted.status_code == HTTP_404_NOT_FOUND )

    def test_get_recommendation_by_type(self):
        log = logging.getLogger("Test GET recommendations by type")
        resp = self.app.get('/recommendations?type=x-sell')
        self.assertTrue(resp.status_code == HTTP_200_OK)
        data = json.loads(resp.data)
        for data_point in data:
            log.debug(data_point)
            self.assertTrue(data_point["type"] == "x-sell",
                            msg=data_point["type"])

    def test_clicked_recommendation_pass(self):
        resp = self.app.get('/recommendations/3')
        data = json.loads(resp.data)
        old_priority = data['priority']
        resp = self.app.put('/recommendations/3/clicked', content_type='application/json')
        self.assertTrue( resp.status_code == HTTP_200_OK )
        resp = self.app.get('/recommendations/3')
        data = json.loads(resp.data)
        new_priority = data['priority']
        if (old_priority == 1):
            self.assertTrue( new_priority == old_priority )
        else:
            self.assertTrue( new_priority == old_priority - 1 )

    def test_clicked_recommendation_id_not_found(self):
        resp = self.app.put('/recommendations/0/clicked', content_type='application/json')
        self.assertEqual( resp.status_code, HTTP_404_NOT_FOUND )

    def test_get_recommendation_by_non_existent_type(self):
        resp = self.app.get('/recommendations?type=foo')
        self.assertTrue(resp.status_code == HTTP_200_OK)
        data = json.loads(resp.data)
        self.assertFalse(data)

    def test_get_recommendation_by_parent_id(self):
        log = logging.getLogger("Test GET recommendations by parent_product_id")

        resp = self.app.get('/recommendations?product-id=1')
        data = json.loads(resp.data)
        self.assertTrue(resp.status_code == HTTP_200_OK, msg=data)
        test_result = all(data_point["parent_product_id"] == 1 for data_point in data)
        self.assertTrue(test_result)

    def test_get_recommendation_by_non_existent_parent_id(self):
        resp = self.app.get('/recommendations?product-id=foo')
        data = json.loads(resp.data)
        self.assertTrue(resp.status_code == HTTP_200_OK, msg=data)
        self.assertFalse(data)

    def test_get_recommendation_by_type_and_parent_id(self):
        log = logging.getLogger("Test GET recommendations by parent_product_id and type")
        log.warning("result with spaces between queries are errorneous.")

        resp = self.app.get('/recommendations?product-id=1&type=up-sell')
        data = json.loads(resp.data)
        self.assertTrue(resp.status_code == HTTP_200_OK, msg=data)
        self.assertFalse(data)

    def test_get_recommendation_by_type_and_non_existent_parent_id(self):
        resp = self.app.get('/recommendations?product-id=foo&type=up-sell')
        data = json.loads(resp.data)
        self.assertTrue(resp.status_code == HTTP_200_OK, msg=data)
        self.assertFalse(data)

    def test_get_recommendation_by_parent_id_and_non_existent_type(self):
        resp = self.app.get('/recommendations?product-id=1&type=bar')
        data = json.loads(resp.data)
        self.assertTrue(resp.status_code == HTTP_200_OK, msg=data)
        self.assertFalse(data)

    def test_get_recommendation_by_non_existent_parent_id_and_non_existent_type(self):
        resp = self.app.get('/recommendations?product-id=foo&type=bar')
        data = json.loads(resp.data)
        self.assertTrue(resp.status_code == HTTP_200_OK, msg=data)
        self.assertFalse(data)

    def test_create_recommendation(self):
        recommendation_count = self.get_recommendation_count()
        new_recommendation = {'parent_product_id': '2', 'priority': '5', 'related_product_id':'2', 'type': 'x-sell'}
        data = json.dumps(new_recommendation)
        resp = self.app.post('/recommendations', data=data, content_type='application/json')
        self.assertTrue( resp.status_code == HTTP_201_CREATED )
        new_json = json.loads(resp.data)
        self.assertEqual (new_json['parent_product_id'], 2)
        self.assertEqual (new_json['priority'], 5)
        self.assertEqual (new_json['related_product_id'], 2)
        self.assertEqual (new_json['type'], 'x-sell')
        resp = self.app.get('/recommendations')
        data = json.loads(resp.data)
        self.assertEqual( resp.status_code, HTTP_200_OK )
        self.assertEqual( len(data), recommendation_count + 1 )
        self.assertIn( new_json, data )

    def test_create_recommendation_with_no_data(self):
        resp = self.app.post('/recommendations', content_type='application/json')
        data = json.loads(resp.data)
        self.assertTrue( resp.status_code == HTTP_400_BAD_REQUEST )

    def test_create_recommendation_with_no_parent_product_id(self):
        new_recommendation = {'priority': '5', 'related_product_id':'2', 'type': 'x-sell'}
        data = json.dumps(new_recommendation)
        resp = self.app.post('/recommendations', data=data, content_type='application/json')
        self.assertEqual( resp.status_code, HTTP_400_BAD_REQUEST )

    def test_create_recommendation_with_no_related_product_id(self):
        new_recommendation = {'parent_product_id': '2', 'priority': '5', 'type': 'x-sell'}
        data = json.dumps(new_recommendation)
        resp = self.app.post('/recommendations', data=data, content_type='application/json')
        self.assertEqual( resp.status_code, HTTP_400_BAD_REQUEST )

    def test_create_recommendation_with_no_priority(self):
        new_recommendation = {'parent_product_id': '2', 'related_product_id':'2', 'type': 'x-sell'}
        data = json.dumps(new_recommendation)
        resp = self.app.post('/recommendations', data=data, content_type='application/json')
        self.assertEqual( resp.status_code, HTTP_400_BAD_REQUEST )

    def test_create_recommendation_with_no_type(self):
        new_recommendation = {'parent_product_id': '2', 'priority': '5', 'related_product_id':'2'}
        data = json.dumps(new_recommendation)
        resp = self.app.post('/recommendations', data=data, content_type='application/json')
        self.assertEqual( resp.status_code, HTTP_400_BAD_REQUEST )

    def test_create_recommendation_with_no_parent_product_id_and_related_product_id(self):
        new_recommendation = {'priority': '5', 'type': 'x-sell'}
        data = json.dumps(new_recommendation)
        resp = self.app.post('/recommendations', data=data, content_type='application/json')
        self.assertEqual( resp.status_code, HTTP_400_BAD_REQUEST )

    def test_create_recommendation_with_no_parent_product_id_and_priority(self):
        new_recommendation = {'related_product_id':'2', 'type': 'x-sell'}
        data = json.dumps(new_recommendation)
        resp = self.app.post('/recommendations', data=data, content_type='application/json')
        self.assertEqual( resp.status_code, HTTP_400_BAD_REQUEST )

    def test_create_recommendation_with_no_priority_and_related_product_id(self):
        new_recommendation = {'parent_product_id': '2', 'type': 'x-sell'}
        data = json.dumps(new_recommendation)
        resp = self.app.post('/recommendations', data=data, content_type='application/json')
        self.assertEqual( resp.status_code, HTTP_400_BAD_REQUEST )

    def test_create_recommendation_with_no_priority_and_type(self):
        new_recommendation = {'parent_product_id': '2', 'related_product_id':'2'}
        data = json.dumps(new_recommendation)
        resp = self.app.post('/recommendations', data=data, content_type='application/json')
        self.assertEqual( resp.status_code, HTTP_400_BAD_REQUEST )

    def test_create_recommendation_with_no_related_product_id_and_type(self):
        new_recommendation = {'parent_product_id': '2', 'priority': '5'}
        data = json.dumps(new_recommendation)
        resp = self.app.post('/recommendations', data=data, content_type='application/json')
        self.assertEqual( resp.status_code, HTTP_400_BAD_REQUEST )

    def test_update_recommendation(self):
        new_recommendation = {'parent_product_id': '2', 'priority': '5', 'related_product_id':'4', 'type': 'x-sell'}
        data = json.dumps(new_recommendation)
        resp = self.app.put('/recommendations/3', data=data, content_type='application/json')
        self.assertEqual( resp.status_code, HTTP_200_OK )
        new_json = json.loads(resp.data)
        self.assertEqual (new_json['type'], 'x-sell')

    def test_update_recommendation_with_no_data(self):
        resp = self.app.put('/recommendations/3', data=None, content_type='application/json')
        self.assertEqual( resp.status_code, HTTP_400_BAD_REQUEST )

    def test_update_recommendation_with_no_parent_product_id(self):
        new_recommendation = {'priority': '5', 'related_product_id':'4', 'type': 'x-sell'}
        data = json.dumps(new_recommendation)
        resp = self.app.put('/recommendations/2', data=data, content_type='application/json')
        self.assertEqual( resp.status_code, HTTP_400_BAD_REQUEST )

    def test_update_recommendation_not_found(self):
        new_recommendation = {'parent_product_id': '2', 'priority': '5', 'related_product_id':'4', 'type': 'up-sell'}
        data = json.dumps(new_recommendation)
        resp = self.app.put('/recommendations/0', data=data, content_type='application/json')
        self.assertEquals( resp.status_code, HTTP_404_NOT_FOUND )

    def test_update_recommendation_idempotency(self):
        new_recommendation = {'parent_product_id': '1', 'priority': '3', 'related_product_id':'3', 'type': 'up-sell'}
        data = json.dumps(new_recommendation)
        resp = self.app.put('/recommendations/1', data=data, content_type='application/json')
        self.assertEquals( resp.status_code, HTTP_200_OK )
        new_json = json.loads(resp.data)
        self.assertEqual (new_json['type'], 'x-sell')
        self.assertEqual (new_json['priority'], 5)
        self.assertEqual (new_json['related_product_id'], 2)

    def test_initialize_db(self):
        server.initialize_mysql()
        self.assertTrue(server.conn != None)

    def test_is_valid_errors_valueerror(self):
        new_recommendation = {'parent_product_id': 'a', 'priority': '3', 'related_product_id':'3', 'type': 'up-sell'}
        data = json.dumps(new_recommendation)
        (message, status) = server.is_valid(data)
        self.assertEqual(status, False)
        data = json.dumps(message)
        self.assertTrue('Data value error' in data)

    def test_is_valid_errors_typeerror(self):
        new_recommendation = {'parent_product_id': [1], 'priority': '3', 'related_product_id':'3', 'type': 'up-sell'}
        data = json.dumps(new_recommendation)
        (message, status) = server.is_valid(data)
        self.assertEqual(status, False)
        data = json.dumps(message)
        self.assertTrue('Data type error' in data)

######################################################################
# Utility functions
######################################################################

    def get_recommendation_count(self):
        # save the current number of recommendations
        resp = self.app.get('/recommendations')
        self.assertTrue( resp.status_code == HTTP_200_OK )
        data = json.loads(resp.data)
        return len(data)

######################################################################
#   M A I N
######################################################################
if __name__ == '__main__':
    unittest.main()
<|endoftext|>


<commit_before>from django.http import HttpResponse
from django.shortcuts import render, render_to_response, redirect
from django.template.context import RequestContext
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
from django.db import transaction
from django.core.urlresolvers import reverse, reverse_lazy
from django.contrib import messages
from django.contrib.messages import views
from django.views.generic import edit
from django.views.decorators.http import require_POST
from app import forms
from app import models
from app.forms.toolRegistration import AddToolForm
from app.models.reservation import Reservation
from app.models.tool import Tool
from django.shortcuts import get_object_or_404

@login_required(redirect_field_name='o')
def registerTool(request):
    currentUser = request.user
    if request.method == 'POST':
        tool_form = AddToolForm(request.POST, request.FILES)

        if tool_form.is_valid():
            with transaction.atomic():
                new_tool = tool_form.save(commit=False)
                new_tool.owner = currentUser
                new_tool.status = 'A'
                new_tool.save()
                tool_form.save_m2m()

            register_url = reverse_lazy("toolManagement:registerTool")

            #NOTE: the 'safe' extra_tag allows the string to be autoescaped so that links can be processed by the template.
            #It SHOULD NOT be used unless you need to add a hyperlink to your message!
            messages.success(request,'You have successfully registered a new tool!

 '
                                     'Click here register another tool
 OR
 '
                                     'click here to return to your toolbox.', extra_tags='safe')

            success_url = reverse_lazy("toolManagement:toolbox")
            return redirect(success_url)
        else:
            return render(request, 'registertool.html', RequestContext(request, {'form': tool_form}))
    else:
        tool_form = AddToolForm(initial = {'pickupArrangement': currentUser.pickup_arrangements})
        return render(request, 'registertool.html', RequestContext(request, {'form': tool_form}))

@login_required(redirect_field_name='o')
def viewTool(request, tool_id):
    currentUser = request.user
    tooldata = get_object_or_404(Tool, pk=tool_id)
    isToolOwner = tooldata.owner == currentUser
    context = {'tooldata': tooldata, 'isToolOwner':isToolOwner}
    return render(request, 'tool.html', context)

@login_required(redirect_field_name='o')
def updateTool(request, tool_id):
    tooldata = get_object_or_404(Tool, pk=tool_id)
    if not tooldata.owner == request.user:
        error_url = reverse_lazy("toolManagement:toolbox")
        messages.error(request,'Error! You do not have permission to edit this tool.

 Click here to return to the toolbox.', extra_tags='safe')
        return redirect(error_url)
    if request.method == 'POST':
        tool_form = AddToolForm(request.POST or None, request.FILES or None, instance=tooldata)
        if tool_form.is_valid():
            tool_form.save()

            #NOTE: the 'safe' extra_tag allows the string to be autoescaped so that links can be processed by the template.
            #It SHOULD NOT be used unless you need to add a hyperlink to your message!
            messages.success(request,'Your tool has been successfully updated!

 Click here to go back to your tool.', extra_tags='safe')

            success_url = reverse_lazy("toolManagement:viewTool", kwargs={'tool_id':tool_id})
            return redirect(success_url)
        else:
            return render(request, 'updatetool.html', RequestContext(request, {'form': tool_form}))
    else:
        tool_form = AddToolForm(instance=tooldata)
        return render(request, 'updatetool.html', RequestContext(request, {'form': tool_form}))

@login_required(redirect_field_name='o')
def toolbox(request):
    user = request.user
    homeTools = Tool.objects.filter(owner_id=user).filter(location='H')
    context = {'homeTools': homeTools}
    return render(request, 'toolbox.html', context)<commit_msg>Removed tool filter from homeTools and renamed to myTools<commit_after>from django.http import HttpResponse
from django.shortcuts import render, render_to_response, redirect
from django.template.context import RequestContext
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
from django.db import transaction
from django.core.urlresolvers import reverse, reverse_lazy
from django.contrib import messages
from django.contrib.messages import views
from django.views.generic import edit
from django.views.decorators.http import require_POST
from app import forms
from app import models
from app.forms.toolRegistration import AddToolForm
from app.models.reservation import Reservation
from app.models.tool import Tool
from django.shortcuts import get_object_or_404

@login_required(redirect_field_name='o')
def registerTool(request):
    currentUser = request.user
    if request.method == 'POST':
        tool_form = AddToolForm(request.POST, request.FILES)

        if tool_form.is_valid():
            with transaction.atomic():
                new_tool = tool_form.save(commit=False)
                new_tool.owner = currentUser
                new_tool.status = 'A'
                new_tool.save()
                tool_form.save_m2m()

            register_url = reverse_lazy("toolManagement:registerTool")

            #NOTE: the 'safe' extra_tag allows the string to be autoescaped so that links can be processed by the template.
            #It SHOULD NOT be used unless you need to add a hyperlink to your message!
            messages.success(request,'You have successfully registered a new tool!

 '
                                     'Click here register another tool
 OR
 '
                                     'click here to return to your toolbox.', extra_tags='safe')

            success_url = reverse_lazy("toolManagement:toolbox")
            return redirect(success_url)
        else:
            return render(request, 'registertool.html', RequestContext(request, {'form': tool_form}))
    else:
        tool_form = AddToolForm(initial = {'pickupArrangement': currentUser.pickup_arrangements})
        return render(request, 'registertool.html', RequestContext(request, {'form': tool_form}))

@login_required(redirect_field_name='o')
def viewTool(request, tool_id):
    currentUser = request.user
    tooldata = get_object_or_404(Tool, pk=tool_id)
    isToolOwner = tooldata.owner == currentUser
    context = {'tooldata': tooldata, 'isToolOwner':isToolOwner}
    return render(request, 'tool.html', context)

@login_required(redirect_field_name='o')
def updateTool(request, tool_id):
    tooldata = get_object_or_404(Tool, pk=tool_id)
    if not tooldata.owner == request.user:
        error_url = reverse_lazy("toolManagement:toolbox")
        messages.error(request,'Error! You do not have permission to edit this tool.

 Click here to return to the toolbox.', extra_tags='safe')
        return redirect(error_url)
    if request.method == 'POST':
        tool_form = AddToolForm(request.POST or None, request.FILES or None, instance=tooldata)
        if tool_form.is_valid():
            tool_form.save()

            #NOTE: the 'safe' extra_tag allows the string to be autoescaped so that links can be processed by the template.
            #It SHOULD NOT be used unless you need to add a hyperlink to your message!
            messages.success(request,'Your tool has been successfully updated!

 Click here to go back to your tool.', extra_tags='safe')

            success_url = reverse_lazy("toolManagement:viewTool", kwargs={'tool_id':tool_id})
            return redirect(success_url)
        else:
            return render(request, 'updatetool.html', RequestContext(request, {'form': tool_form}))
    else:
        tool_form = AddToolForm(instance=tooldata)
        return render(request, 'updatetool.html', RequestContext(request, {'form': tool_form}))

@login_required(redirect_field_name='o')
def toolbox(request):
    user = request.user
    myTools = Tool.objects.filter(owner_id=user)
    context = {'myTools': myTools}
    return render(request, 'toolbox.html', context)<|endoftext|>


<commit_before>#!/usr/bin/python

# Enter the virtualenv
import os.path
_activate = os.path.join(os.path.dirname(__file__),
                         'env/bin/activate_this.py')
execfile(_activate, dict(__file__=_activate))

# Add our code to path.
import sys
sys.path.append(os.path.join(os.path.dirname(__file__),
                             'web_scripts/kdc'))

from werkzeug.exceptions import NotFound
from werkzeug.wsgi import SharedDataMiddleware, DispatcherMiddleware

import kdc

def create_app():
    """
    Serves the entire mess, including hack to make index.html work.
    """
    kdc_app = kdc.create_app()

    web_scripts = os.path.join(os.path.dirname(__file__), 'web_scripts')

    def throw_not_found(e, s): raise NotFound()
    static_app = SharedDataMiddleware(throw_not_found, { '/': web_scripts, })
    def index_html_hack(environ, start_response):
        try:
            return static_app(environ, start_response)
        except NotFound, e:
            environ['PATH_INFO'] = environ.get('PATH_INFO', '') + '/index.html'
            try:
                return static_app(environ, start_response)
            except NotFound, e:
                return e(environ, start_response)

    return DispatcherMiddleware(index_html_hack, { '/kdc': kdc_app, })

if __name__ == '__main__':
    from werkzeug.serving import run_simple
    app = create_app()
    run_simple('127.0.0.1', 5000, app, use_debugger=True, use_reloader=True)
<commit_msg>Slightly less awful hack<commit_after>#!/usr/bin/python

# Enter the virtualenv
import os.path
_activate = os.path.join(os.path.dirname(__file__),
                         'env/bin/activate_this.py')
execfile(_activate, dict(__file__=_activate))

# Add our code to path.
import sys
sys.path.append(os.path.join(os.path.dirname(__file__),
                             'web_scripts/kdc'))

from werkzeug.exceptions import NotFound
from werkzeug.wsgi import SharedDataMiddleware, DispatcherMiddleware

import kdc

def create_app():
    """
    Serves the entire mess, including hack to make index.html work.
    """
    kdc_app = kdc.create_app()

    web_scripts = os.path.join(os.path.dirname(__file__), 'web_scripts')

    def with_index_html(environ, start_response):
        environ['PATH_INFO'] = environ.get('PATH_INFO', '') + '/index.html'
        app = SharedDataMiddleware(NotFound(), { '/': web_scripts, })
        return app(environ, start_response)
    static_app = SharedDataMiddleware(with_index_html, { '/': web_scripts, })

    return DispatcherMiddleware(static_app, { '/kdc': kdc_app, })

if __name__ == '__main__':
    from werkzeug.serving import run_simple
    app = create_app()
    run_simple('127.0.0.1', 5000, app, use_debugger=True, use_reloader=True)
<|endoftext|>


<commit_before>import numpy
import pytest

import snuggs

# Fixtures follow the tests. See the end of the file.

def test_integer():
    assert list(snuggs.integer.parseString('1')) == [1]

def test_real():
    assert list(snuggs.real.parseString('1.1')) == [1.1]

def test_int_expr():
    assert snuggs.eval('(+ 1 2)') == 3

def test_int_mult_expr():
    assert snuggs.eval('(+ 1 2 3)') == 6

def test_real_expr():
    assert round(snuggs.eval('(* 0.1 0.2)'), 3) == 0.02

def test_int_real_expr():
    assert snuggs.eval('(+ 2 1.1)') == 3.1

def test_real_int_expr():
    assert snuggs.eval('(+ 1.1 2)') == 3.1

def test_arr_var(ones):
    r = snuggs.eval('(+ foo 0)', foo=ones)
    assert list(r.flatten()) == [1, 1, 1, 1]

def test_arr_lookup(ones):
    r = snuggs.eval('(read 1)', foo=ones)
    assert list(r.flatten()) == [1, 1, 1, 1]

def test_arr_lookup_2(ones):
    r = snuggs.eval('(read 1 1)', foo=ones)
    assert list(r.flatten()) == [1, 1]

def test_arr_take(ones):
    r = snuggs.eval('(take foo 1)', foo=ones)
    assert list(r.flatten()) == [1, 1]
    r = snuggs.eval('(take foo 2)', foo=ones)
    assert list(r.flatten()) == [1, 1]

def test_int_arr_expr(ones):
    result = snuggs.eval('(+ foo 1)', foo=ones)
    assert list(result.flatten()) == [2, 2, 2, 2]

def test_int_arr_expr_by_name(ones):
    result = snuggs.eval('(+ (read 1) 1.5)', foo=ones)
    assert list(result.flatten()) == [2.5, 2.5, 2.5, 2.5]

def test_int_arr_read(ones):
    result = snuggs.eval('(+ (read 1 1) 1.5)', foo=ones)
    assert list(result.flatten()) == [2.5, 2.5]

def test_list(ones):
    result = snuggs.eval(
        '(asarray (take foo 1) (take foo 1) (take bar 1) (take bar 1))',
        foo=ones, bar=ones)
    assert list(result.flatten()) == [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]

def test_eq(ones):
    ones[0][0] = 2
    result = snuggs.eval('(== foo 1)', foo=ones)
    assert list(result.flatten()) == [False, True, True, True]

def test_or(truetrue, truefalse):
    result = snuggs.eval(
        '(| foo bar)', foo=truetrue, bar=truefalse)
    assert list(result.flatten()) == [True, True]

def test_and(truetrue, truefalse):
    result = snuggs.eval(
        '(& foo bar)', foo=truetrue, bar=truefalse)
    assert list(result.flatten()) == [True, False]

def test_ones_like(truefalse):
    result = snuggs.eval("(ones_like foo 'uint8')", foo=truefalse)
    assert list(result.flatten()) == [1.0, 1.0]

def test_full_like(truefalse):
    result = snuggs.eval("(full_like foo 3.14 'float64')", foo=truefalse)
    assert list(result.flatten()) == [3.14, 3.14]
    result = snuggs.eval('(full_like foo 3.14 "float64")', foo=truefalse)
    assert list(result.flatten()) == [3.14, 3.14]

def test_ufunc(truetrue, truefalse):
    result = snuggs.eval(
        '(where (& foo bar) 1 0)', foo=truetrue, bar=truefalse)
    assert list(result.flatten()) == [1.0, 0.0]

def test_partial():
    result = snuggs.eval('((partial * 2) 2)')
    assert result == 4

def test_map_func():
    result = snuggs.eval('(map sqrt (asarray 1 4 9))')
    assert list(result) == [1, 2, 3]

def test_map_partial():
    result = snuggs.eval('(map (partial * 2) (asarray 1 2 3))')
    assert list(result) == [2, 4, 6]

def test_map_asarray():
    result = snuggs.eval('(asarray (map (partial * 2) (asarray 1 2 3)))')
    assert list(result) == [2, 4, 6]

def test_multi_operator_array(ones):
    result = snuggs.eval(
        '(+ ones (/ ones 1 0.5) (* ones 1 3))', ones=ones)
    assert list(result.flatten()) == [6.0] * 4

def test_nil():
    assert snuggs.eval('(== nil nil)')
    assert not snuggs.eval('(== 1 nil)')
    assert not snuggs.eval('(== nil 1)')
    assert snuggs.eval('(!= 1 nil)')
    assert snuggs.eval('(!= nil 1)')

def test_masked_arr():
    foo = numpy.ma.masked_equal(numpy.array([0, 0, 0, 1], dtype='uint8'), 0)
    r = snuggs.eval('(+ foo 1)', foo=foo)
    assert list(r.data.flatten()) == [0, 0, 0, 2]
    assert list(r.flatten()) == [numpy.ma.masked, numpy.ma.masked, numpy.ma.masked, 2]

# Parse and syntax error testing.
def test_missing_closing_paren():
    with pytest.raises(SyntaxError) as excinfo:
        result = snuggs.eval("(+ 1 2")
    assert excinfo.value.lineno == 1
    assert excinfo.value.offset == 7
    exception_options = ['expected a function or operator',
                         'Expected {Forward: ... | Forward: ...}']
    assert str(excinfo.value) in exception_options

def test_missing_func():
    with pytest.raises(SyntaxError) as excinfo:
        result = snuggs.eval("(0 1 2)")
    assert excinfo.value.lineno == 1
    assert excinfo.value.offset == 2
    assert str(excinfo.value) == "'0' is not a function or operator"

def test_missing_func2():
    with pytest.raises(SyntaxError) as excinfo:
        result = snuggs.eval("(# 1 2)")
    assert excinfo.value.lineno == 1
    assert excinfo.value.offset == 2
    exception_options = ['expected a function or operator',
                         'Expected {Forward: ... | Forward: ...}']
    assert str(excinfo.value) in exception_options

def test_undefined_var():
    with pytest.raises(SyntaxError) as excinfo:
        result = snuggs.eval("(+ 1 bogus)")
    assert excinfo.value.lineno == 1
    assert excinfo.value.offset == 6
    assert str(excinfo.value) == "name 'bogus' is not defined"

def test_bogus_higher_order_func():
    with pytest.raises(SyntaxError) as excinfo:
        result = snuggs.eval("((bogus * 2) 2)")
    assert excinfo.value.lineno == 1
    assert excinfo.value.offset == 3
    exception_options = ['expected a function or operator',
                         'Expected {Forward: ... | Forward: ...}']
    assert str(excinfo.value) in exception_options

def test_type_error():
    with pytest.raises(TypeError) as excinfo:
        result = snuggs.eval("(+ 1 'bogus')")

# Fixtures.
@pytest.fixture
def ones():
    return numpy.ones((2, 2))

@pytest.fixture
def truetrue():
    return numpy.array([True, True])

@pytest.fixture
def truefalse():
    return numpy.array([True, False])
<commit_msg>Add test that catches and shows issue #9 fix<commit_after>from collections import OrderedDict

import numpy
import pytest

import snuggs

# Fixtures follow the tests. See the end of the file.

def test_integer():
    assert list(snuggs.integer.parseString('1')) == [1]

def test_real():
    assert list(snuggs.real.parseString('1.1')) == [1.1]

def test_int_expr():
    assert snuggs.eval('(+ 1 2)') == 3

def test_int_mult_expr():
    assert snuggs.eval('(+ 1 2 3)') == 6

def test_real_expr():
    assert round(snuggs.eval('(* 0.1 0.2)'), 3) == 0.02

def test_int_real_expr():
    assert snuggs.eval('(+ 2 1.1)') == 3.1

def test_real_int_expr():
    assert snuggs.eval('(+ 1.1 2)') == 3.1

def test_arr_var(ones):
    r = snuggs.eval('(+ foo 0)', foo=ones)
    assert list(r.flatten()) == [1, 1, 1, 1]

def test_arr_lookup(ones):
    kwargs = OrderedDict((('foo', ones),
                          ('bar', 2.0 * ones),
                          ('a', 3.0 * ones)))
    r = snuggs.eval('(read 1)', kwargs)
    assert list(r.flatten()) == [1, 1, 1, 1]
    # Passed via kwargs this should fail (see issue #9)
    r = snuggs.eval('(read 1)', **kwargs)
    assert list(r.flatten()) != [1, 1, 1, 1]

def test_arr_lookup_2(ones):
    r = snuggs.eval('(read 1 1)', foo=ones)
    assert list(r.flatten()) == [1, 1]

def test_arr_take(ones):
    r = snuggs.eval('(take foo 1)', foo=ones)
    assert list(r.flatten()) == [1, 1]
    r = snuggs.eval('(take foo 2)', foo=ones)
    assert list(r.flatten()) == [1, 1]

def test_int_arr_expr(ones):
    result = snuggs.eval('(+ foo 1)', foo=ones)
    assert list(result.flatten()) == [2, 2, 2, 2]

def test_int_arr_expr_by_name(ones):
    result = snuggs.eval('(+ (read 1) 1.5)', foo=ones)
    assert list(result.flatten()) == [2.5, 2.5, 2.5, 2.5]

def test_int_arr_read(ones):
    result = snuggs.eval('(+ (read 1 1) 1.5)', foo=ones)
    assert list(result.flatten()) == [2.5, 2.5]

def test_list(ones):
    result = snuggs.eval(
        '(asarray (take foo 1) (take foo 1) (take bar 1) (take bar 1))',
        foo=ones, bar=ones)
    assert list(result.flatten()) == [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]

def test_eq(ones):
    ones[0][0] = 2
    result = snuggs.eval('(== foo 1)', foo=ones)
    assert list(result.flatten()) == [False, True, True, True]

def test_or(truetrue, truefalse):
    result = snuggs.eval(
        '(| foo bar)', foo=truetrue, bar=truefalse)
    assert list(result.flatten()) == [True, True]

def test_and(truetrue, truefalse):
    result = snuggs.eval(
        '(& foo bar)', foo=truetrue, bar=truefalse)
    assert list(result.flatten()) == [True, False]

def test_ones_like(truefalse):
    result = snuggs.eval("(ones_like foo 'uint8')", foo=truefalse)
    assert list(result.flatten()) == [1.0, 1.0]

def test_full_like(truefalse):
    result = snuggs.eval("(full_like foo 3.14 'float64')", foo=truefalse)
    assert list(result.flatten()) == [3.14, 3.14]
    result = snuggs.eval('(full_like foo 3.14 "float64")', foo=truefalse)
    assert list(result.flatten()) == [3.14, 3.14]

def test_ufunc(truetrue, truefalse):
    result = snuggs.eval(
        '(where (& foo bar) 1 0)', foo=truetrue, bar=truefalse)
    assert list(result.flatten()) == [1.0, 0.0]

def test_partial():
    result = snuggs.eval('((partial * 2) 2)')
    assert result == 4

def test_map_func():
    result = snuggs.eval('(map sqrt (asarray 1 4 9))')
    assert list(result) == [1, 2, 3]

def test_map_partial():
    result = snuggs.eval('(map (partial * 2) (asarray 1 2 3))')
    assert list(result) == [2, 4, 6]

def test_map_asarray():
    result = snuggs.eval('(asarray (map (partial * 2) (asarray 1 2 3)))')
    assert list(result) == [2, 4, 6]

def test_multi_operator_array(ones):
    result = snuggs.eval(
        '(+ ones (/ ones 1 0.5) (* ones 1 3))', ones=ones)
    assert list(result.flatten()) == [6.0] * 4

def test_nil():
    assert snuggs.eval('(== nil nil)')
    assert not snuggs.eval('(== 1 nil)')
    assert not snuggs.eval('(== nil 1)')
    assert snuggs.eval('(!= 1 nil)')
    assert snuggs.eval('(!= nil 1)')

def test_masked_arr():
    foo = numpy.ma.masked_equal(numpy.array([0, 0, 0, 1], dtype='uint8'), 0)
    r = snuggs.eval('(+ foo 1)', foo=foo)
    assert list(r.data.flatten()) == [0, 0, 0, 2]
    assert list(r.flatten()) == [numpy.ma.masked, numpy.ma.masked, numpy.ma.masked, 2]

# Parse and syntax error testing.
def test_missing_closing_paren():
    with pytest.raises(SyntaxError) as excinfo:
        result = snuggs.eval("(+ 1 2")
    assert excinfo.value.lineno == 1
    assert excinfo.value.offset == 7
    exception_options = ['expected a function or operator',
                         'Expected {Forward: ... | Forward: ...}']
    assert str(excinfo.value) in exception_options

def test_missing_func():
    with pytest.raises(SyntaxError) as excinfo:
        result = snuggs.eval("(0 1 2)")
    assert excinfo.value.lineno == 1
    assert excinfo.value.offset == 2
    assert str(excinfo.value) == "'0' is not a function or operator"

def test_missing_func2():
    with pytest.raises(SyntaxError) as excinfo:
        result = snuggs.eval("(# 1 2)")
    assert excinfo.value.lineno == 1
    assert excinfo.value.offset == 2
    exception_options = ['expected a function or operator',
                         'Expected {Forward: ... | Forward: ...}']
    assert str(excinfo.value) in exception_options

def test_undefined_var():
    with pytest.raises(SyntaxError) as excinfo:
        result = snuggs.eval("(+ 1 bogus)")
    assert excinfo.value.lineno == 1
    assert excinfo.value.offset == 6
    assert str(excinfo.value) == "name 'bogus' is not defined"

def test_bogus_higher_order_func():
    with pytest.raises(SyntaxError) as excinfo:
        result = snuggs.eval("((bogus * 2) 2)")
    assert excinfo.value.lineno == 1
    assert excinfo.value.offset == 3
    exception_options = ['expected a function or operator',
                         'Expected {Forward: ... | Forward: ...}']
    assert str(excinfo.value) in exception_options

def test_type_error():
    with pytest.raises(TypeError) as excinfo:
        result = snuggs.eval("(+ 1 'bogus')")

# Fixtures.
@pytest.fixture
def ones():
    return numpy.ones((2, 2))

@pytest.fixture
def truetrue():
    return numpy.array([True, True])

@pytest.fixture
def truefalse():
    return numpy.array([True, False])
<|endoftext|>


<commit_before>"""
Unit tests for sorter.py

Run with:

$ py.test -f test_sorter.py -v

"""
from datetime import datetime
import unittest

import mock

import sorter

class RenamerTests(unittest.TestCase):
    def test_basename_from_datetime(self):
        case = sorter.basename_from_datetime(
            datetime(2004, 5, 7, 20, 16, 31)
        )
        expected = '2004-05-07 20.16.31'
        self.assertEquals(case, expected)

    def test_filename_from_datetime(self):
        case = sorter.filename_from_datetime(
            datetime(2004, 5, 7, 20, 16, 31),
            'test_examples/img0001.jpg'
        )
        expected = '2004-05-07 20.16.31.jpg'
        self.assertEquals(case, expected)

        case = sorter.filename_from_datetime(
            datetime(2004, 5, 7, 20, 16, 31),
            'test_examples/somefile.JPG'
        )
        expected = '2004-05-07 20.16.31.jpg'
        self.assertEquals(case, expected)

        case = sorter.filename_from_datetime(
            datetime(2004, 5, 7, 20, 16, 31),
            'test_examples/no-ext'
        )
        expected = '2004-05-07 20.16.31'
        self.assertEquals(case, expected)

    def test_folder_from_datetime(self):
        self.assertEquals(
            sorter.folder_from_datetime(datetime(2014, 2, 7)),
            '2014/2014-02'
        )

    def test_path_from_datetime(self):
        case = sorter.path_from_datetime(
            '',
            datetime(2004, 5, 7, 20, 16, 31),
            'test_examples/img0001.jpg'
        )
        expected = '2004/2004-05/2004-05-07 20.16.31.jpg'
        self.assertEquals(case, expected)

        case = sorter.path_from_datetime(
            '/home/user/Dropbox',
            datetime(2004, 5, 7, 20, 16, 31),
            'test_examples/img0001.jpg'
        )
        expected = '/home/user/Dropbox/2004/2004-05/2004-05-07 20.16.31.jpg'
        self.assertEquals(case, expected)

    def test_dest_path(self):
        case = sorter.dest_path(
            '/home/user/Dropbox',
            'test_examples/2004-05-07 20.16.31.jpg'
        )
        expected = '/home/user/Dropbox/2004/2004-05/2004-05-07 20.16.31.jpg'
        self.assertEquals(case, expected)

    def test_ignore_non_images(self):
        self.assertTrue(sorter.is_valid_filename('test.png'))
        self.assertTrue(sorter.is_valid_filename('test.jpg'))
        self.assertTrue(sorter.is_valid_filename('test.jpeg'))
        self.assertTrue(sorter.is_valid_filename('test.jPeg'))
        self.assertTrue(sorter.is_valid_filename('test.PNG'))
        self.assertTrue(sorter.is_valid_filename('test.JPG'))
        self.assertFalse(sorter.is_valid_filename('test.img'))
        self.assertFalse(sorter.is_valid_filename('test.txt'))
        self.assertFalse(sorter.is_valid_filename('test'))

    # def test_duplicate_marker_index(self):
    #     self.assertEquals(
    #         sorter.duplicate_marker_index('2006-09-09 07.00.24-2.jpg'),
    #         2
    #     )
    #     self.assertEquals(
    #         sorter.duplicate_marker_index('2006-09-09 07.00.24-123.jpg'),
    #         123
    #     )
    #     self.assertEquals(
    #         sorter.duplicate_marker_index('2006-09-09 07.00.24.jpg'),
    #         None
    #     )
    #     self.assertEquals(
    #         sorter.duplicate_marker_index('2006-09-09 07.00.24-9.png'),
    #         9
    #     )

    def test_resolve_duplicate(self):
        case = sorter.resolve_duplicate(
            'test_examples/root/2006/2006-09/2006-09-09 07.00.24.jpg'
        )
        expected = 'test_examples/root/2006/2006-09/2006-09-09 07.00.24-2.jpg'
        self.assertEquals(case, expected)

        case = sorter.resolve_duplicate(
            'test_examples/root/2006/2006-09/2006-09-09 07.00.25.jpg'
        )
        expected = 'test_examples/root/2006/2006-09/2006-09-09 07.00.25.jpg'
        self.assertEquals(case, expected)

    @mock.patch('os.makedirs')
    @mock.patch('shutil.move')
    def test_move_file(self, move_mock, makedirs_mock):
        sorter.move_file('/root', 'test_examples/2006-09-09 07.00.24.jpg')
        makedirs_mock.assert_called_with('/root/2006/2006-09')
        move_mock.assert_called_with(
            'test_examples/2006-09-09 07.00.24.jpg',
            '/root/2006/2006-09/2006-09-09 07.00.24.jpg'
        )

        # Ignore non-images
        makedirs_mock.reset_mock()
        move_mock.reset_mock()
        sorter.move_file('/root', 'test_examples/no_image.txt')
        makedirs_mock.assert_not_called()
        move_mock.assert_not_called()

        # Don't overwrite existing images.
        makedirs_mock.reset_mock()
        move_mock.reset_mock()
        sorter.move_file(
            'test_examples/root/',
            'test_examples/2006-09-09 07.00.24.jpg'
        )
        makedirs_mock.assert_called_with('test_examples/root/2006/2006-09')
        move_mock.assert_called_with(
            'test_examples/2006-09-09 07.00.24.jpg',
            'test_examples/root/2006/2006-09/2006-09-09 07.00.24-2.jpg'
        )

class CreationDateTests(unittest.TestCase):
    def test_file_creation_date(self):
        self.assertEquals(
            sorter.file_creation_date('test_examples/2004-05-07 20.16.31.jpg'),
            datetime(2004, 5, 7, 11, 16, 31)
        )

        self.assertEquals(
            sorter.file_creation_date('test_examples/2006-09-09 07.00.24.jpg'),
            datetime(2006, 9, 8, 22, 0, 24)
        )

        self.assertEquals(
            sorter.file_creation_date('test_examples/2014-02-06 09.15.17.jpg'),
            datetime(2014, 2, 6, 9, 15, 17)
        )

    def test_exif_creation_date(self):
        self.assertEquals(
            sorter.exif_creation_date('test_examples/2004-05-07 20.16.31.jpg'),
            datetime(2004, 5, 7, 20, 16, 31)
        )

        self.assertEquals(
            sorter.exif_creation_date('test_examples/2006-09-09 07.00.24.jpg'),
            datetime(2006, 9, 9, 7, 0, 24)
        )

        self.assertEquals(
            sorter.exif_creation_date('test_examples/2014-02-06 09.15.17.jpg'),
            datetime(2014, 2, 6, 9, 15, 17)
        )

        self.assertIsNone(
            sorter.exif_creation_date('test_examples/no-exif.jpg'),
        )

        self.assertIsNone(
            sorter.exif_creation_date('test_examples/test.png'),
        )

    def test_creation_date(self):
        self.assertEquals(
            sorter.creation_date('test_examples/2004-05-07 20.16.31.jpg'),
            datetime(2004, 5, 7, 20, 16, 31)
        )

        self.assertEquals(
            sorter.creation_date('test_examples/2006-09-09 07.00.24.jpg'),
            datetime(2006, 9, 9, 7, 0, 24)
        )

        self.assertEquals(
            sorter.creation_date('test_examples/2014-02-06 09.15.17.jpg'),
            datetime(2014, 2, 6, 9, 15, 17)
        )

        self.assertEquals(
            sorter.creation_date('test_examples/no-exif.jpg'),
            datetime(2014, 2, 23, 21, 47, 14)
        )

        self.assertEquals(
            sorter.creation_date('test_examples/test.png'),
            datetime(2014, 3, 8, 18, 31, 35)
        )
<commit_msg>Reset test file mtimes to fix tests.<commit_after>"""
Unit tests for sorter.py

Run with:

$ py.test -f test_sorter.py -v

"""
from datetime import datetime
import os
import time
import unittest

import mock

import sorter

def set_mtime(path, dt):
    mtime = time.mktime(dt.timetuple())
    os.utime(path, (-1, mtime))

def reset_mtimes():
    """
    Reset the mtimes on our test files because git doesn't keep them.
    """
    set_mtime(
        'test_examples/2004-05-07 20.16.31.jpg',
        datetime(2004, 5, 7, 11, 16, 31)
    )
    set_mtime(
        'test_examples/2006-09-09 07.00.24.jpg',
        datetime(2006, 9, 8, 22, 0, 24)
    )
    set_mtime(
        'test_examples/2014-02-06 09.15.17.jpg',
        datetime(2014, 2, 6, 9, 15, 17)
    )
    set_mtime(
        'test_examples/no-exif.jpg',
        datetime(2014, 2, 23, 21, 47, 14)
    )
    set_mtime(
        'test_examples/test.png',
        datetime(2014, 3, 8, 18, 31, 35)
    )

class RenamerTests(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        reset_mtimes()

    def test_basename_from_datetime(self):
        case = sorter.basename_from_datetime(
            datetime(2004, 5, 7, 20, 16, 31)
        )
        expected = '2004-05-07 20.16.31'
        self.assertEquals(case, expected)

    def test_filename_from_datetime(self):
        case = sorter.filename_from_datetime(
            datetime(2004, 5, 7, 20, 16, 31),
            'test_examples/img0001.jpg'
        )
        expected = '2004-05-07 20.16.31.jpg'
        self.assertEquals(case, expected)

        case = sorter.filename_from_datetime(
            datetime(2004, 5, 7, 20, 16, 31),
            'test_examples/somefile.JPG'
        )
        expected = '2004-05-07 20.16.31.jpg'
        self.assertEquals(case, expected)

        case = sorter.filename_from_datetime(
            datetime(2004, 5, 7, 20, 16, 31),
            'test_examples/no-ext'
        )
        expected = '2004-05-07 20.16.31'
        self.assertEquals(case, expected)

    def test_folder_from_datetime(self):
        self.assertEquals(
            sorter.folder_from_datetime(datetime(2014, 2, 7)),
            '2014/2014-02'
        )

    def test_path_from_datetime(self):
        case = sorter.path_from_datetime(
            '',
            datetime(2004, 5, 7, 20, 16, 31),
            'test_examples/img0001.jpg'
        )
        expected = '2004/2004-05/2004-05-07 20.16.31.jpg'
        self.assertEquals(case, expected)

        case = sorter.path_from_datetime(
            '/home/user/Dropbox',
            datetime(2004, 5, 7, 20, 16, 31),
            'test_examples/img0001.jpg'
        )
        expected = '/home/user/Dropbox/2004/2004-05/2004-05-07 20.16.31.jpg'
        self.assertEquals(case, expected)

    def test_dest_path(self):
        case = sorter.dest_path(
            '/home/user/Dropbox',
            'test_examples/2004-05-07 20.16.31.jpg'
        )
        expected = '/home/user/Dropbox/2004/2004-05/2004-05-07 20.16.31.jpg'
        self.assertEquals(case, expected)

    def test_ignore_non_images(self):
        self.assertTrue(sorter.is_valid_filename('test.png'))
        self.assertTrue(sorter.is_valid_filename('test.jpg'))
        self.assertTrue(sorter.is_valid_filename('test.jpeg'))
        self.assertTrue(sorter.is_valid_filename('test.jPeg'))
        self.assertTrue(sorter.is_valid_filename('test.PNG'))
        self.assertTrue(sorter.is_valid_filename('test.JPG'))
        self.assertFalse(sorter.is_valid_filename('test.img'))
        self.assertFalse(sorter.is_valid_filename('test.txt'))
        self.assertFalse(sorter.is_valid_filename('test'))

    # def test_duplicate_marker_index(self):
    #     self.assertEquals(
    #         sorter.duplicate_marker_index('2006-09-09 07.00.24-2.jpg'),
    #         2
    #     )
    #     self.assertEquals(
    #         sorter.duplicate_marker_index('2006-09-09 07.00.24-123.jpg'),
    #         123
    #     )
    #     self.assertEquals(
    #         sorter.duplicate_marker_index('2006-09-09 07.00.24.jpg'),
    #         None
    #     )
    #     self.assertEquals(
    #         sorter.duplicate_marker_index('2006-09-09 07.00.24-9.png'),
    #         9
    #     )

    def test_resolve_duplicate(self):
        case = sorter.resolve_duplicate(
            'test_examples/root/2006/2006-09/2006-09-09 07.00.24.jpg'
        )
        expected = 'test_examples/root/2006/2006-09/2006-09-09 07.00.24-2.jpg'
        self.assertEquals(case, expected)

        case = sorter.resolve_duplicate(
            'test_examples/root/2006/2006-09/2006-09-09 07.00.25.jpg'
        )
        expected = 'test_examples/root/2006/2006-09/2006-09-09 07.00.25.jpg'
        self.assertEquals(case, expected)

    @mock.patch('os.makedirs')
    @mock.patch('shutil.move')
    def test_move_file(self, move_mock, makedirs_mock):
        sorter.move_file('/root', 'test_examples/2006-09-09 07.00.24.jpg')
        makedirs_mock.assert_called_with('/root/2006/2006-09')
        move_mock.assert_called_with(
            'test_examples/2006-09-09 07.00.24.jpg',
            '/root/2006/2006-09/2006-09-09 07.00.24.jpg'
        )

        # Ignore non-images
        makedirs_mock.reset_mock()
        move_mock.reset_mock()
        sorter.move_file('/root', 'test_examples/no_image.txt')
        makedirs_mock.assert_not_called()
        move_mock.assert_not_called()

        # Don't overwrite existing images.
        makedirs_mock.reset_mock()
        move_mock.reset_mock()
        sorter.move_file(
            'test_examples/root/',
            'test_examples/2006-09-09 07.00.24.jpg'
        )
        makedirs_mock.assert_called_with('test_examples/root/2006/2006-09')
        move_mock.assert_called_with(
            'test_examples/2006-09-09 07.00.24.jpg',
            'test_examples/root/2006/2006-09/2006-09-09 07.00.24-2.jpg'
        )

class CreationDateTests(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        reset_mtimes()

    def test_file_creation_date(self):
        self.assertEquals(
            sorter.file_creation_date('test_examples/2004-05-07 20.16.31.jpg'),
            datetime(2004, 5, 7, 11, 16, 31)
        )

        self.assertEquals(
            sorter.file_creation_date('test_examples/2006-09-09 07.00.24.jpg'),
            datetime(2006, 9, 8, 22, 0, 24)
        )

        self.assertEquals(
            sorter.file_creation_date('test_examples/2014-02-06 09.15.17.jpg'),
            datetime(2014, 2, 6, 9, 15, 17)
        )

    def test_exif_creation_date(self):
        self.assertEquals(
            sorter.exif_creation_date('test_examples/2004-05-07 20.16.31.jpg'),
            datetime(2004, 5, 7, 20, 16, 31)
        )

        self.assertEquals(
            sorter.exif_creation_date('test_examples/2006-09-09 07.00.24.jpg'),
            datetime(2006, 9, 9, 7, 0, 24)
        )

        self.assertEquals(
            sorter.exif_creation_date('test_examples/2014-02-06 09.15.17.jpg'),
            datetime(2014, 2, 6, 9, 15, 17)
        )

        self.assertIsNone(
            sorter.exif_creation_date('test_examples/no-exif.jpg'),
        )

        self.assertIsNone(
            sorter.exif_creation_date('test_examples/test.png'),
        )

    def test_creation_date(self):
        self.assertEquals(
            sorter.creation_date('test_examples/2004-05-07 20.16.31.jpg'),
            datetime(2004, 5, 7, 20, 16, 31)
        )

        self.assertEquals(
            sorter.creation_date('test_examples/2006-09-09 07.00.24.jpg'),
            datetime(2006, 9, 9, 7, 0, 24)
        )

        self.assertEquals(
            sorter.creation_date('test_examples/2014-02-06 09.15.17.jpg'),
            datetime(2014, 2, 6, 9, 15, 17)
        )

        self.assertEquals(
            sorter.creation_date('test_examples/no-exif.jpg'),
            datetime(2014, 2, 23, 21, 47, 14)
        )

        self.assertEquals(
            sorter.creation_date('test_examples/test.png'),
            datetime(2014, 3, 8, 18, 31, 35)
        )
<|endoftext|>


<commit_before>
from controller import WORKER_SCRIPT
from launch_instance import launch
from upload_download_s3 import upload_to_s3, download_from_s3, remove_s3_bucket
from utils import timestring

from boto import sqs, ec2, s3
from boto import Config
import json
from time import sleep
import os

# Assuming that the testing system has the AWS config already set.
try:
    proc_name = "aws_ska_test_worker_" + timestring()
    region = "us-west-2"

    # Read in credentials
    config = Config()
    config.load_credential_file(os.path.join(os.path.expanduser("~"),".aws/credentials"))
    info = config.items("default")[2:]
    key = info[0][1]
    secret = info[1][1]

    # Create a test file and upload to S3
    if not os.path.exists("tests/test.txt"):
        test_string = "ALLGLORYTOTHEHYPNOTOAD"

        with open("tests/test.txt", "w") as f:
            f.write(test_string)

    print("Uploading to S3")

    upload_to_s3(proc_name, "tests/test.txt", key_prefix="data/",
                 aws_access={"aws_access_key_id": key,
                             "aws_secret_access_key": secret},
                 create_bucket=True)

    # Create an SQS queue and message for the worker
    queue = sqs.connect_to_region(region).create_queue(proc_name)

    mess = {}
    mess["proc_name"] = proc_name
    mess["bucket"] = proc_name
    mess['key_name'] = "data/test.txt"
    mess['command'] = ["ls", "/home/ubuntu/data/"]
    mess['parameters'] = ""

    mess = queue.new_message(body=json.dumps(mess))
    queue.write(mess)

    print("Launching instance")

    # Launch an instance with the worker script
    user_data = WORKER_SCRIPT \
        % {"USER": "ubuntu",
           "QUEUE_NAME": proc_name,
           "REGION": region,
           "KEY": key,
           "SECRET": secret,
           "RESP_QUEUE_NAME": proc_name + "_response"}

    inst = launch(key_name=None, region=region, image_id="ami-22decf43",
                  user_data=user_data)

    # sleep 1 min
    sleep(60)

    if inst.state == u"running":
        print("Terminating after 1 min.")
        inst.terminate()

    print("Checking for response message.")

    resp_queue = sqs.connect_to_region(region).create_queue(proc_name + "_response")

    if resp_queue.count() > 0:
        mess = resp_queue.read(10)
        content = json.loads(mess.get_body())
        print("Saving content.")
        with open("tests/test_response.txt", "w") as f:
            json.dump(content, f)
    else:
        print("No message received!")

    # Now download the output file
    download_from_s3("data_products/*", proc_name,
                     aws_access={"aws_access_key_id": key,
                                 "aws_secret_access_key": secret},
                     output_dir="tests/")

except Exception as e:
    print("Failed with :")
    print(e)

queue.delete()
resp_queue.delete()
remove_s3_bucket(proc_name, s3.connection.S3Connection())
<commit_msg>Timeout for worker<commit_after>
from controller import WORKER_SCRIPT
from launch_instance import launch
from upload_download_s3 import upload_to_s3, download_from_s3, remove_s3_bucket
from utils import timestring

from boto import sqs, ec2, s3
from boto import Config
import json
from time import sleep, time
import os

# Assuming that the testing system has the AWS config already set.
try:
    proc_name = "aws_ska_test_worker_" + timestring()
    region = "us-west-2"

    # Read in credentials
    config = Config()
    config.load_credential_file(os.path.join(os.path.expanduser("~"),".aws/credentials"))
    info = config.items("default")[2:]
    key = info[0][1]
    secret = info[1][1]

    # Create a test file and upload to S3
    if not os.path.exists("tests/test.txt"):
        test_string = "ALLGLORYTOTHEHYPNOTOAD"

        with open("tests/test.txt", "w") as f:
            f.write(test_string)

    print("Uploading to S3")

    upload_to_s3(proc_name, "tests/test.txt", key_prefix="data/",
                 aws_access={"aws_access_key_id": key,
                             "aws_secret_access_key": secret},
                 create_bucket=True)

    # Create an SQS queue and message for the worker
    queue = sqs.connect_to_region(region).create_queue(proc_name)

    mess = {}
    mess["proc_name"] = proc_name
    mess["bucket"] = proc_name
    mess['key_name'] = "data/test.txt"
    mess['command'] = ["ls", "/home/ubuntu/data/"]
    mess['parameters'] = ""

    mess = queue.new_message(body=json.dumps(mess))
    queue.write(mess)

    print("Launching instance")

    # Launch an instance with the worker script
    user_data = WORKER_SCRIPT \
        % {"USER": "ubuntu",
           "QUEUE_NAME": proc_name,
           "REGION": region,
           "KEY": key,
           "SECRET": secret,
           "RESP_QUEUE_NAME": proc_name + "_response"}

    inst = launch(key_name=None, region=region, image_id="ami-22decf43",
                  user_data=user_data)

    # sleep 1 min
    t0 = time()
    while time() < t0 + 60:
        update = inst.update()
        print update
        if update in [u"stopping", u"stopped"]:
            break
        sleep(5)
    else:
        print("Reached time limit. Terminating after 1 min.")

    inst.terminate()

    print("Checking for response message.")

    resp_queue = sqs.connect_to_region(region).create_queue(proc_name + "_response")

    if resp_queue.count() > 0:
        mess = resp_queue.read(10)
        content = json.loads(mess.get_body())
        print("Saving content.")
        with open("tests/test_response.txt", "w") as f:
            json.dump(content, f)
    else:
        print("No message received!")

    # Now download the output file
    download_from_s3("data_products/*", proc_name,
                     aws_access={"aws_access_key_id": key,
                                 "aws_secret_access_key": secret},
                     output_dir="tests/")

except Exception as e:
    print("Failed with :")
    print(e)

queue.delete()
resp_queue.delete()
remove_s3_bucket(proc_name, s3.connection.S3Connection())
<|endoftext|>


<commit_before>from tempfile import mkdtemp
from shutil import rmtree

from docutils.nodes import (
    list_item, paragraph,
)
from mock import Mock
from spec import eq_
from sphinx.application import Sphinx
import six
import sphinx

from releases import (
    Issue,
    issues_role,
    Release,
    release_role,
    construct_releases,
)
from releases import setup as releases_setup # avoid unittest crap

def make_app(**kwargs):
    # Create a real Sphinx app, with stupid temp dirs because it assumes.
    # Helps catch things like "testing a config option but forgot
    # app.add_config_value()"
    src, dst, doctree = mkdtemp(), mkdtemp(), mkdtemp()
    try:
        # STFU Sphinx :(
        Sphinx._log = lambda self, message, wfile, nonl=False: None
        app = Sphinx(
            srcdir=src,
            confdir=None,
            outdir=dst,
            doctreedir=doctree,
            buildername='html',
        )
    finally:
        [rmtree(x) for x in (src, doctree)]
    releases_setup(app)
    # Mock out the config within. More horrible assumptions by Sphinx :(
    config = {
        'releases_release_uri': 'foo_%s',
        'releases_issue_uri': 'bar_%s',
        'releases_debug': False,
    }
    # Allow tinkering with document filename
    if 'docname' in kwargs:
        app.env.temp_data['docname'] = kwargs.pop('docname')
    # Allow config overrides
    for name in kwargs:
        config['releases_{0}'.format(name)] = kwargs[name]
    # Stitch together as the sphinx app init() usually does w/ real conf files
    app.config._raw_config = config
    # init_values() requires a 'warn' runner on Sphinx 1.3+, give it no-op.
    init_args = []
    if sphinx.version_info[:2] > (1, 2):
        init_args = [lambda x: x]
    app.config.init_values(*init_args)
    return app

def inliner(app=None):
    app = app or make_app()
    return Mock(document=Mock(settings=Mock(env=Mock(app=app))))

# Obtain issue() object w/o wrapping all parse steps
def issue(type_, number, **kwargs):
    text = str(number)
    if kwargs.get('backported', False):
        text += " backported"
    if kwargs.get('major', False):
        text += " major"
    if kwargs.get('spec', None):
        text += " (%s)" % kwargs['spec']
    app = kwargs.get('app', None)
    return issues_role(
        name=type_,
        rawtext='',
        text=text,
        lineno=None,
        inliner=inliner(app=app),
    )[0][0]

# Even shorter shorthand!
def b(number, **kwargs):
    return issue('bug', str(number), **kwargs)

def f(number, **kwargs):
    return issue('feature', str(number), **kwargs)

def s(number, **kwargs):
    return issue('support', str(number), **kwargs)

def entry(i):
    """
    Easy wrapper for issue/release objects.

    Default is to give eg an issue/release object that gets wrapped in a LI->P.

    May give your own (non-issue/release) object to skip auto wrapping. (Useful
    since entry() is often called a few levels deep.)
    """
    if not isinstance(i, (Issue, Release)):
        return i
    return list_item('', paragraph('', '', i))

def release(number, **kwargs):
    app = kwargs.get('app', None)
    nodes = release_role(
        name=None,
        rawtext='',
        text='%s <2013-11-20>' % number,
        lineno=None,
        inliner=inliner(app=app),
    )[0]
    return list_item('', paragraph('', '', *nodes))

def release_list(*entries, **kwargs):
    skip_initial = kwargs.pop('skip_initial', False)
    entries = list(entries) # lol tuples
    # Translate simple objs into changelog-friendly ones
    for index, item in enumerate(entries):
        if isinstance(item, six.string_types):
            entries[index] = release(item)
        else:
            entries[index] = entry(item)
    # Insert initial/empty 1st release to start timeline
    if not skip_initial:
        entries.append(release('1.0.0'))
    return entries

def changelog2dict(changelog):
    d = {}
    for r in changelog:
        d[r['obj'].number] = r['entries']
    return d

def releases(*entries, **kwargs):
    app = kwargs.pop('app', None) or make_app()
    return construct_releases(release_list(*entries, **kwargs), app)

def setup_issues(self):
    self.f = f(12)
    self.s = s(5)
    self.b = b(15)
    self.mb = b(200, major=True)
    self.bf = f(27, backported=True)
    self.bs = s(29, backported=True)

def expect_releases(entries, release_map, skip_initial=False):
    kwargs = {'skip_initial': skip_initial}
    changelog = changelog2dict(releases(*entries, **kwargs))
    err = "Got unexpected contents for {0}: wanted {1}, got {2}"
    for rel, issues in six.iteritems(release_map):
        eq_(changelog[rel], issues, err.format(rel, issues, changelog[rel]))
<commit_msg>Have expect_releases complain about leftovers<commit_after>from tempfile import mkdtemp
from shutil import rmtree

from docutils.nodes import (
    list_item, paragraph,
)
from mock import Mock
from spec import eq_, ok_
from sphinx.application import Sphinx
import six
import sphinx

from releases import (
    Issue,
    issues_role,
    Release,
    release_role,
    construct_releases,
)
from releases import setup as releases_setup # avoid unittest crap

def make_app(**kwargs):
    # Create a real Sphinx app, with stupid temp dirs because it assumes.
    # Helps catch things like "testing a config option but forgot
    # app.add_config_value()"
    src, dst, doctree = mkdtemp(), mkdtemp(), mkdtemp()
    try:
        # STFU Sphinx :(
        Sphinx._log = lambda self, message, wfile, nonl=False: None
        app = Sphinx(
            srcdir=src,
            confdir=None,
            outdir=dst,
            doctreedir=doctree,
            buildername='html',
        )
    finally:
        [rmtree(x) for x in (src, doctree)]
    releases_setup(app)
    # Mock out the config within. More horrible assumptions by Sphinx :(
    config = {
        'releases_release_uri': 'foo_%s',
        'releases_issue_uri': 'bar_%s',
        'releases_debug': False,
    }
    # Allow tinkering with document filename
    if 'docname' in kwargs:
        app.env.temp_data['docname'] = kwargs.pop('docname')
    # Allow config overrides
    for name in kwargs:
        config['releases_{0}'.format(name)] = kwargs[name]
    # Stitch together as the sphinx app init() usually does w/ real conf files
    app.config._raw_config = config
    # init_values() requires a 'warn' runner on Sphinx 1.3+, give it no-op.
    init_args = []
    if sphinx.version_info[:2] > (1, 2):
        init_args = [lambda x: x]
    app.config.init_values(*init_args)
    return app

def inliner(app=None):
    app = app or make_app()
    return Mock(document=Mock(settings=Mock(env=Mock(app=app))))

# Obtain issue() object w/o wrapping all parse steps
def issue(type_, number, **kwargs):
    text = str(number)
    if kwargs.get('backported', False):
        text += " backported"
    if kwargs.get('major', False):
        text += " major"
    if kwargs.get('spec', None):
        text += " (%s)" % kwargs['spec']
    app = kwargs.get('app', None)
    return issues_role(
        name=type_,
        rawtext='',
        text=text,
        lineno=None,
        inliner=inliner(app=app),
    )[0][0]

# Even shorter shorthand!
def b(number, **kwargs):
    return issue('bug', str(number), **kwargs)

def f(number, **kwargs):
    return issue('feature', str(number), **kwargs)

def s(number, **kwargs):
    return issue('support', str(number), **kwargs)

def entry(i):
    """
    Easy wrapper for issue/release objects.

    Default is to give eg an issue/release object that gets wrapped in a LI->P.

    May give your own (non-issue/release) object to skip auto wrapping. (Useful
    since entry() is often called a few levels deep.)
    """
    if not isinstance(i, (Issue, Release)):
        return i
    return list_item('', paragraph('', '', i))

def release(number, **kwargs):
    app = kwargs.get('app', None)
    nodes = release_role(
        name=None,
        rawtext='',
        text='%s <2013-11-20>' % number,
        lineno=None,
        inliner=inliner(app=app),
    )[0]
    return list_item('', paragraph('', '', *nodes))

def release_list(*entries, **kwargs):
    skip_initial = kwargs.pop('skip_initial', False)
    entries = list(entries) # lol tuples
    # Translate simple objs into changelog-friendly ones
    for index, item in enumerate(entries):
        if isinstance(item, six.string_types):
            entries[index] = release(item)
        else:
            entries[index] = entry(item)
    # Insert initial/empty 1st release to start timeline
    if not skip_initial:
        entries.append(release('1.0.0'))
    return entries

def changelog2dict(changelog):
    d = {}
    for r in changelog:
        d[r['obj'].number] = r['entries']
    return d

def releases(*entries, **kwargs):
    app = kwargs.pop('app', None) or make_app()
    return construct_releases(release_list(*entries, **kwargs), app)

def setup_issues(self):
    self.f = f(12)
    self.s = s(5)
    self.b = b(15)
    self.mb = b(200, major=True)
    self.bf = f(27, backported=True)
    self.bs = s(29, backported=True)

def expect_releases(entries, release_map, skip_initial=False):
    kwargs = {'skip_initial': skip_initial}
    changelog = changelog2dict(releases(*entries, **kwargs))
    err = "Got unexpected contents for {0}: wanted {1}, got {2}"
    for rel, issues in six.iteritems(release_map):
        found = changelog.pop(rel)
        eq_(found, issues, err.format(rel, issues, found))
    # Sanity: ensure no leftover issue lists exist (empty ones are OK)
    for key in changelog.keys():
        if not changelog[key]:
            del changelog[key]
    ok_(not changelog, "Found leftovers: {0}".format(changelog))
<|endoftext|>