Commit 09e3b86fe4e1cfd7777f2659029855f2afae59b1

Authored by Jay Berkenbilt
1 parent a218ed48

Refactor generate_auto_job to prepare for json

Showing 2 changed files with 95 additions and 102 deletions
generate_auto_job
@@ -229,12 +229,15 @@ class Main: @@ -229,12 +229,15 @@ class Main:
229 self.options_without_help = set( 229 self.options_without_help = set(
230 ['--completion-bash', '--completion-zsh', '--help'] 230 ['--completion-bash', '--completion-zsh', '--help']
231 ) 231 )
  232 + self.prepare(data)
232 with open(self.DESTS['decl'], 'w') as f: 233 with open(self.DESTS['decl'], 'w') as f:
233 print(BANNER, file=f) 234 print(BANNER, file=f)
234 - self.generate_decl(data, f) 235 + for i in self.decls:
  236 + print(i, file=f)
235 with open(self.DESTS['init'], 'w') as f: 237 with open(self.DESTS['init'], 'w') as f:
236 print(BANNER, file=f) 238 print(BANNER, file=f)
237 - self.generate_init(data, f) 239 + for i in self.init:
  240 + print(i, file=f)
238 with open(self.DESTS['help'], 'w') as f: 241 with open(self.DESTS['help'], 'w') as f:
239 with open('manual/cli.rst', 'r') as df: 242 with open('manual/cli.rst', 'r') as df:
240 print(BANNER, file=f) 243 print(BANNER, file=f)
@@ -245,136 +248,126 @@ class Main: @@ -245,136 +248,126 @@ class Main:
245 self.update_hashes() 248 self.update_hashes()
246 # DON'T ADD CODE TO generate AFTER update_hashes 249 # DON'T ADD CODE TO generate AFTER update_hashes
247 250
248 - def check_keys(self, what, d, exp):  
249 - if not isinstance(d, dict):  
250 - exit(f'{what} is not a dictionary')  
251 - actual = set(d.keys())  
252 - extra = actual - exp  
253 - if extra:  
254 - exit(f'{what}: unknown keys = {extra}')  
255 -  
256 - def validate(self, data):  
257 - self.check_keys('top', data, set(['choices', 'options']))  
258 - for o in data['options']:  
259 - self.check_keys('top', o, set(  
260 - ['table', 'prefix', 'bare', 'positional',  
261 - 'optional_parameter', 'required_parameter',  
262 - 'required_choices', 'optional_choices', 'from_table'])) 251 + def prepare(self, data):
  252 + self.decls = []
  253 + self.init = []
263 254
264 - def to_identifier(self, label, prefix, const):  
265 - identifier = re.sub(r'[^a-zA-Z0-9]', '_', label)  
266 - if const:  
267 - identifier = identifier.upper()  
268 - else:  
269 - identifier = identifier.lower()  
270 - identifier = re.sub(r'(?:^|_)([a-z])',  
271 - lambda x: x.group(1).upper(),  
272 - identifier).replace('_', '')  
273 - return prefix + identifier 255 + self.init.append('auto b = [this](void (ArgParser::*f)()) {')
  256 + self.init.append(' return QPDFArgParser::bindBare(f, this);')
  257 + self.init.append('};')
  258 + self.init.append('auto p = [this](void (ArgParser::*f)(char *)) {')
  259 + self.init.append(' return QPDFArgParser::bindParam(f, this);')
  260 + self.init.append('};')
  261 + self.init.append('')
  262 + for k, v in data['choices'].items():
  263 + s = f'char const* {k}_choices[] = {{'
  264 + for i in v:
  265 + s += f'"{i}", '
  266 + self.init.append(s + '0};')
  267 + self.init.append('')
274 268
275 - def generate_decl(self, data, f):  
276 for o in data['options']: 269 for o in data['options']:
277 table = o['table'] 270 table = o['table']
278 if table in ('main', 'help'): 271 if table in ('main', 'help'):
279 continue 272 continue
280 - i = self.to_identifier(table, 'O_', True)  
281 - print(f'static constexpr char const* {i} = "{table}";', file=f)  
282 - print('', file=f) 273 + i = self.to_identifier(table, 'O', True)
  274 + self.decls.append(f'static constexpr char const* {i} = "{table}";')
  275 + self.decls.append('')
283 for o in data['options']: 276 for o in data['options']:
284 table = o['table'] 277 table = o['table']
285 - prefix = 'arg' + o.get('prefix', '')  
286 - if o.get('positional', False):  
287 - print(f'void {prefix}Positional(char*);', file=f)  
288 - for i in o.get('bare', []):  
289 - identifier = self.to_identifier(i, prefix, False)  
290 - print(f'void {identifier}();', file=f)  
291 - for i in o.get('optional_parameter', []):  
292 - identifier = self.to_identifier(i, prefix, False)  
293 - print(f'void {identifier}(char *);', file=f)  
294 - for i in o.get('required_parameter', {}):  
295 - identifier = self.to_identifier(i, prefix, False)  
296 - print(f'void {identifier}(char *);', file=f)  
297 - for i in o.get('required_choices', {}):  
298 - identifier = self.to_identifier(i, prefix, False)  
299 - print(f'void {identifier}(char *);', file=f)  
300 - for i in o.get('optional_choices', {}):  
301 - identifier = self.to_identifier(i, prefix, False)  
302 - print(f'void {identifier}(char *);', file=f)  
303 - if table not in ('main', 'help'):  
304 - identifier = self.to_identifier(table, 'argEnd', False)  
305 - print(f'void {identifier}();', file=f)  
306 278
307 - def generate_init(self, data, f):  
308 - print('auto b = [this](void (ArgParser::*f)()) {', file=f)  
309 - print(' return QPDFArgParser::bindBare(f, this);', file=f)  
310 - print('};', file=f)  
311 - print('auto p = [this](void (ArgParser::*f)(char *)) {', file=f)  
312 - print(' return QPDFArgParser::bindParam(f, this);', file=f)  
313 - print('};', file=f)  
314 - print('', file=f)  
315 - for k, v in data['choices'].items():  
316 - print(f'char const* {k}_choices[] = {{', file=f, end='')  
317 - for i in v:  
318 - print(f'"{i}", ', file=f, end='')  
319 - print('0};', file=f)  
320 - print('', file=f)  
321 - for o in data['options']:  
322 - table = o['table']  
323 if table == 'main': 279 if table == 'main':
324 - print('this->ap.selectMainOptionTable();', file=f) 280 + self.init.append('this->ap.selectMainOptionTable();')
325 elif table == 'help': 281 elif table == 'help':
326 - print('this->ap.selectHelpOptionTable();', file=f) 282 + self.init.append('this->ap.selectHelpOptionTable();')
327 else: 283 else:
328 identifier = self.to_identifier(table, 'argEnd', False) 284 identifier = self.to_identifier(table, 'argEnd', False)
329 - print(f'this->ap.registerOptionTable("{table}",'  
330 - f' b(&ArgParser::{identifier}));', file=f) 285 + self.init.append(f'this->ap.registerOptionTable("{table}",'
  286 + f' b(&ArgParser::{identifier}));')
331 prefix = 'arg' + o.get('prefix', '') 287 prefix = 'arg' + o.get('prefix', '')
332 if o.get('positional', False): 288 if o.get('positional', False):
333 - print('this->ap.addPositional('  
334 - f'p(&ArgParser::{prefix}Positional));', file=f) 289 + identifier = self.to_identifier(i, prefix, False)
  290 + self.decls.append(f'void {prefix}Positional(char*);')
  291 + self.init.append('this->ap.addPositional('
  292 + f'p(&ArgParser::{prefix}Positional));')
335 for i in o.get('bare', []): 293 for i in o.get('bare', []):
336 self.options_without_help.add(f'--{i}') 294 self.options_without_help.add(f'--{i}')
337 identifier = self.to_identifier(i, prefix, False) 295 identifier = self.to_identifier(i, prefix, False)
338 - print(f'this->ap.addBare("{i}", '  
339 - f'b(&ArgParser::{identifier}));', file=f) 296 + self.decls.append(f'void {identifier}();')
  297 + self.init.append(f'this->ap.addBare("{i}", '
  298 + f'b(&ArgParser::{identifier}));')
340 for i in o.get('optional_parameter', []): 299 for i in o.get('optional_parameter', []):
341 self.options_without_help.add(f'--{i}') 300 self.options_without_help.add(f'--{i}')
342 identifier = self.to_identifier(i, prefix, False) 301 identifier = self.to_identifier(i, prefix, False)
343 - print(f'this->ap.addOptionalParameter("{i}", '  
344 - f'p(&ArgParser::{identifier}));', file=f)  
345 - for k, v in o.get('required_parameter', {}).items():  
346 - self.options_without_help.add(f'--{k}')  
347 - identifier = self.to_identifier(k, prefix, False)  
348 - print(f'this->ap.addRequiredParameter("{k}", '  
349 - f'p(&ArgParser::{identifier})'  
350 - f', "{v}");', file=f)  
351 - for k, v in o.get('required_choices', {}).items():  
352 - self.options_without_help.add(f'--{k}')  
353 - identifier = self.to_identifier(k, prefix, False)  
354 - print(f'this->ap.addChoices("{k}", '  
355 - f'p(&ArgParser::{identifier})'  
356 - f', true, {v}_choices);', file=f)  
357 - for k, v in o.get('optional_choices', {}).items():  
358 - self.options_without_help.add(f'--{k}')  
359 - identifier = self.to_identifier(k, prefix, False)  
360 - print(f'this->ap.addChoices("{k}", '  
361 - f'p(&ArgParser::{identifier})'  
362 - f', false, {v}_choices);', file=f) 302 + self.decls.append(f'void {identifier}(char *);')
  303 + self.init.append(f'this->ap.addOptionalParameter("{i}", '
  304 + f'p(&ArgParser::{identifier}));')
  305 + for i, v in o.get('required_parameter', {}).items():
  306 + self.options_without_help.add(f'--{i}')
  307 + identifier = self.to_identifier(i, prefix, False)
  308 + self.decls.append(f'void {identifier}(char *);')
  309 + self.init.append(f'this->ap.addRequiredParameter("{i}", '
  310 + f'p(&ArgParser::{identifier})'
  311 + f', "{v}");')
  312 + for i, v in o.get('required_choices', {}).items():
  313 + self.options_without_help.add(f'--{i}')
  314 + identifier = self.to_identifier(i, prefix, False)
  315 + self.decls.append(f'void {identifier}(char *);')
  316 + self.init.append(f'this->ap.addChoices("{i}", '
  317 + f'p(&ArgParser::{identifier})'
  318 + f', true, {v}_choices);')
  319 + for i, v in o.get('optional_choices', {}).items():
  320 + self.options_without_help.add(f'--{i}')
  321 + identifier = self.to_identifier(i, prefix, False)
  322 + self.decls.append(f'void {identifier}(char *);')
  323 + self.init.append(f'this->ap.addChoices("{i}", '
  324 + f'p(&ArgParser::{identifier})'
  325 + f', false, {v}_choices);')
  326 + if table not in ('main', 'help'):
  327 + identifier = self.to_identifier(table, 'argEnd', False)
  328 + self.decls.append(f'void {identifier}();')
363 for o in data['options']: 329 for o in data['options']:
364 table = o['table'] 330 table = o['table']
365 if 'from_table' not in o: 331 if 'from_table' not in o:
366 continue 332 continue
367 if table == 'main': 333 if table == 'main':
368 - print('this->ap.selectMainOptionTable();', file=f) 334 + self.init.append('this->ap.selectMainOptionTable();')
369 elif table == 'help': 335 elif table == 'help':
370 - print('this->ap.selectHelpOptionTable();', file=f) 336 + self.init.append('this->ap.selectHelpOptionTable();')
371 else: 337 else:
372 - print(f'this->ap.selectOptionTable("{table}");', file=f) 338 + self.init.append(f'this->ap.selectOptionTable("{table}");')
373 ft = o['from_table'] 339 ft = o['from_table']
374 other_table = ft['table'] 340 other_table = ft['table']
375 for j in ft['options']: 341 for j in ft['options']:
376 - print('this->ap.copyFromOtherTable'  
377 - f'("{j}", "{other_table}");', file=f) 342 + self.init.append('this->ap.copyFromOtherTable'
  343 + f'("{j}", "{other_table}");')
  344 +
  345 + def check_keys(self, what, d, exp):
  346 + if not isinstance(d, dict):
  347 + exit(f'{what} is not a dictionary')
  348 + actual = set(d.keys())
  349 + extra = actual - exp
  350 + if extra:
  351 + exit(f'{what}: unknown keys = {extra}')
  352 +
  353 + def validate(self, data):
  354 + self.check_keys('top', data, set(['choices', 'options']))
  355 + for o in data['options']:
  356 + self.check_keys('top', o, set(
  357 + ['table', 'prefix', 'bare', 'positional',
  358 + 'optional_parameter', 'required_parameter',
  359 + 'required_choices', 'optional_choices', 'from_table']))
  360 +
  361 + def to_identifier(self, label, prefix, const):
  362 + identifier = re.sub(r'[^a-zA-Z0-9]', '_', label)
  363 + if const:
  364 + identifier = f'{prefix}_{identifier.upper()}'
  365 + else:
  366 + identifier = f'{prefix}_{identifier.lower()}'
  367 + identifier = re.sub(r'_([a-z])',
  368 + lambda x: x.group(1).upper(),
  369 + identifier).replace('_', '')
  370 + return identifier
378 371
379 372
380 if __name__ == '__main__': 373 if __name__ == '__main__':
job.sums
1 # Generated by generate_auto_job 1 # Generated by generate_auto_job
2 -generate_auto_job 466aa9211549cebeb3fedc6413108981aeeddd89936621095f5f5223cee9880b 2 +generate_auto_job b70f64314f1ae1f100fa6a11975dee5f7669038e2a619b6c9da1e5230db1dd1b
3 job.yml 8177cadf41096efdc174f04daadfe5d98c592ad44ad10cb96537521fd79a801a 3 job.yml 8177cadf41096efdc174f04daadfe5d98c592ad44ad10cb96537521fd79a801a
4 libqpdf/qpdf/auto_job_decl.hh 97395ecbe590b23ae04d6cce2080dbd0e998917ff5eeaa5c6aafa91041d3cd6a 4 libqpdf/qpdf/auto_job_decl.hh 97395ecbe590b23ae04d6cce2080dbd0e998917ff5eeaa5c6aafa91041d3cd6a
5 libqpdf/qpdf/auto_job_help.hh 9f4bd3e42510446a714771143e6a1db599a614818329d6c7126bb9fbcccd1f36 5 libqpdf/qpdf/auto_job_help.hh 9f4bd3e42510446a714771143e6a1db599a614818329d6c7126bb9fbcccd1f36