Advertisement
gauravssnl

making_pys60_plugins.txt

Nov 5th, 2016
114
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 17.43 KB | None | 0 0
  1. Making plugins on Python! by: Virtuos86 -------------
  2. I present to you an interesting article about Python. Article is not mine
  3. (though
  4. something where I worked on it, I hope not at the expense of content).
  5. In the attached file text article in html and txt, as well as some scripts to
  6. Examples. Making plugins in Python
  7. introduction Many programs support the so-called plug-ins (addition, expansion and
  8. etc.), with which you can extend the functionality of the program. In
  9. Python
  10. make programs that support plug-ins are particularly easy and pleasant
  11. because
  12. high-grade classes can act as a plug. Let's see what you need to do to your program also supports plug-ins. At the same time as it shall see
  13. easily.
  14. the first example. Main functions
  15. First, let's agree on the structure of the test cases. the main module
  16. the program will be called main.py, and plug-ins will be in the plugins
  17. folder, located next to the file (that is, if main.py is to
  18. example, in the folder C: resource, and the plugins folder must be in the
  19. same place)..
  20. To Python plugins accepted for the package, it should be a file named
  21. __init__.py (it will be empty in this case). First, imagine that we do not need to dynamically at runtime
  22. recognize the plugin name and we know it in the programming phase.
  23. Let plugin
  24. my_plugin.py has a name and is located in the plugins folder. And even
  25. within a file
  26. my_plugin.py pluginClass is a class that contains all the functionality plugin. Here is the code: class pluginClass (object): .... def __init __ (self): ........ pass def run (self): .... print u "Hello, Plug- in!"
  27. Ultimately, we need a run-time access to this class to instantiate and
  28. execute the run method. For simplicity, for the first time we agree that
  29. this module has no other classes except pluginClass. How would we do if
  30. all the names (and module, and class) would have been available at the
  31. time of programming? that's likely because: import plugins.my_plugin cls = plugins.my_plugin.pluginClass () cls.run ()
  32. And the result would have got the message "Hello, Plug-in!". Now back to
  33. our problem. We need to do the same, but the name of the module and
  34. class my_plugin pluginClass name is stored in the corresponding string
  35. variables. Import plug-in module. The analog built-in import directive is __import__ function, it allows you
  36. to import the modules whose names are in the stage of writing the
  37. program are unknown. In function __import__ five parameters, but only
  38. the first is mandatory. Optional parameters in this article we will not use,
  39. so keep silent about them. So, the only required parameter - this is the
  40. package name or a module that we want to import. If the import is successful, the function returns an instance of the class that stores all
  41. imported items.
  42. Let's start with the module import. The import directive will not help us.
  43. But we can
  44. use function __import__. An analogue of the first line of the recorded
  45. above an example would be the following code: package_obj = __import __ ( "plugins.my_plugin" )
  46. Thereafter package_obj variable will be an instance of the loaded module
  47. class
  48. (Package) plugins. To see this run: print package_obj
  49. (: Online print command is optional, if you call a variable
  50. interpreter "Default" returns the contents of the object, to which
  51. reference is placed in this variable through the assignment operator "=")
  52. At the same time we get something like (the way, of course, may be
  53. different): This post has little informative, so is applicable to variable package_obj
  54. the dir built-in function, which returns available package_obj attributes.
  55. Now, execute the following code: print dir (package_obj)
  56. As a result, the screen will indicate the following list: [ '__builtins__', '__doc__' , '__file__', '__name__', '__path__', 'my_plugin']
  57. Pay attention to the last item in the list - this is our plugin. So,
  58. package we downloaded, but how do we get to our module plugin? For
  59. this
  60. first use the built-in function getattr, which can be obtained from a
  61. module or package (in this case package_obj) attribute instance (and this case my_plugin). This function takes two parameters: the instance of the
  62. object, respectively, an attribute which is necessary to obtain and a string
  63. variable that contains the name of the attribute. Using the getattr
  64. function in the package, if successful, we will get a copy of the loaded
  65. module. Run the following code: module_obj = getattr (package_obj, "my_plugin ") print module_obj
  66. If all goes well, we will see on the screen something like this result:
  67. But most likely the program does not have to download a plug-in, but
  68. several. how
  69. In this case, the function will behave __import__? Consider an example in
  70. which downloaded two plugins (they should all be in the plugins folder, the
  71. easiest way
  72. my_plugin.py make a copy, and rename both files.). modulename1 = "my_plugin_1" modulename2 = "my_plugin_2" classname = "pluginClass1" package_obj = __import __ ( "plugins. " modulename1) package_obj = __import __ ( "plugins. " modulename2) print dir (package_obj)
  73. As a result, on the screen you will see the following result: [ '__builtins__', '__doc__' , '__file__', '__name__', '__path__', 'my_plugin_1', 'my_plugin_2']
  74. In this example, we import every time the result is assigned to the same
  75. variable. But as a result of the import operation after each added to it
  76. new imported module.
  77. We get access to the class
  78. So, my_plugin module we loaded (that is now in the plugins folder must be again
  79. be only one file - my_plugin.py). It remains to get to class,
  80. contained inside. For this we use the familiar function dir
  81. and make sure that is really stored in our class: print dir (module_obj)
  82. As a result of this code we get: [ '__builtins__', '__doc__' , '__file__', '__name__', 'pluginClass']
  83. As you can see, pluginClass class actually contained within module_obj.
  84. Again
  85. use getattr function: obj = getattr (module_obj, "pluginClass ") In principle, after that we can make an instance of pluginClass, but
  86. to start making a small test of what we got. We show that
  87. the resulting object really is a class, the class derived from the object. To
  88. do this, use the built-in issubclass. How to use it is clear from the
  89. following code: if issubclass (obj, object): a = obj () a.run () else: print u "Not class"
  90. If done correctly, the result is we will see a message "Hello,
  91. Plug-in! "
  92. And all together
  93. Now, for clarity, bringing together all the code that we wrote earlier. AT
  94. comments after the print statements given that they will bring to the screen.
  95. modulename = "my_plugin" classname = "pluginClass" package_obj = __import __ ( "plugins. " modulename) print package_obj # print dir (package_obj) # [ '__builtins__', '__doc__ ', '__file__', '__name__', '__path__', 'My_plugin'] module_obj = getattr (package_obj, modulename) print module_obj # print dir (module_obj) # [ '__builtins__', '__doc__ ', '__file__', '__name__', 'PluginClass'] obj = getattr (module_obj, classname) if issubclass (obj, object): print obj # a = obj () print a # a.run () else: print u "Not class"
  96. The second example, close to reality
  97. In this example, we will not know in advance the names of any modules,
  98. plug-ins, no class names contained within. And as we require that all
  99. plugins have been derived from the base class baseplugin. The plugins
  100. folder except the file __init__.py (remind, empty) are still three modules. One of them is named
  101. base.py contains a base class: class baseplugin (object): .... def run (self): ........ pass
  102. In the second my_plugin_1.py module contains a single class: import base class pluginClass1 (base.baseplugin): .... def __init __ (self): ........ pass def run (self): .... print u "Hello, first plug -in!" A third my_plugin_2.py two classes: import base class pluginClass2 (base.baseplugin): .... def __init __ (self): ........ pass def run (self): .... print u "Hello, second plug -in!" class pluginClass3 (base.baseplugin): .... def __init __ (self): ........ pass def run (self): .... print u "Hello, third plug -in!"
  103. Below is the code that gets the names of all the files in the plugins folder.
  104. Then import modules found (except base.py and __init__.py files). After
  105. that, through all the attributes within each of the imported module
  106. instantiates found in classes derived from base.baseplugin and executes
  107. the run method. import os plugin_dir = "plugins" import plugins.base
  108. # Here we add the names of loaded modules modules = []
  109. # Loop through the files in the plugins folder for fname in os.listdir (plugin_dir):
  110. # We are only interested in files with the extension .py if fname.endswith ( "py.") :
  111. # Gather the .py extension in the file name module_name = fname [: -3]
  112. # Skip files and base.py __init__.py if module_name = "base" and module_name = "__init__"!!: .... print u "Load module" module_name
  113. # Load the module and add it to the list of loaded modules package_obj = __import __ (plugin_dir ". " module_name) modules.append (module_name) print u "dir (package_obj) = " str (dir (package_obj)) print else: .... print u "Skip" fname
  114. # Loop through the loaded modules for modulename in modules: module_obj = getattr (package_obj, modulename) print modulename print dir (module_obj)
  115. # Loop through all that is inside the module for elem in dir (module_obj): .... obj = getattr (module_obj, elem )
  116. # Create an instance and execute the run function a = obj () a.run () print
  117. During the execution of the script displays additional information on the
  118. progress of work. AT
  119. resulting in the following message screen will be displayed: Skip base.py Load module my_plugin_1 dir (package_obj) = [ '__builtins__ ', '__doc__', '__file__', '__name__', '__path__', 'base', 'my_plugin_1'] Load module my_plugin_2 dir (package_obj) = [ '__builtins__ ', '__doc__', '__file__', '__name__', '__path__', 'base', 'my_plugin_1', 'my_plugin_2'] Skip __init__.py my_plugin_1 [ '__builtins__', '__doc__' , '__file__', '__name__', 'base', 'pluginClass1'] Hello, first plug-in! my_plugin_2 [ '__builtins__', '__doc__' , '__file__', '__name__', 'base', 'pluginClass2', 'pluginClass3'] Hello, second plug-in! Hello, third plug-in! Plugins and py2sis (edited)
  120. Make sis
  121. Now we learn how to work with plug-ins, and if the program
  122. It is distributed in the form of application.
  123. First, consider a simple example consisting of a main script and a plugin
  124. main.py plugin.py, located in the plugins folder; main.py and plugins folder (do not forget, in addition to plugin.py it should also be an empty
  125. __init__.py file) put in the resource folder on drive C.
  126. The main script (main.py): import appuifw modulename = "plugin" classname = "pluginClass" package_obj = __import __ ( "plugins. " modulename) print dir (package_obj) module_obj = getattr (package_obj, modulename) print dir (module_obj) obj = getattr (module_obj, classname) def import_plugin (): if issubclass (obj, object): .... a = obj () .... a.run () else: .... appuifw.note (u "Not class" , "error") def exit (): .... if appuifw.query (u "You want exit?", "query") == 1: .... appuifw.app.set_exit () appuifw.app.menu = [(u "Import plugin ", import_plugin), (u "Exit", exit)]
  127. And the source plug-in (plugin.py): class pluginClass (object): .... def __init __ (self): ........ pass def run (self): .... from appuifw import note .... note (u "Hello, Plugin !", "conf")
  128. If you run main.py file, the console will see the following: [ '__builtins__', '__doc__' , '__file__', '__name__', '__path__', 'plugin'] [ '__builtins__', '__doc__' , '__file__', '__name__', 'pluginClass'] Hello, Plugin!
  129. In order to make the sis-package, we use a great program
  130. SmartSIS v.2.2 by smart4n:
  131. Immediately I say, that I myself began to study it only recently (during
  132. Editing of this article), so it is to admit that some of the produced
  133. manipulations can be simplified by me. Also, I have no information on how to look and work the previous and subsequent versions.
  134. Now, run the program. Those who are familiar with it, can safely skip this
  135. paragraph. First of all, you need to set up a program of favorite (th):
  136. 1.) Go to the "Options": if the English menu, look for the item Settings ->
  137. "Language" -> "Russian" -> "Options" -> "save" -> "Back" and restart
  138. SmartSIS, the need for which we kindly and notifies the program. 2.) Run SmartSIS, -> "Options" -> "Settings" and start to configure:
  139. Workplace - C: or E: - here everything is just where you have more free
  140. space, the disk and specify. Alert - select how the notification of the
  141. successful completion of the operation - is determined solely by your
  142. culinary, musical, or even ask
  143. forgiveness, sexual preferences, in a word, at the user's discretion. "Kill" headband - for some reason it is recommended to put the "Yes",
  144. otherwise, they say, the program
  145. hang up - I prefer to take this advice into action.
  146. Packing Mode - determines the behavior of the program, for details, see
  147. "Help" ->
  148. "Help" (in which, incidentally, is all that I'm explaining) - here I guided by "Step by step wizard."
  149. Language - interface language selection - with this item, we are already
  150. familiar.
  151. Avtopodpis - yes, SmartSIS knows more and sign the newly created
  152. sis-bags, of course, if you have your certificate and key - If you select
  153. "Yes", then the remaining two paragraphs specify the full path to the certificate and key: for example, E: certmycert.cer and E: keymykey.key.
  154. However, I failed to establish devcert-signature SmartSIS, and I take
  155. MobileSigner by Leftup.
  156. Configuring SmartSIS, run X-plore, main.py put to the root of drive C (for
  157. simplicity). You also need to create a project folder on disk E in it to create
  158. the folder C, which, in turn, create a resource directory, and it finally put our folder plugins. So
  159. the way it will look like this:
  160. E: projectCresourceplugins.py.
  161. Now we go to smartSIS folder on the drive that you have defined as a
  162. worker. It create a text file py2sis.pkg, containing 13 lines:
  163. C: main.py_plyus_E: project main 1.0.0
  164. 0x7f7e8f69
  165. C
  166. Vendor
  167. default
  168. nocaps noautostart
  169. None
  170. RU
  171. noautorun
  172. nohidden
  173. Explanations (SmartSIS for help): 1) the full path to the script additional files (no spaces between the
  174. filenames and the sign _plyus_);
  175. 2) the name of the program, which you will see when you install the
  176. program in the smartphone's menu;
  177. 3.) version of the program: major.minor.build - required number of 3 (can
  178. deliver even 12345.85746353.04049.98858) and point (you can use a comma) between
  179. them;
  180. 4.) UID sis, written in hexadecimal;
  181. 5.) The name of the drive, which will be installed the necessary files for
  182. the script;
  183. 6) the name of the supplier, that is to say the author. Be sure to replace with your :-);
  184. 7) the full path to the icon in SVG or MIF format, default points to the
  185. Python standard icon;
  186. 8.) caps - for devcert applications, nocaps - for selfcert applications;
  187. 9) our sis-package will not have a startup function at startup;
  188. 10.) If you want to be displayed when you install some text (For example, the copyright of the author), then specify the full path to
  189. the text file
  190. (Win 1251 encodings, Unicode, utf-8) of no more than 1 Kbytes (None
  191. It means that the default text is absent);
  192. 11.) language code which sis-package will be packed;
  193. 12) the program will not start automatically after installation sis-package; 13) the program will not be hidden in the menu.
  194. For more information, read the FAQ in SmartSIS.
  195. Creating py2sis.pkg, back in SmartSIS.
  196. Select "Options" -> "Tools"
  197. -> "Py2sis". If you do not make any mistakes, py2sis starts and displays
  198. the information extracted from py2sis.pkg. Check it if everything is correct (pay special attention to whether the plugins and its contents included in
  199. the list of the folder), then "Options" -> "Compress". After the package
  200. you will find the full path to the sis-packed package.
  201. Go back to X-plore and folder:! SmartSISpacked find our sis-package that
  202. can be installed immediately, if you have entrusted SmartSIS signature,
  203. otherwise the sign themselves. Next, go to the smartphone's menu, main run our program -> "Options" -> "Import plugin" and make sure that it is
  204. not in vain were our efforts. Naturally main.py plugin.py and can be
  205. changed, with the case if the changes will have to repeat the main
  206. package, the plugin.py change is very simple: go to the folder:!
  207. Resourceplugins, plugin.py open, edit (for example, instead of writing
  208. "Hello, plugin! "-"! Hello, User ") and, voila, we have a new plugin with new functionality (:-) what can be verified by repeating the" Import plugin
  209. "!
  210. Thus, we are done, roughly speaking, a kind of wrapper that without
  211. almost any functionality, however due to the plugin can import
  212. capabilities to expand its functionality, and to do it, you see, is quite
  213. convenient. Plug-ins and additional moduli.Davayte Now make a full application of
  214. the example discussed in the
  215. the "second example, close to reality", but with a slight complication.
  216. Suppose that one of the plugins import other Python module, which is
  217. not
  218. It imports the main program. Suppose, for example, one of the plugins you will need a library Xoltar toolkit (author Bryn Keller) (I recently
  219. lecturing
  220. in the section Documentation / Article 3 of the articles on functional
  221. programming
  222. Python (author David Mertz), who are interested - you can search), but
  223. specifically it module functional. In this case, the code would look like this: import base import functional from appuifw import note class functionalpluginClass (base.baseplugin): def __init __ (self): .... pass def run (self): .... note (u "Hello, FP !", "conf") conclusion So, we have learned to do so that our program is able to dynamically load
  224. modules (plug-ins), and also made a full application. That's all that I
  225. wanted to tell :-)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement