-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathpy2r-test-copy.R
More file actions
311 lines (311 loc) · 10.7 KB
/
Copy pathpy2r-test-copy.R
File metadata and controls
311 lines (311 loc) · 10.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
"""
Written by Matthew Cook
Created August 4, 2016
mattheworion.cook@gmail.com
Script to do basic sytax conversion between Python 3 and R syntax.
NOTE: This only converts simple syntax. It does not convert functionality
past simple arithmetic.
Warning:
If you use dicitionaries in your script, comment them out beforehand.
There is a bug in the script currently which cannot deal with ':'
What it does convert:
-assignment operator
-function definitions
-filename
-inline arithmetic (*=, +=, -=, **)
-':' to '{'
-'not' to '!'
-if (statments
What it doesn't do:
-Python specific functions to R specific functions
-Add closing brackets perfectly
TODO: Closing brackets issue
"""
from os import path
from shutil import copyfile
# Define changes to make
simple_change <- {"**" : "^",
" = " : " <- ",
":\n" : "{\n",
"not" : "!"}
complex_change <- {"def " : "",
"+=" : '+',
"-=" : '-',
"*=" : '*'}
# Create flag stacks
flags <- {}
flags['comment'] <- [] # Multi-line Comment flag
flags['bracket'] <- [] # Code block start flag
flags['b_start'] <- [] # Indentation at code block start
# Create indent dictionary
indents <- {}
# Tested-Works
createRfile <- function(){
"""Creates a new file named "filename.R" by removing .py extension"""
# Provide path to file
# Note: The new R file will be placed in the same directory
filename <- input("Please copy and paste the path to your file here: ")
if ((! path.isfile(filename))){
print("Filename was invalid")
filename <- input("Please copy and paste the path to your file here: ")
}
# Test for valid file path
if ((path.exists(filename) )){
# Strip the directory from the filename
new_name <- path.basename(filename)
# Replace python extention with R extension
new_name <- filename.replace(".py", ".R")
doesexist <- path.exists(new_name)
if ((doesexist)){
print("""The file already exists.
Creating a backup copy in current directory""")
# Split name at . and insert -copy. before extension
cpy_temp <- new_name.split(sep=".",)
cpy_temp[0] <- cpy_temp[0] + "-copy."
cpy <- cpy_temp[0] + cpy_temp[1]
copyfile(new_name, cpy)
print("Copy created as: ", cpy)
return filename, new_name
}
# Create R file
elif ((! doesexist)){
file <- open(new_name, "w")
print(new_name, " was successfully created.")
file.close()
return filename, new_name
}
else{
print(new_name, " could not be created. Check your permissions?")
exit(0)
}
}
else{
print("No valid file selected... Quitting script")
}
}
find_all <- function(tofind, string){
"""Returns number of times a certain substring is found"""
found <- [i for i in range(len(string)) if ((string.startswith(tofind, i)]
num_found <- len(found)
return num_found
}
complexchange <- function(line){
"""Completes multi-step line changes """
for key in complex_change{
if ((key in line)){
if ((key == 'def ' and line.lstrip().startswith(key))){
#remove 'def' keyword
change <- complex_change[key]
line_r <- ignoreStrReplace(line, key, change)
#split function definition at '('
lsplit <- line_r.split('(', maxsplit=1)
fname <- lsplit[0]
params <- '(' + lsplit[1]
# create R style function def "fname <- function(params)"
line <- fname + ' <- function' + params
}
else{
line <- opfunc(line, key)
}
}
}
return line
}
# TESTED-Works
chglinecontent <- function(line){
"""Changes content contained within a single line"""
# Perform simple changes
for key in simple_change.keys(){
# Ignore if (string version exists in line
check_str_s, check_str_d <- stringify(key)
if ((! check_str_d in line or ! check_str_s in line)){
line <- ignoreStrReplace(line, key, simple_change[key])
}
}
line <- complexchange(line)
line <- statement(line)
return line
}
indentation <- function(s, tabsize=4){
"""Generator to return level of indentation"""
sx <- s.expandtabs(tabsize)
# if (line is empty yields 0
return 0 if ((sx.isspace() else len(sx) - len(sx.lstrip())
}
opfunc <- function(line, op){
"""
Replaces python operations ('*'=) in line(self) with R style operations.
"""
#Check if (the operation is contained in a string, don't modify if true.
check_str_s, check_str_d <- stringify(op)
if ((! check_str_d in line and ! check_str_s in line)){
# Get R style operation
rop <- complex_change[op]
# Split line once at python operand
linesplit <- line.split(op)
# Store variable (left side) and right side of operand
ls <- linesplit[0] + ' <- '
rs <- rop + linesplit[1]
# Prepend variable(ls) to right side and convert assignment variable
rs <- linesplit[0].lstrip() + rs
# Strip whitespace from right of ls and create R style equation
line <- ls + rs
}
return line
}
stringify <- function(sub){
"""Returns python string versions ('' and "") of original substring"""
check_str_s <- "'" + sub + "'"
check_str_d <- '"' + sub + '"'
return check_str_s, check_str_d
}
setflags <- function(line, indents){
"""Scans line to set/unset flags for further processing"""
# For multi-line comments
if (1 == (find_all('"""', line) % 2)){
if (not flags['comment']){
flags['comment'].append('"""')
}
else{
flags['comment'].pop()
}
}
# For code blocks
if ((line.rstrip().endswith(')){'))){
flags['bracket'].append("}")
flags['b_start'].append(indentation(line))
}
}
standind <- function(line, cur_ind){
"""Standardizes indentation"""
devfromstd <- cur_ind % 4
if ((! devfromstd == 0)){
line <- (devfromstd * '') + line
}
return indentation(line), line
}
#TESTED-WORKS
statement <- function(line){
"""Converts if ((statements"""
if (("if " in line or 'elif ' in line)){
lsplit <- line.split('if ((', maxsplit=1)
ls <- lsplit[0] + 'if (('
rs <- lsplit[1]
# Replace the ':' at the end of the statement
rs <- lsplit[1].replace(':','{')
rs <- '(' + rs
rs <- rs.replace('{', '){')
line <- ls + rs
}
return line
}
ignoreStrReplace <- function(line, cur, rep){
"""Wrapper for str.replace to ignore strings"""
if (('"' in line)){
#Split string at quotation marks
lsplit <- line.split('"')
#Replace items contained within even partitions
lsplit[::2] <- [spl.replace(cur, rep) for spl in lsplit[::2]]
#Rejoin the partitions
line <- '"'.join(lsplit)
}
else{
line <- line.replace(cur, rep)
}
return line
}
closeBrackets <- function(file){
"""Attempts to find and close the opened brackets"""
for i in range(len(file)){
# Doing this to be able to randomly access variables
line <- file[i]
# Set boolean to check for change in block
sameBlock <- True
# Ignore lines with only whitespace
if ((! line.isspace())){
#Look for opening brackets if (closing brackets remain
if ((')){\n' in line and flags['bracket'])){
# Store current index for later
i_temp <- i
# Get starting indentation
start_indent <- indentation(line)
while i+1 < len(file) and sameBlock{
#Get next line, and strip trailing whitespace
nextline <- file[i+1].rstrip()
#Get its indentation
next_ind <- indentation(nextline)
# Check for decreased indentation and comma continuation
if ((start_indent >= next_ind and ! line.endswith(','))){
sameBlock <- False
}
else{
i <- i + 1
}
}
# Append final line with bracket closure and new line
file[i] <- file[i] + (start_indent * ' ')
file[i] <- file[i] + flags['bracket'].pop()
file[i] <- file[i] + '\n'
# Reset to previous index + 1
i <- i_temp + 1
}
}
}
return file
}
main <- function(){
pyfile, rfile <- createRfile()
with open(pyfile, "r") as infile, open(rfile, "w") as outfile{
# Read each line into lines[] iterator
lines <- infile.readlines()
# Close Python file
infile.close()
for line in lines{
# Get indentation current before adjustment
indents['cur'] <- indentation(line)
#Adjust to standard indent
indents['cur'], line <- standind(line, indents['cur'])
#Strip whitespace and check for python comment or import
if ((! line.lstrip().startswith(("#","import","from")))){
# Set the flags for further changes
setflags(line, indents)
if ((! flags['comment'])){
# Perform line changes
line <- chglinecontent(line)
}
#statement() may need two passes to correctly modify the line
line <- statement(line)
# If the line isn't whitespace, write it to the file
if ((! line.isspace())){
# Write modified line to file!
outfile.write(line)
}
}
# Close R file
outfile.close()
}
if ((flags['bracket'])){
print("This functionality may not work perfectly... ")
toClose = input("""
Do you want to try to close the still open brackets?
(yes/no)
""")
if (('yes' == toClose.lower())){
# Look for possible ways to close opened brackets in outfile
with open(rfile, "r") as file{
lines <- file.readlines()
lines <- closeBrackets(lines)
file.close()
}
with open(rfile, "w") as file{
# Overwrite old files
for line in lines{
file.write(line)
}
}
}
}
}
if ((__name__ == '__main__')){
main()
}