Package: wiji
wijiCodacy BadgeCircleCIcodecovCode style:
blackWijiis an asyncio distributed task processor/queue.It’s name is derived from the late Kenyan hip hop artiste, Gwiji.It is a bit likeCelerywijihas no third-party dependencies and it requires python version
3.7+wijiis work in progress and very early. It’s API may change in
backward incompatible ways.https://pypi.python.org/pypi/wijiContents:InstallationUsage+As a library+As cli app+Writing testsFeatures+async everywhere+monitoring-and-observability+logging+hooks+Rate limiting+QueuingInstallationpipinstallwijiUsage1. As a libraryimportasyncioimportwijiclassAdderTask(wiji.task.Task):the_broker=wiji.broker.InMemoryBroker()queue_name="AdderTaskQueue1"asyncdefrun(self,a,b):result=a+bprint("\nresult:{0}\n".format(result))returnresult# queue some tasksmyAdderTask=AdderTask()myAdderTask.synchronous_delay(a=4,b=37)myAdderTask.synchronous_delay(a=67,b=847)# run the workersworker=wiji.Worker(the_task=myAdderTask)asyncio.run(worker.consume_tasks())2. As a cli appwijialso ships with a commandline app calledwiji-cli.create awijiapp file(which is just any python file that has a
class instance ofwiji.app.App), eg;examples/my_app.pyimportwijiclassAdderTask(wiji.task.Task):the_broker=wiji.broker.InMemoryBroker()queue_name="AdderTaskQueue1"asyncdefrun(self,a,b):res=a+bprint()print("res:: ",res)print()returnresMyAppInstance=wiji.app.App(task_classes=[AdderTask])NB:the directory where your place that file(in this case;examples/) ought to be in yourPYTHONPATHthen runwiji-clipointing it to the dotted path of thewiji.app.Appinstance:wiji-cli--appexamples.my_app.MyAppInstanceWriting testsLets say you havewijitasks in your project and you want to write
integration or unit tests for them and their use.# my_tasks.pyimportwijiimportMyRedisBroker# a custom broker using redisDATABASE={}classAdderTask(wiji.task.Task):the_broker=MyRedisBroker()queue_name="AdderTask"asyncdefrun(self,a,b):"""
        adds two numbers and stores the resut in a database
        """result=a+bDATABASE["result"]=resultreturnresultclassExampleView:defpost(self,request):a=request["a"]b=request["b"]AdderTask().synchronous_delay(a=a,b=b)In the example above we have a view with onepostmethod. When
that method is called it queues a task that adds two numbers and then
stores the result of that addition in a database.That task uses a broker(MyRedisBroker) that is backed by redis.One way to write your tests would be;# test_tasks.pyfrommy_tasksimportExampleViewfromunittestimportTestCaseclassTestExampleView(TestCase):deftest_view(self):view=ExampleView()view.post(request={"a":45,"b":46})# do your asserts hereThe problem with the above approach is that this will require you to
have an instance of redis running for that test to run succesfully.This may not be what you want. Ideally you do not want your tests be
dependent on external services.wijiships with an in-memory broker that you can use in your
tests.So the test above can be re-written in this manner;# test_tasks.pyimportasynciofrommy_tasksimportExampleView,AdderTask,DATABASEfromunittestimportTestCase,mockclassTestExampleView(TestCase):@staticmethoddef_run(coro):"""
        helper function that runs any coroutine in an event loop.
        see:: https://blog.miguelgrinberg.com/post/unit-testing-asyncio-code
        """loop=asyncio.get_event_loop()returnloop.run_until_complete(coro)deftest_view(self):withmock.patch.object(# ie, substitute the redis broker with an in-memory one during test runsAdderTask,"the_broker",wiji.broker.InMemoryBroker())asmock_broker:view=ExampleView()view.post(request={"a":45,"b":46})# do your asserts heredeftest_whole_flow(self):withmock.patch.object(AdderTask,"the_broker",wiji.broker.InMemoryBroker())asmock_broker:# 1. assert that the database is initially emptyself.assertDictEqual(DATABASE,{})# 2. when `post` is called it will queue a taskview=ExampleView()view.post(request={"a":45,"b":46})# 3. we need to run workersworker=wiji.Worker(the_task=AdderTask())self._run(worker.consume_tasks(TESTING=True))# 4. assert that database has been updated succesfully.self.assertDictEqual(DATABASE,{"result":91})