def _get_filepath(cp):
        def get_key_filepath(key):
            for i in range(len(dir_infos)):
                info = dir_infos[i]
                if key in info.filemap:
                    basepath = basepaths[i]
                    return path.join(basepath, info.filemap[key])
            return None

        cp_key = tuple([cp])
        cp_key = unicode_data.get_canonical_emoji_sequence(cp_key) or cp_key
        fp = get_key_filepath(cp_key)
        if not fp:
            if cp_key in aliases:
                fp = get_key_filepath(aliases[cp_key])
            else:
                print('no alias for %s' % unicode_data.seq_to_string(cp_key))
        if not fp:
            print('no part for %s in %s' %
                  (unicode_data.seq_to_string(cp_key),
                   unicode_data.seq_to_string(key_tuple)))
        return fp
Exemple #2
0
def _parse_annotation_file(afile):
  """Parse file and return a map from sequences to one of 'ok', 'warning',
  or 'error'.

  The file format consists of two kinds of lines.  One defines the annotation
  to apply, it consists of the text 'annotation:' followed by one of 'ok',
  'warning', or 'error'.  The other defines a sequence that should get the most
  recently defined annotation, this is a series of codepoints expressed in hex
  separated by spaces.  The initial default annotation is 'error'.  '#' starts
  a comment to end of line, blank lines are ignored.
  """

  annotations = {}
  line_re = re.compile(r'annotation:\s*(ok|warning|error)|([0-9a-f ]+)')
  annotation = 'error'
  with open(afile, 'r') as f:
    for line in f:
      line = line.strip()
      if not line or line[0] == '#':
        continue
      m = line_re.match(line)
      if not m:
        raise Exception('could not parse annotation "%s"' % line)
      new_annotation = m.group(1)
      if new_annotation:
        annotation = new_annotation
      else:
        seq = tuple([int(s, 16) for s in m.group(2).split()])
        canonical_seq = unicode_data.get_canonical_emoji_sequence(seq)
        if canonical_seq:
          seq = canonical_seq
        if seq in annotations:
          raise Exception(
              'duplicate sequence %s in annotations' %
              unicode_data.seq_to_string(seq))
        annotations[seq] = annotation
  return annotations
def add_aliases(srcdir,
                dstdir,
                aliasfile,
                prefix,
                ext,
                replace=False,
                copy=False,
                canonical_names=False,
                dry_run=False):
    """Use aliasfile to create aliases of files in srcdir matching prefix/ext in
  dstdir.  If dstdir is null, use srcdir as dstdir.  If replace is false
  and a file already exists in dstdir, report and do nothing.  If copy is false
  create a symlink, else create a copy.

  If canonical_names is true, check all source files and generate aliases/copies
  using the canonical name if different from the existing name.

  If dry_run is true, report what would be done.  Dstdir will be created if
  necessary, even if dry_run is true."""

    if not path.isdir(srcdir):
        print('%s is not a directory' % srcdir, file=sys.stderr)
        return

    if not dstdir:
        dstdir = srcdir
    elif not path.isdir(dstdir):
        os.makedirs(dstdir)

    prefix_len = len(prefix)
    suffix_len = len(ext) + 1
    filenames = [
        path.basename(f)
        for f in glob.glob(path.join(srcdir, '%s*.%s' % (prefix, ext)))
    ]
    seq_to_file = {
        str_to_seq(name[prefix_len:-suffix_len]): name
        for name in filenames
    }

    aliases = read_emoji_aliases(aliasfile)
    aliases_to_create = {}
    aliases_to_replace = []
    alias_exists = False

    def check_alias_seq(seq):
        alias_str = seq_to_str(seq)
        alias_name = '%s%s.%s' % (prefix, alias_str, ext)
        alias_path = path.join(dstdir, alias_name)
        if path.exists(alias_path):
            if replace:
                aliases_to_replace.append(alias_name)
            else:
                print('alias %s exists' % alias_str, file=sys.stderr)
                alias_exists = True
                return None
        return alias_name

    canonical_to_file = {}
    for als, trg in sorted(aliases.items()):
        if trg not in seq_to_file:
            print('target %s for %s does not exist' %
                  (seq_to_str(trg), seq_to_str(als)),
                  file=sys.stderr)
            continue
        alias_name = check_alias_seq(als)
        if alias_name:
            target_file = seq_to_file[trg]
            aliases_to_create[alias_name] = target_file
            if canonical_names:
                canonical_seq = unicode_data.get_canonical_emoji_sequence(als)
                if canonical_seq and canonical_seq != als:
                    canonical_alias_name = check_alias_seq(canonical_seq)
                    if canonical_alias_name:
                        canonical_to_file[canonical_alias_name] = target_file

    if canonical_names:
        print('adding %d canonical aliases' % len(canonical_to_file))
        for seq, f in seq_to_file.iteritems():
            canonical_seq = unicode_data.get_canonical_emoji_sequence(seq)
            if canonical_seq and canonical_seq != seq:
                alias_name = check_alias_seq(canonical_seq)
                if alias_name:
                    canonical_to_file[alias_name] = f

        print('adding %d total canonical sequences' % len(canonical_to_file))
        aliases_to_create.update(canonical_to_file)

    if replace:
        if not dry_run:
            for k in sorted(aliases_to_replace):
                os.remove(path.join(dstdir, k))
        print('replacing %d files' % len(aliases_to_replace))
    elif alias_exists:
        print('aborting, aliases exist.', file=sys.stderr)
        return

    for k, v in sorted(aliases_to_create.items()):
        if dry_run:
            msg = 'replace ' if k in aliases_to_replace else ''
            print('%s%s -> %s' % (msg, k, v))
        else:
            try:
                if copy:
                    shutil.copy2(path.join(srcdir, v), path.join(dstdir, k))
                else:
                    # fix this to create relative symlinks
                    if srcdir == dstdir:
                        os.symlink(v, path.join(dstdir, k))
                    else:
                        raise Exception(
                            'can\'t create cross-directory symlinks yet')
            except Exception as e:
                print('failed to create %s -> %s' % (k, v), file=sys.stderr)
                raise Exception('oops, ' + str(e))
    print('created %d %s' %
          (len(aliases_to_create), 'copies' if copy else 'symlinks'))
Exemple #4
0
def _generate_content(basedir, font, dir_infos, limit, annotate, standalone,
                      colors):
    """Generate an html table for the infos.  basedir is the parent directory
  of the content, filenames will be made relative to this if underneath it,
  else absolute. If limit is true and there are multiple dirs, limit the set of
  sequences to those in the first dir.  If font is not none, generate columns
  for the text rendered in the font before other columns.  if annotate is
  not none, highlight sequences that appear in this set."""

    if len(dir_infos) == 1 or limit:
        all_keys = frozenset(dir_infos[0].filemap.keys())
    else:
        all_keys = _merge_keys([info.filemap for info in dir_infos])

    basedir = path.abspath(path.expanduser(basedir))
    if not path.isdir(basedir):
        os.makedirs(basedir)

    basepaths = []

    if standalone:
        # auxiliary images are used in the decomposition of multi-part emoji but
        # aren't part of main set.  e.g. if we have female basketball player
        # color-3 we want female, basketball player, and color-3 images available
        # even if they aren't part of the target set.
        aux_info = _collect_aux_info(dir_infos, all_keys)

        # create image subdirectories in target dir, copy image files to them,
        # and adjust paths
        for i, info in enumerate(dir_infos):
            subdir = '%02d' % i
            dstdir = path.join(basedir, subdir)
            if not path.isdir(dstdir):
                os.mkdir(dstdir)

            aux_keys = aux_info[i]
            copy_keys = all_keys if not aux_keys else (all_keys | aux_keys)
            srcdir = info.directory
            filemap = info.filemap
            for key in copy_keys:
                if key in filemap:
                    filename = filemap[key]
                    srcfile = path.join(srcdir, filename)
                    dstfile = path.join(dstdir, filename)
                    shutil.copy2(srcfile, dstfile)
            basepaths.append(subdir)
    else:
        for srcdir, _, _ in dir_infos:
            abs_srcdir = path.abspath(path.expanduser(srcdir))
            if abs_srcdir == basedir:
                dirspec = ''
            elif abs_srcdir.startswith(basedir):
                dirspec = abs_srcdir[len(basedir) + 1:]
            else:
                dirspec = abs_srcdir
            basepaths.append(dirspec)

    lines = ['<table>']
    header_row = ['']
    if font:
        header_row.extend(['Emoji ltr', 'Emoji rtl'])
    header_row.extend([info.title for info in dir_infos])
    if len(colors) > 1:
        header_row.extend([dir_infos[-1].title] * (len(colors) - 1))
    header_row.extend(['Sequence', 'Name'])
    lines.append('<th>'.join(header_row))

    for key in sorted(all_keys):
        row = []
        canonical_key = unicode_data.get_canonical_emoji_sequence(key)
        if not canonical_key:
            canonical_key = key

        row.extend(
            _generate_row_cells(key, canonical_key, font, dir_infos, basepaths,
                                colors))
        row.append(_get_desc(canonical_key, dir_infos, basepaths))
        row.append(_get_name(canonical_key, annotate))
        try:
            lines.append(''.join(row))
        except:
            raise Exception('couldn\'t decode %s' % row)
    return '\n  <tr>'.join(lines) + '\n</table>'
Exemple #5
0
 def canon(seq):
   return unicode_data.get_canonical_emoji_sequence(seq) or seq
Exemple #6
0
def add_aliases(
    srcdir, dstdir, aliasfile, prefix, ext, replace=False, copy=False,
    canonical_names=False, dry_run=False):
  """Use aliasfile to create aliases of files in srcdir matching prefix/ext in
  dstdir.  If dstdir is null, use srcdir as dstdir.  If replace is false
  and a file already exists in dstdir, report and do nothing.  If copy is false
  create a symlink, else create a copy.

  If canonical_names is true, check all source files and generate aliases/copies
  using the canonical name if different from the existing name.

  If dry_run is true, report what would be done.  Dstdir will be created if
  necessary, even if dry_run is true."""

  if not path.isdir(srcdir):
    print('%s is not a directory' % srcdir, file=sys.stderr)
    return

  if not dstdir:
    dstdir = srcdir
  elif not path.isdir(dstdir):
    os.makedirs(dstdir)

  prefix_len = len(prefix)
  suffix_len = len(ext) + 1
  filenames = [path.basename(f)
               for f in glob.glob(path.join(srcdir, '%s*.%s' % (prefix, ext)))]
  seq_to_file = {
      str_to_seq(name[prefix_len:-suffix_len]) : name
      for name in filenames}

  aliases = read_emoji_aliases(aliasfile)
  aliases_to_create = {}
  aliases_to_replace = []
  alias_exists = False

  def check_alias_seq(seq):
    alias_str = seq_to_str(seq)
    alias_name = '%s%s.%s' % (prefix, alias_str, ext)
    alias_path = path.join(dstdir, alias_name)
    if path.exists(alias_path):
      if replace:
        aliases_to_replace.append(alias_name)
      else:
        print('alias %s exists' % alias_str, file=sys.stderr)
        alias_exists = True
        return None
    return alias_name

  canonical_to_file = {}
  for als, trg in sorted(aliases.items()):
    if trg not in seq_to_file:
      print('target %s for %s does not exist' % (
          seq_to_str(trg), seq_to_str(als)), file=sys.stderr)
      continue
    alias_name = check_alias_seq(als)
    if alias_name:
      target_file = seq_to_file[trg]
      aliases_to_create[alias_name] = target_file
      if canonical_names:
        canonical_seq = unicode_data.get_canonical_emoji_sequence(als)
        if canonical_seq and canonical_seq != als:
          canonical_alias_name = check_alias_seq(canonical_seq)
          if canonical_alias_name:
            canonical_to_file[canonical_alias_name] = target_file

  if canonical_names:
    print('adding %d canonical aliases' % len(canonical_to_file))
    for seq, f in seq_to_file.iteritems():
      canonical_seq = unicode_data.get_canonical_emoji_sequence(seq)
      if canonical_seq and canonical_seq != seq:
        alias_name = check_alias_seq(canonical_seq)
        if alias_name:
          canonical_to_file[alias_name] = f

    print('adding %d total canonical sequences' % len(canonical_to_file))
    aliases_to_create.update(canonical_to_file)

  if replace:
    if not dry_run:
      for k in sorted(aliases_to_replace):
        os.remove(path.join(dstdir, k))
    print('replacing %d files' % len(aliases_to_replace))
  elif alias_exists:
    print('aborting, aliases exist.', file=sys.stderr)
    return

  for k, v in sorted(aliases_to_create.items()):
    if dry_run:
      msg = 'replace ' if k in aliases_to_replace else ''
      print('%s%s -> %s' % (msg, k, v))
    else:
      try:
        if copy:
          shutil.copy2(path.join(srcdir, v), path.join(dstdir, k))
        else:
          # fix this to create relative symlinks
          if srcdir == dstdir:
            os.symlink(v, path.join(dstdir, k))
          else:
            raise Exception('can\'t create cross-directory symlinks yet')
      except Exception as e:
        print('failed to create %s -> %s' % (k, v), file=sys.stderr)
        raise Exception('oops, ' + str(e))
  print('created %d %s' % (
      len(aliases_to_create), 'copies' if copy else 'symlinks'))