attachments.py 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. # SPDX-FileCopyrightText: 2024 geisserml <geisserml@gmail.com>
  2. # SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
  3. from pathlib import Path
  4. # TODO? consider dotted access
  5. from pypdfium2._cli._parsers import (
  6. add_input, get_input,
  7. parse_numtext,
  8. )
  9. ACTION_LIST = "list"
  10. ACTION_EXTRACT = "extract"
  11. ACTION_EDIT = "edit"
  12. def attach(parser): # hook
  13. add_input(parser, pages=False)
  14. subparsers = parser.add_subparsers(dest="action")
  15. subparsers.add_parser(ACTION_LIST)
  16. parser_extract = subparsers.add_parser(ACTION_EXTRACT)
  17. parser_extract.add_argument(
  18. "--numbers",
  19. type = parse_numtext,
  20. )
  21. parser_extract.add_argument(
  22. "--output-dir", "-o",
  23. type = Path,
  24. required = True,
  25. )
  26. parser_edit = subparsers.add_parser(ACTION_EDIT)
  27. parser_edit.add_argument(
  28. "--del-numbers", "-d",
  29. type = parse_numtext,
  30. )
  31. parser_edit.add_argument(
  32. "--add-files", "-a",
  33. nargs = "+",
  34. metavar = "F",
  35. type = Path,
  36. )
  37. parser_edit.add_argument(
  38. "--output", "-o",
  39. type = Path,
  40. required = True,
  41. )
  42. def main(args):
  43. pdf = get_input(args)
  44. n_attachments = pdf.count_attachments()
  45. if args.action == ACTION_LIST:
  46. for i in range(n_attachments):
  47. attachment = pdf.get_attachment(i)
  48. print(f"[{i+1}]", attachment.get_name())
  49. elif args.action == ACTION_EXTRACT:
  50. if not args.numbers:
  51. args.numbers = range(n_attachments)
  52. n_digits = len(str( max(args.numbers) + 1 ))
  53. for i in args.numbers:
  54. attachment = pdf.get_attachment(i)
  55. name = attachment.get_name()
  56. out_path = args.output_dir / ("%0*d_%s" % (n_digits, i+1, name))
  57. out_path.write_bytes( attachment.get_data() )
  58. elif args.action == ACTION_EDIT:
  59. if args.del_numbers:
  60. for i in sorted(args.del_numbers, reverse=True):
  61. pdf.del_attachment(i)
  62. if args.add_files:
  63. for fp in args.add_files:
  64. attachment = pdf.new_attachment(fp.name)
  65. attachment.set_data( fp.read_bytes() )
  66. pdf.save(args.output)
  67. else:
  68. assert False