class MyException(Exception):
    """this is my excpetion"""
    
    def __init__(self, *args):
        if args:
            self.massage = args[0]
        else:
            self.message = None

    def __str__(self):
        print('str called')
        if self.message:
            return f"MyException {self.message}"
        else:
            return "MyException is empty"


# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

class SnakeExceptionBase(Exception):
    """Основной класс ошибок змейки"""
    pass

class SnakeBorderException(SnakeExceptionBase):
    """Ошибка соприкосновения змеи со стенкой"""
    pass

class SnakeTailException(SnakeBorderException):
    """Соприкосновение змеи и тела"""
    pass

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

class UserNotFoundError(Exception):
    pass

users = {
        "alice": {"name": "Alice Smith", "email": "alice@example.com"},
        "bob": {"name": "Bob Johnson", "email": "bob@example.com"},
        "jack": {"name": "Jack Wild", "email": "jack_wild@example.com"}
    }

def get_user(username):
    if username not in users.keys():
        raise UserNotFoundError("User not found")
    return users[username]['name']

def get_user_test():
    try:
        username = get_user('bob')
    except UserNotFoundError as e:
        print(e)
    else:
        print(username)

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

class NegativeDepositError(Exception):
    pass

class InsufficientFundsError(Exception):
    pass

class BankAccount:

    def __init__(self, balance):
        self.balance = balance

    def deposit(self, value):
        if value < 0:
            raise NegativeDepositError("Нельзя пополнить счет отрицательным значением")
        self.balance += value
        
    def withdraw(self, value):
        if value > self.balance:
            raise InsufficientFundsError("Недостаточно средств для снятия")
        self.balance -= value

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

class PasswordInvalidError(Exception):
    pass

class PasswordLengthError(PasswordInvalidError):
    pass

class PasswordContainUpperError(PasswordInvalidError):
    pass

class PasswordContainDigitError(PasswordInvalidError):
    pass


class User:

    def __init__(self, username, password=None):
        self.username = username
        self.password = password

    def set_password(self, value):
        up_str = ''
        digit_str = ''

        if len(value) < 8:
            raise PasswordLengthError("Пароль должен быть не менее 8 символов")
        
        for sim in value:
            if sim.isupper():
                up_str += sim
            if sim.isdigit():
                digit_str += sim
        if not up_str:
            raise PasswordContainUpperError('Пароль должен содержать хотя бы одну заглавную букву')
        if not digit_str:
            raise PasswordContainDigitError('Пароль должен содержать хотя бы одну цифру')

        self.password = value


# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

def func_1():
    # raise MyException('asdf', 1, 2, 3)
    raise MyException()

    # try:
    #     raise MyException('asdf', 1, 2, 3)
    # except MyException:
    #     print('done')

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

def main():
    # get_user_test()
    # func_1()

    assert issubclass(PasswordInvalidError, Exception)
    assert issubclass(PasswordLengthError, PasswordInvalidError)
    assert issubclass(PasswordContainUpperError, PasswordInvalidError)
    assert issubclass(PasswordContainDigitError, PasswordInvalidError)   

    user = User("johndoe")

    try:
        user.set_password("weakpwd")
    except PasswordLengthError as e:
        print(e)

    try:
        user.set_password("strongpassword8")
    except PasswordContainUpperError as e:
        print(e)

    try:
        user.set_password("Safepassword")
    except PasswordContainDigitError as e:
        print(e)

    user.set_password("SecurePass123")
    assert user.password == 'SecurePass123'



if __name__ == "__main__":
    main()