Skip to content

Add tests and type hints to hill_cipher.py #1862

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

Closed
wants to merge 4 commits into from

Conversation

mrvnmchm
Copy link
Member

Describe your change:

Adding tests for issue Fixes: #1788

  • removed string type dependency for option selection
  • added 9 doctests
  • removed lambdas, defined functions
  • added type hints

Checklist:

  • I have read CONTRIBUTING.md.
  • This pull request is all my own work -- I have not plagiarized.
  • I know that pull requests will not be merged if they fail the automated tests.
  • This PR only changes one algorithm file. To ease review, please open separate PRs for separate algorithms.
  • All new Python files are placed inside an existing directory.
  • All filenames are in all lowercase characters with no spaces or dashes.
  • All functions and variable names follow Python naming conventions.
  • All function parameters and return values are annotated with Python type hints.
  • All functions have doctests that pass the automated testing.
  • All new algorithms have a URL in its comments that points to Wikipedia or other similar explanation.
  • If this pull request resolves one or more open issues then the commit message contains Fixes: #{$ISSUE_NO}.

@cclauss cclauss changed the title Fixes: #1788 Add tests and type hints to hill_cipher.py Apr 13, 2020
Copy link
Member

@cclauss cclauss left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome! Thanks for doing this. I changed the title so that reviewers know what this pull request does without having to find, open up, and read an issue. The commit Submodule Python added at 8f2c99 must be removed before this PR can be landed. Tons of comments but we really appreciate this PR and want to see it landed.

"""
self.encrypt_key = self.modulus(encrypt_key) # mod36 calc's on the encrypt key
self.check_determinant() # validate the determinant of the encryption key
self.decrypt_key = None
self.break_key = encrypt_key.shape[0]

def replace_letters(self, letter):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need type hints. This function does not really replace anything. Can we rename to something more self documenting? get_letter_by_letter or lookup_letter_by_letter. Alternatively could we have a single function instead of two functions? get_letter or lookup_letter could start with isinstance(key, int) and return the right result if key was a str or int.

batch_vec = numpy.matrix([batch_vec]).T
batch_encrypted = self.modulus(self.encrypt_key.dot(batch_vec)).T.tolist()[
0
]
encrypted_batch = "".join(list(map(self.replaceNumbers, batch_encrypted)))
encrypted_batch = "".join(
list(map(HillCipher(self.encrypt_key).replace_numbers, batch_encrypted))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please make this a list comprehension as discussed in CONTRIBUTING.md.

"""
return self.key_string.index(letter)

def replace_numbers(self, num):
Copy link
Member

@cclauss cclauss Apr 13, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Type hints? Combine with previous function? Or replace with __index__().

>>>
"""
text: list = list(text.upper())
text: list = [char for char in text if char in self.key_string]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is too confusing to use the same variable as both a str and as a list. Can we replace lines 113 and 114 with:
chars = [char for char in text.upper() if char in self.key_string]
and then change the variable name in the lines below? We do not need to declare the type because CPython is smart enough to know that a list comprehension returns a list.

@@ -94,26 +120,37 @@ def process_text(self, text):
return "".join(text)

def encrypt(self, text):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def encrypt(self, text):
def encrypt(self, text: str) -> str:

batch_vec = numpy.matrix([batch_vec]).T
batch_decrypted = self.modulus(self.decrypt_key.dot(batch_vec)).T.tolist()[
0
]
decrypted_batch = "".join(list(map(self.replaceNumbers, batch_decrypted)))
decrypted_batch = "".join(
list(map(HillCipher(self.encrypt_key).replace_numbers, batch_decrypted))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comprehension please.

decrypted += decrypted_batch

return decrypted


def main():
if __name__ == "__main__":
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doctests do not work in if __name__ == "__main__": so please bring back main().

N = int(input("Enter the order of the encryption key: "))
hill_matrix = []
hill_matrix: list = []
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The type hint is not really required here because CPython is smart enough to know that [] is a list. A useful type hint would be hill_matrix: List[int] = [] assuming that from typing import List was added above.

@@ -42,6 +42,10 @@


def gcd(a, b):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add type hints to function parameters and return values. This is where type hints are most valuable/helpful because in other locations CPython is often smart enough to determine the type from the context.

Suggested change
def gcd(a, b):
def gcd(a: int, b: int) -> int

@@ -84,8 +105,13 @@ def check_determinant(self):
)

def process_text(self, text):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def process_text(self, text):
def process_text(self, text: str) -> str:

@mrvnmchm
Copy link
Member Author

Thanks @cclauss apologies for the delay. I will work to get these requested changes made 👍

@stale
Copy link

stale bot commented May 30, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale Used to mark an issue or pull request stale. label May 30, 2020
@cclauss cclauss closed this May 30, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stale Used to mark an issue or pull request stale.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

tests for Hill Cipher algorithm
2 participants