Browse Source

Replace '+pya' with a bit smarter app class

Alois Mahdal 1 year ago
parent
commit
37d5465b78
1 changed files with 102 additions and 15 deletions
  1. 102
    15
      bin/mkx

+ 102
- 15
bin/mkx View File

@@ -110,42 +110,129 @@ mktemplate() {
110 110
             ;;
111 111
 
112 112
         pya)
113
-            echo '#!/usr/bin/python'
113
+            echo '#!/usr/bin/python3'
114 114
             echo '"""'
115 115
             echo 'A simple application'
116 116
             echo '"""'
117 117
             echo ''
118 118
             echo 'import sys'
119
+            echo 'import traceback'
119 120
             echo ''
120 121
             echo ''
121
-            echo 'class App(object):'
122
+            echo 'class UsageError(ValueError):'
123
+            echo '    pass'
124
+            echo ''
125
+            echo ''
126
+            echo 'class AppError(RuntimeError):'
127
+            echo '    pass'
128
+            echo ''
129
+            echo ''
130
+            echo 'class BaseApp:'
122 131
             echo '    """'
123 132
             echo '    Main application class'
124 133
             echo '    """'
125 134
             echo ''
126
-            echo '    def __init__(self, argv):'
127
-            echo '        self.argv = argv'
128
-            echo '        # agument decoding and further initializations'
135
+            echo '    @classmethod'
136
+            echo '    def main(cls, factory=None):'
137
+            echo '        factory = factory if factory else cls.from_argv'
138
+            echo '        try:'
139
+            echo '            app = factory()'
140
+            echo '            es = app.run()'
141
+            echo '        except UsageError as e:'
142
+            echo '            print(e, file=sys.stderr)'
143
+            echo '            sys.exit(2)'
144
+            echo '        except AppError as e:'
145
+            echo '            print(e, file=sys.stderr)'
146
+            echo '            sys.exit(3)'
147
+            echo '        except Exception:'
148
+            echo '            sys.stderr.write(traceback.format_exc())'
149
+            echo '            sys.exit(4)'
150
+            echo '        if type(es) is not int:'
151
+            echo '            msg = ('
152
+            echo '                "%s.run() did not return proper exit status: %r is not int"'
153
+            echo '                % (app.__class__.__name__, es)'
154
+            echo '            )'
155
+            echo '            BaseApp.WARN(msg)'
156
+            echo '            es = 4'
157
+            echo '        sys.exit(es)'
129 158
             echo ''
130 159
             echo '    @classmethod'
131
-            echo '    def main(cls, argv):'
160
+            echo '    def from_argv(cls):'
161
+            echo '        return cls('
162
+            echo '            name=sys.argv[0],'
163
+            echo '            args=sys.argv[1:]'
164
+            echo '        )'
165
+            echo ''
166
+            echo '    def __init__(self, name, args):'
167
+            echo '        self.name = name'
168
+            echo '        self.args = args'
169
+            echo ''
170
+            echo '    def _throw_usage(self, pattern=None):'
132 171
             echo '        """'
133
-            echo '        Initialize and launch'
172
+            echo '        Throw UsageError with pattern *pattern*.'
134 173
             echo '        """'
135
-            echo '        app = cls(argv)'
136
-            echo '        app.run()'
174
+            echo '        parts = ["usage:", self.name]'
175
+            echo '        if pattern:'
176
+            echo '            parts.append(pattern)'
177
+            echo '        raise UsageError(" ".join(parts))'
178
+            echo ''
179
+            echo '    @staticmethod'
180
+            echo '    def WARN(msg):'
181
+            echo '        """'
182
+            echo '        Warn user with message *msg*.  *msg* can be string or a list of lines.'
183
+            echo '        """'
184
+            echo '        if type(msg) is list:'
185
+            echo '            lines = msg'
186
+            echo '        else:'
187
+            echo '            lines = [str(msg)]'
188
+            echo '        for line in lines:'
189
+            echo '            print(line, file=sys.stderr)'
190
+            echo ''
191
+            echo '    def _validate(self):'
192
+            echo '        """'
193
+            echo '        Validate *self.args*; throw UsageError if needed.'
194
+            echo '        """'
195
+            echo '        if not self.args:'
196
+            echo '            self._throw_usage("ARG..")'
137 197
             echo ''
138 198
             echo '    def run(self):'
139 199
             echo '        """'
140
-            echo '        Run the application'
200
+            echo '        Run the application; return integer exit status'
141 201
             echo '        """'
142
-            echo '        # actual action (calling other methods)'
143
-            echo '        print self.argv'
144
-            echo '        print __doc__'
202
+            echo '        self._validate()'
203
+            echo '        if self.args[0] == "--fail":'
204
+            echo '            raise AppError("you asked for it")'
205
+            echo '        if self.args[0] == "--fail-unexpectedly":'
206
+            echo '            raise RuntimeError("you asked for it ANyway")'
207
+            echo '        if self.args[0] == "--warn":'
208
+            echo '            BaseApp.WARN("you asked for a warning")'
209
+            echo '            return 0'
210
+            echo '        if self.args[0] == "--badret":'
211
+            echo '            return object()'
212
+            echo '        return 0'
213
+            echo ''
214
+            echo ''
215
+            echo 'class App(BaseApp):'
216
+            echo ''
217
+            echo '    def _validate(self):'
218
+            echo '        """'
219
+            echo '        Validate *self.args*; throw UsageError as needed.'
145 220
             echo ''
221
+            echo '        Prefer using self._throw_usage().'
222
+            echo '        """'
223
+            echo '        App.WARN("You need to rewrite App._validate()!!!")'
224
+            echo '        super()._validate()'
146 225
             echo ''
147
-            echo 'if __name__ == '__main__':'
148
-            echo '    App.main(sys.argv)'
226
+            echo '    def run(self):'
227
+            echo '        """'
228
+            echo '        Run the application; return integer exit status'
229
+            echo '        """'
230
+            echo '        App.WARN("You need to rewrite App.run()")'
231
+            echo '        super().run()'
232
+            echo ''
233
+            echo ''
234
+            echo 'if __name__ == "__main__":'
235
+            echo '    App.main()'
149 236
             ;;
150 237
 
151 238
         shellfu)