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 229 self.options_without_help = set(
230 230 ['--completion-bash', '--completion-zsh', '--help']
231 231 )
  232 + self.prepare(data)
232 233 with open(self.DESTS['decl'], 'w') as f:
233 234 print(BANNER, file=f)
234   - self.generate_decl(data, f)
  235 + for i in self.decls:
  236 + print(i, file=f)
235 237 with open(self.DESTS['init'], 'w') as f:
236 238 print(BANNER, file=f)
237   - self.generate_init(data, f)
  239 + for i in self.init:
  240 + print(i, file=f)
238 241 with open(self.DESTS['help'], 'w') as f:
239 242 with open('manual/cli.rst', 'r') as df:
240 243 print(BANNER, file=f)
... ... @@ -245,136 +248,126 @@ class Main:
245 248 self.update_hashes()
246 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 269 for o in data['options']:
277 270 table = o['table']
278 271 if table in ('main', 'help'):
279 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 276 for o in data['options']:
284 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 279 if table == 'main':
324   - print('this->ap.selectMainOptionTable();', file=f)
  280 + self.init.append('this->ap.selectMainOptionTable();')
325 281 elif table == 'help':
326   - print('this->ap.selectHelpOptionTable();', file=f)
  282 + self.init.append('this->ap.selectHelpOptionTable();')
327 283 else:
328 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 287 prefix = 'arg' + o.get('prefix', '')
332 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 293 for i in o.get('bare', []):
336 294 self.options_without_help.add(f'--{i}')
337 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 299 for i in o.get('optional_parameter', []):
341 300 self.options_without_help.add(f'--{i}')
342 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 329 for o in data['options']:
364 330 table = o['table']
365 331 if 'from_table' not in o:
366 332 continue
367 333 if table == 'main':
368   - print('this->ap.selectMainOptionTable();', file=f)
  334 + self.init.append('this->ap.selectMainOptionTable();')
369 335 elif table == 'help':
370   - print('this->ap.selectHelpOptionTable();', file=f)
  336 + self.init.append('this->ap.selectHelpOptionTable();')
371 337 else:
372   - print(f'this->ap.selectOptionTable("{table}");', file=f)
  338 + self.init.append(f'this->ap.selectOptionTable("{table}");')
373 339 ft = o['from_table']
374 340 other_table = ft['table']
375 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 373 if __name__ == '__main__':
... ...
job.sums
1 1 # Generated by generate_auto_job
2   -generate_auto_job 466aa9211549cebeb3fedc6413108981aeeddd89936621095f5f5223cee9880b
  2 +generate_auto_job b70f64314f1ae1f100fa6a11975dee5f7669038e2a619b6c9da1e5230db1dd1b
3 3 job.yml 8177cadf41096efdc174f04daadfe5d98c592ad44ad10cb96537521fd79a801a
4 4 libqpdf/qpdf/auto_job_decl.hh 97395ecbe590b23ae04d6cce2080dbd0e998917ff5eeaa5c6aafa91041d3cd6a
5 5 libqpdf/qpdf/auto_job_help.hh 9f4bd3e42510446a714771143e6a1db599a614818329d6c7126bb9fbcccd1f36
... ...