# Path: magnate/market.py
# class CommodityData:
# class Commodity:
# class SystemData:
# class LocationData:
# class Market:
#     def __init__(self, pubpen, commodity_data):
#     def __getattr__(self, key):
#     def __repr__(self):
#     def __init__(self, magnate, location_data, commodity_data):
#     def __getattr__(self, key):
#     def handle_market_info(self):
#     def handle_movement(self, new_location, *args):
#     def recalculate_prices(self):
#     def _calculate_price(self, commodity):
# 
# Path: magnate/ui/urwid/abcwidget.py
# class ABCWidget(urwid.WidgetMeta, ABCMeta):
#     """Combine ABCMeta and Widgetmeta together so that we can have a metaclass with both"""
#     pass
# 
# Path: magnate/ui/urwid/indexed_menu.py
# class IndexedMenuButton(urwid.Button):
#     """A button without decorations"""
#     button_left = urwid.Text("")
#     button_right = urwid.Text("")
# 
# class IndexedMenuEnumerator(MutableMapping):
#     """
#     Generates new indexes for enumerating a menu and associates an index to
#     a vselection.
# 
#     A selection is used by calling code to tell which entry was selected via
#     a keypress
#     """
#     idx_names = [str(c) for c in itertools.chain(
#         range(1, 10),
#         [0],
#         (c for c in punctuation if c not in frozenset('(){}[]<>'))
#     )]
# 
#     def __init__(self):
#         self.association = {}
#         self.idx = 0
# 
#     def set_next(self, selection):
#         """
#         Adds a new selection to the IndexedMenuEnumerator, picking the new key
#         from the list of valid enumerations
# 
#         :arg selection: The value being set
#         :returns: The key that was picked
#         """
#         try:
#             key = self.idx_names[self.idx]
#         except IndexError:
#             raise IndexError('Not enough prefixes to enumerate all list entries')
#         self.idx += 1
#         self.association[key] = selection
#         return key
# 
#     def clear(self):
#         """
#         Clear the mapping
# 
#         In addition to normal dict behaviour, this also resets the next index back to the beginning
#         """
#         super().clear()
#         self.idx = 0
# 
#     def __setitem__(self, name, selection):
#         """Sets a key's value.
# 
#         :arg name: The key
#         :arg selection: The value
# 
#         .. warning:: Unlike dict, this cannot be used to set new keys.  Use
#             :meth:`set_next` instead.
#         """
#         if name not in self.association:
#             raise KeyError('Can only create new keys for an IndexedMenuEnumerator via set_next()')
#         self.association[name] = selection
# 
#     def __getitem__(self, name):
#         return self.association[name]
# 
#     def __delitem__(self, name):
#         del self.association[name]
# 
#     def __iter__(self):
#         return iter(self.association)
# 
#     def __len__(self):
#         return len(self.association)
# 
# Path: magnate/ui/urwid/numbers.py
# def format_number(number, max_chars=7):
#     """
#     Format a number in a human readable form.  This adds locale-specific separators.
# 
#     If the number is too long, se scientific notation.
# 
#     :kwarg max_chars: The maximum number of characters a number can take on
#         the screen before it is turned into scientific notation.
#     """
#     formatted_number = locale.format('%d', number, grouping=True)
#     if len(formatted_number) > max_chars:
#         formatted_number = '{:.1E}'.format(number)
# 
#     return formatted_number


from collections import OrderedDict
from abc import abstractmethod
from functools import partial
from ...market import CommodityType
from .abcwidget import ABCWidget
from .indexed_menu import IndexedMenuButton, IndexedMenuEnumerator
from .numbers import format_number
import attr
import urwid

class CommodityCatalog(urwid.WidgetWrap, metaclass=ABCWidget):
    """Display a catalog of commodities to buy and sell"""
    _selectable = True

    """
    Must have a signals attribute that is a list containing at least two urwid signal names.

    (1) The signal to close the display
    (2) The signal to open an orderdialog

    These are referenced by offset into the list so it's important to keep
    these in order.  Other widgets interested in these two events may
    depend upon the order they appear in the signals list.  No other
    signals in the list may be referenced by their offset.  If the widget
    implements more urwid signals, define them afterwards.  Example::

        signals = ['close_market_display', 'open_order_dialog']

    .. warn:: Different CommodityCatalog implementations **must not**
        share the same signal names.

    .. note: This may be implemented as a **class** attribute rather than
        a property
    """
    signals = []

    @abstractmethod
    def __init__(self, pubpen, order_info_event, primary_title='Commodity',
                 auxiliary_cols=None, price_col_idx=0,

# Path: magnate/market.py
# class CommodityData:
# class Commodity:
# class SystemData:
# class LocationData:
# class Market:
#     def __init__(self, pubpen, commodity_data):
#     def __getattr__(self, key):
#     def __repr__(self):
#     def __init__(self, magnate, location_data, commodity_data):
#     def __getattr__(self, key):
#     def handle_market_info(self):
#     def handle_movement(self, new_location, *args):
#     def recalculate_prices(self):
#     def _calculate_price(self, commodity):
# 
# Path: magnate/ui/urwid/abcwidget.py
# class ABCWidget(urwid.WidgetMeta, ABCMeta):
#     """Combine ABCMeta and Widgetmeta together so that we can have a metaclass with both"""
#     pass
# 
# Path: magnate/ui/urwid/indexed_menu.py
# class IndexedMenuButton(urwid.Button):
#     """A button without decorations"""
#     button_left = urwid.Text("")
#     button_right = urwid.Text("")
# 
# class IndexedMenuEnumerator(MutableMapping):
#     """
#     Generates new indexes for enumerating a menu and associates an index to
#     a vselection.
# 
#     A selection is used by calling code to tell which entry was selected via
#     a keypress
#     """
#     idx_names = [str(c) for c in itertools.chain(
#         range(1, 10),
#         [0],
#         (c for c in punctuation if c not in frozenset('(){}[]<>'))
#     )]
# 
#     def __init__(self):
#         self.association = {}
#         self.idx = 0
# 
#     def set_next(self, selection):
#         """
#         Adds a new selection to the IndexedMenuEnumerator, picking the new key
#         from the list of valid enumerations
# 
#         :arg selection: The value being set
#         :returns: The key that was picked
#         """
#         try:
#             key = self.idx_names[self.idx]
#         except IndexError:
#             raise IndexError('Not enough prefixes to enumerate all list entries')
#         self.idx += 1
#         self.association[key] = selection
#         return key
# 
#     def clear(self):
#         """
#         Clear the mapping
# 
#         In addition to normal dict behaviour, this also resets the next index back to the beginning
#         """
#         super().clear()
#         self.idx = 0
# 
#     def __setitem__(self, name, selection):
#         """Sets a key's value.
# 
#         :arg name: The key
#         :arg selection: The value
# 
#         .. warning:: Unlike dict, this cannot be used to set new keys.  Use
#             :meth:`set_next` instead.
#         """
#         if name not in self.association:
#             raise KeyError('Can only create new keys for an IndexedMenuEnumerator via set_next()')
#         self.association[name] = selection
# 
#     def __getitem__(self, name):
#         return self.association[name]
# 
#     def __delitem__(self, name):
#         del self.association[name]
# 
#     def __iter__(self):
#         return iter(self.association)
# 
#     def __len__(self):
#         return len(self.association)
# 
# Path: magnate/ui/urwid/numbers.py
# def format_number(number, max_chars=7):
#     """
#     Format a number in a human readable form.  This adds locale-specific separators.
# 
#     If the number is too long, se scientific notation.
# 
#     :kwarg max_chars: The maximum number of characters a number can take on
#         the screen before it is turned into scientific notation.
#     """
#     formatted_number = locale.format('%d', number, grouping=True)
#     if len(formatted_number) > max_chars:
#         formatted_number = '{:.1E}'.format(number)
# 
#     return formatted_number


# Path: magnate/ui/urwid/commodity_catalog.py
from collections import OrderedDict
from abc import abstractmethod
from functools import partial
from ...market import CommodityType
from .abcwidget import ABCWidget
from .indexed_menu import IndexedMenuButton, IndexedMenuEnumerator
from .numbers import format_number
import attr
import urwid


class CommodityCatalog(urwid.WidgetWrap, metaclass=ABCWidget):
    """Display a catalog of commodities to buy and sell"""
    _selectable = True

    """
    Must have a signals attribute that is a list containing at least two urwid signal names.

    (1) The signal to close the display
    (2) The signal to open an orderdialog

    These are referenced by offset into the list so it's important to keep
    these in order.  Other widgets interested in these two events may
    depend upon the order they appear in the signals list.  No other
    signals in the list may be referenced by their offset.  If the widget
    implements more urwid signals, define them afterwards.  Example::

        signals = ['close_market_display', 'open_order_dialog']

    .. warn:: Different CommodityCatalog implementations **must not**
        share the same signal names.

    .. note: This may be implemented as a **class** attribute rather than
        a property
    """
    signals = []

    @abstractmethod
    def __init__(self, pubpen, order_info_event, primary_title='Commodity',
                 auxiliary_cols=None, price_col_idx=0,

                 types_traded=frozenset((CommodityType.cargo, CommodityType.property,