def get_data_for_last_day(cls, pk: int) -> list: stock_data_for_last_day = [] datetime_now = datetime.now().strftime(DATETIME_PATTERN) datetime_yesterday = (datetime.now() - timedelta(days=1)).strftime(DATETIME_PATTERN) with pool_manager() as conn: query = """SELECT * FROM stocks_data WHERE stock_id = %(stock_id)s AND %(yesterday)s <= created_at AND created_at < %(today)s ORDER BY created_at;""" try: conn.cursor.execute( query, { 'stock_id': pk, 'yesterday': datetime_yesterday, 'today': datetime_now }) stock_data_for_last_day = conn.cursor.fetchall() except (psycopg2.DataError, psycopg2.ProgrammingError, TypeError) as err: logger.info(f"Error! {err}") stock_data_for_last_day = [ StockData(pk=pk, stock_id=stock_id, price=price, created_at=created_at) for pk, stock_id, price, created_at in stock_data_for_last_day ] return stock_data_for_last_day
def test_put_success(self, mock_get, mock_put): with app.app_context(): mock_get.return_value = StockData(stock_id=2, price=300, created_at="2020-08-19 01:55:19", pk=1) mock_put.return_value = StockData(stock_id=2, price=500, created_at="2020-09-19 01:55:19", pk=1) with app.test_client() as client: data = {"price": 500, "created_at": "2020-09-19 01:55:19"} response = client.put('/stocks_data/1', json=data) body = json.loads(response.data) assert response.status_code == 200 assert body['created_at'] == "2020-09-19 01:55:19" assert body['price'] == 500 assert body['stock_id'] == 2
def test_put_wrong_json(self, mock_get): with app.app_context(): message = b"Wrong data provided" mock_get.return_value = StockData(stock_id=2, price=300, created_at="2020-09-19 01:55:19", pk=1) with app.test_client() as client: incorrect_json = '{ "stock_id:"12 "price":30 "created_at:"None" }' response = client.put('/stocks_data/2', data=incorrect_json) assert response.status_code == 400 assert response.data == message
def test_put_wrong_price(self, mock_get): with app.app_context(): message = b"Incorrect price specified, price should be integer (ex. 300)" mock_get.return_value = StockData(stock_id=2, price=300, created_at="19/09/19 01:55:19", pk=1) with app.test_client() as client: data = {"price": "wrong", "created_at": "19/09/19 01:55:19"} response = client.put('/stocks_data/2', json=data) assert response.status_code == 400 assert response.data == message
def test_put_wrong_create_at(self, mock_get): with app.app_context(): message = b"Incorrect date specified, example '2018-09-19 01:55:19'(year-month-day hour:minute:second))" mock_get.return_value = StockData(stock_id=2, price=300, created_at="19/09/19 01:55:19", pk=1) with app.test_client() as client: data = {"price": 300, "created_at": "2021/01/08"} response = client.put('/stocks_data/2', json=data) assert response.status_code == 400 assert response.data == message
def get(self, pk: int) -> Response: # pylint: disable=C0103, R0201 """A get method is used to send a specific GET request to access Stock Data by id :param pk: Stock Data primary key :return: a Response object with specific data and status code """ stock_data = StockData.get_by_id(pk=pk) if stock_data is None: message = "Can not find stock data, wrong id" logger.info(message) return make_response(message, 400) return make_response(jsonify(stock_data.to_dict()), 200)
def delete(self, pk: int) -> Response: # pylint: disable=C0103, R0201 """A delete method is used to send a specific DELETE request to delete Stock Data by id :param pk: Stock Data primary key :return: a Response object with specific data and status code """ stock_data_deleted = StockData.delete_by_id(pk=pk) if stock_data_deleted: return make_response("Stock data deleted", 200) message = "Stock data not deleted" logger.info(message) return make_response(message, 400)
def test_put_unknown_error(self, mock_put, mock_get): with app.app_context(): message = b"Stock Data is not updated, possible you input wrong data" mock_get.return_value = StockData(stock_id=2, price=300, created_at="18/09/19 01:55:19", pk=1) mock_put.return_value = None with app.test_client() as client: data = {"price": 500, "created_at": "2020-09-19 01:55:19"} response = client.put('/stocks_data/1', json=data) assert response.status_code == 400 assert response.data == message
def test_get_pass(self, mock_get): with app.app_context(): mock_get.return_value = StockData(stock_id=2, price=300, created_at="18-09-19 01:55:19", pk=1) with app.test_client() as client: response = client.get('/stocks_data/1') body = json.loads(response.data) assert response.status_code == 200 assert body['id'] == 1 assert body['created_at'] == '18-09-19 01:55:19' assert body['price'] == 300 assert body['stock_id'] == 2
def post(self) -> Response: # pylint: disable=R0201 """A post method is used to send a specific POST request to create Stock Data :return: a Response object with specific data and status code """ body = get_body(request) if not body: return make_response("Wrong data provided", 400) price = body.get('price') created_at = body.get('created_at') stock_id = body.get('stock_id') if not isinstance(price, int): message = "Incorrect price specified, price should be integer (ex. 300)" logger.info(message) return make_response(message, 400) if not isinstance(stock_id, int): message = "Incorrect stock id specified, stock id should be integer (ex. 1)" logger.info(message) return make_response(message, 400) if not isinstance(created_at, str): message = ( "Incorrect created_at specified, " "example '2018-09-19 01:55:19'(year-month-day hour:minute:second))" ) logger.info(message) return make_response(message, 400) try: created_at = datetime.strptime(created_at, '%Y-%m-%d %H:%M:%S') except ValueError: message = ( "Incorrect created_at specified, " "example '2018-09-19 01:55:19'(year-month-day hour:minute:second))" ) logger.info(message) return make_response(message, 400) data_to_create = { 'price': price, 'created_at': created_at, 'stock_id': stock_id } stock_data = StockData.create(**data_to_create) if stock_data: return make_response(jsonify(stock_data.to_dict()), 201) return make_response("Creating error", 400)
def test_post_pass(self, mock_post): with app.app_context(): mock_post.return_value = StockData( stock_id=1, price=500, created_at="2020-05-11 04:22:30") with app.test_client() as client: data = { "price": 500, "created_at": "2020-05-11 04:22:30", "stock_id": 1 } response = client.post('/stocks_data/', json=data) assert response.status_code == 201 body = json.loads(response.data) assert response.status_code == 201 assert body['created_at'] == "2020-05-11 04:22:30" assert body['price'] == 500 assert body['stock_id'] == 1
def put(self, pk: int) -> Response: # pylint: disable=C0103, R0201 """A put method is used to send a specific PUT request to edit Stock Data by id :param pk: Stock Data primary key :return: a Response object with specific data and status code """ body = get_body(request) if not body: return make_response("Wrong data provided", 400) stock_data = StockData.get_by_id(pk=pk) if stock_data is None: message = "Can not find stock data, wrong id" logger.info(message) return make_response(message, 400) price, created_at = body.get('price'), body.get('created_at') if price is not None and not isinstance(price, int): message = "Incorrect price specified, price should be integer (ex. 300)" logger.info(message) return make_response(message, 400) if created_at: if not isinstance(created_at, str): message = ( "Incorrect created_at specified, " "example '2018-09-19 01:55:19'(year-month-day hour:minute:second)" ) logger.info(message) return make_response(message, 400) try: created_at = datetime.strptime(created_at, '%Y-%m-%d %H:%M:%S') except ValueError: message = "Incorrect date specified, example '2018-09-19 01:55:19'(year-month-day hour:minute:second))" logger.info(message) return make_response(message, 400) data_to_update = {"price": price, "created_at": created_at} stock_data_updated = stock_data.update(**data_to_update) if stock_data_updated: return make_response(jsonify(stock_data.to_dict()), 200) message = "Stock Data is not updated, possible you input wrong data" logger.info(message) return make_response(message, 400)
def get_data_for_time_period(self, datetime_from: datetime, datetime_to: datetime) -> list: """ Return list of stock datas for current stock in specified period of time :param datetime_from: start time of period to get stock data :param datetime_to: end time of period to get stock data :return: list of StockData """ stock_data_for_time_period = [] datetime_from_str, datetime_to_str = datetime_from.strftime( DATETIME_PATTERN), datetime_to.strftime(DATETIME_PATTERN) with pool_manager() as conn: query = "SELECT id, stock_id, price, created_at FROM stocks_data " \ "WHERE stock_id = %(stock_id)s " \ "AND %(datetime_from)s <= created_at AND created_at < %(datetime_to)s " \ "ORDER BY created_at;" try: conn.cursor.execute( query, { 'stock_id': self.pk, 'datetime_from': datetime_from_str, 'datetime_to': datetime_to_str }) stock_data_for_time_period = conn.cursor.fetchall() except (psycopg2.DataError, psycopg2.ProgrammingError, TypeError): message = f"Could not get stock data for pk={self.pk}, datetime_from={datetime_from_str}, " \ f"datetime_to={datetime_to_str}" logger.warning(message) stock_data_for_time_period = [ StockData(pk=pk, stock_id=stock_id, price=price, created_at=created_at) for pk, stock_id, price, created_at in stock_data_for_time_period ] if Stock._are_gaps_in_data(datetime_from, datetime_to, stock_data_for_time_period): self._fill_gaps_in_data(datetime_from, datetime_to, stock_data_for_time_period) return stock_data_for_time_period
def test_create_false(self, pool_manager): pool_manager.return_value.__enter__.return_value.cursor.execute.side_effect = psycopg2.DataError self.assertEqual(StockData.create(1, 441.5, datetime(2021, 1, 2, 3, 4, 5)), None)
def test_get_by_id_error(self, pool_manager): pool_manager.return_value.__enter__.return_value.cursor.execute.side_effect = psycopg2.DataError self.assertEqual(StockData.get_by_id(1), None)
def test_update_true(self, pool_manager): pool_manager.return_value.__enter__.return_value.cursor.fetchone.return_value = ( 2, 1, 441.5, datetime(2021, 1, 2, 3, 4, 5)) pool_manager.return_value.__exit__.return_value = True self.assertEqual( StockData(1, 111.1, datetime(2020, 3, 2, 1, 5, 6)).update(441.5, datetime(2021, 1, 2, 3, 4, 5)), True)
def test_update_false(self, pool_manager): pool_manager.return_value.__enter__.return_value.cursor.execute.side_effect = psycopg2.DataError self.assertEqual( StockData(2, 114.6, datetime(2020, 1, 2, 3, 4, 5)).update(441.5, datetime(2021, 1, 2, 3, 4, 5)), False)
def test_get_by_id(self, pool_manager): data = {"id": 1, "stock_id": 1, "price": 441.5, "created_at": datetime(2021, 1, 2, 3, 4, 6)} pool_manager.return_value.__enter__.return_value.cursor.fetchone.return_value = ( 1, 1, 441.5, datetime(2021, 1, 2, 3, 4, 6)) self.assertEqual(StockData.get_by_id(1).to_dict(), data)
def test_delete_true(self, get_by_id, pool_manager): get_by_id.return_value = True pool_manager.return_value.__enter__.return_value.cursor.execute.return_value = True self.assertEqual(StockData.delete_by_id(1), True)
def test_delete_error(self, get_by_id, pool_manager): get_by_id.return_value = True pool_manager.return_value.__enter__.return_value.cursor.execute.side_effect = psycopg2.DataError self.assertEqual(StockData.delete_by_id(1), False)