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 +14 -0
- parse4u-1.0.0/README.md +1 -0
- parse4u-1.0.0/pyproject.toml +35 -0
- parse4u-1.0.0/setup.cfg +4 -0
- parse4u-1.0.0/src/parse4u/__init__.py +0 -0
- parse4u-1.0.0/src/parse4u/docstring_generator.py +26 -0
- parse4u-1.0.0/src/parse4u/identify_assignment.py +33 -0
- parse4u-1.0.0/src/parse4u/identify_functions.py +51 -0
- parse4u-1.0.0/src/parse4u/identify_logical_operators.py +193 -0
- parse4u-1.0.0/src/parse4u/identify_operation.py +91 -0
- parse4u-1.0.0/src/parse4u/iterables.py +109 -0
- parse4u-1.0.0/src/parse4u/parse_function_declaration.py +170 -0
- parse4u-1.0.0/src/parse4u/try_except.py +27 -0
- parse4u-1.0.0/src/parse4u.egg-info/PKG-INFO +14 -0
- parse4u-1.0.0/src/parse4u.egg-info/SOURCES.txt +15 -0
- parse4u-1.0.0/src/parse4u.egg-info/dependency_links.txt +1 -0
- parse4u-1.0.0/src/parse4u.egg-info/top_level.txt +1 -0
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
|
parse4u-1.0.0/README.md
ADDED
|
@@ -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]
|
parse4u-1.0.0/setup.cfg
ADDED
|
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
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
parse4u
|