Last active
December 18, 2015 13:19
-
-
Save abhijangda/5788737 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import kivy | |
| import re | |
| import os, sys, imp, inspect | |
| from kivy.app import App | |
| from kivy.uix.boxlayout import BoxLayout | |
| from kivy.uix.floatlayout import FloatLayout | |
| from kivy.uix.button import Button | |
| from kivy.base import runTouchApp | |
| from kivy.factory import Factory | |
| from kivy.properties import ObjectProperty | |
| from kivy.lang import Builder | |
| from kivy.uix.sandbox import Sandbox | |
| class WidgetRule(object): | |
| def __init__(self, widget, parent): | |
| super(WidgetRule, self).__init__() | |
| self.name = widget | |
| self.parent = parent | |
| self.file = None | |
| self.module = None | |
| class ClassRule(WidgetRule): | |
| def __init__(self, class_name): | |
| super(ClassRule, self).__init__(class_name, None) | |
| class RootRule(ClassRule): | |
| def __init__(self, class_name): | |
| super(RootRule, self).__init__(class_name, None) | |
| class ProjectLoaderException(Exception): | |
| pass | |
| class ProjectLoader(object): | |
| '''ProjectLoader class, used to load Project | |
| ''' | |
| def _get_file_list(self, path): | |
| file_list = [] | |
| sys.path.insert(0, path) | |
| for _file in os.listdir(path): | |
| file_path = os.path.join(path, _file) | |
| if os.path.isdir(file_path): | |
| file_list += self._get_file_list(file_path) | |
| else: | |
| #Consider only py files | |
| if file_path[file_path.rfind('.'):] == '.py': | |
| file_list.append(file_path) | |
| return file_list | |
| def load_project(self, kv_path): | |
| self.cleanup() | |
| self.kv_path = kv_path | |
| #Remove all the 'app' lines | |
| f = open(self.kv_path, 'r') | |
| kv_string = f.read() | |
| f.close() | |
| for app_str in re.findall(r'.+app+.+', kv_string): | |
| kv_string = kv_string.replace(app_str, '#'+app_str) | |
| root_rule = Builder.load_string(kv_string) | |
| self.root_rule = None | |
| if root_rule: | |
| self.root_rule = RootRule(str(root_rule)) | |
| self.class_rules = [] | |
| #Get all the class_rules | |
| for class_str in re.findall(r'<+([\w_]+)>', kv_string): | |
| self.class_rules.append(ClassRule(class_str)) | |
| self.proj_dir = kv_path[:kv_path.rfind('/')] | |
| parent_proj_dir = self.proj_dir[:self.proj_dir.rfind('/')] | |
| sys.path.insert(0, parent_proj_dir) | |
| self.file_list = self._get_file_list(self.proj_dir) | |
| self._get_class_files() | |
| self._list_modules = [] | |
| def _app_in_string(self, s): | |
| if 'runTouchApp' in s: | |
| self._app_class = 'runTouchApp' | |
| return True | |
| elif 'kivy.app' in s: | |
| for _class in re.findall(r'\bclass\b.+:', s): | |
| b_index1 = _class.find('(') | |
| b_index2 = _class.find(')') | |
| if _class[b_index1+1:b_index2].strip() == 'App': | |
| self._app_class = _class[_class.find(' '):b_index1].strip() | |
| return True | |
| return False | |
| def _get_class_files(self): | |
| found_app = False | |
| #Search for main.py | |
| for _file in self.file_list: | |
| if _file[_file.rfind('/')+1:] == 'main.py': | |
| f = open(_file, 'r') | |
| s = f.read() | |
| f.close() | |
| if self._app_in_string(s): | |
| self._app_module = __import__( | |
| _file[_file.rfind('/')+1:].replace('.py','')) | |
| self._app_file = _file | |
| found_app = True | |
| #Search for a file with app in its name | |
| if not found_app: | |
| for _file in self.file_list: | |
| if 'app' in _file[_file.rfind('/'):]: | |
| f = open(_file, 'r') | |
| s = f.read() | |
| f.close() | |
| if self._app_in_string(s): | |
| self._app_module = __import__( | |
| _file[_file.rfind('/')+1:].replace('.py','')) | |
| self._app_file = _file | |
| found_app = True | |
| to_find = self.class_rules[:] | |
| if self.root_rule: | |
| to_find.append(self.root_rule) | |
| #If cannot find due to above methods, search every file | |
| for _file in self.file_list: | |
| mod = __import__(_file[_file.rfind('/')+1:].replace('.py','')) | |
| f = open(_file, 'r') | |
| s = f.read() | |
| f.close() | |
| if not found_app and self._app_in_string(s): | |
| self._app_file = _file | |
| found_app = True | |
| for _rule in to_find[:]: | |
| if hasattr(mod, _rule.name): | |
| _rule.file = _file | |
| to_find.remove(_rule) | |
| _rule.module = mod | |
| #Cannot Find App, So, use default runTouchApp | |
| if not found_app: | |
| self._app_class = 'runTouchApp' | |
| self._app_file = None | |
| #to_find should be empty, if not some class's files are not detected | |
| if to_find != []: | |
| raise ProjectLoaderException( | |
| 'Cannot find class files for all classes') | |
| def cleanup(self): | |
| self._app_file = None | |
| self._app_class = None | |
| self._app_module = None | |
| self._app = None | |
| self.file_list = [] | |
| def get_app(self): | |
| if not self._app_file or not self._app_class or not self._app_module: | |
| return App.get_running_app() | |
| if self._app: | |
| return self._app | |
| for name, obj in inspect.getmembers(self._app_module): | |
| if inspect.isclass(obj) and self._app_class == name: | |
| self._app = obj() | |
| return self._app | |
| #if still couldn't get app, although that shouldn't happen | |
| return App.get_running_app() | |
| def get_widget_of_class(self, class_name): | |
| self.root = getattr(Factory, class_name)() | |
| return self.root | |
| box = BoxLayout(size_hint=[1,1], pos_hint={'top': 1}) | |
| s = Sandbox() | |
| button = None | |
| def button_press(*args): | |
| box.remove_widget(button) | |
| with s: | |
| proj_loader = ProjectLoader() | |
| proj_loader.load_project('/home/abhi/kivy_designer/test/test/test.kv') | |
| w = proj_loader.get_widget_of_class("Designer") | |
| box.add_widget(w) | |
| button = Button(text='presss me', on_press=button_press) | |
| box.add_widget(button) | |
| s.add_widget(box) | |
| runTouchApp(s) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment