docs: def store(self, seq, nsaliases):
          """nsaliases is a list of dicts, like:
  
            [{"namespace": "en", "alias": "rose"},
             {"namespace": "fr", "alias": "rose"},
             {"namespace": "es", "alias": "rosa"}]
  
          """
          if not self._writeable:
              raise RuntimeError("Cannot write -- opened read-only")
  
          if self._upcase:
              seq = seq.upper()
  
          try:
              seqhash = bioutils.digests.seq_seqhash(seq)
          except Exception as e:
              import pprint
              _logger.critical("Exception raised for " + pprint.pformat(nsaliases))
              raise
          seq_id = seqhash
  
          # add sequence if not present
          n_seqs_added = n_aliases_added = 0
          msg = "sh{nsa_sep}{seq_id:.10s}... ({l} residues; {na} aliases {aliases})".format(
              seq_id=seq_id,
              l=len(seq),
              na=len(nsaliases),
              nsa_sep=nsa_sep,
              aliases=", ".join("{nsa[namespace]}:{nsa[alias]}".format(nsa=nsa) for nsa in nsaliases))
          if seq_id not in self.sequences:
              _logger.info("Storing " + msg)
              if len(seq) > ct_n_residues:    # pragma: no cover
                  _logger.debug("Precommit for large sequence")
                  self.commit()
              self.sequences.store(seq_id, seq)
              n_seqs_added += 1
              self._pending_sequences += 1
              self._pending_sequences_len += len(seq)
              self._pending_aliases += self._update_digest_aliases(seq_id, seq)
          else:
              _logger.debug("Sequence exists: " + msg)
  
          # add/update external aliases for new and existing sequences
          # updating is optimized to load only new <seq_id,ns,alias> tuples
          existing_aliases = self.aliases.fetch_aliases(seq_id)
          ea_tuples = [(r["seq_id"], r["namespace"], r["alias"]) for r in existing_aliases]
          new_tuples = [(seq_id, r["namespace"], r["alias"]) for r in nsaliases]
          upd_tuples = set(new_tuples) - set(ea_tuples)
          if upd_tuples:
              _logger.info("{} new aliases for {}".format(len(upd_tuples), msg))
              for _, namespace, alias in upd_tuples:
                  self.aliases.store_alias(seq_id=seq_id, namespace=namespace, alias=alias)
              self._pending_aliases += len(upd_tuples)
              n_aliases_added += len(upd_tuples)
          if (self._pending_sequences > ct_n_seqs or self._pending_aliases > ct_n_aliases
                  or self._pending_sequences_len > ct_n_residues):    # pragma: no cover
              _logger.info("Hit commit thresholds ({self._pending_sequences} sequences, "
                          "{self._pending_aliases} aliases, {self._pending_sequences_len} residues)".format(self=self))
              self.commit()
          return n_seqs_added, n_aliases_added