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
             ;;
110
             ;;
111
 
111
 
112
         pya)
112
         pya)
113
-            echo '#!/usr/bin/python'
113
+            echo '#!/usr/bin/python3'
114
             echo '"""'
114
             echo '"""'
115
             echo 'A simple application'
115
             echo 'A simple application'
116
             echo '"""'
116
             echo '"""'
117
             echo ''
117
             echo ''
118
             echo 'import sys'
118
             echo 'import sys'
119
+            echo 'import traceback'
119
             echo ''
120
             echo ''
120
             echo ''
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
             echo '    """'
131
             echo '    """'
123
             echo '    Main application class'
132
             echo '    Main application class'
124
             echo '    """'
133
             echo '    """'
125
             echo ''
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
             echo ''
158
             echo ''
130
             echo '    @classmethod'
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
             echo '        """'
171
             echo '        """'
133
-            echo '        Initialize and launch'
172
+            echo '        Throw UsageError with pattern *pattern*.'
134
             echo '        """'
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
             echo ''
197
             echo ''
138
             echo '    def run(self):'
198
             echo '    def run(self):'
139
             echo '        """'
199
             echo '        """'
140
-            echo '        Run the application'
200
+            echo '        Run the application; return integer exit status'
141
             echo '        """'
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
             echo ''
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
             echo ''
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
         shellfu)
238
         shellfu)