docs: def gen_blocks(output, ascii_props=False, append=False, prefix=""):
      """Generate Unicode blocks."""
  
      with codecs.open(output, 'a' if append else 'w', 'utf-8') as f:
          if not append:
              f.write(HEADER)
          f.write('%s_blocks = {' % prefix)
          no_block = []
          last = -1
  
          max_range = MAXASCII if ascii_props else MAXUNICODE
          formatter = bytesformat if ascii_props else uniformat
  
          with codecs.open(os.path.join(HOME, 'unicodedata', UNIVERSION, 'Blocks.txt'), 'r', 'utf-8') as uf:
              for line in uf:
                  if not line.startswith('#'):
                      data = line.split(';')
                      if len(data) < 2:
                          continue
                      block = [int(i, 16) for i in data[0].strip().split('..')]
                      if block[0] > last + 1:
                          if (last + 1) <= max_range:
                              endval = block[0] - 1 if (block[0] - 1) < max_range else max_range
                              no_block.append((last + 1, endval))
                      last = block[1]
                      name = format_name(data[1])
                      inverse_range = []
                      if block[0] > max_range:
                          if ascii_props:
                              f.write('\n    "%s": "",' % name)
                              f.write('\n    "^%s": "%s-%s",' % (name, formatter(0), formatter(max_range)))
                          continue
                      if block[0] > 0:
                          inverse_range.append("%s-%s" % (formatter(0), formatter(block[0] - 1)))
                      if block[1] < max_range:
                          inverse_range.append("%s-%s" % (formatter(block[1] + 1), formatter(max_range)))
                      f.write('\n    "%s": "%s-%s",' % (name, formatter(block[0]), formatter(block[1])))
                      f.write('\n    "^%s": "%s",' % (name, ''.join(inverse_range)))
              if last < max_range:
                  if (last + 1) <= max_range:
                      no_block.append((last + 1, max_range))
              last = -1
              no_block_inverse = []
              if not no_block:
                  no_block_inverse.append((0, max_range))
              else:
                  for piece in no_block:
                      if piece[0] > last + 1:
                          no_block_inverse.append((last + 1, piece[0] - 1))
                      last = piece[1]
              for block, name in ((no_block, 'noblock'), (no_block_inverse, '^noblock')):
                  f.write('\n    "%s": "' % name)
                  for piece in block:
                      if piece[0] == piece[1]:
                          f.write(formatter(piece[0]))
                      else:
                          f.write("%s-%s" % (formatter(piece[0]), formatter(piece[1])))
                  f.write('",')
              f.write('\n}\n')