parse4u 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
parse4u-1.0.0/PKG-INFO ADDED
@@ -0,0 +1,14 @@
1
+ Metadata-Version: 2.4
2
+ Name: parse4u
3
+ Version: 1.0.0
4
+ Summary: converts python language into plain english
5
+ Author-email: Fawaz Shariff <placeholder0254@gmail.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/Chungywungy/BCIT-Hacakathon
8
+ Project-URL: Documentation, https://github.com/Chungywungy/BCIT-Hacakathon
9
+ Project-URL: Source, https://github.com/Chungywungy/BCIT-Hacakathon/tree/main/src/parse4u
10
+ Keywords: automation,parsing,Summarizing
11
+ Requires-Python: >=3.12
12
+ Description-Content-Type: text/markdown
13
+
14
+ # BCIT-Hacakathon
@@ -0,0 +1 @@
1
+ # BCIT-Hacakathon
@@ -0,0 +1,35 @@
1
+ [build-system]
2
+ requires = ["setuptools>=80.0.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "parse4u"
7
+ version = "1.0.0"
8
+ description = "converts python language into plain english"
9
+ readme = { file = "README.md", content-type = "text/markdown" }
10
+ license = { text = "MIT" }
11
+ authors = [
12
+ { name = "Fawaz Shariff", email = "placeholder0254@gmail.com" }
13
+ ]
14
+ requires-python = ">=3.12"
15
+
16
+ dependencies = [
17
+
18
+ ]
19
+
20
+ keywords = ["automation", "parsing", "Summarizing"]
21
+
22
+ [project.urls]
23
+ Homepage = "https://github.com/Chungywungy/BCIT-Hacakathon"
24
+ Documentation = "https://github.com/Chungywungy/BCIT-Hacakathon"
25
+ Source = "https://github.com/Chungywungy/BCIT-Hacakathon/tree/main/src/parse4u"
26
+
27
+
28
+ [tool.setuptools]
29
+ package-dir = {"" = "src"}
30
+
31
+ [tool.setuptools.packages.find]
32
+ where = ["src"]
33
+
34
+
35
+ [project.scripts]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
File without changes
@@ -0,0 +1,26 @@
1
+ import parse_function_declaration
2
+ import iterables
3
+
4
+
5
+ def main():
6
+ print("Enter/Paste your content. Type \" END \" or press Ctrl-D or Ctrl-Z on windows to save it.")
7
+ contents = []
8
+ while True:
9
+ try:
10
+ line = input()
11
+ if line == "END":
12
+ break
13
+ except EOFError:
14
+ break
15
+ contents.append(line)
16
+
17
+
18
+ line1 = parse_function_declaration.parse_function_declaration(contents[0])
19
+ contents.pop(0)
20
+ result = iterables.conditionals(contents)
21
+
22
+ print(line1)
23
+ print(result)
24
+
25
+ if __name__ == "__main__":
26
+ main()
@@ -0,0 +1,33 @@
1
+ import identify_operation
2
+
3
+
4
+ def identify_assignment(split_string: str):
5
+ if "=" in split_string and "==" not in split_string:
6
+ return True
7
+ return None
8
+
9
+
10
+ def print_assignment(split_string_line: str):
11
+ string_parts = split_string_line.split("=")
12
+ assignee = string_parts[0].strip()
13
+ string_parts.pop(0)
14
+ index = 0
15
+ assigner = ""
16
+ while index < len(string_parts):
17
+ assigner = identify_operation.identify_operations(string_parts[index].strip())
18
+ index += 1
19
+
20
+ return f"Sets {assignee} equal to {assigner}"
21
+
22
+
23
+ def main():
24
+ my_string = "x = y"
25
+ if identify_assignment(my_string):
26
+ print_assignment(my_string)
27
+ my_string = "x = y + z"
28
+ if identify_assignment(my_string):
29
+ print(print_assignment(my_string))
30
+
31
+
32
+ if __name__ == "__main__":
33
+ main()
@@ -0,0 +1,51 @@
1
+ def replaces_function_calls(line):
2
+ """
3
+ Acts as the final call to a function which translate any builtin function to its English counterpart. The function
4
+ will not interfere with any of the grammatical structure of the passed string. That is, it will only replace a
5
+ builtin named function.
6
+
7
+ :param line:
8
+ :return:
9
+ """
10
+ english_translation_look_up = {
11
+ "int": lambda param: f"{param} as an integer",
12
+ "list": lambda param: f"{param} as a list",
13
+ "str": lambda param: f"{param} as a string",
14
+ "type": lambda param: f"the type of {param}",
15
+ "input": lambda param: f"user input provided from the prompt {param}",
16
+ "print": lambda param: f"prints {param} to the console",
17
+ "range": lambda param: f"range of {param}",
18
+ "len": lambda param: f"length of {param}"
19
+ }
20
+
21
+ new_string = line
22
+
23
+ for basic_function, eng_translation in english_translation_look_up.items():
24
+ remaining = new_string
25
+ while basic_function + "(" in remaining:
26
+ function_call_index = remaining.index(basic_function + "(")
27
+ # make sure it's not part of another word e.g. "int" inside "print"
28
+ if function_call_index > 0 and remaining[function_call_index - 1].isalpha():
29
+ break
30
+ # stops at the index of the first parameter passed
31
+ start = remaining.index(basic_function + "(") + len(basic_function) + 1
32
+ # starts looking for the closing from the start index
33
+ end = remaining.rindex(")", start)
34
+ # slices the line to parse argument
35
+ args = remaining[start: end].strip()
36
+ function_call = remaining[function_call_index: end + 1]
37
+ new_string = new_string.replace(function_call, eng_translation(args))
38
+ # looks if there are any instances of other basic functions invoked in the line
39
+ remaining = remaining[end + 1:]
40
+
41
+ return new_string
42
+
43
+
44
+ def main():
45
+ pass
46
+
47
+
48
+ if __name__ == "__main__":
49
+ main()
50
+
51
+
@@ -0,0 +1,193 @@
1
+ """
2
+ This module identifies and explains logical operations and comparison operations in
3
+ a line of a function.
4
+ """
5
+ import identify_operation
6
+
7
+
8
+ def parse_logical_operators(split_string: str, operator: str) -> list:
9
+ """
10
+ Divide a string by the operator in the string.
11
+
12
+ :param split_string: string representing a line of code
13
+ :param operator: is a logical or a membership operator
14
+ :postcondition: convert the split_string into a list
15
+ :postcondition: make a copy of this list
16
+ :postcondition: find the location of the operator
17
+ :postcondition: pop the elements in the copied list to form the second operand
18
+ :postcondition: move each popped element into a new list to form the right operand
19
+ :return: list containing right operands and left operands
20
+ """
21
+ parts = split_string.split()
22
+ logical_operator_location = parts.index(operator)
23
+ index = 0
24
+ first_term = []
25
+ parts_copy = parts[:]
26
+ while index <= logical_operator_location:
27
+ if parts_copy[index] == operator:
28
+ parts.pop(0)
29
+ index += 1
30
+ else:
31
+ first_term.append(parts_copy[index])
32
+ parts.pop(0)
33
+ index += 1
34
+ first_operand = " ".join(first_term)
35
+ second_operand = " ".join(parts)
36
+ return [first_operand, second_operand]
37
+
38
+
39
+ def identify_comparison_operators(split_string: str):
40
+ """
41
+ Recursively identify and explain the comparison operators in an expression in a plain English( a line of code).
42
+
43
+ :param split_string: string representing a line of code
44
+ :precondition: split_string is a correctly formatted string
45
+ :postcondition: find the comparison operator and pride English description of the comparison,
46
+ assignment, or arithmetic operation found in split_string
47
+ :postcondition: recursively processes split_string by splitting on the first
48
+ comparison operator found, formatting the left side into plain
49
+ English, and passing the right side back into itself until no
50
+ comparison operators remain; the base case delegates to
51
+ identify_assignment or identify_operations
52
+ :return: a plain English string describing the full expression as a string or a call to assignment
53
+ function if it's a simple assignment (=), or call to identify operation function to check
54
+ for any other operations that could be in an expression
55
+ """
56
+ if "==" in split_string:
57
+ result = parse_logical_operators(split_string, "==")
58
+ return f"{identify_comparison_operators(result[0])} is equal to {identify_comparison_operators(result[1])}"
59
+ elif "!=" in split_string:
60
+ result = parse_logical_operators(split_string, "!=")
61
+ return f"{identify_comparison_operators(result[0])} is not equal to {identify_comparison_operators(result[1])}"
62
+ elif "<=" in split_string:
63
+ result = parse_logical_operators(split_string, "<=")
64
+ return f"{identify_comparison_operators(result[0])} is less than or equal to {identify_comparison_operators(result[1])}"
65
+ elif ">=" in split_string:
66
+ result = parse_logical_operators(split_string, ">=")
67
+ return f"{identify_comparison_operators(result[0])} is greater than or equal to{identify_comparison_operators(result[1])}"
68
+ elif "<" in split_string:
69
+ result = parse_logical_operators(split_string, "<")
70
+ return f"{identify_comparison_operators(result[0])} is less than {identify_comparison_operators(result[1])}"
71
+ elif ">" in split_string:
72
+ result = parse_logical_operators(split_string, ">")
73
+ return f"{identify_comparison_operators(result[0])} is greater than {identify_comparison_operators(result[1])}"
74
+ else:
75
+ return identify_operation.identify_operations(split_string)
76
+
77
+
78
+ def identify_membership_operators(split_string: str):
79
+ """
80
+ Recursively identify and explain membership operations in an expression.
81
+
82
+ Checks for operators in the order not, and, or, is, in.
83
+ Splits the expression on the first operator found, recursively processes
84
+ both sides, and combines them into a plain English description.
85
+ If none of these operators are present, call
86
+ identify_comparison_operators as the base case, which will investigate any other operations that
87
+ might be seen in the expression such as comparison, math operations etc.
88
+
89
+ :param split_string: string representing a line of code
90
+ :precondition: correctly formatted string representing a valid Python expression
91
+ :postcondition: recursively splits split_string on the first membership or
92
+ logical operator found, processes the left and right sides
93
+ independently, and combines them into a plain English string
94
+ :postcondition: correctly handle partial expressions where one side may be None by
95
+ returning only the non-None side with the other operator
96
+ :return: a plain English string describing the full expression built
97
+ recursively, or call to comparison operators function to check for any other
98
+ operations in the expressions from there
99
+ """
100
+ parts = split_string.split()
101
+ if "not" in parts:
102
+ not_index = parts.index("not")
103
+ result = parse_logical_operators(split_string, "not")
104
+ first_operand = identify_membership_operators(result[0])
105
+ second_operand = identify_membership_operators(result[1])
106
+ if parts[not_index + 1] == "in":
107
+ if result[0] is None:
108
+ return f"is not in{second_operand}"
109
+ elif result[1] is None:
110
+ return f"{first_operand}is not in"
111
+ else:
112
+ return f"{first_operand} is not{second_operand}"
113
+ elif parts[not_index - 1] == "is":
114
+ if result[0] is None:
115
+ return f"not {second_operand}"
116
+ elif result[1] is None:
117
+ return f"{first_operand} not"
118
+ else:
119
+ return f"{first_operand}not {second_operand}"
120
+ else:
121
+ if result[0] is None:
122
+ return f"is not{second_operand}"
123
+ elif result[1] is None:
124
+ return f"{first_operand} is not"
125
+ else:
126
+ return f"{first_operand} is not {second_operand}"
127
+ elif "and" in parts:
128
+ result = parse_logical_operators(split_string, "and")
129
+ first_operand = identify_membership_operators(result[0])
130
+ second_operand = identify_membership_operators(result[1])
131
+ if result[0] is None:
132
+ return f"and {second_operand}"
133
+ elif result[1] is None:
134
+ return f"{first_operand} and"
135
+ else:
136
+ return f"{first_operand} and {second_operand}"
137
+ elif "or" in parts:
138
+ result = parse_logical_operators(split_string, "or")
139
+ first_operand = identify_membership_operators(result[0])
140
+ second_operand = identify_membership_operators(result[1])
141
+ if result[0] is None:
142
+ return f"or {second_operand}"
143
+ elif result[1] is None:
144
+ return f"{first_operand} or"
145
+ else:
146
+ return f"{first_operand} or {second_operand}"
147
+ elif "is" in parts:
148
+ result = parse_logical_operators(split_string, "is")
149
+ first_operand = identify_membership_operators(result[0])
150
+ second_operand = identify_membership_operators(result[1])
151
+ if result[0] is None:
152
+ return f"is {second_operand}"
153
+ elif result[1] is None:
154
+ return f"{first_operand} is"
155
+ else:
156
+ return f"{first_operand} is {second_operand}"
157
+ elif "in" in parts:
158
+ result = parse_logical_operators(split_string, "in")
159
+ first_operand = identify_membership_operators(result[0])
160
+ second_operand = identify_membership_operators(result[1])
161
+ if result[0] is None:
162
+ return f"in {second_operand}"
163
+ elif result[1] is None:
164
+ return f"{first_operand} in"
165
+ else:
166
+ return f"{first_operand} in {second_operand}"
167
+ else:
168
+ return identify_comparison_operators(split_string)
169
+
170
+
171
+ def main():
172
+ """
173
+ Drive the program.
174
+ """
175
+ print(identify_membership_operators("x not in y"))
176
+ print(identify_membership_operators("x not y"))
177
+ print(identify_membership_operators("x in y"))
178
+ print(identify_membership_operators("x in y and x is not z or is x and not p"))
179
+ print(identify_comparison_operators("x == y"))
180
+ print(identify_comparison_operators("x != y"))
181
+ print(identify_comparison_operators("x <= y"))
182
+ print(identify_comparison_operators("x >= y"))
183
+ print(identify_comparison_operators("x = y"))
184
+ print(identify_comparison_operators("x + y"))
185
+ print(identify_comparison_operators("x == y + z * 3"))
186
+ print(identify_comparison_operators("x > y"))
187
+ print(identify_comparison_operators("x < y"))
188
+ print(identify_comparison_operators("x = y"))
189
+ print(identify_comparison_operators("guess_conversion > 5 or guess_conversion < 1"))
190
+
191
+
192
+ if __name__ == "__main__":
193
+ main()
@@ -0,0 +1,91 @@
1
+ # assume that the function is split and each line of code is
2
+ # stored in a string inside a list, we loop
3
+ # so list[index] refers to each line in the string
4
+ # precondition : there is a white space around operators -saba
5
+
6
+ # i think += and -= should be in assignment instead of operators, im not going to move them this instant but
7
+ # this should be considered for making everything mesh in the future when we're refactoring this -ollie
8
+
9
+ def return_operations(split_string: str, operator: str) -> list:
10
+ """
11
+ Extracts the two operands surrounding a given operator in a tokenized expression string.
12
+
13
+ :param split_string: a whitespace-separated expression string
14
+ :param operator: the operator token to locate
15
+ :precondition: there is a white space around the operators
16
+ :postcondition: find the index of the operator, split the strings in 2 parts,
17
+ first operand (left of the operator) and second operand (right of the operator)
18
+ :return: a two-element list, the first operand (immediately left
19
+ of the operator) and the second operand (all remaining tokens joined).
20
+ """
21
+ parts = split_string.split(operator)
22
+ first_operand = parts[0].strip()
23
+ second_operand = parts[1].strip()
24
+
25
+ return [first_operand, second_operand]
26
+
27
+ def identify_operations(split_string: str) -> str:
28
+ """
29
+ Recursively translates a Python arithmetic expression string into plain English.
30
+
31
+ :param split_string: a whitespace-separated arithmetic expression
32
+ :precondition: split_string is a whitespace-separated expression string containing
33
+ at most one operator per recursive level. Compound operators ( += or -= etc.)
34
+ must be checked before their substrings (e.g. +) to avoid mismatches.
35
+ :postcondition: whenever there is an operation in the line, split it calling the return_operation
36
+ function, to get the right hand side and left hand side of the operation
37
+ :postcondition: repeat the process until there's no other arithmetic operation in the line
38
+ :postcondition: if split_string contains no recognized operator, it is returned unchanged
39
+ as the base case of the recursion
40
+ :return: a plain-English translation of the arithmetic operation in an expression in string
41
+ """
42
+ if "+=" in split_string:
43
+ result = return_operations(split_string, "+=")
44
+
45
+ return f"Increases {result[0]} by {identify_operations(result[1])}"
46
+ elif "-=" in split_string:
47
+ result = return_operations(split_string, "-=")
48
+
49
+ return f"Decrease {result[0]} by {identify_operations(result[1])}"
50
+ elif "**=" in split_string:
51
+ # we should do this first otherwise we're not getting into this block
52
+ result = return_operations(split_string, "**=")
53
+
54
+ return f"Set {result[0]} to itself raised to the power of {identify_operations(result[1])}."
55
+ elif "*=" in split_string:
56
+ # *= and * are translated the same
57
+ result = return_operations(split_string, "*=")
58
+
59
+ return f"Multiply {result[0]} by {identify_operations(result[1])}"
60
+ elif "/=" in split_string:
61
+ result = return_operations(split_string, "/=")
62
+
63
+ return f"Divide {result[0]} by {identify_operations(result[1])}"
64
+ elif "%=" in split_string:
65
+ result = return_operations(split_string, "%=")
66
+
67
+ return f"Set {result[0]} to the remainder when divided by {identify_operations(result[1])}"
68
+ elif "=" in split_string:
69
+ result = return_operations(split_string, "=")
70
+
71
+ return f"sets {result[0]} equal to {identify_operations(result[1])}"
72
+ elif "**" in split_string:
73
+ return split_string.replace("**", "^")
74
+ else:
75
+ return split_string
76
+
77
+
78
+ def main():
79
+ my_string = "x += y"
80
+ print(identify_operations(my_string))
81
+ my_second_string = "x + y"
82
+ print(identify_operations(my_second_string))
83
+ # i minorly refactored this function for this exact case. i feel like this reads a heck of a lot better than
84
+ # "increases x by x added to y" which is what the recursive case would give us. i will look more into what
85
+ # sort of edge cases this approach could produce though and we'll come up with a final decision tmrw
86
+ my_third_string = "x += (x + (c ** y)) * 2"
87
+ print(identify_operations(my_third_string))
88
+
89
+
90
+ if __name__ == "__main__":
91
+ main()
@@ -0,0 +1,109 @@
1
+ from src.parse4u.identify_logical_operators import *
2
+ from src.parse4u.identify_functions import *
3
+ from try_except import *
4
+
5
+ def while_loop(split_string: str) -> str | None:
6
+ if "while" in split_string:
7
+ storage = split_string.split(":")[0].split("while")[1].strip()
8
+
9
+
10
+ return (f'While {replaces_function_calls(identify_comparison_operators(storage))} is true, it repeatedly '
11
+ f' {continuation(split_string)}{breaker(split_string)}{passer(split_string)}')
12
+
13
+
14
+ def for_loop(split_string: str) -> str | None:
15
+ if "for" in split_string:
16
+ idx = split_string.find("for")
17
+ if split_string[idx + len("for")].isalpha(): return None
18
+ split_string = split_string.split()
19
+ return (f"Iterates through each {split_string[1]} in the {replaces_function_calls(split_string[3].replace(":", ""))} using a for loop. "
20
+ f"{continuation(split_string)}{breaker(split_string)}{passer(split_string)} ")
21
+
22
+
23
+ def continuation(split_string):
24
+ if "continue" in split_string:
25
+ return f"the loop then goes to the top and begins again "
26
+ return ""
27
+
28
+ def breaker(split_string):
29
+ if "break" in split_string:
30
+ return f"it then exits the loop "
31
+ else:
32
+ return ""
33
+
34
+ def passer(split_string):
35
+ if "pass" in split_string:
36
+ return "calls pass"
37
+ else:
38
+ return ""
39
+
40
+
41
+ def conditionals(split_string: list):
42
+ lambdamentality = {
43
+ "if": lambda statement: f"checks if {replaces_function_calls(identify_comparison_operators(statement))} then ",
44
+ "elif": lambda statement: f"otherwise it checks {replaces_function_calls(identify_comparison_operators(statement))} then ",
45
+ "else": lambda statement: f"if none of these conditions are true it "
46
+ }
47
+
48
+ container = []
49
+
50
+ for line in split_string:
51
+ non_applicable = False
52
+ for cond in {"elif", "else", "if"}:
53
+ if cond in line:
54
+ argument = line[len(cond):].strip().split(":")[0]
55
+ container.append(f"{lambdamentality[cond](argument)}" )
56
+ non_applicable = True
57
+ break
58
+
59
+ while_output = while_loop(line)
60
+ if while_output:
61
+ container.append(while_output)
62
+ non_applicable = True
63
+ break
64
+
65
+ for_output = for_loop(line)
66
+ if for_output:
67
+ container.append(for_output)
68
+ non_applicable = True
69
+ break
70
+
71
+ continuation_output = continuation(line)
72
+ if continuation_output:
73
+ container.append(continuation_output+"\n")
74
+ non_applicable = True
75
+ break
76
+
77
+ breaker_output = breaker(line)
78
+ if breaker_output:
79
+ container.append(breaker_output+"\n")
80
+ non_applicable = True
81
+ break
82
+
83
+ passer_output = passer(line)
84
+ if passer_output:
85
+ container.append(passer_output+"\n")
86
+ non_applicable = True
87
+ break
88
+
89
+ try_except_output = try_and_except(line)
90
+ if try_except_output:
91
+ container.append(try_except_output+"\n")
92
+ non_applicable = True
93
+ break
94
+
95
+ if not non_applicable:
96
+ value = replaces_function_calls(identify_comparison_operators(line))
97
+ container.append(value.strip()+"\n")
98
+
99
+
100
+ return "".join(container)
101
+
102
+
103
+ def main():
104
+ code_block_conditionals = ["if 1 > int(2):", "do_anything()", "elif 1 < range(2):", "please_work()", "else:", "1 + 2"]
105
+ sample = ["while number > 1: pass"]
106
+ return conditionals(sample)
107
+
108
+ if __name__ == "__main__":
109
+ print(main())
@@ -0,0 +1,170 @@
1
+ """
2
+ Parses functions declarations and annotations.
3
+
4
+ Assumption:
5
+ Only parses annotations when available
6
+
7
+ def function_name(x: int, y: float) -> int:
8
+ def function_name(x, y):
9
+ def function_name() -> str:
10
+ def function_name():
11
+ """
12
+
13
+
14
+ def get_return_type(function_string: str) -> str:
15
+ """
16
+ Get the function's return type.
17
+ :param function_string: a string of text representing the line declaring a function in the python language
18
+ :precondition: function_string must be a syntactically correct string for declaring a function
19
+ :postcondition: parse the data type that the function will return, if available
20
+ :return: a string that represents the function's returns data type
21
+ """
22
+ if "def" and "->" in function_string:
23
+ return_type = function_string.split("->")
24
+ return_type = return_type[1].replace(":", "").strip()
25
+ # this gets the return type of the function
26
+ else:
27
+ return_type = "" # return type is None when the function_string does not include the return annotation
28
+ # print("return type:", return_type)
29
+ return return_type
30
+
31
+
32
+ def get_function_name(function_string: str) -> str:
33
+ """
34
+ Get the function's name.
35
+ :param function_string: a string of text representing the line declaring a function in the python language
36
+ :precondition: function_string must be a syntactically correct string for declaring a function
37
+ :postcondition: correctly parse the function name
38
+ :return: the function name as a string
39
+ """
40
+ # removes def from the string
41
+ if "def" in function_string:
42
+ function_string = function_string.replace("def", "")
43
+
44
+ split_function_string = function_string.split("(")
45
+ function_name = split_function_string[0].strip()
46
+ # splits string at ( to get the function name
47
+ # print("function name:", function_name)
48
+
49
+ return function_name
50
+
51
+
52
+ def get_parameters(function_string: str) -> str:
53
+ """
54
+ Get parameters in function.
55
+ :param function_string: a string of text representing the line declaring a function in the python language
56
+ :precondition: function_string must be a syntactically correct string for declaring a function
57
+ :postcondition: translate the text for the parameters
58
+ :return: a description of the parameters as the string
59
+ """
60
+ left_split_function_string = function_string.split("(")
61
+
62
+ right_split_function_string = left_split_function_string[1].split(")")
63
+ parameters = right_split_function_string[0]
64
+ # split at the '(' and ')' to get everything in between the parentheses
65
+
66
+ if parameters and ":" in parameters: # runs if there are parameters with annotations
67
+ parameters_list = parameters.split(",") # returns a list of variables and function annotations
68
+ # parse parameters; create dictionary to hold each parameter and its type
69
+
70
+ variable_type_dict = {}
71
+ for item in parameters_list:
72
+ stripped_item = item.strip()
73
+
74
+ if ":" in stripped_item:
75
+ parameter_annotation = stripped_item.split(":")
76
+ variable = parameter_annotation[0].strip() # this gets the variable that will become the key in dict
77
+ variable_type = parameter_annotation[1].strip() # this is the variable type that will be the value pair
78
+ variable_type_dict[variable] = variable_type
79
+
80
+ # iterating through the variables to create a list to hold parameter descriptions
81
+ parameter_description = []
82
+ for key, value in variable_type_dict.items():
83
+ parameter_description.append(f"{key} as {value}")
84
+ # creates list to hold parameter descriptions i.e. ['x as int, y as float']
85
+
86
+ if len(parameters_list) >= 3:
87
+ parameter_text = "{}, and {} for parameters".format(", ".join(parameter_description[:-1]),
88
+ parameter_description[-1])
89
+ elif len(parameters_list) == 2:
90
+ parameter_text = "{} for parameters".format(" and ".join(parameter_description), )
91
+ else:
92
+ parameter_text = "{} for a parameter".format(", ".join(parameter_description), )
93
+
94
+ elif parameters and ":" not in parameters: # runs case where parameters exist, but no annotations are written
95
+ parameters_list = parameters.split(",")
96
+ stripped_parameters_list = []
97
+
98
+ for item in parameters_list:
99
+ stripped_item = item.strip()
100
+ stripped_parameters_list.append(stripped_item)
101
+
102
+ if len(parameters_list) >= 3:
103
+ parameter_text = "{}, and {} for parameters".format(", ".join(stripped_parameters_list[:-1]),
104
+ stripped_parameters_list[-1])
105
+ elif len(parameters_list) == 2:
106
+ parameter_text = "{} for parameters".format(" and ".join(stripped_parameters_list))
107
+ else:
108
+ parameter_text = "{} for a parameter".format(", ".join(stripped_parameters_list), )
109
+
110
+ else: # runs in the case there are no parameters
111
+ parameter_text = "no parameters"
112
+
113
+ return parameter_text
114
+
115
+
116
+ def parse_function_declaration(function_string: str) -> str:
117
+ """
118
+ Put together full text string to give brief description of the function declaration.
119
+ :param function_string: a string of text representing the line declaring a function in the python language
120
+ :precondition: function_string must be a syntactically correct string for declaring a function
121
+ :postcondition: correctly describe the function declaration
122
+ :return: a string that describes the function declaration
123
+ """
124
+ return_type = get_return_type(function_string)
125
+ function_name = get_function_name(function_string)
126
+ parameter_text = get_parameters(function_string)
127
+
128
+ if return_type: # runs if there is a return type
129
+ function_declaration_string = (f"{function_name} is declared as a function. It takes {parameter_text} and "
130
+ f"returns {return_type}.")
131
+ else: #runs if there return type is None
132
+ function_declaration_string = f"{function_name} is declared as a function. It takes {parameter_text}."
133
+
134
+ return function_declaration_string
135
+
136
+
137
+ def main():
138
+ """
139
+ Drive the function.
140
+ """
141
+ # with 3 parameters and annotations
142
+ print(parse_function_declaration("def function_name(x: int, y: float, z: str) -> int:"))
143
+
144
+ #with 2 parameters and annotations
145
+ print(parse_function_declaration("def function_name(x: int, y: float) -> int:"))
146
+
147
+ # with 1 parameter and annotations
148
+ print(parse_function_declaration("def function_name(x: int) -> int:"))
149
+
150
+ # with 3 parameters without annotations
151
+ print(parse_function_declaration("def function_name(x, y, z) -> int:"))
152
+
153
+ # with 2 parameters without annotations
154
+ print(parse_function_declaration("def function_name(x, y) -> int:"))
155
+
156
+ # with 1 parameter without annotations
157
+ print(parse_function_declaration("def function_name(x) -> int:"))
158
+
159
+ # with parameters without annotations, without return annotation
160
+ print(parse_function_declaration("def function_name(x, y)"))
161
+
162
+ #without parameters
163
+ print(parse_function_declaration("def another_function() -> int:"))
164
+
165
+ #without parameters and return annotation
166
+ print(parse_function_declaration("def wow_another_one():"))
167
+
168
+
169
+ if __name__ == "__main__":
170
+ main()
@@ -0,0 +1,27 @@
1
+ def try_and_except(split_string):
2
+ lines = split_string.split()
3
+
4
+ for term in lines:
5
+ if "try:" == term:
6
+ return "The function tries performing the following actions:"
7
+ elif "raise" in term:
8
+ error = lines[1].split("(")
9
+ error_message = error[1] + " " + lines[2].replace(")","")
10
+ return f"The function will raise an {error[0]} with message, {error_message}."
11
+ elif "except" in term:
12
+ lines[1] = lines[1].replace(":", "")
13
+ return f"If the function fails to perform these actions a {lines[1]} will occur, so the function:"
14
+ elif "finally:" == term:
15
+ return "Finally, the function will:"
16
+ else:
17
+ return None
18
+
19
+
20
+ def main():
21
+ print(try_and_except("try:"))
22
+ print(try_and_except("except ValueError:"))
23
+ print(try_and_except("raise ValueError(\"Useful message\")"))
24
+ print(try_and_except("finally:"))
25
+
26
+ if __name__ == "__main__":
27
+ main()
@@ -0,0 +1,14 @@
1
+ Metadata-Version: 2.4
2
+ Name: parse4u
3
+ Version: 1.0.0
4
+ Summary: converts python language into plain english
5
+ Author-email: Fawaz Shariff <placeholder0254@gmail.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/Chungywungy/BCIT-Hacakathon
8
+ Project-URL: Documentation, https://github.com/Chungywungy/BCIT-Hacakathon
9
+ Project-URL: Source, https://github.com/Chungywungy/BCIT-Hacakathon/tree/main/src/parse4u
10
+ Keywords: automation,parsing,Summarizing
11
+ Requires-Python: >=3.12
12
+ Description-Content-Type: text/markdown
13
+
14
+ # BCIT-Hacakathon
@@ -0,0 +1,15 @@
1
+ README.md
2
+ pyproject.toml
3
+ src/parse4u/__init__.py
4
+ src/parse4u/docstring_generator.py
5
+ src/parse4u/identify_assignment.py
6
+ src/parse4u/identify_functions.py
7
+ src/parse4u/identify_logical_operators.py
8
+ src/parse4u/identify_operation.py
9
+ src/parse4u/iterables.py
10
+ src/parse4u/parse_function_declaration.py
11
+ src/parse4u/try_except.py
12
+ src/parse4u.egg-info/PKG-INFO
13
+ src/parse4u.egg-info/SOURCES.txt
14
+ src/parse4u.egg-info/dependency_links.txt
15
+ src/parse4u.egg-info/top_level.txt
@@ -0,0 +1 @@
1
+ parse4u