Forráskód Böngészése

cleaner project structure.

Tomislav Cvetic 7 éve
szülő
commit
2b0aae7518
6 módosított fájl, 207 hozzáadás és 133 törlés
  1. 3 1
      .gitignore
  2. 91 69
      calculate.py
  3. 35 48
      project.py
  4. 56 0
      pydux_sqlite.py
  5. 20 14
      pydux_thunk.py
  6. 2 1
      requirements.txt

+ 3 - 1
.gitignore

@@ -10,5 +10,7 @@
 [Ss]hare
 __pycache__
 pyvenv.cfg
+.idea
 .venv
-pip-selfcheck.json
+pip-selfcheck.json
+state.db

+ 91 - 69
calculate.py

@@ -2,83 +2,105 @@ import pydux_thunk
 import asyncio
 
 initial_state = {
-	'running': False,
-	'result': None,
-	'error': None
+    'running': False,
+    'result': None,
+    'error': None
 }
 
+
 class ActionTypes(object):
-	CALCULATE = 'calculate/CALCULATE'
-	START = 'calculate/START'
-	FAILURE = 'calculate/FAILURE'
-	SUCCESS = 'calculate/SUCCESS'
+    START = 'calculate/START'
+    FAILURE = 'calculate/FAILURE'
+    SUCCESS = 'calculate/SUCCESS'
+
 
 class ActionCreators(object):
-	def calculate(value1, value2):
-		return thunk(value1, value2)
-
-	def start():
-		return dict(
-			type=ActionTypes.START
-		)
-
-	def success(result):
-		return dict(
-			type=ActionTypes.SUCCESS,
-			result=result
-		)
-
-	def failure(error):
-		return dict(
-			type=ActionTypes.FAILURE,
-			error=error
-		)
-
-def reducer (state=None, action=None):
-	if state is None:
-		state = initial_state
-	if not (isinstance(action, dict) and 'type' in action):
-		return state
-	if action['type'] == ActionTypes.CALCULATE:
-		state['running'] = True
-	elif action['type'] == ActionTypes.SUCCESS:
-		state['running'] = False
-		state['result'] = action['result']
-		state['error'] = None
-	elif action['type'] == ActionTypes.FAILURE:
-		state['running'] = False
-		state['result'] = None
-		state['error'] = action['error']
-	return state
+
+    @staticmethod
+    def calculate(value1, value2):
+        return thunk(value1, value2)
+
+    @staticmethod
+    def start():
+        return dict(
+            type=ActionTypes.START
+        )
+
+    @staticmethod
+    def success(result):
+        return dict(
+            type=ActionTypes.SUCCESS,
+            result=result
+        )
+
+    @staticmethod
+    def failure(error):
+        return dict(
+            type=ActionTypes.FAILURE,
+            error=error
+        )
+
+
+def reducer(state=None, action=None):
+    if state is None:
+        state = initial_state
+    if not (isinstance(action, dict) and 'type' in action):
+        return state
+    if action['type'] == ActionTypes.START:
+        state['running'] = True
+    elif action['type'] == ActionTypes.SUCCESS:
+        state['running'] = False
+        state['result'] = action['result']
+        state['error'] = None
+    elif action['type'] == ActionTypes.FAILURE:
+        state['running'] = False
+        state['result'] = None
+        state['error'] = action['error']
+    return state
+
 
 async def calculate(value1, value2):
-	print('calculating pi', value1, value2)
-	await asyncio.sleep(5)
-	return data**2
+    print('dividing', value1, value2)
+    await asyncio.sleep(3)
+    return value1 / value2
+
 
 def thunk(value1, value2):
-	async def wrapper(dispatch, get_state):
-		dispatch(ActionCreators.calculate())
-		result = await calculate(value1, value2)
-		dispatch(ActionCreators.success(result))
-	return wrapper
+    async def wrapper(dispatch, get_state):
+        dispatch(ActionCreators.start())
+        try:
+            result = await calculate(value1, value2)
+            dispatch(ActionCreators.success(result))
+        except Exception as error:
+            dispatch(ActionCreators.failure(dict(
+                type=error.__class__.__name__,
+                description=str(error)
+            )))
+
+    return wrapper
+
 
 if __name__ == '__main__':
-	import unittest
-
-	class TestSuite(unittest.TestCase):
-		def test_action_creators(self):
-			#self.assertEqual(ActionCreators.calculate(1, 2), thunk(1, 2))
-			self.assertEqual(ActionCreators.start(), {'type': 'calculate/START'})
-			self.assertEqual(ActionCreators.success(4), {'type': 'calculate/SUCCESS', 'result': 4})
-			#self.assertEqual(ActionCreators.failure(ZeroDivisionError()), {'type': 'calculate/FAILURE', 'error': ZeroDivisionError()})
-
-		def test_reducer(self):
-			self.assertEqual(reducer(None, ActionCreators.calculate(6,2)), {'running': False, 'result': None, 'error': None})
-			#self.assertEqual(reducer(452, ActionCreators.set_state(13)), 13)
-			#self.assertEqual(reducer(None, ActionCreators.increment()), 1)
-			#self.assertEqual(reducer(341, ActionCreators.increment()), 342)
-			#self.assertEqual(reducer(None, ActionCreators.decrement()), -1)
-			#self.assertEqual(reducer(251, ActionCreators.decrement()), 250)
-
-	unittest.main()
+    import unittest
+
+
+    class TestSuite(unittest.TestCase):
+        def test_action_creators(self):
+            # self.assertEqual(ActionCreators.calculate(1, 2), thunk(1, 2))
+            self.assertEqual(ActionCreators.start(), {'type': 'calculate/START'})
+            self.assertEqual(ActionCreators.success(4), {'type': 'calculate/SUCCESS', 'result': 4})
+
+        # self.assertEqual(ActionCreators.failure(ZeroDivisionError()), {'type': 'calculate/FAILURE', 'error': ZeroDivisionError()})
+
+        def test_reducer(self):
+            self.assertEqual(reducer(None, ActionCreators.calculate(2)),
+							 {'running': False, 'result': None, 'error': None})
+
+        # self.assertEqual(reducer(452, ActionCreators.set_state(13)), 13)
+        # self.assertEqual(reducer(None, ActionCreators.increment()), 1)
+        # self.assertEqual(reducer(341, ActionCreators.increment()), 342)
+        # self.assertEqual(reducer(None, ActionCreators.decrement()), -1)
+        # self.assertEqual(reducer(251, ActionCreators.decrement()), 250)
+
+
+    unittest.main()

+ 35 - 48
project.py

@@ -1,60 +1,49 @@
+# Import dependencies
 import pydux
 import asyncio
 import time
-import threading
-import counter
-import calculate
 import pydux_thunk
+import pydux_sqlite
 
-def loop_in_thread(loop):
-	async def main_task():
-		print('Starting loop')
-		while True:
-			await asyncio.sleep(1)
-			pending = asyncio.Task.all_tasks()
-			my_sum = 0
-			for task in pending:
-				if not task.done():
-					my_sum += 1
-			if my_sum == 1:
-				break
-		print('All tasks finished, exiting loop.')
-
-	asyncio.set_event_loop(loop)
-	loop.run_until_complete(main_task())
-	loop.close()
+# Import modules
+import counter
+import calculate
 
+# Define the async loop
 loop = asyncio.get_event_loop()
-t = threading.Thread(target=loop_in_thread, args=(loop,))
-t.start()
-
-def log_middleware(store):
-	def wrapper(next_):
-		def log_dispatch(action):
-			print('Dispatch Action:', action)
-			return next_(action)
-		return log_dispatch
-	return wrapper
-
+pydux_thunk.loop = loop
 
+# Combine the middleware
+middleware = [
+    pydux_thunk.middleware,
+    pydux_sqlite.middleware
+]
+middleware = pydux.apply_middleware(*middleware)
 
+# Combine the state
 initial_state = {
-	'counter': counter.initial_state,
-	'calculate': calculate.initial_state
+    'counter': counter.initial_state,
+    'calculate': calculate.initial_state
 }
 
+# Combine the reducers
 root_reducer = pydux.combine_reducers({
-	'counter': counter.reducer,
-	'calculate': calculate.reducer
+    'counter': counter.reducer,
+    'calculate': calculate.reducer
 })
 
-middleware = pydux.apply_middleware(log_middleware, pydux_thunk.middleware)
-
+# Create the store
 store = pydux.create_store(root_reducer, initial_state, middleware)
 
+
 def my_subscriber():
-	print('Current state', store.get_state())
+    """
+    Dummy subscriber, just prints the state.
+    :return: Nothing
+    """
+    print('Current state', store.get_state())
 
+# Subscribe to the store
 store.subscribe(my_subscriber)
 
 print('starting.')
@@ -62,14 +51,12 @@ store.dispatch(counter.ActionCreators.increment())
 store.dispatch(counter.ActionCreators.increment())
 store.dispatch(counter.ActionCreators.increment())
 store.dispatch(calculate.ActionCreators.calculate(3, 4))
-#store.dispatch(my_thunk(4))
-time.sleep(2)
-#store.dispatch(ActionCreators.decrement())
-#store.dispatch(my_thunk(3))
 time.sleep(1)
-#store.dispatch(my_bump())
-while loop.is_running():
-	time.sleep(1)
-print('Loop done, closing task.')
-t.join()
-print('Task finished, bye!')
+store.dispatch(calculate.ActionCreators.calculate(5, 0))
+time.sleep(1)
+store.dispatch(calculate.ActionCreators.calculate(9, 3))
+store.dispatch(counter.ActionCreators.increment())
+store.dispatch(counter.ActionCreators.increment())
+store.dispatch(counter.ActionCreators.increment())
+store.dispatch(counter.ActionCreators.increment())
+loop.run_forever()

+ 56 - 0
pydux_sqlite.py

@@ -0,0 +1,56 @@
+import sqlite3
+import json
+import datetime, time
+import threading
+import queue
+
+
+db_path = 'state.db'
+
+
+def sql_thread(command_queue, response_queue):
+    connection = sqlite3.connect(db_path)
+    cursor = connection.cursor()
+    cursor.execute('CREATE TABLE IF NOT EXISTS actions (id INTEGER PRIMARY KEY, date TEXT, action TEXT)')
+    cursor.execute('CREATE TABLE IF NOT EXISTS state (id INTEGER PRIMARY KEY, date TEXT, state TEXT)')
+    connection.commit()
+    task_done = False
+
+    while not task_done:
+        table, data = command_queue.get()
+        try:
+            if table == 'actions':
+                cursor.execute('INSERT INTO actions VALUES (NULL, ?, ?)', data)
+                connection.commit()
+            elif table == 'state':
+                cursor.execute('INSERT INTO state VALUES (NULL, ?, ?)', data)
+                connection.commit()
+            elif table == 'DONE':
+                task_done = True
+                response_queue.put('Bye!')
+            else:
+                response_queue.put(ValueError('table {} doesn\'t exist.'.format(table)))
+        except Exception as error:
+            response_queue.put(error)
+
+
+command_queue = queue.Queue()
+response_queue = queue.Queue()
+t = threading.Thread(target=sql_thread, args=(command_queue, response_queue))
+t.start()
+
+
+def middleware(store):
+    dispatch = store['dispatch']
+    get_state = store['get_state']
+
+    def wrapper(next_):
+        def update_db(action):
+            state = get_state()
+            now = datetime.datetime.now()
+            command_queue.put(('actions', [now, json.dumps(action)]))
+            command_queue.put(('state', [now, json.dumps(state)]))
+            return next_(action)
+
+        return update_db
+    return wrapper

+ 20 - 14
pydux_thunk.py

@@ -1,19 +1,25 @@
 import asyncio
 import inspect
 
+
+loop = None
+
+
 def middleware(store):
-	dispatch = store['dispatch']
-	get_state = store['get_state']
+    dispatch = store['dispatch']
+    get_state = store['get_state']
+
+    def wrapper(next_):
+        def thunk_dispatch(action):
+            if callable(action):
+                if inspect.iscoroutinefunction(action):
+                    print('found async action')
+                    return loop.call_soon_threadsafe(asyncio.ensure_future, action(dispatch, get_state))
+                else:
+                    print('found sync action')
+                    return action(dispatch, get_state)
+            return next_(action)
+
+        return thunk_dispatch
 
-	def wrapper(next_):
-		def thunk_dispatch(action):
-			if callable(action):
-				if inspect.iscoroutinefunction(action):
-					print('found async action')
-					return loop.call_soon_threadsafe(asyncio.ensure_future, action(dispatch, get_state))
-				else:
-					print('found sync action')
-					return action(dispatch, get_state)
-			return next_(action)
-		return thunk_dispatch
-	return wrapper
+    return wrapper

+ 2 - 1
requirements.txt

@@ -1 +1,2 @@
-pydux
+pydux
+janus