23
23
24
24
from .common import *
25
25
26
+
26
27
def find_matching_bracket (lines , start_line_index , start_char_index , matching_char = "{" ):
27
28
"""Finds the position of the matching closing bracket from a list of lines.
28
29
@@ -216,6 +217,7 @@ def convert_for_loop(line):
216
217
217
218
return new_line
218
219
220
+
219
221
# Removes all indentation from file to reformat indentation for python later
220
222
def remove_all_indentation (input_lines ):
221
223
"""Removes all indentation for reformatting according to python's indentation rules
@@ -228,7 +230,7 @@ def remove_all_indentation(input_lines):
228
230
"""
229
231
output_lines = []
230
232
for index , line in enumerate (input_lines ):
231
- output_lines .append (line .lstrip ())
233
+ output_lines .append (line .lstrip ())
232
234
return output_lines
233
235
234
236
@@ -244,14 +246,21 @@ def check_map_functions(input_lines):
244
246
output_lines = []
245
247
currentNumOfNestedFuncs = 0
246
248
for index , line in enumerate (input_lines ):
247
- if (line .strip ().endswith (".map(" ) and input_lines [index + 1 ].strip ().replace (" " , "" ).startswith ("function(" )) or \
248
- (line .strip ().endswith (".map(function(" ) and input_lines [index + 1 ].strip ().replace (" " , "" ).endswith ("{" )):
249
- input_lines [index + 1 ] = line + input_lines [index + 1 ]
249
+ if (
250
+ line .strip ().endswith (".map(" )
251
+ and input_lines [index + 1 ].strip ().replace (" " , "" ).startswith ("function(" )
252
+ ) or (
253
+ line .strip ().endswith (".map(function(" )
254
+ and input_lines [index + 1 ].strip ().replace (" " , "" ).endswith ("{" )
255
+ ):
256
+ input_lines [index + 1 ] = line + input_lines [index + 1 ]
250
257
continue
251
258
252
- if ".map(function" in line .replace (" " , "" ) or \
253
- "returnfunction" in line .replace (" " , "" ) or \
254
- "function(" in line .replace (" " , "" ):
259
+ if (
260
+ ".map(function" in line .replace (" " , "" )
261
+ or "returnfunction" in line .replace (" " , "" )
262
+ or "function(" in line .replace (" " , "" )
263
+ ):
255
264
try :
256
265
bracket_index = line .index ("{" )
257
266
matching_line_index , matching_char_index = find_matching_bracket (
@@ -272,13 +281,11 @@ def check_map_functions(input_lines):
272
281
273
282
new_lines = check_map_functions (new_lines )
274
283
275
- for sub_index , tmp_line in enumerate (
276
- new_lines
277
- ):
278
- output_lines .append ((' ' * currentNumOfNestedFuncs ) + tmp_line )
279
- if '{' in tmp_line :
284
+ for sub_index , tmp_line in enumerate (new_lines ):
285
+ output_lines .append ((" " * currentNumOfNestedFuncs ) + tmp_line )
286
+ if "{" in tmp_line :
280
287
currentNumOfNestedFuncs += 1
281
- if '}' in tmp_line :
288
+ if "}" in tmp_line :
282
289
currentNumOfNestedFuncs -= 1
283
290
input_lines [index + 1 + sub_index ] = ""
284
291
@@ -287,7 +294,9 @@ def check_map_functions(input_lines):
287
294
header_line = line [:func_start_index ] + func_name
288
295
header_line = header_line .rstrip ()
289
296
290
- func_footer = input_lines [matching_line_index ][: matching_char_index + 1 ]
297
+ func_footer = input_lines [matching_line_index ][
298
+ : matching_char_index + 1
299
+ ]
291
300
output_lines .append (func_footer )
292
301
293
302
footer_line = input_lines [matching_line_index ][
@@ -300,7 +309,7 @@ def check_map_functions(input_lines):
300
309
input_lines [matching_line_index ] = footer_line
301
310
302
311
output_lines .append (header_line )
303
- #output_lines.append(footer_line)
312
+ # output_lines.append(footer_line)
304
313
except Exception as e :
305
314
print (
306
315
f"An error occurred: { e } . The closing curly bracket could not be found in Line { index + 1 } : { line } . Please reformat the function definition and make sure that both the opening and closing curly brackets appear on the same line as the function keyword. "
@@ -423,25 +432,28 @@ def js_to_python(
423
432
matching_char_index ,
424
433
) = find_matching_bracket (lines , index , bracket_index )
425
434
426
- if ' func_' not in line :
435
+ if " func_" not in line :
427
436
currentNumOfNestedFuncs += 1
428
-
437
+
429
438
for sub_index , tmp_line in enumerate (
430
439
lines [index + 1 : matching_line_index ]
431
440
):
432
- #lines[sub_index] = (' ' * currentNumOfNestedFuncs) + tmp_line
433
- if '{' in tmp_line and ' function' not in line :
441
+ # lines[sub_index] = (' ' * currentNumOfNestedFuncs) + tmp_line
442
+ if "{" in tmp_line and " function" not in line :
434
443
currentNumOfNestedFuncs += 1
435
- if '}' in tmp_line and ' function' not in line :
444
+ if "}" in tmp_line and " function" not in line :
436
445
currentNumOfNestedFuncs -= 1
437
- lines [index + 1 + sub_index ] = (' ' * currentNumOfNestedFuncs ) + lines [index + 1 + sub_index ]
446
+ lines [index + 1 + sub_index ] = (
447
+ " " * currentNumOfNestedFuncs
448
+ ) + lines [index + 1 + sub_index ]
438
449
439
450
currentNumOfNestedFuncs -= 1
440
451
441
452
line = line [:bracket_index ] + line [bracket_index + 1 :]
442
453
if matching_line_index == index :
443
454
line = (
444
- line [:matching_char_index ] + line [matching_char_index + 1 :]
455
+ line [:matching_char_index ]
456
+ + line [matching_char_index + 1 :]
445
457
)
446
458
else :
447
459
tmp_line = lines [matching_line_index ]
@@ -476,7 +488,7 @@ def js_to_python(
476
488
+ line .strip ()
477
489
+ ":"
478
490
)
479
- elif "{" in line and '({' not in line :
491
+ elif "{" in line and "({" not in line :
480
492
bracket_index = line .index ("{" )
481
493
(
482
494
matching_line_index ,
@@ -488,24 +500,30 @@ def js_to_python(
488
500
for sub_index , tmp_line in enumerate (
489
501
lines [index + 1 : matching_line_index ]
490
502
):
491
- lines [index + 1 + sub_index ] = (' ' * currentNumOfNestedFuncs ) + lines [index + 1 + sub_index ]
492
- if '{' in tmp_line and 'if' not in line and 'for' not in line :
503
+ lines [index + 1 + sub_index ] = (
504
+ " " * currentNumOfNestedFuncs
505
+ ) + lines [index + 1 + sub_index ]
506
+ if "{" in tmp_line and "if" not in line and "for" not in line :
493
507
currentNumOfNestedFuncs += 1
494
- if '}' in tmp_line and 'if' not in line and ' for' not in line :
508
+ if "}" in tmp_line and "if" not in line and " for" not in line :
495
509
currentNumOfNestedFuncs -= 1
496
510
497
511
currentNumOfNestedFuncs -= 1
498
512
499
513
if (matching_line_index == index ) and (":" in line ):
500
514
pass
501
- elif ("for (" in line ) or ("for(" in line ) or \
502
- ('if (' in line ) or ('if(' in line ):
503
- if 'if' not in line :
515
+ elif (
516
+ ("for (" in line )
517
+ or ("for(" in line )
518
+ or ("if (" in line )
519
+ or ("if(" in line )
520
+ ):
521
+ if "if" not in line :
504
522
line = convert_for_loop (line )
505
523
else :
506
524
start_index = line .index ("(" )
507
525
end_index = line .index (")" )
508
- line = ' if ' + line [start_index :end_index ]+ ' ):{'
526
+ line = " if " + line [start_index :end_index ] + " ):{"
509
527
lines [index ] = line
510
528
bracket_index = line .index ("{" )
511
529
(
@@ -539,86 +557,102 @@ def js_to_python(
539
557
line = line .replace ("= new" , "=" )
540
558
line = line .replace ("exports." , "" )
541
559
line = line .replace ("Map." , f"{ Map } ." )
542
- line = line .replace ("Export.table.toDrive" , "geemap.ee_export_vector_to_drive" )
543
- line = line .replace ("Export.table.toAsset" , "geemap.ee_export_vector_to_asset" )
544
- line = line .replace ("Export.image.toAsset" , "geemap.ee_export_image_to_asset" )
545
- line = line .replace ("Export.video.toDrive" , "geemap.ee_export_video_to_drive" )
560
+ line = line .replace (
561
+ "Export.table.toDrive" , "geemap.ee_export_vector_to_drive"
562
+ )
563
+ line = line .replace (
564
+ "Export.table.toAsset" , "geemap.ee_export_vector_to_asset"
565
+ )
566
+ line = line .replace (
567
+ "Export.image.toAsset" , "geemap.ee_export_image_to_asset"
568
+ )
569
+ line = line .replace (
570
+ "Export.video.toDrive" , "geemap.ee_export_video_to_drive"
571
+ )
546
572
line = line .replace ("||" , "or" )
547
- line = line .replace (' \****' , '#' )
548
- line = line .replace (' def =' , ' _def =' )
549
- line = line .replace (' , def, ' , ' , _def, ' )
550
- line = line .replace (' (def, ' , ' (_def, ' )
551
- line = line .replace (' , def)' , ' , _def)' )
552
- line = line .replace (' ===' , '==' )
553
-
573
+ line = line .replace (" \****" , "#" )
574
+ line = line .replace (" def =" , " _def =" )
575
+ line = line .replace (" , def, " , " , _def, " )
576
+ line = line .replace (" (def, " , " (_def, " )
577
+ line = line .replace (" , def)" , " , _def)" )
578
+ line = line .replace (" ===" , "==" )
579
+
554
580
# Replaces all javascript operators with python operators
555
- if '!' in line :
581
+ if "!" in line :
556
582
try :
557
- if (line .replace (" " , "" ))[line .find ('!' ) + 1 ] != '=' :
583
+ if (line .replace (" " , "" ))[line .find ("!" ) + 1 ] != "=" :
558
584
line = line .replace ("!" , "not " )
559
585
except :
560
586
print ("continue..." )
561
587
562
588
line = line .rstrip ()
563
589
564
590
# If the function concat is used, replace it with python's concatenation
565
- if ' concat' in line :
566
- line = line .replace (' .concat(' , '+' )
567
- line = line .replace (',' , '+' )
568
- line = line .replace (')' , '' )
591
+ if " concat" in line :
592
+ line = line .replace (" .concat(" , "+" )
593
+ line = line .replace ("," , "+" )
594
+ line = line .replace (")" , "" )
569
595
570
596
# Checks if an equal sign is at the end of a line. If so, add backslashes
571
597
if shouldCheckForEmptyLines :
572
- if line .strip () == '' or '#' in line :
573
- if line .strip ().endswith ('[' ):
574
- line = '['
598
+ if line .strip () == "" or "#" in line :
599
+ if line .strip ().endswith ("[" ):
600
+ line = "["
575
601
shouldCheckForEmptyLines = False
576
602
else :
577
- line = ' \\ '
603
+ line = " \\ "
578
604
else :
579
605
shouldCheckForEmptyLines = False
580
-
581
- if line .strip ().endswith ('=' ):
582
- line = line + ' \\ '
606
+
607
+ if line .strip ().endswith ("=" ):
608
+ line = line + " \\ "
583
609
shouldCheckForEmptyLines = True
584
610
585
611
# Adds getInfo at the end of print statements involving maps
586
612
endOfPrintReplaced = False
587
-
588
- if (' print(' in line and '=' not in line ) or checkNextLineForPrint :
613
+
614
+ if (" print(" in line and "=" not in line ) or checkNextLineForPrint :
589
615
for i in range (len (line ) - 1 ):
590
- if line [len (line ) - i - 1 ] == ')' :
591
- line = line [:len (line ) - i - 1 ] + ' .getInfo())'
616
+ if line [len (line ) - i - 1 ] == ")" :
617
+ line = line [: len (line ) - i - 1 ] + " .getInfo())"
592
618
print (line )
593
619
endOfPrintReplaced = True
594
620
break
595
621
if endOfPrintReplaced :
596
622
checkNextLineForPrint = False
597
623
else :
598
624
checkNextLineForPrint = True
599
-
625
+
600
626
# Removes potential commas after imports. Causes tuple type errors
601
627
if line .endswith ("," ):
602
- if '=' in lines [index + 1 ] and not lines [index + 1 ].strip ().startswith ("'" ):
628
+ if "=" in lines [index + 1 ] and not lines [
629
+ index + 1
630
+ ].strip ().startswith ("'" ):
603
631
line = line [:- 1 ]
604
632
605
633
# Changes object argument to individual parameters
606
- if line .strip ().endswith ("({" ) and not 'ee.Dictionary' in line and not '.set(' in line and '.addLayer' not in line and 'cast' not in line :
634
+ if (
635
+ line .strip ().endswith ("({" )
636
+ and not "ee.Dictionary" in line
637
+ and not ".set(" in line
638
+ and ".addLayer" not in line
639
+ and "cast" not in line
640
+ ):
607
641
line = line .rstrip ()[:- 1 ]
608
642
numIncorrectParameters = numIncorrectParameters + 1
609
643
610
644
if numIncorrectParameters > 0 :
611
645
if line .strip ().startswith ("})" ):
612
- line = line .replace ('})' , ')' )
646
+ line = line .replace ("})" , ")" )
613
647
numIncorrectParameters = numIncorrectParameters - 1
614
648
else :
615
649
if currentDictionaryScopeDepth < 1 :
616
650
line = line .replace (":" , " =" )
617
651
618
- if ' = {' in line and '({' not in line :
652
+ if " = {" in line and "({" not in line :
619
653
currentDictionaryScopeDepth += 1
620
654
621
- if '}' in line and currentDictionaryScopeDepth > 0 :
655
+ if "}" in line and currentDictionaryScopeDepth > 0 :
622
656
currentDictionaryScopeDepth -= 1
623
657
624
658
# if ".style(" in line and ".style(**" not in line:
@@ -648,19 +682,24 @@ def js_to_python(
648
682
):
649
683
line = ""
650
684
651
- if "#" in line and not line .strip ().startswith ("#" ) and not line [line .index ("#" ) - 1 ] == "'" :
685
+ if (
686
+ "#" in line
687
+ and not line .strip ().startswith ("#" )
688
+ and not line [line .index ("#" ) - 1 ] == "'"
689
+ ):
652
690
line = line [: line .index ("#" )]
653
691
654
692
if line .lstrip ().startswith ("." ):
655
- if lines [index - 1 ].strip ().endswith ('\\ ' ) and lines [index - 1 ].strip ().startswith ('#' ):
656
- lines [index - 1 ] = '\\ '
693
+ if lines [index - 1 ].strip ().endswith ("\\ " ) and lines [
694
+ index - 1
695
+ ].strip ().startswith ("#" ):
696
+ lines [index - 1 ] = "\\ "
657
697
if "#" in line :
658
698
line = line [: line .index ("#" )]
659
699
output = output .rstrip () + " " + "\\ " + "\n " + line + "\n "
660
700
else :
661
701
output += line + "\n "
662
702
663
-
664
703
if show_map :
665
704
output += "Map"
666
705
@@ -762,7 +801,12 @@ def js_snippet_to_py(
762
801
763
802
764
803
def js_to_python_dir (
765
- in_dir , out_dir = None , use_qgis = True , github_repo = None , import_geemap = False , Map = "Map"
804
+ in_dir ,
805
+ out_dir = None ,
806
+ use_qgis = True ,
807
+ github_repo = None ,
808
+ import_geemap = False ,
809
+ Map = "Map" ,
766
810
):
767
811
"""Converts all Earth Engine JavaScripts in a folder recursively to Python scripts.
768
812
0 commit comments