TouchPortalAPI v1.7.8

TouchPortalAPI.TpToPy

  1#!/usr/bin/env python3
  2__copyright__ = """
  3This file is part of the TouchPortal-API project.
  4Copyright TouchPortal-API Developers
  5Copyright (c) 2021 DamienS
  6All rights reserved.
  7
  8This program is free software: you can redistribute it and/or modify
  9it under the terms of the GNU General Public License as published by
 10the Free Software Foundation, either version 3 of the License, or
 11(at your option) any later version.
 12
 13This program is distributed in the hope that it will be useful,
 14but WITHOUT ANY WARRANTY; without even the implied warranty of
 15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 16GNU General Public License for more details.
 17
 18You should have received a copy of the GNU General Public License
 19along with this program.  If not, see <https://www.gnu.org/licenses/>.
 20"""
 21
 22
 23import json
 24import re
 25from pathlib import Path
 26
 27
 28class TpToPy():
 29    """
 30    This is used to convert entry.tp to a fully usable python version entry.
 31    """
 32
 33    def __init__(self, entry):
 34        self.entry = json.loads(Path(entry).resolve().read_text())
 35        self.structState = {}
 36        self.structAction = {}
 37        self.structEvent = {}
 38        self.structConnector = {}
 39        self.structCalegories = {}
 40    
 41    def getPluginId(self):
 42        """ 
 43        A helper method that returns the plugin id from entry.tp
 44        """
 45        return self.entry.get("id", "")
 46
 47    def __convertData(self, data):
 48        """
 49        convert Action and connector data to python struct format
 50        """
 51        newData = {}
 52        if isinstance(data, list):
 53            for item in range(len(data)):
 54                newData[item] = data[item]
 55        return newData
 56
 57    def __convertFormat(self, actionFormat, data):
 58        """
 59        This will automatically convert `format`. eg `{$dataid$}` to `$[data_index starts from 1]  
 60        """
 61
 62        newFormat = actionFormat
 63        for item in range(len(data)):
 64            if data[item]['id'] in actionFormat:
 65                newFormat = newFormat.replace("{$" + data[item]['id'] + "$}", "$[" + str(item+1) + "]")
 66
 67        return newFormat
 68
 69    def generateInfo(self):
 70        """
 71        This will generate TP_PLUGIN_INFO struct
 72        """
 73
 74        generatedInfo = {}
 75        infoKeys = ["sdk", "version", "name", "id", "configuration", "plugin_start_cmd_windows", "plugin_start_cmd_linux", "plugin_start_cmd_mac", "plugin_start_cmd"]
 76
 77        for key in self.entry.keys():
 78            if key in infoKeys:
 79                generatedInfo[key] = self.entry[key]
 80
 81        return generatedInfo
 82    
 83    def generateSettings(self):
 84        """
 85        This will generate TP_PLUGIN_SETTINGS struct
 86        """
 87
 88        generatedSetting = {}
 89        if not self.entry.get("settings", True): return generatedSetting
 90
 91        settings = self.entry.get("settings", [])
 92
 93        if isinstance(settings, list):
 94            for setting in range(len(settings)):
 95                generatedSetting[setting+1] = settings[setting]
 96
 97        return generatedSetting
 98
 99    def generateStates(self, data, category):
100        """
101        This generates TP_PLUGIN_STATES struct
102        """
103
104        startIndex = len(self.structState)
105
106        for state in data:
107            self.structState[startIndex] = state
108            self.structState[startIndex]["category"] = category
109
110            startIndex += 1
111
112        return self.structState
113        
114
115    def generateActions(self, data, category):
116        """
117        This generates TP_PLUGIN_ACTION struct
118        """
119
120        startIndex = len(self.structAction)
121
122        for action in data:
123            startIndex += 1
124            self.structAction[startIndex] = action
125            if self.structAction[startIndex].get("format", False):
126                self.structAction[startIndex]['format'] = self.__convertFormat(action["format"], action['data'])
127            if action.get('data', False):
128                self.structAction[startIndex]['data'] = self.__convertData(action['data'])
129            self.structAction[startIndex]["category"] = category
130
131        return self.structAction
132
133    def generateEvents(self, data, category):
134        """
135        This will generates TP_PLUGIN_EVENTS struct
136        """
137
138        startIndex = len(self.structEvent)
139
140        for event in data:
141            self.structEvent[startIndex] = event
142            self.structEvent[startIndex]["category"] = category
143
144        return self.structEvent
145
146    def generateConnectors(self, data, category):
147        """
148        This generates TP_PLUGIN_CONNECTORS struct
149        """
150
151        startIndex = len(self.structConnector)
152
153        for connector in data:
154            self.structConnector[startIndex] = connector
155            self.structConnector[startIndex]['category'] = category
156            if self.structConnector[startIndex].get('format', False):
157                self.structConnector[startIndex]['format'] = self.__convertFormat(connector['format'], connector['data'])
158            if connector.get("data", False):
159                self.structConnector[startIndex]['data'] = self.__convertData(connector['data'])
160
161        return self.structConnector
162    
163    def generateCalegories(self):
164        """
165        This generates TP_PLUGIN_CATEGORIES struct and also when looping each category it will
166        populate Actions, States, Connectors and Event struct.
167        """
168
169        generatedCalegory = {}
170        categories = self.entry.get("categories", [])
171
172        for category in categories:
173            categId = category.get("id", "").split(".")
174            generatedCalegory[categId[-1]] = {
175                "id": category.get("id"),
176                "name": category.get("name", ""),
177                "imagepath": category.get("imagepath", ""),
178            }
179
180            todoList = {"actions": self.generateActions, "states": self.generateStates,
181                        "connectors": self.generateConnectors, "events": self.generateEvents}
182
183            for todo in todoList: # hack
184                if (data := category.get(todo)) and isinstance(data, list):
185                    todoList[todo](data, categId[-1])
186        
187        return generatedCalegory
188
189    def writetoFile(self, fileName):
190        """
191        This method will collects struct INFO, SETTINGS, STATES etc... and write python
192        version of entry.tp to file.
193        """
194
195        TP_PLUGIN_INFO = self.generateInfo()
196        TP_PLUGIN_SETTINGS = self.generateSettings()
197        TP_PLUGIN_STATES = self.structState
198        TP_PLUGIN_ACTIONS = self.structAction
199        TP_PLUGIN_CONNECTORS = self.structConnector
200        TP_PLUGIN_EVENTS = self.structEvent
201        TP_PLUGIN_CATEGORIES = self.generateCalegories()
202
203        with open(fileName, 'w') as f:
204            f.write("#!/usr/bin/env python3\n")
205            for entryVar in ["TP_PLUGIN_INFO", "TP_PLUGIN_SETTINGS", "TP_PLUGIN_CATEGORIES", "TP_PLUGIN_CONNECTORS", "TP_PLUGIN_ACTIONS", "TP_PLUGIN_STATES", "TP_PLUGIN_EVENTS"]:
206                struct = json.dumps(locals()[entryVar], indent=4, sort_keys=False, skipkeys=True)
207                struct = re.sub(r'": (true|false)(,?)\n', lambda m: f'": {m.group(1).title()}{m.group(2)}\n', struct)
208                f.write(f"{entryVar} = {struct}\n\n")
209
210class toString():
211    """
212    This basically `emulate` import a python struct. for example
213
214    ```py
215    import TPPEntry # Python file
216
217    TPPEntry.TP_PLUGIN_INFO # because it contain `TP_PLUGIN_INFO` variable in that file
218    ```
219
220    and This trys to do same thing as that.
221    ```py
222    import TpToPy
223
224    myEntry = TpToPy.toString(TpToPy.TpToPy("entry.tp"))
225    myEntry.TP_PLUGIN_INFO
226    ```
227    """
228
229    def __init__(self, entry):
230        self.entry = TpToPy(entry)
231
232        self.TP_PLUGIN_INFO = self.entry.generateInfo()
233        self.TP_PLUGIN_SETTINGS = self.entry.generateSettings()
234        self.TP_PLUGIN_CATEGORIES = self.entry.generateCalegories()
235        self.TP_PLUGIN_STATES = self.entry.structState
236        self.TP_PLUGIN_ACTIONS = self.entry.structAction
237        self.TP_PLUGIN_CONNECTORS = self.entry.structConnector
238        self.TP_PLUGIN_EVENTS = self.entry.structEvent
class TpToPy:
 29class TpToPy():
 30    """
 31    This is used to convert entry.tp to a fully usable python version entry.
 32    """
 33
 34    def __init__(self, entry):
 35        self.entry = json.loads(Path(entry).resolve().read_text())
 36        self.structState = {}
 37        self.structAction = {}
 38        self.structEvent = {}
 39        self.structConnector = {}
 40        self.structCalegories = {}
 41    
 42    def getPluginId(self):
 43        """ 
 44        A helper method that returns the plugin id from entry.tp
 45        """
 46        return self.entry.get("id", "")
 47
 48    def __convertData(self, data):
 49        """
 50        convert Action and connector data to python struct format
 51        """
 52        newData = {}
 53        if isinstance(data, list):
 54            for item in range(len(data)):
 55                newData[item] = data[item]
 56        return newData
 57
 58    def __convertFormat(self, actionFormat, data):
 59        """
 60        This will automatically convert `format`. eg `{$dataid$}` to `$[data_index starts from 1]  
 61        """
 62
 63        newFormat = actionFormat
 64        for item in range(len(data)):
 65            if data[item]['id'] in actionFormat:
 66                newFormat = newFormat.replace("{$" + data[item]['id'] + "$}", "$[" + str(item+1) + "]")
 67
 68        return newFormat
 69
 70    def generateInfo(self):
 71        """
 72        This will generate TP_PLUGIN_INFO struct
 73        """
 74
 75        generatedInfo = {}
 76        infoKeys = ["sdk", "version", "name", "id", "configuration", "plugin_start_cmd_windows", "plugin_start_cmd_linux", "plugin_start_cmd_mac", "plugin_start_cmd"]
 77
 78        for key in self.entry.keys():
 79            if key in infoKeys:
 80                generatedInfo[key] = self.entry[key]
 81
 82        return generatedInfo
 83    
 84    def generateSettings(self):
 85        """
 86        This will generate TP_PLUGIN_SETTINGS struct
 87        """
 88
 89        generatedSetting = {}
 90        if not self.entry.get("settings", True): return generatedSetting
 91
 92        settings = self.entry.get("settings", [])
 93
 94        if isinstance(settings, list):
 95            for setting in range(len(settings)):
 96                generatedSetting[setting+1] = settings[setting]
 97
 98        return generatedSetting
 99
100    def generateStates(self, data, category):
101        """
102        This generates TP_PLUGIN_STATES struct
103        """
104
105        startIndex = len(self.structState)
106
107        for state in data:
108            self.structState[startIndex] = state
109            self.structState[startIndex]["category"] = category
110
111            startIndex += 1
112
113        return self.structState
114        
115
116    def generateActions(self, data, category):
117        """
118        This generates TP_PLUGIN_ACTION struct
119        """
120
121        startIndex = len(self.structAction)
122
123        for action in data:
124            startIndex += 1
125            self.structAction[startIndex] = action
126            if self.structAction[startIndex].get("format", False):
127                self.structAction[startIndex]['format'] = self.__convertFormat(action["format"], action['data'])
128            if action.get('data', False):
129                self.structAction[startIndex]['data'] = self.__convertData(action['data'])
130            self.structAction[startIndex]["category"] = category
131
132        return self.structAction
133
134    def generateEvents(self, data, category):
135        """
136        This will generates TP_PLUGIN_EVENTS struct
137        """
138
139        startIndex = len(self.structEvent)
140
141        for event in data:
142            self.structEvent[startIndex] = event
143            self.structEvent[startIndex]["category"] = category
144
145        return self.structEvent
146
147    def generateConnectors(self, data, category):
148        """
149        This generates TP_PLUGIN_CONNECTORS struct
150        """
151
152        startIndex = len(self.structConnector)
153
154        for connector in data:
155            self.structConnector[startIndex] = connector
156            self.structConnector[startIndex]['category'] = category
157            if self.structConnector[startIndex].get('format', False):
158                self.structConnector[startIndex]['format'] = self.__convertFormat(connector['format'], connector['data'])
159            if connector.get("data", False):
160                self.structConnector[startIndex]['data'] = self.__convertData(connector['data'])
161
162        return self.structConnector
163    
164    def generateCalegories(self):
165        """
166        This generates TP_PLUGIN_CATEGORIES struct and also when looping each category it will
167        populate Actions, States, Connectors and Event struct.
168        """
169
170        generatedCalegory = {}
171        categories = self.entry.get("categories", [])
172
173        for category in categories:
174            categId = category.get("id", "").split(".")
175            generatedCalegory[categId[-1]] = {
176                "id": category.get("id"),
177                "name": category.get("name", ""),
178                "imagepath": category.get("imagepath", ""),
179            }
180
181            todoList = {"actions": self.generateActions, "states": self.generateStates,
182                        "connectors": self.generateConnectors, "events": self.generateEvents}
183
184            for todo in todoList: # hack
185                if (data := category.get(todo)) and isinstance(data, list):
186                    todoList[todo](data, categId[-1])
187        
188        return generatedCalegory
189
190    def writetoFile(self, fileName):
191        """
192        This method will collects struct INFO, SETTINGS, STATES etc... and write python
193        version of entry.tp to file.
194        """
195
196        TP_PLUGIN_INFO = self.generateInfo()
197        TP_PLUGIN_SETTINGS = self.generateSettings()
198        TP_PLUGIN_STATES = self.structState
199        TP_PLUGIN_ACTIONS = self.structAction
200        TP_PLUGIN_CONNECTORS = self.structConnector
201        TP_PLUGIN_EVENTS = self.structEvent
202        TP_PLUGIN_CATEGORIES = self.generateCalegories()
203
204        with open(fileName, 'w') as f:
205            f.write("#!/usr/bin/env python3\n")
206            for entryVar in ["TP_PLUGIN_INFO", "TP_PLUGIN_SETTINGS", "TP_PLUGIN_CATEGORIES", "TP_PLUGIN_CONNECTORS", "TP_PLUGIN_ACTIONS", "TP_PLUGIN_STATES", "TP_PLUGIN_EVENTS"]:
207                struct = json.dumps(locals()[entryVar], indent=4, sort_keys=False, skipkeys=True)
208                struct = re.sub(r'": (true|false)(,?)\n', lambda m: f'": {m.group(1).title()}{m.group(2)}\n', struct)
209                f.write(f"{entryVar} = {struct}\n\n")

This is used to convert entry.tp to a fully usable python version entry.

TpToPy(entry)
34    def __init__(self, entry):
35        self.entry = json.loads(Path(entry).resolve().read_text())
36        self.structState = {}
37        self.structAction = {}
38        self.structEvent = {}
39        self.structConnector = {}
40        self.structCalegories = {}
def getPluginId(self)
42    def getPluginId(self):
43        """ 
44        A helper method that returns the plugin id from entry.tp
45        """
46        return self.entry.get("id", "")

A helper method that returns the plugin id from entry.tp

def generateInfo(self)
70    def generateInfo(self):
71        """
72        This will generate TP_PLUGIN_INFO struct
73        """
74
75        generatedInfo = {}
76        infoKeys = ["sdk", "version", "name", "id", "configuration", "plugin_start_cmd_windows", "plugin_start_cmd_linux", "plugin_start_cmd_mac", "plugin_start_cmd"]
77
78        for key in self.entry.keys():
79            if key in infoKeys:
80                generatedInfo[key] = self.entry[key]
81
82        return generatedInfo

This will generate TP_PLUGIN_INFO struct

def generateSettings(self)
84    def generateSettings(self):
85        """
86        This will generate TP_PLUGIN_SETTINGS struct
87        """
88
89        generatedSetting = {}
90        if not self.entry.get("settings", True): return generatedSetting
91
92        settings = self.entry.get("settings", [])
93
94        if isinstance(settings, list):
95            for setting in range(len(settings)):
96                generatedSetting[setting+1] = settings[setting]
97
98        return generatedSetting

This will generate TP_PLUGIN_SETTINGS struct

def generateStates(self, data, category)
100    def generateStates(self, data, category):
101        """
102        This generates TP_PLUGIN_STATES struct
103        """
104
105        startIndex = len(self.structState)
106
107        for state in data:
108            self.structState[startIndex] = state
109            self.structState[startIndex]["category"] = category
110
111            startIndex += 1
112
113        return self.structState

This generates TP_PLUGIN_STATES struct

def generateActions(self, data, category)
116    def generateActions(self, data, category):
117        """
118        This generates TP_PLUGIN_ACTION struct
119        """
120
121        startIndex = len(self.structAction)
122
123        for action in data:
124            startIndex += 1
125            self.structAction[startIndex] = action
126            if self.structAction[startIndex].get("format", False):
127                self.structAction[startIndex]['format'] = self.__convertFormat(action["format"], action['data'])
128            if action.get('data', False):
129                self.structAction[startIndex]['data'] = self.__convertData(action['data'])
130            self.structAction[startIndex]["category"] = category
131
132        return self.structAction

This generates TP_PLUGIN_ACTION struct

def generateEvents(self, data, category)
134    def generateEvents(self, data, category):
135        """
136        This will generates TP_PLUGIN_EVENTS struct
137        """
138
139        startIndex = len(self.structEvent)
140
141        for event in data:
142            self.structEvent[startIndex] = event
143            self.structEvent[startIndex]["category"] = category
144
145        return self.structEvent

This will generates TP_PLUGIN_EVENTS struct

def generateConnectors(self, data, category)
147    def generateConnectors(self, data, category):
148        """
149        This generates TP_PLUGIN_CONNECTORS struct
150        """
151
152        startIndex = len(self.structConnector)
153
154        for connector in data:
155            self.structConnector[startIndex] = connector
156            self.structConnector[startIndex]['category'] = category
157            if self.structConnector[startIndex].get('format', False):
158                self.structConnector[startIndex]['format'] = self.__convertFormat(connector['format'], connector['data'])
159            if connector.get("data", False):
160                self.structConnector[startIndex]['data'] = self.__convertData(connector['data'])
161
162        return self.structConnector

This generates TP_PLUGIN_CONNECTORS struct

def generateCalegories(self)
164    def generateCalegories(self):
165        """
166        This generates TP_PLUGIN_CATEGORIES struct and also when looping each category it will
167        populate Actions, States, Connectors and Event struct.
168        """
169
170        generatedCalegory = {}
171        categories = self.entry.get("categories", [])
172
173        for category in categories:
174            categId = category.get("id", "").split(".")
175            generatedCalegory[categId[-1]] = {
176                "id": category.get("id"),
177                "name": category.get("name", ""),
178                "imagepath": category.get("imagepath", ""),
179            }
180
181            todoList = {"actions": self.generateActions, "states": self.generateStates,
182                        "connectors": self.generateConnectors, "events": self.generateEvents}
183
184            for todo in todoList: # hack
185                if (data := category.get(todo)) and isinstance(data, list):
186                    todoList[todo](data, categId[-1])
187        
188        return generatedCalegory

This generates TP_PLUGIN_CATEGORIES struct and also when looping each category it will populate Actions, States, Connectors and Event struct.

def writetoFile(self, fileName)
190    def writetoFile(self, fileName):
191        """
192        This method will collects struct INFO, SETTINGS, STATES etc... and write python
193        version of entry.tp to file.
194        """
195
196        TP_PLUGIN_INFO = self.generateInfo()
197        TP_PLUGIN_SETTINGS = self.generateSettings()
198        TP_PLUGIN_STATES = self.structState
199        TP_PLUGIN_ACTIONS = self.structAction
200        TP_PLUGIN_CONNECTORS = self.structConnector
201        TP_PLUGIN_EVENTS = self.structEvent
202        TP_PLUGIN_CATEGORIES = self.generateCalegories()
203
204        with open(fileName, 'w') as f:
205            f.write("#!/usr/bin/env python3\n")
206            for entryVar in ["TP_PLUGIN_INFO", "TP_PLUGIN_SETTINGS", "TP_PLUGIN_CATEGORIES", "TP_PLUGIN_CONNECTORS", "TP_PLUGIN_ACTIONS", "TP_PLUGIN_STATES", "TP_PLUGIN_EVENTS"]:
207                struct = json.dumps(locals()[entryVar], indent=4, sort_keys=False, skipkeys=True)
208                struct = re.sub(r'": (true|false)(,?)\n', lambda m: f'": {m.group(1).title()}{m.group(2)}\n', struct)
209                f.write(f"{entryVar} = {struct}\n\n")

This method will collects struct INFO, SETTINGS, STATES etc... and write python version of entry.tp to file.

class toString:
211class toString():
212    """
213    This basically `emulate` import a python struct. for example
214
215    ```py
216    import TPPEntry # Python file
217
218    TPPEntry.TP_PLUGIN_INFO # because it contain `TP_PLUGIN_INFO` variable in that file
219    ```
220
221    and This trys to do same thing as that.
222    ```py
223    import TpToPy
224
225    myEntry = TpToPy.toString(TpToPy.TpToPy("entry.tp"))
226    myEntry.TP_PLUGIN_INFO
227    ```
228    """
229
230    def __init__(self, entry):
231        self.entry = TpToPy(entry)
232
233        self.TP_PLUGIN_INFO = self.entry.generateInfo()
234        self.TP_PLUGIN_SETTINGS = self.entry.generateSettings()
235        self.TP_PLUGIN_CATEGORIES = self.entry.generateCalegories()
236        self.TP_PLUGIN_STATES = self.entry.structState
237        self.TP_PLUGIN_ACTIONS = self.entry.structAction
238        self.TP_PLUGIN_CONNECTORS = self.entry.structConnector
239        self.TP_PLUGIN_EVENTS = self.entry.structEvent

This basically emulate import a python struct. for example

import TPPEntry # Python file

TPPEntry.TP_PLUGIN_INFO # because it contain `TP_PLUGIN_INFO` variable in that file

and This trys to do same thing as that.

import TpToPy

myEntry = TpToPy.toString(TpToPy.TpToPy("entry.tp"))
myEntry.TP_PLUGIN_INFO
toString(entry)
230    def __init__(self, entry):
231        self.entry = TpToPy(entry)
232
233        self.TP_PLUGIN_INFO = self.entry.generateInfo()
234        self.TP_PLUGIN_SETTINGS = self.entry.generateSettings()
235        self.TP_PLUGIN_CATEGORIES = self.entry.generateCalegories()
236        self.TP_PLUGIN_STATES = self.entry.structState
237        self.TP_PLUGIN_ACTIONS = self.entry.structAction
238        self.TP_PLUGIN_CONNECTORS = self.entry.structConnector
239        self.TP_PLUGIN_EVENTS = self.entry.structEvent