Skip to content

Commit

Permalink
Merge pull request #2 from Josh-Voyles/linting
Browse files Browse the repository at this point in the history
Linting and formatting
  • Loading branch information
Josh-Voyles authored Jul 23, 2024
2 parents 814117b + 852272e commit 88a17aa
Show file tree
Hide file tree
Showing 4 changed files with 158 additions and 105 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
/.pytest_cache/
/src/__pycache__/
/tests/__pycache__/
venv
2 changes: 2 additions & 0 deletions data/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# MISSING DATA

This folder contains an alpha roster and distribution list normally.
I omitted them for privacy reasons obviously.
You can check the test_data for examples.
146 changes: 95 additions & 51 deletions src/parse_roster.py
Original file line number Diff line number Diff line change
@@ -1,40 +1,71 @@
"""
This program compares an 'alphe roster' and 'email distribution list' and compares them.
Often, squadron members aren't properly removed or added to the email list when out-
processing or in-processing.
This program serves to solve that by comparing lists and telling you who needs to be
added or removed.
The alpha roster is generated by squadron leadership and serves as the reference point.
"""

import re

# hard coded file paths for now
ALPHA_ROSTER_DIR = './data/alpha_roster.txt'
DISTRO_TREE_DIR = './data/USAF_DISTRO_TREE.txt'
ALPHA_ROSTER_DIR = "./data/alpha_roster.txt"
DISTRO_TREE_DIR = "./data/USAF_DISTRO_TREE.txt"


def is_correct_format(roster, name) -> list:
errors = list()
"""
accepts distribution list or alphe roster.
validates lists are properly formatted.
returns empty list or list of errors w/
line number to train user.
"""
errors = []
line_number = 1
alpha_format = r'[A-Z]+(\s[A-Z]+)?,(\s[A-Z]+)*$'
tree_format = \
r'[A-Z]+(\s[A-Z]+)?,\s[A-Z]+\s[a-zA-Z0-9\/\s\-]+' + \
r'\s<[a-zA-Z0-9\.\_\-]+@us\.af\.mil>[;]?'
correct_format = "LASTNAME, FIRSTNAME M Rank " + \
"USAF AFDW BAND/FLIGHT <john.doe@us.af.mil>;"


with open(roster, 'r') as file:
alpha_format = r"[A-Z]+(\s[A-Z]+)?,(\s[A-Z]+)*$"
tree_format = (
r"[A-Z]+(\s[A-Z]+)?,\s[A-Z]+\s[a-zA-Z0-9\/\s\-]+"
+ r"\s<[a-zA-Z0-9\.\_\-]+@us\.af\.mil>[;]?"
)
correct_format = (
"LASTNAME, FIRSTNAME M Rank " + "USAF AFDW BAND/FLIGHT <john.doe@us.af.mil>;"
)

with open(roster, "r", encoding="utf8") as file:
for line in file:
# removes semi-colon and new line char
line = remove_semic_newline(line)
match (name):
case "alpha":
if not re.match(alpha_format, line) \
and line != '' and line != '\n' \
and not is_distro_name(line):
errors.append(f'Fix alpha roster at line: {line_number} -> {line}')
if (
not re.match(alpha_format, line)
and line != ""
and line != "\n"
and not is_distro_name(line)
):
errors.append(
f"Fix alpha roster at line: {line_number} -> {line}"
)
case "distro":
if not re.match(tree_format, line) \
and line != '' and line != '\n' \
and not is_distro_name(line):
errors.append(f'Fix distro format at line: {line_number} -> {line}')
if (
not re.match(tree_format, line)
and line != ""
and line != "\n"
and not is_distro_name(line)
):
errors.append(
f"Fix distro format at line: {line_number} -> {line}"
)
line_number += 1

if errors != [] and name == 'alpha':
if errors and name == "alpha":
errors.append("Required Format -> LASTNAME, FIRSTNAME M")
return errors
elif errors != [] and name == 'distro':
if errors and name == "distro":
errors.append(f"Required Format -> {correct_format}")
return errors
return errors
Expand All @@ -45,98 +76,111 @@ def load_roster(roster) -> list:
Appends FIRSTNAME LASTNAME to roster
returns roster
"""
formated_roster = list()
with open(roster, 'r') as file:
formated_roster = []
with open(roster, "r", encoding="utf8") as file:
for line in file:
first_last = get_first_last(line)
formated_roster.append(first_last)
return formated_roster


def get_first_last(last_first_middle) -> str:
"""
Converts LASTNAME, FIRSTNAME MIDDLE {opt} ->
FIRSTNAME MIDDLE {opt} LASTNAME ->
FIRSTNAME LASTNAME <- RETURNS
"""
last, fm = last_first_middle.split(',')
fm = fm.strip().split(' ')
last, fm = last_first_middle.split(",")
fm = fm.strip().split(" ")
last = last.strip()
return fm[0] + " " + last


def remove_semic_newline(line) -> str:
"""formats string by removing ; and new line character"""
return line.rstrip().replace(';', '').replace('\n', '')
return line.rstrip().replace(";", "").replace("\n", "")


def is_distro_name(line) -> bool:
"""checks for distro list name XXX_XXX_XXX"""
distro_list_pattern = r'[A-Z]+(\_[A-Z]+)+$'
return line != '' \
and re.match(distro_list_pattern, line) != None
distro_list_pattern = r"[A-Z]+(\_[A-Z]+)+$"
return line != "" and re.match(distro_list_pattern, line) is not None


def get_email(line) -> str:
"""remove brackets around email, returns it"""
line = line.split(' ')
email = line[-1].replace('<', '').replace('>', '')
line = line.split(" ")
email = line[-1].replace("<", "").replace(">", "")
return email.strip()

def get_distro_users(directory, roster):

def get_distro_users(directory):
"""Creates name : email dictionary"""
distro_users = {}
with open(directory, 'r') as file:
with open(directory, "r", encoding="utf8") as file:
for line in file:
line = remove_semic_newline(line)
if line != '' and not is_distro_name(line):
if line != "" and not is_distro_name(line):
full_name = get_first_last(line)
email = get_email(line)
distro_users[full_name] = email
return distro_users


def to_remove_from_distro_list(tree, roster):
"""
Compares distro tree to alpha roster
print distribution list
prints names and email if not in roster
"""
remove = list()
remove = []

with open(tree, 'r') as file:
with open(tree, "r", encoding="utf8") as file:
for line in file:
line = remove_semic_newline(line)
if is_distro_name(line):
remove.append(f'\n--{line}--')
elif line != '':
remove.append(f"\n--{line}--")
elif line != "":
full_name = get_first_last(line)
email = get_email(line)
if full_name not in roster:
remove.append(full_name + " " + email)
return remove


def find_not_in_distro(roster, distro_users):
"""
Compares alpha roster and distro list names.
return names not found in distro list.
"""
missing = []
for name in roster:
if name not in distro_users.keys():
missing.append(name)
return missing


def main():
alpha_errors = is_correct_format(ALPHA_ROSTER_DIR, 'alpha')
distro_erros = is_correct_format(DISTRO_TREE_DIR, 'distro')
if alpha_errors == [] and distro_erros == []:
"""
Valids alpha roster and distribution list are correct format.
Prints errors, or prints missing members from lists.
"""
alpha_errors = is_correct_format(ALPHA_ROSTER_DIR, "alpha")
distro_erros = is_correct_format(DISTRO_TREE_DIR, "distro")
if not alpha_errors and not distro_erros:
alpha_roster = load_roster(ALPHA_ROSTER_DIR)
print()
print('******IN A DISTRO LIST BUT NOT IN ALPHA ROSTER*****')
[print(x) for x in
to_remove_from_distro_list(DISTRO_TREE_DIR, alpha_roster)]
print("******IN A DISTRO LIST BUT NOT IN ALPHA ROSTER*****")
for x in to_remove_from_distro_list(DISTRO_TREE_DIR, alpha_roster):
print(x)
print()
print('*****IN ALPHA ROSTER BUT NOT IN ANY DISTRO LIST******')
[print(y) for y in
find_not_in_distro(alpha_roster,
get_distro_users(DISTRO_TREE_DIR, alpha_roster))]
print("*****IN ALPHA ROSTER BUT NOT IN ANY DISTRO LIST******")
for y in find_not_in_distro(alpha_roster, get_distro_users(DISTRO_TREE_DIR)):
print(y)
else:
for line in alpha_errors + distro_erros:
print(line)



if __name__ == '__main__':
if __name__ == "__main__":
main()
Loading

0 comments on commit 88a17aa

Please sign in to comment.