Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use objects as codecs instead of modules #13

Merged
merged 3 commits into from
Jul 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ updates:
patterns:
- "pytest*"
- "ruff"
- "refurb"

- package-ecosystem: "github-actions"
directory: "/"
Expand Down
8 changes: 4 additions & 4 deletions alternative_encodings/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@


def register_all() -> None:
cp859.register()
cp866i.register()
romaji.register()
viscii.register()
cp859.codec.register()
cp866i.codec.register()
romaji.codec.register()
viscii.codec.register()
22 changes: 22 additions & 0 deletions alternative_encodings/common.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import codecs
import contextlib
from abc import ABC, abstractmethod
from typing import TYPE_CHECKING, Union

if TYPE_CHECKING:
Expand Down Expand Up @@ -44,3 +46,23 @@ class StreamReader(codec, codecs.StreamReader):
pass

return StreamReader


class CodecBase(ABC):
@abstractmethod
def get_codec_info(self) -> codecs.CodecInfo:
raise NotImplementedError

def search_function(self, encoding: str) -> codecs.CodecInfo | None:
codec_info = self.get_codec_info()
if codec_info.name == encoding:
return codec_info

return None

def register(self) -> None:
codecs.register(self.search_function)

def unregister(self) -> None:
with contextlib.suppress(AttributeError):
codecs.unregister(self.search_function)
35 changes: 13 additions & 22 deletions alternative_encodings/cp859.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import codecs
import contextlib

from .common import (
CodecBase,
get_codec,
get_incremental_decoder,
get_incremental_encoder,
Expand Down Expand Up @@ -46,29 +46,20 @@

# encodings module API

codec = Codec()
_codec = Codec()


regentry = codecs.CodecInfo(
name="cp859",
encode=codec.encode,
decode=codec.decode,
incrementalencoder=IncrementalEncoder,
incrementaldecoder=IncrementalDecoder,
)


def search_function(encoding: str) -> codecs.CodecInfo | None:
if regentry.name == encoding:
return regentry

return None

class Cp859Codec(CodecBase):
codec_info = codecs.CodecInfo(
name="cp859",
encode=_codec.encode,
decode=_codec.decode,
incrementalencoder=IncrementalEncoder,
incrementaldecoder=IncrementalDecoder,
)

def register() -> None:
codecs.register(search_function)
def get_codec_info(self) -> codecs.CodecInfo:
return self.codec_info


def unregister() -> None:
with contextlib.suppress(AttributeError):
codecs.unregister(search_function)
codec = Cp859Codec()
36 changes: 14 additions & 22 deletions alternative_encodings/cp866i.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import codecs
import contextlib
from encodings import cp866

from alternative_encodings.common import CodecBase


# Codec APIs
class Codec(cp866.Codec):
Expand All @@ -19,29 +20,20 @@ def encode(self, input_string: str, final: bool = False) -> bytes: # noqa: FBT0
IncrementalDecoder = cp866.IncrementalDecoder

# encodings module API
codec = Codec()


regentry = codecs.CodecInfo(
name="cp866i",
encode=codec.encode,
decode=codec.decode,
incrementalencoder=IncrementalEncoder,
incrementaldecoder=IncrementalDecoder,
)


def search_function(encoding: str) -> codecs.CodecInfo | None:
if regentry.name == encoding:
return regentry
_codec = Codec()

return None

class Cp866iCodec(CodecBase):
codec_info = codecs.CodecInfo(
name="cp866i",
encode=_codec.encode,
decode=_codec.decode,
incrementalencoder=IncrementalEncoder,
incrementaldecoder=IncrementalDecoder,
)

def register() -> None:
codecs.register(search_function)
def get_codec_info(self) -> codecs.CodecInfo:
return self.codec_info


def unregister() -> None:
with contextlib.suppress(AttributeError):
codecs.unregister(search_function)
codec = Cp866iCodec()
35 changes: 14 additions & 21 deletions alternative_encodings/romaji.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import codecs
import contextlib
import re
from collections.abc import Iterator
from encodings import cp437

import cutlet

from alternative_encodings.common import CodecBase

katsu = cutlet.Cutlet(use_foreign_spelling=False)


Expand Down Expand Up @@ -48,28 +49,20 @@ def encode(self, input_string: str, final: bool = False) -> bytes: # noqa: FBT0
IncrementalDecoder = cp437.IncrementalDecoder

# encodings module API
codec = Codec()

regentry = codecs.CodecInfo(
name="romaji",
encode=codec.encode,
decode=codec.decode,
incrementalencoder=IncrementalEncoder,
incrementaldecoder=IncrementalDecoder,
)


def search_function(encoding: str) -> codecs.CodecInfo | None:
if regentry.name == encoding:
return regentry
_codec = Codec()

return None

class RomajiCodec(CodecBase):
codec_info = codecs.CodecInfo(
name="romaji",
encode=_codec.encode,
decode=_codec.decode,
incrementalencoder=IncrementalEncoder,
incrementaldecoder=IncrementalDecoder,
)

def register() -> None:
codecs.register(search_function)
def get_codec_info(self) -> codecs.CodecInfo:
return self.codec_info


def unregister() -> None:
with contextlib.suppress(AttributeError):
codecs.unregister(search_function)
codec = RomajiCodec()
35 changes: 13 additions & 22 deletions alternative_encodings/viscii.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import codecs
import contextlib

from .common import (
CodecBase,
get_codec,
get_incremental_decoder,
get_incremental_encoder,
Expand Down Expand Up @@ -46,29 +46,20 @@

# encodings module API

codec = Codec()
_codec = Codec()


regentry = codecs.CodecInfo(
name="viscii",
encode=codec.encode,
decode=codec.decode,
incrementalencoder=IncrementalEncoder,
incrementaldecoder=IncrementalDecoder,
)


def search_function(encoding: str) -> codecs.CodecInfo | None:
if regentry.name == encoding:
return regentry

return None

class VisciiCodec(CodecBase):
codec_info = codecs.CodecInfo(
name="viscii",
encode=_codec.encode,
decode=_codec.decode,
incrementalencoder=IncrementalEncoder,
incrementaldecoder=IncrementalDecoder,
)

def register() -> None:
codecs.register(search_function)
def get_codec_info(self) -> codecs.CodecInfo:
return self.codec_info


def unregister() -> None:
with contextlib.suppress(AttributeError):
codecs.unregister(search_function)
codec = VisciiCodec()
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ line-length = 120

[tool.ruff.lint]
select = ["ALL"]
ignore = ["D"] # Ignore all documentation warnings. Probably not the best option in real projects.
ignore = ["D"] # Ignore all documentation warnings
fixable = ["ALL"]

[tool.ruff.lint.per-file-ignores]
Expand Down
8 changes: 4 additions & 4 deletions tests/test_cp859.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,12 @@

@pytest.fixture(scope="module", autouse=True)
def _register_codec_fixture() -> Generator[None, None, None]:
with register_codec(cp859):
with register_codec(cp859.codec):
yield


source_data = (
"J'aime l'idée que le plus grand des Sex-symbols new-yorkais, "
"n'était qu'un chien dans un foyer de Brazzaville"
"J'aime l'idée que le plus grand des Sex-symbols new-yorkais, n'était qu'un chien dans un foyer de Brazzaville"
)

encoded = (
Expand All @@ -26,7 +25,8 @@ def _register_codec_fixture() -> Generator[None, None, None]:
)


@pytest.mark.parametrize(("source_data", "encoded"),
@pytest.mark.parametrize(
("source_data", "encoded"),
[
(source_data, encoded),
("\r\n", b"\r\n"),
Expand Down
2 changes: 1 addition & 1 deletion tests/test_cp866i.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

@pytest.fixture(scope="module", autouse=True)
def _register_codec_fixture() -> Generator[None, None, None]:
with register_codec(cp866i):
with register_codec(cp866i.codec):
yield


Expand Down
12 changes: 7 additions & 5 deletions tests/test_general.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,20 @@

import pytest

from alternative_encodings import cp859, cp866i, viscii
from alternative_encodings import cp859, cp866i, romaji, viscii

from .utils import register_codec

codecs_pairs = [
("cp859", cp859),
("cp866i", cp866i),
("viscii", viscii),
("cp859", cp859.codec),
("cp866i", cp866i.codec),
("romaji", romaji.codec),
("viscii", viscii.codec),
]


@pytest.mark.parametrize("string",
@pytest.mark.parametrize(
"string",
[
"\r\n",
],
Expand Down
5 changes: 3 additions & 2 deletions tests/test_romaji.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

@pytest.fixture(scope="module", autouse=True)
def _register_codec_fixture() -> Generator[None, None, None]:
with register_codec(romaji):
with register_codec(romaji.codec):
yield


Expand All @@ -25,7 +25,8 @@ def _register_codec_fixture() -> Generator[None, None, None]:
"""


@pytest.mark.parametrize(("source_data", "encoded"),
@pytest.mark.parametrize(
("source_data", "encoded"),
[
(source_data, encoded),
("\r\n", b"\r\n"),
Expand Down
2 changes: 1 addition & 1 deletion tests/test_viscii.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

@pytest.fixture(scope="module", autouse=True)
def _register_codec_fixture() -> Generator[None, None, None]:
with register_codec(viscii):
with register_codec(viscii.codec):
yield


Expand Down