Add Caesar cipher project with Doxygen docs
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
## @file __init__.py
|
||||
# @brief Public API of the caesar_cipher package.
|
||||
|
||||
from caesar_cipher.cipher import encrypt
|
||||
|
||||
__all__ = ["encrypt"]
|
||||
@@ -0,0 +1,6 @@
|
||||
## @file __main__.py
|
||||
# @brief Enables `python -m caesar_cipher`.
|
||||
|
||||
from caesar_cipher.main import main
|
||||
|
||||
main()
|
||||
@@ -0,0 +1,21 @@
|
||||
## @file cipher.py
|
||||
# @brief Caesar cipher encryption.
|
||||
|
||||
from caesar_cipher.constants import ALPHABET
|
||||
|
||||
|
||||
def encrypt(text: str, shift: int) -> str:
|
||||
## @brief Encrypt a text with the Caesar cipher.
|
||||
# @param text Original text.
|
||||
# @param shift Positions to move each letter (may be negative or > 26).
|
||||
# @return The encrypted text; non-letters are kept, case is preserved.
|
||||
result = []
|
||||
for char in text:
|
||||
lower = char.lower()
|
||||
if lower in ALPHABET:
|
||||
new_position = (ALPHABET.index(lower) + shift) % len(ALPHABET)
|
||||
new_char = ALPHABET[new_position]
|
||||
result.append(new_char.upper() if char.isupper() else new_char)
|
||||
else:
|
||||
result.append(char)
|
||||
return "".join(result)
|
||||
@@ -0,0 +1,13 @@
|
||||
## @file constants.py
|
||||
# @brief Constants used by the Caesar cipher.
|
||||
|
||||
## Lowercase alphabet used to look up letter positions.
|
||||
ALPHABET = list("abcdefghijklmnopqrstuvwxyz")
|
||||
|
||||
## Prompt for the message.
|
||||
PROMPT_TEXT = "Type your message:\n"
|
||||
## Prompt for the shift number.
|
||||
PROMPT_SHIFT = "Type the shift number:\n"
|
||||
|
||||
## Name of the environment file holding tokens.
|
||||
ENV_FILE = ".env"
|
||||
@@ -0,0 +1,31 @@
|
||||
## @file env.py
|
||||
# @brief Minimal stdlib `.env` reader (no third-party dependency).
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
from caesar_cipher.constants import ENV_FILE
|
||||
|
||||
|
||||
def load_env(path: str | Path = ENV_FILE) -> dict[str, str]:
|
||||
## @brief Read KEY=VALUE pairs from an env file.
|
||||
# @param path Path of the env file.
|
||||
# @return Mapping of variables; empty if the file does not exist.
|
||||
values: dict[str, str] = {}
|
||||
env_path = Path(path)
|
||||
if not env_path.is_file():
|
||||
return values
|
||||
for line in env_path.read_text(encoding="utf-8").splitlines():
|
||||
line = line.strip()
|
||||
if not line or line.startswith("#") or "=" not in line:
|
||||
continue
|
||||
key, _, value = line.partition("=")
|
||||
values[key.strip()] = value.strip().strip("\"'")
|
||||
return values
|
||||
|
||||
|
||||
def get_token(name: str, path: str | Path = ENV_FILE) -> str | None:
|
||||
## @brief Get a token from the process environment or the env file.
|
||||
# @param name Variable name, e.g. GITEA_TOKEN.
|
||||
# @return The token or None when not set.
|
||||
return os.environ.get(name) or load_env(path).get(name)
|
||||
@@ -0,0 +1,20 @@
|
||||
## @file main.py
|
||||
# @brief Interactive command line interface.
|
||||
|
||||
from caesar_cipher import constants as c
|
||||
from caesar_cipher.cipher import encrypt
|
||||
|
||||
|
||||
def main() -> None:
|
||||
## @brief Ask for a message and a shift, then print the encrypted text.
|
||||
text = input(c.PROMPT_TEXT)
|
||||
try:
|
||||
shift = int(input(c.PROMPT_SHIFT))
|
||||
except ValueError:
|
||||
print("The shift must be a whole number.")
|
||||
return
|
||||
print(f"Here's the encoded result: {encrypt(text, shift)}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user