multiformats / multiformats/py-multibase

`Encoder` class only accepts encoding names, not prefix characters

Open Beginner friendly
#39 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
25
Forks
9
PR merge metrics
No merged PRs in 30d

Description

The Encoder class only accepts encoding name strings (e.g., "base16"). go-multibase's EncoderByName() accepts both names and single-character prefix codes (e.g., "f" for base16), making it more flexible for CLI tools and config-driven encoding.

Problem

Current Python Encoder:

class Encoder:
    def __init__(self, encoding):
        if encoding not in ENCODINGS_LOOKUP:
            raise UnsupportedEncodingError(...)
        self.encoding = encoding
        self._codec = ENCODINGS_LOOKUP[encoding]

This only works with name strings:

Encoder("base16")   # ✅ Works
Encoder("f")        # ❌ Raises UnsupportedEncodingError
Encoder(b"f")       # ❌ Raises UnsupportedEncodingError

Go's EncoderByName() accepts both:

// Go: both work
enc1, _ := EncoderByName("base16")  // by name
enc2, _ := EncoderByName("f")       // by single-char prefix

The implementation checks if the string is a single Unicode rune and treats it as a prefix code:

func EncoderByName(str string) (Encoder, error) {
    if utf8.RuneCountInString(str) == 1 {
        r, _ := utf8.DecodeRuneInString(str)
        base = Encoding(r)  // treat as prefix code
    } else {
        base = Encodings[str]  // treat as name
    }
}
Proposed Solution

Add an encoder_by_name() factory function (keeping Encoder.__init__ unchanged for backward compatibility):

def encoder_by_name(name_or_prefix: str) -> Encoder:
    """Create an Encoder from a name or single-character prefix.

    >>> encoder_by_name("base16")  # by name
    >>> encoder_by_name("f")       # by prefix character
    >>> encoder_by_name("🚀")      # by emoji prefix (base256emoji)
    """
    # Try as name first
    if name_or_prefix in ENCODINGS_LOOKUP:
        return Encoder(name_or_prefix)

    # Try as single-character prefix
    prefix_bytes = name_or_prefix.encode("utf-8")
    if prefix_bytes in ENCODINGS_LOOKUP:
        codec = ENCODINGS_LOOKUP[prefix_bytes]
        return Encoder(codec.encoding)

    raise UnsupportedEncodingError(
        f"Encoding {name_or_prefix!r} not supported."
    )

Export from __init__.py and add tests.

Related

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the module containing Encoder and ENCODINGS_LOOKUP, then inspect init.py to see how public functions are exported. Add the proposed encoder_by_name() factory and tests covering encoding names and single-character Unicode prefixes, including the base16 and emoji examples. Done means the factory returns the expected Encoder or raises UnsupportedEncodingError for unknown input.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
backend
Issue type
Feature
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
75/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.