Repository: liampauling/flumine (python)

Issue:
Flumine.info
Add `flumine.info` property which shows current state of all objects:

```python
{
    "markets": {
        "live_event_count": 27,
        "open_market_count": 216,
        "live_market_count": 217,
        "total_market_count": 288,
        "closed_market_count": 494
    },
    "client": {
        "exchange": "BETFAIR",
        "username": "username",
        "betting_client": "<APIClient [username]>",
        "account_balance": 10036.03,
        "exposure": -1.4,
        "commission_rate": 0.02,
        "chargeable_transaction_count": 0,
        "trading_controls": [
            "MAX_ORDER_COUNT"
         ]
    },
    "markets": [
        "Market: 1.170562963, £-12.22, 71 orders, closed: True",
        "Market: 1.170562965, £-2.04, 13 orders, closed: True",
        "Market: 1.170562967, £-2.18, 40 orders, closed: True",
        "Market: 1.170562970, £3.34, 50 orders, closed: True",
        "Market: 1.170553165, £-3.80, 58 orders, closed: True",
        "Market: 1.170553157, £22.51, 28 orders, closed: True",
        "Market: 1.170553167, £8.84, 53 orders, closed: True",
        "Market: 1.170553153, £-4.60, 51 orders, closed: True",
    ],
    },
    "streams": [
        "<OrderStreaming(OrderStreaming, started daemon 140624477026048)>",
        "<OrderStreaming(OrderStreaming, started daemon 140624468633344)>",
        "<MarketStreaming(MarketStreaming, started daemon 140624451847936)>",
    ],
    "logging_controls": [
        "<APIControl(logging_control, started daemon 140624065980160)>"
    ],
    "threads": [
        "<_MainThread(MainThread, started 140475220645696)>",
        "<BackgroundWorker(memory_profiler, started daemon 140475181455104)>",
        "<BackgroundWorker(keep_alive, started daemon 140475092694784)>",
        "<BackgroundWorker(poll_account_balance, started daemon 140475084302080)>",
        "<BackgroundWorker(poll_market_catalogue, started daemon 140475075909376)>",
        "<BackgroundWorker(poll_cleared_orders, started daemon 140475067516672)>",
        "<OrderStream(OrderStream, started daemon 140475059123968)>",
        "<DataStream(DataStream, started daemon 140475050731264)>",
        "<Thread(OrderStream_output_thread, started daemon 140475042338560)>",
        "<MarketStream(MarketStream, started daemon 140474622932736)>",
        "<Thread(MarketStream_output_thread, started daemon 140474614540032)>",
        "<Thread(raven-sentry.BackgroundWorker, started daemon 140474606147328)>"
    ]
}
```

Pull request description:
closes #179
info properties added

Patch:
diff --git a/HISTORY.rst b/HISTORY.rst
index 7f7b70a..860a60f 100644
--- a/HISTORY.rst
+++ b/HISTORY.rst
@@ -3,18 +3,6 @@
 Release History
 ---------------
 
-1.6.3 (2020-06-03)
-+++++++++++++++++++
-
-**Improvements**
-
-- #178 Client order stream disable/enable
-- #179 Info properties
-
-**Bug Fixes**
-
-- #191 missing git config
-
 1.6.2 (2020-06-03)
 +++++++++++++++++++
 
diff --git a/flumine/__version__.py b/flumine/__version__.py
index 709bed4..a0c94e1 100644
--- a/flumine/__version__.py
+++ b/flumine/__version__.py
@@ -1,6 +1,6 @@
 __title__ = "flumine"
 __description__ = "Betfair trading framework"
 __url__ = "https://github.com/liampauling/flumine"
-__version__ = "1.6.3"
+__version__ = "1.6.2"
 __author__ = "Liam Pauling"
 __license__ = "MIT"
diff --git a/flumine/baseflumine.py b/flumine/baseflumine.py
index fa526df..c695493 100644
--- a/flumine/baseflumine.py
+++ b/flumine/baseflumine.py
@@ -1,5 +1,6 @@
 import queue
 import logging
+import threading
 from typing import Type
 from betfairlightweight import resources
 
@@ -151,7 +152,7 @@ class BaseFlumine:
     ) -> Market:
         market = Market(self, market_id, market_book)
         self.markets.add_market(market_id, market)
-        logger.info("Adding: {0} to markets".format(market.market_id))
+        logger.info("Adding: {0} to markets".format(market.market_id), extra=self.info)
         return market
 
     def _process_raw_data(self, event: events.RawDataEvent) -> None:
@@ -213,11 +214,15 @@ class BaseFlumine:
 
         self.cleared_market_queue.put(market.market_id)
         self.log_control(event)
+        logger.info(
+            "Market removed", extra={"market_id": market.market_id, **self.info}
+        )
 
     def _process_cleared_orders(self, event):
         # todo update blotter?
         logger.info(
-            "Market closed and cleared", extra={"market_id": event.event.market_id},
+            "Market closed and cleared",
+            extra={"market_id": event.event.market_id, **self.info},
         )
 
     def _process_cleared_markets(self, event: events.ClearedMarketsEvent):
@@ -236,8 +241,23 @@ class BaseFlumine:
         for strategy in self.strategies:
             strategy.finish()
 
+    @property
+    def info(self) -> dict:
+        return {
+            "client": self.client.info,
+            "markets": {
+                "market_count": len(self.markets),
+                "open_market_count": len(self.markets.open_market_ids),
+                "live_orders": self.markets.live_orders,
+                "markets": self.markets,
+            },
+            "streams": [s for s in self.streams],
+            "logging_controls": self._logging_controls,
+            "threads": threading.enumerate(),
+        }
+
     def __enter__(self):
-        logger.info("Starting flumine")
+        logger.info("Starting flumine", extra=self.info)
         # add execution to clients
         self.client.add_execution(self)
         # simulated
@@ -276,4 +296,4 @@ class BaseFlumine:
         # logout
         self.client.logout()
         self._running = False
-        logger.info("Exiting flumine")
+        logger.info("Exiting flumine", extra=self.info)
diff --git a/flumine/clients/baseclient.py b/flumine/clients/baseclient.py
index a7b814e..cc93f43 100644
--- a/flumine/clients/baseclient.py
+++ b/flumine/clients/baseclient.py
@@ -22,7 +22,6 @@ class BaseClient:
         commission_base: float = DEFAULT_COMMISSION_BASE,
         interactive_login: bool = False,
         id_: str = None,
-        order_stream: bool = True,
     ):
         self.id = id_ or create_short_uuid()
         self.betting_client = betting_client
@@ -30,7 +29,6 @@ class BaseClient:
         self.capital_base = capital_base
         self.commission_base = commission_base
         self.interactive_login = interactive_login
-        self.order_stream = order_stream
 
         self.account_details = None
         self.account_funds = None
@@ -69,3 +67,13 @@ class BaseClient:
     @property
     def min_bsp_liability(self) -> Optional[float]:
         raise NotImplementedError
+
+    @property
+    def info(self) -> dict:
+        return {
+            "id": self.id,
+            "exchange": self.EXCHANGE.value if self.EXCHANGE else None,
+            "betting_client": self.betting_client,
+            "chargeable_transaction_count": self.chargeable_transaction_count,
+            "trading_controls": self.trading_controls,
+        }
diff --git a/flumine/streams/streams.py b/flumine/streams/streams.py
index 98214d4..c453a59 100644
--- a/flumine/streams/streams.py
+++ b/flumine/streams/streams.py
@@ -31,10 +31,10 @@ class Streams:
             strategy.streams.append(stream)
 
     def add_client(self, client: BaseClient) -> None:
-        if client.order_stream:
-            # todo if paper_trade: add_simulated_order_stream()
-            if client.EXCHANGE == ExchangeType.BETFAIR:
-                self.add_order_stream(client)
+        if client.EXCHANGE == ExchangeType.SIMULATED:
+            self.add_simulated_order_stream()
+        elif client.EXCHANGE == ExchangeType.BETFAIR:
+            self.add_order_stream(client)
 
     """ market data """
 


Test patch:
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 79d1968..1c30c22 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -65,8 +65,6 @@ jobs:
 
     - name: Publish
       run: |
-        git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
-        git config --local user.name "GitHub Action"
         twine upload dist/*
         mkdocs gh-deploy --force
       env:
diff --git a/tests/test_baseflumine.py b/tests/test_baseflumine.py
index 4558083..f90b498 100644
--- a/tests/test_baseflumine.py
+++ b/tests/test_baseflumine.py
@@ -170,8 +170,9 @@ class BaseFlumineTest(unittest.TestCase):
         mock_event.callback.assert_called_with(self.base_flumine, mock_event)
         mock__process_market_orders.assert_called_with(mock_market)
 
+    @mock.patch("flumine.baseflumine.BaseFlumine.info")
     @mock.patch("flumine.baseflumine.BaseFlumine.log_control")
-    def test__process_close_market(self, mock_log_control):
+    def test__process_close_market(self, mock_log_control, mock_info):
         mock_strategy = mock.Mock()
         mock_strategy.stream_ids = [1, 2, 3]
         self.base_flumine.strategies = [mock_strategy]
@@ -219,6 +220,9 @@ class BaseFlumineTest(unittest.TestCase):
     def test__process_end_flumine(self):
         self.base_flumine._process_end_flumine()
 
+    def test_info(self):
+        self.assertTrue(self.base_flumine.info)
+
     @mock.patch("flumine.baseflumine.events")
     @mock.patch("flumine.baseflumine.BaseFlumine.log_control")
     def test_enter_exit(self, mock_log_control, mock_events):
diff --git a/tests/test_clients.py b/tests/test_clients.py
index 954b1a4..a30a6a7 100644
--- a/tests/test_clients.py
+++ b/tests/test_clients.py
@@ -27,7 +27,6 @@ class BaseClientTest(unittest.TestCase):
         self.assertEqual(self.base_client.chargeable_transaction_count, 0)
         self.assertIsNone(self.base_client.execution)
         self.assertEqual(self.base_client.trading_controls, [])
-        self.assertTrue(self.base_client.order_stream)
 
     def test_login(self):
         with self.assertRaises(NotImplementedError):
@@ -66,6 +65,9 @@ class BaseClientTest(unittest.TestCase):
         with self.assertRaises(NotImplementedError):
             assert self.base_client.min_bsp_liability
 
+    def test_info(self):
+        self.assertTrue(self.base_client.info)
+
 
 class BetfairClientTest(unittest.TestCase):
     def setUp(self):
diff --git a/tests/test_streams.py b/tests/test_streams.py
index 6bd467c..3da6bd7 100644
--- a/tests/test_streams.py
+++ b/tests/test_streams.py
@@ -58,19 +58,19 @@ class StreamsTest(unittest.TestCase):
         self.streams(mock_strategy)
         self.assertEqual(len(mock_strategy.streams), 0)
 
-    @mock.patch("flumine.streams.streams.Streams.add_order_stream")
-    def test_add_client_betfair(self, mock_add_order_stream):
-        mock_client = mock.Mock(order_stream=True)
-        mock_client.EXCHANGE = streams.ExchangeType.BETFAIR
+    @mock.patch("flumine.streams.streams.Streams.add_simulated_order_stream")
+    def test_add_client_simulated(self, mock_add_simulated_order_stream):
+        mock_client = mock.Mock()
+        mock_client.EXCHANGE = streams.ExchangeType.SIMULATED
         self.streams.add_client(mock_client)
-        mock_add_order_stream.assert_called_with(mock_client)
+        mock_add_simulated_order_stream.assert_called_with()
 
     @mock.patch("flumine.streams.streams.Streams.add_order_stream")
-    def test_add_client_no_order_stream(self, mock_add_order_stream):
-        mock_client = mock.Mock(order_stream=False)
+    def test_add_client_betfair(self, mock_add_order_stream):
+        mock_client = mock.Mock()
         mock_client.EXCHANGE = streams.ExchangeType.BETFAIR
         self.streams.add_client(mock_client)
-        mock_add_order_stream.assert_not_called()
+        mock_add_order_stream.assert_called_with(mock_client)
 
     @mock.patch("flumine.streams.streams.Streams._increment_stream_id")
     def test_add_stream_new(self, mock_increment):