# Path: async_v20/definitions/base.py
# def create_attribute(typ, data):
#     """Correctly instantiate object based upon type of argument passed"""
#     try:
#         if isinstance(data, dict):
#             result = typ(**data)
#         elif isinstance(data, Specifier):
#             if not issubclass(typ, Specifier):
#                 msg = f'{data} must be a {Specifier} is {type(data)}'
#                 logger.error(msg)
#                 raise IncompatibleValue(msg)
#             result = typ(data)
#         elif isinstance(data, InstrumentName):
#             result = typ(data)
#         elif isinstance(data, (Model, Array, Primitive)):
#             if not issubclass(type(data), typ):
#                 msg = f'{data} must be of type {typ} is {type(data)}'
#                 logger.error(msg)
#                 raise IncompatibleValue(msg)
#             result = data
#         elif isinstance(data, (tuple, list)):
#             result = typ(*data)
#         else:
#             result = typ(data)
#     except (TypeError, ValueError, UnknownKeywordArgument):
#         # This error handling is required when there is no
#         # schema available to parse the data. Typically
#         # when an error code has been returned
#         # A none value should be returned if this is the case
#         if typ is not None:
#             msg = f'Could not create {typ}. DATA: {data}, TYPE: {type(data)}'
#             logger.error(msg)
#             raise InstantiationFailure(msg)
#     else:
#         return result
# 
# Path: async_v20/definitions/types.py
# class OrderRequest(Model, jit=False):
#     """The base Order specification. Contains all attributes an OrderRequest
#     may contain.
# 
#     Attributes:
# 
#         instrument: :class:`~async_v20.InstrumentName`
#         trade_id: :class:`~async_v20.TradeID`
#         price: :class:`~async_v20.PriceValue`
#         type: :class:`~async_v20.OrderType`
#         client_trade_id: :class:`~async_v20.ClientID`
#         time_in_force: :class:`~async_v20.TimeInForce`
#         gtd_time: :class:`~async_v20.DateTime`
#         trigger_condition: :class:`~async_v20.OrderTriggerCondition`
#         client_extensions: :class:`~async_v20.ClientExtensions`
#         distance: :class:`~async_v20.PriceValue`
#         instrument: :class:`~async_v20.InstrumentName`
#         units: :class:`~async_v20.DecimalNumber`
#         price_bound: :class:`~async_v20.PriceValue`
#         position_fill: :class:`~async_v20.OrderPositionFill`
#         take_profit_on_fill: :class:`~async_v20.TakeProfitDetails`
#         stop_loss_on_fill: :class:`~async_v20.StopLossDetails`
#         trailing_stop_loss_on_fill: :class:`~async_v20.TrailingStopLossDetails`
#         trade_client_extensions: :class:`~async_v20.ClientExtensions`
#     """
# 
#     def __init__(self, instrument: InstrumentName, trade_id: TradeID = sentinel, price: PriceValue = sentinel,
#                  type: OrderType = sentinel,
#                  client_trade_id: ClientID = sentinel, time_in_force: TimeInForce = sentinel,
#                  gtd_time: DateTime = sentinel,
#                  trigger_condition: OrderTriggerCondition = sentinel, client_extensions: ClientExtensions = sentinel,
#                  distance: PriceValue = sentinel, units: DecimalNumber = sentinel,
#                  price_bound: PriceValue = sentinel, position_fill: OrderPositionFill = sentinel,
#                  take_profit_on_fill: TakeProfitDetails = sentinel, stop_loss_on_fill: StopLossDetails = sentinel,
#                  trailing_stop_loss_on_fill: TrailingStopLossDetails = sentinel,
#                  trade_client_extensions: ClientExtensions = sentinel):
#         Model.__init__(**locals())
# 
# Path: async_v20/definitions/helpers.py
# def check_conflicting_arguments(self, kwargs, preset_values):
# def json_to_instance_attributes(self, kwargs, template):
# def domain_check(value, example=None, possible_values=None):
# def flatten_dict(dictionary, delimiter='_'):
#     def unpack(parent_key, parent_value):
# def create_doc_signature(obj, sig):
# 
# Path: async_v20/endpoints/annotations.py
# class LastTransactionID(TransactionID):
#     """Contains the most recent TransactionID"""
#     pass
# 
# Path: async_v20/endpoints/annotations.py
# class SinceTransactionID(TransactionID):
#     """The account changes to get Since LastTransactionID for account_changes() method"""
#     pass
# 
# Path: async_v20/exceptions.py
# class FailedToCreatePath(AsyncV20Exception):
#     """Unable to construct the path for the requested endpoint"""
#     pass
# 
# class InvalidOrderRequest(AsyncV20Exception):
#     """The order request is not with in the instruments specification
#     the order is for"""
#     pass


import logging
import pandas as pd
from functools import partial
from inspect import _empty
from ..definitions.base import create_attribute
from ..definitions.types import OrderRequest
from ..definitions.helpers import sentinel
from ..endpoints.annotations import LastTransactionID
from ..endpoints.annotations import SinceTransactionID
from ..exceptions import FailedToCreatePath, InvalidOrderRequest
    """Create the JSON body to add to the HTTP request

    Args:
        request_schema: -- the endpoints request schema
        arguments: -- dict of user supplied arguments

    Returns:
        Dict containing the formatted data
    """

    def dumps():
        """Iterate over the arguments returning dicts of matching objects
        and format order requests where required"""
        for key, value in arguments.items():
            try:
                key = request_schema[key]
            except KeyError:
                continue
            else:
                # Only attempt to format OrderRequests that have an `instrument` attribute
                if isinstance(value, OrderRequest):
                    instrument = self.instruments.get_instrument(value.instrument)
                    if instrument is not None:
                        value = _format_order_request(value,
                                                      instrument,
                                                      self.format_order_requests)
                    else:
                        msg = f'The instrument specified instrument {value.instrument} ' \
                              f'for OrderRequest {value} is not tradeable by this account'
                        logger.error(msg)

# Path: async_v20/definitions/base.py
# def create_attribute(typ, data):
#     """Correctly instantiate object based upon type of argument passed"""
#     try:
#         if isinstance(data, dict):
#             result = typ(**data)
#         elif isinstance(data, Specifier):
#             if not issubclass(typ, Specifier):
#                 msg = f'{data} must be a {Specifier} is {type(data)}'
#                 logger.error(msg)
#                 raise IncompatibleValue(msg)
#             result = typ(data)
#         elif isinstance(data, InstrumentName):
#             result = typ(data)
#         elif isinstance(data, (Model, Array, Primitive)):
#             if not issubclass(type(data), typ):
#                 msg = f'{data} must be of type {typ} is {type(data)}'
#                 logger.error(msg)
#                 raise IncompatibleValue(msg)
#             result = data
#         elif isinstance(data, (tuple, list)):
#             result = typ(*data)
#         else:
#             result = typ(data)
#     except (TypeError, ValueError, UnknownKeywordArgument):
#         # This error handling is required when there is no
#         # schema available to parse the data. Typically
#         # when an error code has been returned
#         # A none value should be returned if this is the case
#         if typ is not None:
#             msg = f'Could not create {typ}. DATA: {data}, TYPE: {type(data)}'
#             logger.error(msg)
#             raise InstantiationFailure(msg)
#     else:
#         return result
# 
# Path: async_v20/definitions/types.py
# class OrderRequest(Model, jit=False):
#     """The base Order specification. Contains all attributes an OrderRequest
#     may contain.
# 
#     Attributes:
# 
#         instrument: :class:`~async_v20.InstrumentName`
#         trade_id: :class:`~async_v20.TradeID`
#         price: :class:`~async_v20.PriceValue`
#         type: :class:`~async_v20.OrderType`
#         client_trade_id: :class:`~async_v20.ClientID`
#         time_in_force: :class:`~async_v20.TimeInForce`
#         gtd_time: :class:`~async_v20.DateTime`
#         trigger_condition: :class:`~async_v20.OrderTriggerCondition`
#         client_extensions: :class:`~async_v20.ClientExtensions`
#         distance: :class:`~async_v20.PriceValue`
#         instrument: :class:`~async_v20.InstrumentName`
#         units: :class:`~async_v20.DecimalNumber`
#         price_bound: :class:`~async_v20.PriceValue`
#         position_fill: :class:`~async_v20.OrderPositionFill`
#         take_profit_on_fill: :class:`~async_v20.TakeProfitDetails`
#         stop_loss_on_fill: :class:`~async_v20.StopLossDetails`
#         trailing_stop_loss_on_fill: :class:`~async_v20.TrailingStopLossDetails`
#         trade_client_extensions: :class:`~async_v20.ClientExtensions`
#     """
# 
#     def __init__(self, instrument: InstrumentName, trade_id: TradeID = sentinel, price: PriceValue = sentinel,
#                  type: OrderType = sentinel,
#                  client_trade_id: ClientID = sentinel, time_in_force: TimeInForce = sentinel,
#                  gtd_time: DateTime = sentinel,
#                  trigger_condition: OrderTriggerCondition = sentinel, client_extensions: ClientExtensions = sentinel,
#                  distance: PriceValue = sentinel, units: DecimalNumber = sentinel,
#                  price_bound: PriceValue = sentinel, position_fill: OrderPositionFill = sentinel,
#                  take_profit_on_fill: TakeProfitDetails = sentinel, stop_loss_on_fill: StopLossDetails = sentinel,
#                  trailing_stop_loss_on_fill: TrailingStopLossDetails = sentinel,
#                  trade_client_extensions: ClientExtensions = sentinel):
#         Model.__init__(**locals())
# 
# Path: async_v20/definitions/helpers.py
# def check_conflicting_arguments(self, kwargs, preset_values):
# def json_to_instance_attributes(self, kwargs, template):
# def domain_check(value, example=None, possible_values=None):
# def flatten_dict(dictionary, delimiter='_'):
#     def unpack(parent_key, parent_value):
# def create_doc_signature(obj, sig):
# 
# Path: async_v20/endpoints/annotations.py
# class LastTransactionID(TransactionID):
#     """Contains the most recent TransactionID"""
#     pass
# 
# Path: async_v20/endpoints/annotations.py
# class SinceTransactionID(TransactionID):
#     """The account changes to get Since LastTransactionID for account_changes() method"""
#     pass
# 
# Path: async_v20/exceptions.py
# class FailedToCreatePath(AsyncV20Exception):
#     """Unable to construct the path for the requested endpoint"""
#     pass
# 
# class InvalidOrderRequest(AsyncV20Exception):
#     """The order request is not with in the instruments specification
#     the order is for"""
#     pass


# Path: async_v20/interface/helpers.py
import logging
import pandas as pd
from functools import partial
from inspect import _empty
from ..definitions.base import create_attribute
from ..definitions.types import OrderRequest
from ..definitions.helpers import sentinel
from ..endpoints.annotations import LastTransactionID
from ..endpoints.annotations import SinceTransactionID
from ..exceptions import FailedToCreatePath, InvalidOrderRequest

    """Create the JSON body to add to the HTTP request

    Args:
        request_schema: -- the endpoints request schema
        arguments: -- dict of user supplied arguments

    Returns:
        Dict containing the formatted data
    """

    def dumps():
        """Iterate over the arguments returning dicts of matching objects
        and format order requests where required"""
        for key, value in arguments.items():
            try:
                key = request_schema[key]
            except KeyError:
                continue
            else:
                # Only attempt to format OrderRequests that have an `instrument` attribute
                if isinstance(value, OrderRequest):
                    instrument = self.instruments.get_instrument(value.instrument)
                    if instrument is not None:
                        value = _format_order_request(value,
                                                      instrument,
                                                      self.format_order_requests)
                    else:
                        msg = f'The instrument specified instrument {value.instrument} ' \
                              f'for OrderRequest {value} is not tradeable by this account'
                        logger.error(msg)

                        raise InvalidOrderRequest(msg)