{ "info": { "author": "Ronaldo Webb", "author_email": "mobil3.g3nius@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Environment :: Console", "Intended Audience :: Developers", "Intended Audience :: End Users/Desktop", "Intended Audience :: System Administrators", "Programming Language :: Python", "Topic :: Communications :: Email", "Topic :: Software Development :: Bug Tracking" ], "description": "============\r\nIntroduction\r\n============\r\n\r\nSometime in the development or implementation we encounter things to be processed by different specialization. For example, we receive a CSV file that is intended from importing to a table. We found out that the CSV file is not formatted to what the table can consume. Thus, we need to do two thing:\r\n\r\n1. Transform or create a CSV file to meet the table requirement based on the CSV file at hand.\r\n2. Wrap the contents of the transformed and newly created CSV to create the SQL statements that can be readily run against a database.\r\n\r\nAs we can see above, these then can be created by two different individuals one that is specialized in manipulating CSV file and knowledge in generating SQL scripts. Addition, these two thing must be run in sequence and not on the other way around. \r\n\r\nThis is the idea around the conveyor that the work is done in sequence and can use some tools.\r\n\r\n============\r\nInstallation\r\n============\r\n\r\nThe installation is as easy as downloading the conveyor--py3-none-any.whl package and run the following command in the download folder in the command line:\r\n\r\n**Command 1. Using pip module for installation**\r\n\r\nIf you have the wheel package\r\n::\r\n\r\n python -m pip install mg_conveyor--py3-none-any.whl\r\n\r\nOr simply\r\n\r\n::\r\n\r\n python -m pip install mg-conveyor\r\n\r\n==================\r\nUsing the conveyor \r\n==================\r\n\r\n**Conveyor** is not intended be used as a standalone command but a least a plugin must be made available to it to process. \r\n\r\nThe ISequencialPlugin Interface\r\n-------------------------------\r\n\r\nAs its name suggests it is executed based on sequence. This plugin needs the following methods to be implemented:\r\n\r\nMethods to be implemented\r\n^^^^^^^^^^^^^^^^^^^^^^^^^\r\n\r\n::\r\n\r\n\tdef sequence(self)\r\n\tdef process(self, identity, context, *args, **kwargs)\r\n\r\nThe **sequence method** must return an integer that will dictate sequence on when it must be executed.\r\n\r\n.. note:: **Every plugin** must return a different sequence number.\r\n\r\nThe **process method** is the entrypoint for each plugin and this is where our plugin logic must reside. This method has two important parameters namely identity and context. Currently the identity is the name of the plugin (i.e. defined in the yapsy configuration file that is particularly the **Name** attribute) and the context contains some information about the plugin. Also this method must return one of the predefined status.\r\n\r\n**ISequencialPlugin Return Status**\r\n\r\n======================= ======================================================\r\nStatus Description\r\n======================= ======================================================\r\nSTATUS_SUCCESS\t\t\tFinished successfully.\r\nSTATUS_FAILED\t\t\tError encountered also abort the execution of conveyor\r\nSTATUS_ABORT Abort the execution of conveyor.\r\nSTATUS_RETRY The plugin is requesting an interactive retry.\r\nSTATUS_CONFIRM_RETRY The user responded Y to the interactive retry.\r\nSTATUS_CONFIRM_ABORT The user responded N to the interactive retry.\r\nSTATUS_SKIPPED Skipped plugin\r\nSTATUS_STARTED Plugin is currently started.\r\n======================= ======================================================\r\n\r\n**Example 1. Simple Plugin Implementation**\r\n\r\n::\r\n\r\n\timport mg_conveyor as conveyor\r\n\tclass PluginOne(conveyor.ISequencialPlugin):\r\n\t def sequence(self):\r\n\t return 100\r\n\t def process(self, identity, context, *args, **kwargs):\r\n\t \tprint(\"Hello Worlds.\")\r\n\t return conveyor.STATUS_SUCCESS\r\n\r\nUsing the context Parameter\r\n^^^^^^^^^^^^^^^^^^^^^^^^^^^\r\n\r\nThe context parameter contains some information about the plugin like its status (i.e. CONTEXT_KEY_STATUS) and its instance (i.e. CONTEXT_KEY_PLUGIN_OBJECT). This parameter is just a simple dictionary. By default each plugin has its own context inside the context with the key as its identity (i.e. context[identity]). Thus, to get the plugin object of the current plugin we should access it like the following snippet inside the process method.\r\n\r\n::\r\n\r\n\tpluginObj = context[identity][CONTEXT_KEY_PLUGIN_OBJECT]\r\n\r\n**Pre-defined Context Keys per identity**\r\n\r\n========================= ============================================================\r\nStatus Description\r\n========================= ============================================================\r\nCONTEXT_KEY_STATUS\t\t Contains the numerical equivalent of the **ISequencialPlugin Return Status**.\r\nCONTEXT_KEY_PLUGIN_OBJECT The instance of the plugin associated with the identity.\r\n========================= ============================================================\r\n\r\nThe context has another purpose that it can hold custom plugin information. To add a new entry to the context it is better to add it under the identity key. This can be done by the snippet below (i.e. inside the process method):\r\n\r\n::\r\n\r\n\tplugin_context = context[identity]\r\n\tplugin_context['item1']='This is item 1'\r\n\tplugin_context['item2']='This is item 2'\r\n\r\nMore over this context is shared by all the plugins loaded by the conveyor. Therefore, we can use the context to pass information between plugins. For example the result of the first plugin can be stored in the context and that item will be processed by the following plugin.\r\n\r\nYapsy Configuration File\r\n------------------------\r\n\r\nOnce the plugin is ready we must create a configuration file. Since we are using yapsy the sample configuration file is as follows:\r\n\r\n::\r\n\r\n\t[Core]\r\n\tName = Hello World\r\n\tModule = helloworld\r\n\r\n\t[Documentation]\r\n\tAuthor = Ronaldo Webb\r\n\tVersion = 0.1\r\n\tWebsite = http://www.ronella.xyz\r\n\tDescription = Test only\r\n\r\n.. note:: The **Name attribute** in this configuration file is the one being used as the **identity parameter** in the process method.\r\n\r\nSee `yapsy-plugin`_ for more information about the content of the configuration file.\r\n\r\n.. _yapsy-plugin: http://yapsy.sourceforge.net/PluginFileLocator.html\r\n\r\nThe IUtilityPlugin Interface\r\n-------------------------------\r\n\r\nThis plugin is the one that can be shared by all ISequencialPlugin implementations. Thus, we can think of the IUtilityPlugin implementation as a **tool** that the ISequencialPlugin (i.e. activing as a worker) can use to do its job properly. This tool is always available in the context and only has one method to be implemented. \r\n\r\nMethod to be implemented\r\n^^^^^^^^^^^^^^^^^^^^^^^^^\r\n\r\n::\r\n\r\n\tdef use(self, *args, **kwargs)\r\n\r\nThe **use method** must contain the implmentation on what the ISequencialPlugin implementaion demands it to do according to what it's purpose as a tool. It can return any type therefore the a proper documentation of the return type is necessary.\r\n\r\nBuilt-in Properties\r\n^^^^^^^^^^^^^^^^^^^\r\n\r\nThe IUtilityPlugin has built-in properties as we can see in the following table:\r\n\r\n============ ==========================================================================================\r\nProperty Description\r\n============ ==========================================================================================\r\nidentity Contains the identity of the plugin (i.e. the Name attribute in yapsy configuration file.)\r\ncontext The context shared by all the plugins.\r\nlocalContext This is equals to context[identity].\r\n============ ==========================================================================================\r\n\r\nAcquiring IUtilityPlugin from context\r\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\r\n\r\nTo acquire an instance of the IUtilityPlugin we must know its identity (i.e. Name attribute in yapsy configuraiton file.). Once we have the instance we can call it's use method.\r\n\r\n**Example 2: Acquiring IUtilityPlugin**\r\n\r\nIf have **Utility** as the identity then in the process method of the ISequencialPlugin implementation we can retrieve its instance like in the snippet below:\r\n\r\n::\r\n\r\n def process(self, identity, context, *args, **kwargs):\r\n \r\n utilObj = context['Utility'][conveyor.CONTEXT_KEY_PLUGIN_OBJECT].use()\r\n\r\n.. note:: We can pass any number of arguments to the use method.\r\n\r\nStarting The Conveyor\r\n---------------------\r\n\r\nOnce the plugin is working fine and the configuration file were created, we can now create an implmenetation to start the conveyor. The first thing that we must do is to instantiate the Conveyor class then load the plugins and finally start it. See the sample snippet below:\r\n\r\n**Example 3: Starting the Conveyor**\r\n\r\n::\r\n\r\n\tconv = conveyor.Conveyor()\r\n\tconv.loadPlugins([\"plugins\"])\r\n\tconv.start()\r\n\r\n.. note:: In the **loadPlugins method** we must pass in an **array of locations** of the plugins.\r\n\r\n========\r\nAppendix\r\n========\r\n\r\nComplete Hello World Implementation\r\n-----------------------------------\r\n\r\nplugins/helloworld_plugin.py\r\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^\r\n\r\n::\r\n\r\n\timport mg_conveyor as conveyor\r\n\tclass PluginOne(conveyor.ISequencialPlugin):\r\n\t def sequence(self):\r\n\t return 100\r\n\t def process(self, identity, context, *args, **kwargs):\r\n\t \tprint(\"Hello World.\")\r\n\t return conveyor.STATUS_SUCCESS\r\n\r\nplugins/helloworld.yapsy-plugin\r\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\r\n\r\n::\r\n\r\n\t[Core]\r\n\tName = Hello World\r\n\tModule = helloworld_plugin\r\n\r\n\t[Documentation]\r\n\tAuthor = Ronaldo Webb\r\n\tVersion = 0.1\r\n\tWebsite = http://www.ronella.xyz\r\n\tDescription = Test only\r\n\r\nhelloworld.py\r\n^^^^^^^^^^^^^\r\n\r\n::\r\n\r\n import mg_conveyor as conveyor\r\n \r\n if __name__ == '__main__':\r\n \r\n conv=conveyor.Conveyor()\r\n conv.loadPlugins([\"plugins\"])\r\n conv.start() \r\n\r\nSample Context Usage\r\n--------------------\r\n\r\nplugins/plugin1.py\r\n^^^^^^^^^^^^^^^^^^\r\n\r\n::\r\n\r\n\timport mg_conveyor as conveyor\r\n\tclass Plugin(conveyor.ISequencialPlugin):\r\n\t def sequence(self):\r\n\t return 100\r\n\t \r\n\t def process(self, identity, context, *args, **kwargs):\r\n\t plugin_context = context[identity]\r\n\t \r\n\t plugin_context['Message'] = \"From plugin 1\"\r\n\t \r\n\t return conveyor.STATUS_SUCCESS\r\n\r\nplugins/plugin1.yapsy-plugin\r\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^\r\n\r\n::\r\n\r\n\t[Core]\r\n\tName = Plugin1\r\n\tModule = plugin1\r\n\r\n\t[Documentation]\r\n\tAuthor = Ronaldo Webb\r\n\tVersion = 0.1\r\n\tWebsite = http://www.ronella.xyz\r\n\tDescription = Test only\r\n\r\nplugins/plugin2.py\r\n^^^^^^^^^^^^^^^^^^\r\n\r\n::\r\n\r\n\timport mg_conveyor as conveyor\r\n\tclass Plugin(conveyor.ISequencialPlugin):\r\n\t def sequence(self):\r\n\t return 200\r\n\t \r\n\t def process(self, identity, context, *args, **kwargs):\r\n\t \r\n\t #Plugin1 is the Name found in plugin1.yapsy-plugin\r\n\t plugin1_context = context['Plugin1']\r\n\t \r\n\t \r\n\t print(\"I'm in plugin 2...\")\r\n\t print(\"Message from plugin 1: \" + plugin1_context['Message'])\r\n\t return conveyor.STATUS_SUCCESS\r\n\r\nplugins/plugin2.yapsy-plugin\r\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^\r\n\r\n::\r\n\r\n\t[Core]\r\n\tName = Plugin2\r\n\tModule = plugin2\r\n\r\n\t[Documentation]\r\n\tAuthor = Ronaldo Webb\r\n\tVersion = 0.1\r\n\tWebsite = http://www.ronella.xyz\r\n\tDescription = Test only\r\n\r\ncontext_usage.py\r\n^^^^^^^^^^^^^^^^\r\n\r\n::\r\n\r\n\timport mg_conveyor as conveyor\r\n\r\n\tif __name__ == '__main__':\r\n\r\n\t conv=conveyor.Conveyor()\r\n\t conv.loadPlugins([\"plugins\"])\r\n\t conv.start() \r\n\r\nPassing Parameter to the Process Method\r\n---------------------------------------\r\n\r\nplugins/parameter.py\r\n^^^^^^^^^^^^^^^^^^^^\r\n\r\n::\r\n\r\n import mg_conveyor as conveyor\r\n class PluginOne(conveyor.ISequencialPlugin):\r\n\r\n def sequence(self):\r\n return 100\r\n\t \r\n def process(self, identity, context, *args, **kwargs):\r\n print(\"Argument 1: \" + args[0])\r\n print(\"Arguemnt 2: \" + args[1])\r\n print(\"Parameter 1: \" + kwargs['param1'])\r\n print(\"Parameter 2: \" + kwargs['param2'])\r\n \r\n return conveyor.STATUS_SUCCESS\r\n\r\nplugins/parameter.yapsy-plugin\r\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\r\n\r\n::\r\n\r\n\t[Core]\r\n\tName = Parameter Passing\r\n\tModule = parameter\r\n\r\n\t[Documentation]\r\n\tAuthor = Ronaldo Webb\r\n\tVersion = 0.1\r\n\tWebsite = http://www.ronella.xyz\r\n\tDescription = Test only\r\n\r\nprocess_parameter.py\r\n^^^^^^^^^^^^^^^^^^^^\r\n\r\n::\r\n\r\n import mg_conveyor as conveyor\r\n \r\n if __name__ == '__main__':\r\n \r\n conv=conveyor.Conveyor()\r\n conv.loadPlugins([\"plugins\"])\r\n conv.start(\"arg0\"\r\n , \"arg1\"\r\n , param1=\"This is parameter 1\"\r\n , param2=\"This is parameter 2\") \r\n\r\nBasic Sample for using IUtilityPlugin\r\n-------------------------------------\r\n\r\nutility.py\r\n^^^^^^^^^^\r\n\r\n::\r\n\r\n import mg_conveyor as conveyor\r\n \r\n class Utility(conveyor.IUtilityPlugin):\r\n \r\n def __init__(self):\r\n super().__init__()\r\n \r\n def use(self, *args, **kwargs):\r\n \r\n self.localContext['Message'] = \"I'm in Utility plugin\"\r\n return \"This is a test.\"\r\n\r\nutility.yapsy-plugin\r\n^^^^^^^^^^^^^^^^^^^^\r\n\r\n::\r\n\r\n [Core]\r\n Name = Utility\r\n Module = utility\r\n \r\n [Documentation]\r\n Author = Ronaldo Webb\r\n Version = 0.1\r\n Website = http://www.ronella.xyz\r\n Description = Test only\r\n\r\nsequence.py\r\n^^^^^^^^^^^\r\n\r\n::\r\n\r\n import mg_conveyor as conveyor\r\n \r\n class PluginOne(conveyor.ISequencialPlugin):\r\n def sequence(self):\r\n return 100\r\n \r\n def process(self, identity, context, *args, **kwargs):\r\n \r\n utilCtx = context['Utility']\r\n utilOutput = utilCtx[conveyor.CONTEXT_KEY_PLUGIN_OBJECT].use()\r\n \r\n if 'util_message' in kwargs:\r\n kwargs['util_message'](utilCtx['Message'])\r\n \r\n if 'util_output' in kwargs:\r\n kwargs['util_output'](utilOutput)\r\n \r\n return conveyor.STATUS_SUCCESS\r\n\r\nsequence.yapsy-plugin\r\n^^^^^^^^^^^^^^^^^^^^^\r\n\r\n::\r\n\r\n [Core]\r\n Name = Sequence\r\n Module = sequence\r\n \r\n [Documentation]\r\n Author = Ronaldo Webb\r\n Version = 0.1\r\n Website = http://www.ronella.xyz\r\n Description = Test only\r\n\r\nutility_usage.py\r\n^^^^^^^^^^^^^^^^\r\n\r\n::\r\n\r\n\timport mg_conveyor as conveyor\r\n\r\n\tif __name__ == '__main__':\r\n\r\n\t conv=conveyor.Conveyor()\r\n\t conv.loadPlugins([\"plugins\"])\r\n\t conv.start()", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://sourceforge.net/projects/mobgenconveyor", "keywords": "tool plugin utility development dev", "license": "UNKNOWN", "maintainer": "", "maintainer_email": "", "name": "mg-conveyor", "package_url": "https://pypi.org/project/mg-conveyor/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/mg-conveyor/", "project_urls": { "Download": "UNKNOWN", "Homepage": "https://sourceforge.net/projects/mobgenconveyor" }, "release_url": "https://pypi.org/project/mg-conveyor/1.0.0/", "requires_dist": null, "requires_python": null, "summary": "A tool for having a sequential execution of plugins", "version": "1.0.0" }, "last_serial": 1407493, "releases": { "1.0.0": [ { "comment_text": "", "digests": { "md5": "531654c18aa2e95ba23e2ad4acdd18c8", "sha256": "d9cac0efb86e936ae1aed81528c2eb93d021f99833d42c85e782aa5b44bf8606" }, "downloads": -1, "filename": "mg_conveyor-1.0.0-py3-none-any.whl", "has_sig": false, "md5_digest": "531654c18aa2e95ba23e2ad4acdd18c8", "packagetype": "bdist_wheel", "python_version": "3.4", "requires_python": null, "size": 12137, "upload_time": "2015-02-03T09:40:17", "url": "https://files.pythonhosted.org/packages/f5/e2/abeee4e5f80c2040bfa47bfe516d661598113f10c2faad7011acfed00ee9/mg_conveyor-1.0.0-py3-none-any.whl" } ], "1.0.0b": [ { "comment_text": "", "digests": { "md5": "90210d0a2fce6b8fe21112dd48b10672", "sha256": "c6c9460e5792e9f3f3ac65d346eafc751aff2f3cbab9a45171443e849b3a2f93" }, "downloads": -1, "filename": "mg_conveyor-1.0.0b-py3-none-any.whl", "has_sig": false, "md5_digest": "90210d0a2fce6b8fe21112dd48b10672", "packagetype": "bdist_wheel", "python_version": "3.4", "requires_python": null, "size": 12154, "upload_time": "2015-02-03T09:22:04", "url": "https://files.pythonhosted.org/packages/9b/3f/d35542c2d384f94498bf98f03b6c3bb136e95363297ae0197df4c8fd7a3a/mg_conveyor-1.0.0b-py3-none-any.whl" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "531654c18aa2e95ba23e2ad4acdd18c8", "sha256": "d9cac0efb86e936ae1aed81528c2eb93d021f99833d42c85e782aa5b44bf8606" }, "downloads": -1, "filename": "mg_conveyor-1.0.0-py3-none-any.whl", "has_sig": false, "md5_digest": "531654c18aa2e95ba23e2ad4acdd18c8", "packagetype": "bdist_wheel", "python_version": "3.4", "requires_python": null, "size": 12137, "upload_time": "2015-02-03T09:40:17", "url": "https://files.pythonhosted.org/packages/f5/e2/abeee4e5f80c2040bfa47bfe516d661598113f10c2faad7011acfed00ee9/mg_conveyor-1.0.0-py3-none-any.whl" } ] }