0

I am writing a class called 'Message' which takes a string 'message' in its constructor function. It basically encodes and decodes the message with some algorithms. Very basic and beginner stuff. The class is as follows: (It is a very long one.)

class Message:
def __init__(self, message: str) -> None:
    self.message: str = message.strip()
    self.__displacement: int = 0
    self.__info: dict[Any, Any] = {
        "Encoded": False, "Algorithms": (), "Caesar_shift": "NONE"}

def __str__(self) -> str:
    return self.message

def __repr__(self) -> str:
    return self.message

_enc_types: list[str] = ["None", "CAESAR", "MORSE"]

_enc_funcs: dict[str, Any] = {
    "CAESAR": lambda message, *args: Message(message)._caesar_encode(*args),
    "MORSE": lambda message: Message(message)._morse_encode()
}

_dec_funcs: dict[str, Any] = {
    "CAESAR": lambda message: Message(message)._caesar_decode(),
    "MORSE": lambda message: Message(message)._morse_decode()
}

@staticmethod
def __modify_val(value: int, shift: str, mag: int) -> int:
    if shift == "LEFT":
        value -= mag
        if value < 0:
            value += 27
    elif shift == "RIGHT":
        value += mag
        if value > 26:
            value -= 27
    else:
        raise ValueError(
            f"Argument '{shift}' for parameter 'shift' is not allowed.")

    return value

def __displace(self, shift: str, mag: int) -> None:
    if shift.upper() == "RIGHT":
        self.__displacement += mag
    else:
        self.__displacement -= mag

    eval_dict: dict[bool, str] = {
        True: "LEFT",
        False: "RIGHT"
    }

    if self.__displacement != 0:
        self.__info["Caesar_shift"] = eval_dict.get(
            (self.__displacement < 0), "NONE")

def _caesar_encode(self, shift: str, mag: int) -> str:
    mag -= 1

    with open("F:\Practice_Python\jsons\caesar.json", "r") as file:
        dict_list = json.load(file)
        letter_dict: dict[str, int] = dict_list[0]
        num_dict: dict[str, str] = dict_list[1]

    self.message = ''.join([num_dict.get(str(self.__modify_val(letter_dict.get(
        letter, -1), shift, mag)), "?") for letter in self.message.lower()])

    self.__displace(shift, mag)
    return self.message

def _caesar_decode(self) -> None:
    if (not self.__info["Encoded"]) and (self.__info["Algorithms"][-1] != "Caesar"):
        raise EncodingError(
            "Given message is not encoded by allowed algorithms.")
    shift: str = self.__info["Caesar_shift"]
    mag: int = self.__displacement + 1

    if shift == "RIGHT":
        shift = "LEFT"
        self._caesar_encode(shift, mag)
        self.__displace(shift, mag)
    elif shift == "LEFT":
        shift = "RIGHT"
        self._caesar_encode(shift, mag)
        self.__displace(shift, mag)
    else:
        raise EncodingError(
            "Given message is not encoded by allowed algorithms.")

def _morse_encode(self) -> None:
    with open("F:\Practice_Python\jsons\morse.json", "r") as file:
        dict_morse: dict[str, str] = json.load(file)

    self.message = "".join(
        [dict_morse.get(char, char) + '   ' for char in self.message.lower()])

def _morse_decode(self) -> None:
    with open('F:\Practice_Python\jsons\morse.json', 'r') as file:
        dict_morse: dict[str, str] = json.load(file)
        dict_decode: dict[str, str] = {
            value: key for key, value in dict_morse.items()}

    self.message = ''

    for sub1 in self.message.lower().split('       '):
        for sub2 in sub1.split('   '):
            self.message += dict_decode.get(sub2, '?')
        self.message += ' '

def __update_encoded(self, type: str) -> None:
    self.__info["Encoded"] = True

    self.__info["Algorithms"] = list(self.__info["Algorithms"])
    self.__info["Algorithms"].append(type)
    self.__info["Algorithms"] = tuple(self.__info["Algorithms"])

def __update_decoded(self) -> None:
    self.__info["Algorithms"] = list(self.__info["Algorithms"])
    del self.__info["Algorithms"][-1]
    self.__info["Algorithms"] = tuple(self.__info["Algorithms"])

    if len(self.__info["Algorithms"]) == 0:
        self.__info["Encoded"] = False

def encode(self, type: str, *args):

    type = type.upper().strip()

    if type not in self._enc_types:
        raise EncodingError(
            "Given algorithm for encoding message is not present.")
    self._enc_funcs.get(type, type)(self.message, *args)

    self.__update_encoded(type)

def decode(self):
    type: str = self.__info["Algorithms"][-1]

    self._dec_funcs.get(type, type)()

    self.__update_decoded(type)

Sorry if it is poorly written. But the encode function when called does not behave properly. Expected:

>>> message = Message('Hello')
>>> message.encode('CAESAR', 'RIGHT', 4)
>>> print(message)
khoor

Actual:

>>> message = Message('Hello')
>>> message.encode('CAESAR', 'RIGHT', 4)
>>> print(message)
Hello

So, it does not change the attribute to the desired value. But the function does it properly. It is probably the encode function's fault. I cannot find the problem. Please help and guide me. Thank you. And again sorry for the messy code.

0

1 Answer 1

0
_enc_funcs: dict[str, Any] = {
    "CAESAR": lambda message, *args: Message(message)._caesar_encode(*args),
    "MORSE": lambda message: Message(message)._morse_encode()
}

These lambda functions create a new Message object (which is then discarded); they do not encode the current Message object.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.