OLD | NEW |
---|---|
1 # Copyright (c) 2012 Google Inc. All rights reserved. | 1 # Copyright (c) 2012 Google Inc. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 from compiler.ast import Const | 5 from compiler.ast import Const |
6 from compiler.ast import Dict | 6 from compiler.ast import Dict |
7 from compiler.ast import Discard | 7 from compiler.ast import Discard |
8 from compiler.ast import List | 8 from compiler.ast import List |
9 from compiler.ast import Module | 9 from compiler.ast import Module |
10 from compiler.ast import Node | 10 from compiler.ast import Node |
(...skipping 519 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
530 elif phase == PHASE_LATE: | 530 elif phase == PHASE_LATE: |
531 variable_re = late_variable_re | 531 variable_re = late_variable_re |
532 expansion_symbol = '>' | 532 expansion_symbol = '>' |
533 elif phase == PHASE_LATELATE: | 533 elif phase == PHASE_LATELATE: |
534 variable_re = latelate_variable_re | 534 variable_re = latelate_variable_re |
535 expansion_symbol = '^' | 535 expansion_symbol = '^' |
536 else: | 536 else: |
537 assert False | 537 assert False |
538 | 538 |
539 input_str = str(input) | 539 input_str = str(input) |
540 if IsStrCanonicalInt(input_str): | |
541 return int(input_str) | |
542 | |
540 # Do a quick scan to determine if an expensive regex search is warranted. | 543 # Do a quick scan to determine if an expensive regex search is warranted. |
541 if expansion_symbol in input_str: | 544 if expansion_symbol not in input_str: |
542 # Get the entire list of matches as a list of MatchObject instances. | 545 return input_str |
543 # (using findall here would return strings instead of MatchObjects). | 546 |
544 matches = [match for match in variable_re.finditer(input_str)] | 547 # Get the entire list of matches as a list of MatchObject instances. |
548 # (using findall here would return strings instead of MatchObjects). | |
549 matches = [match for match in variable_re.finditer(input_str)] | |
550 if not matches: | |
551 return input_str | |
552 | |
553 output = input_str | |
554 # Reverse the list of matches so that replacements are done right-to-left. | |
Nico
2012/05/28 21:54:50
Rietveld doesn't show it well, but from here on ev
| |
555 # That ensures that earlier replacements won't mess up the string in a | |
556 # way that causes later calls to find the earlier substituted text instead | |
557 # of what's intended for replacement. | |
558 matches.reverse() | |
559 for match_group in matches: | |
560 match = match_group.groupdict() | |
561 gyp.DebugOutput(gyp.DEBUG_VARIABLES, | |
562 "Matches: %s" % repr(match)) | |
563 # match['replace'] is the substring to look for, match['type'] | |
564 # is the character code for the replacement type (< > <! >! <| >| <@ | |
565 # >@ <!@ >!@), match['is_array'] contains a '[' for command | |
566 # arrays, and match['content'] is the name of the variable (< >) | |
567 # or command to run (<! >!). match['command_string'] is an optional | |
568 # command string. Currently, only 'pymod_do_main' is supported. | |
569 | |
570 # run_command is true if a ! variant is used. | |
571 run_command = '!' in match['type'] | |
572 command_string = match['command_string'] | |
573 | |
574 # file_list is true if a | variant is used. | |
575 file_list = '|' in match['type'] | |
576 | |
577 # Capture these now so we can adjust them later. | |
578 replace_start = match_group.start('replace') | |
579 replace_end = match_group.end('replace') | |
580 | |
581 # Find the ending paren, and re-evaluate the contained string. | |
582 (c_start, c_end) = FindEnclosingBracketGroup(input_str[replace_start:]) | |
583 | |
584 # Adjust the replacement range to match the entire command | |
585 # found by FindEnclosingBracketGroup (since the variable_re | |
586 # probably doesn't match the entire command if it contained | |
587 # nested variables). | |
588 replace_end = replace_start + c_end | |
589 | |
590 # Find the "real" replacement, matching the appropriate closing | |
591 # paren, and adjust the replacement start and end. | |
592 replacement = input_str[replace_start:replace_end] | |
593 | |
594 # Figure out what the contents of the variable parens are. | |
595 contents_start = replace_start + c_start + 1 | |
596 contents_end = replace_end - 1 | |
597 contents = input_str[contents_start:contents_end] | |
598 | |
599 # Do filter substitution now for <|(). | |
600 # Admittedly, this is different than the evaluation order in other | |
601 # contexts. However, since filtration has no chance to run on <|(), | |
602 # this seems like the only obvious way to give them access to filters. | |
603 if file_list: | |
604 processed_variables = copy.deepcopy(variables) | |
605 ProcessListFiltersInDict(contents, processed_variables) | |
606 # Recurse to expand variables in the contents | |
607 contents = ExpandVariables(contents, phase, | |
608 processed_variables, build_file) | |
609 else: | |
610 # Recurse to expand variables in the contents | |
611 contents = ExpandVariables(contents, phase, variables, build_file) | |
612 | |
613 # Strip off leading/trailing whitespace so that variable matches are | |
614 # simpler below (and because they are rarely needed). | |
615 contents = contents.strip() | |
616 | |
617 # expand_to_list is true if an @ variant is used. In that case, | |
618 # the expansion should result in a list. Note that the caller | |
619 # is to be expecting a list in return, and not all callers do | |
620 # because not all are working in list context. Also, for list | |
621 # expansions, there can be no other text besides the variable | |
622 # expansion in the input string. | |
623 expand_to_list = '@' in match['type'] and input_str == replacement | |
624 | |
625 if run_command or file_list: | |
626 # Find the build file's directory, so commands can be run or file lists | |
627 # generated relative to it. | |
628 build_file_dir = os.path.dirname(build_file) | |
629 if build_file_dir == '': | |
630 # If build_file is just a leaf filename indicating a file in the | |
631 # current directory, build_file_dir might be an empty string. Set | |
632 # it to None to signal to subprocess.Popen that it should run the | |
633 # command in the current directory. | |
634 build_file_dir = None | |
635 | |
636 # Support <|(listfile.txt ...) which generates a file | |
637 # containing items from a gyp list, generated at gyp time. | |
638 # This works around actions/rules which have more inputs than will | |
639 # fit on the command line. | |
640 if file_list: | |
641 if type(contents) == list: | |
642 contents_list = contents | |
643 else: | |
644 contents_list = contents.split(' ') | |
645 replacement = contents_list[0] | |
646 path = replacement | |
647 if not os.path.isabs(path): | |
648 path = os.path.join(build_file_dir, path) | |
649 f = gyp.common.WriteOnDiff(path) | |
650 for i in contents_list[1:]: | |
651 f.write('%s\n' % i) | |
652 f.close() | |
653 | |
654 elif run_command: | |
655 use_shell = True | |
656 if match['is_array']: | |
657 contents = eval(contents) | |
658 use_shell = False | |
659 | |
660 # Check for a cached value to avoid executing commands, or generating | |
661 # file lists more than once. | |
662 # TODO(http://code.google.com/p/gyp/issues/detail?id=112): It is | |
663 # possible that the command being invoked depends on the current | |
664 # directory. For that case the syntax needs to be extended so that the | |
665 # directory is also used in cache_key (it becomes a tuple). | |
666 # TODO(http://code.google.com/p/gyp/issues/detail?id=111): In theory, | |
667 # someone could author a set of GYP files where each time the command | |
668 # is invoked it produces different output by design. When the need | |
669 # arises, the syntax should be extended to support no caching off a | |
670 # command's output so it is run every time. | |
671 cache_key = str(contents) | |
672 cached_value = cached_command_results.get(cache_key, None) | |
673 if cached_value is None: | |
674 gyp.DebugOutput(gyp.DEBUG_VARIABLES, | |
675 "Executing command '%s' in directory '%s'" % | |
676 (contents,build_file_dir)) | |
677 | |
678 replacement = '' | |
679 | |
680 if command_string == 'pymod_do_main': | |
681 # <!pymod_do_main(modulename param eters) loads |modulename| as a | |
682 # python module and then calls that module's DoMain() function, | |
683 # passing ["param", "eters"] as a single list argument. For modules | |
684 # that don't load quickly, this can be faster than | |
685 # <!(python modulename param eters). Do this in |build_file_dir|. | |
686 oldwd = os.getcwd() # Python doesn't like os.open('.'): no fchdir. | |
687 os.chdir(build_file_dir) | |
688 | |
689 parsed_contents = shlex.split(contents) | |
690 py_module = __import__(parsed_contents[0]) | |
691 replacement = str(py_module.DoMain(parsed_contents[1:])).rstrip() | |
692 | |
693 os.chdir(oldwd) | |
694 assert replacement != None | |
695 elif command_string: | |
696 raise Exception("Unknown command string '%s' in '%s'." % | |
697 (command_string, contents)) | |
698 else: | |
699 # Fix up command with platform specific workarounds. | |
700 contents = FixupPlatformCommand(contents) | |
701 p = subprocess.Popen(contents, shell=use_shell, | |
702 stdout=subprocess.PIPE, | |
703 stderr=subprocess.PIPE, | |
704 stdin=subprocess.PIPE, | |
705 cwd=build_file_dir) | |
706 | |
707 p_stdout, p_stderr = p.communicate('') | |
708 | |
709 if p.wait() != 0 or p_stderr: | |
710 sys.stderr.write(p_stderr) | |
711 # Simulate check_call behavior, since check_call only exists | |
712 # in python 2.5 and later. | |
713 raise Exception("Call to '%s' returned exit status %d." % | |
714 (contents, p.returncode)) | |
715 replacement = p_stdout.rstrip() | |
716 | |
717 cached_command_results[cache_key] = replacement | |
718 else: | |
719 gyp.DebugOutput(gyp.DEBUG_VARIABLES, | |
720 "Had cache value for command '%s' in directory '%s'" % | |
721 (contents,build_file_dir)) | |
722 replacement = cached_value | |
723 | |
724 else: | |
725 if not contents in variables: | |
726 if contents[-1] in ['!', '/']: | |
727 # In order to allow cross-compiles (nacl) to happen more naturally, | |
728 # we will allow references to >(sources/) etc. to resolve to | |
729 # and empty list if undefined. This allows actions to: | |
730 # 'action!': [ | |
731 # '>@(_sources!)', | |
732 # ], | |
733 # 'action/': [ | |
734 # '>@(_sources/)', | |
735 # ], | |
736 replacement = [] | |
737 else: | |
738 raise KeyError, 'Undefined variable ' + contents + \ | |
739 ' in ' + build_file | |
740 else: | |
741 replacement = variables[contents] | |
742 | |
743 if isinstance(replacement, list): | |
744 for item in replacement: | |
745 if (not contents[-1] == '/' and | |
746 not isinstance(item, str) and not isinstance(item, int)): | |
747 raise TypeError, 'Variable ' + contents + \ | |
748 ' must expand to a string or list of strings; ' + \ | |
749 'list contains a ' + \ | |
750 item.__class__.__name__ | |
751 # Run through the list and handle variable expansions in it. Since | |
752 # the list is guaranteed not to contain dicts, this won't do anything | |
753 # with conditions sections. | |
754 ProcessVariablesAndConditionsInList(replacement, phase, variables, | |
755 build_file) | |
756 elif not isinstance(replacement, str) and \ | |
757 not isinstance(replacement, int): | |
758 raise TypeError, 'Variable ' + contents + \ | |
759 ' must expand to a string or list of strings; ' + \ | |
760 'found a ' + replacement.__class__.__name__ | |
761 | |
762 if expand_to_list: | |
763 # Expanding in list context. It's guaranteed that there's only one | |
764 # replacement to do in |input_str| and that it's this replacement. See | |
765 # above. | |
766 if isinstance(replacement, list): | |
767 # If it's already a list, make a copy. | |
768 output = replacement[:] | |
769 else: | |
770 # Split it the same way sh would split arguments. | |
771 output = shlex.split(str(replacement)) | |
772 else: | |
773 # Expanding in string context. | |
774 encoded_replacement = '' | |
775 if isinstance(replacement, list): | |
776 # When expanding a list into string context, turn the list items | |
777 # into a string in a way that will work with a subprocess call. | |
778 # | |
779 # TODO(mark): This isn't completely correct. This should | |
780 # call a generator-provided function that observes the | |
781 # proper list-to-argument quoting rules on a specific | |
782 # platform instead of just calling the POSIX encoding | |
783 # routine. | |
784 encoded_replacement = gyp.common.EncodePOSIXShellList(replacement) | |
785 else: | |
786 encoded_replacement = replacement | |
787 | |
788 output = output[:replace_start] + str(encoded_replacement) + \ | |
789 output[replace_end:] | |
790 # Prepare for the next match iteration. | |
791 input_str = output | |
792 | |
793 # Look for more matches now that we've replaced some, to deal with | |
794 # expanding local variables (variables defined in the same | |
795 # variables block as this one). | |
796 gyp.DebugOutput(gyp.DEBUG_VARIABLES, | |
797 "Found output %s, recursing." % repr(output)) | |
798 if isinstance(output, list): | |
799 if output and isinstance(output[0], list): | |
800 # Leave output alone if it's a list of lists. | |
801 # We don't want such lists to be stringified. | |
802 pass | |
803 else: | |
804 new_output = [] | |
805 for item in output: | |
806 new_output.append( | |
807 ExpandVariables(item, phase, variables, build_file)) | |
808 output = new_output | |
545 else: | 809 else: |
546 matches = None | 810 output = ExpandVariables(output, phase, variables, build_file) |
547 | |
548 output = input_str | |
549 if matches: | |
550 # Reverse the list of matches so that replacements are done right-to-left. | |
551 # That ensures that earlier replacements won't mess up the string in a | |
552 # way that causes later calls to find the earlier substituted text instead | |
553 # of what's intended for replacement. | |
554 matches.reverse() | |
555 for match_group in matches: | |
556 match = match_group.groupdict() | |
557 gyp.DebugOutput(gyp.DEBUG_VARIABLES, | |
558 "Matches: %s" % repr(match)) | |
559 # match['replace'] is the substring to look for, match['type'] | |
560 # is the character code for the replacement type (< > <! >! <| >| <@ | |
561 # >@ <!@ >!@), match['is_array'] contains a '[' for command | |
562 # arrays, and match['content'] is the name of the variable (< >) | |
563 # or command to run (<! >!). match['command_string'] is an optional | |
564 # command string. Currently, only 'pymod_do_main' is supported. | |
565 | |
566 # run_command is true if a ! variant is used. | |
567 run_command = '!' in match['type'] | |
568 command_string = match['command_string'] | |
569 | |
570 # file_list is true if a | variant is used. | |
571 file_list = '|' in match['type'] | |
572 | |
573 # Capture these now so we can adjust them later. | |
574 replace_start = match_group.start('replace') | |
575 replace_end = match_group.end('replace') | |
576 | |
577 # Find the ending paren, and re-evaluate the contained string. | |
578 (c_start, c_end) = FindEnclosingBracketGroup(input_str[replace_start:]) | |
579 | |
580 # Adjust the replacement range to match the entire command | |
581 # found by FindEnclosingBracketGroup (since the variable_re | |
582 # probably doesn't match the entire command if it contained | |
583 # nested variables). | |
584 replace_end = replace_start + c_end | |
585 | |
586 # Find the "real" replacement, matching the appropriate closing | |
587 # paren, and adjust the replacement start and end. | |
588 replacement = input_str[replace_start:replace_end] | |
589 | |
590 # Figure out what the contents of the variable parens are. | |
591 contents_start = replace_start + c_start + 1 | |
592 contents_end = replace_end - 1 | |
593 contents = input_str[contents_start:contents_end] | |
594 | |
595 # Do filter substitution now for <|(). | |
596 # Admittedly, this is different than the evaluation order in other | |
597 # contexts. However, since filtration has no chance to run on <|(), | |
598 # this seems like the only obvious way to give them access to filters. | |
599 if file_list: | |
600 processed_variables = copy.deepcopy(variables) | |
601 ProcessListFiltersInDict(contents, processed_variables) | |
602 # Recurse to expand variables in the contents | |
603 contents = ExpandVariables(contents, phase, | |
604 processed_variables, build_file) | |
605 else: | |
606 # Recurse to expand variables in the contents | |
607 contents = ExpandVariables(contents, phase, variables, build_file) | |
608 | |
609 # Strip off leading/trailing whitespace so that variable matches are | |
610 # simpler below (and because they are rarely needed). | |
611 contents = contents.strip() | |
612 | |
613 # expand_to_list is true if an @ variant is used. In that case, | |
614 # the expansion should result in a list. Note that the caller | |
615 # is to be expecting a list in return, and not all callers do | |
616 # because not all are working in list context. Also, for list | |
617 # expansions, there can be no other text besides the variable | |
618 # expansion in the input string. | |
619 expand_to_list = '@' in match['type'] and input_str == replacement | |
620 | |
621 if run_command or file_list: | |
622 # Find the build file's directory, so commands can be run or file lists | |
623 # generated relative to it. | |
624 build_file_dir = os.path.dirname(build_file) | |
625 if build_file_dir == '': | |
626 # If build_file is just a leaf filename indicating a file in the | |
627 # current directory, build_file_dir might be an empty string. Set | |
628 # it to None to signal to subprocess.Popen that it should run the | |
629 # command in the current directory. | |
630 build_file_dir = None | |
631 | |
632 # Support <|(listfile.txt ...) which generates a file | |
633 # containing items from a gyp list, generated at gyp time. | |
634 # This works around actions/rules which have more inputs than will | |
635 # fit on the command line. | |
636 if file_list: | |
637 if type(contents) == list: | |
638 contents_list = contents | |
639 else: | |
640 contents_list = contents.split(' ') | |
641 replacement = contents_list[0] | |
642 path = replacement | |
643 if not os.path.isabs(path): | |
644 path = os.path.join(build_file_dir, path) | |
645 f = gyp.common.WriteOnDiff(path) | |
646 for i in contents_list[1:]: | |
647 f.write('%s\n' % i) | |
648 f.close() | |
649 | |
650 elif run_command: | |
651 use_shell = True | |
652 if match['is_array']: | |
653 contents = eval(contents) | |
654 use_shell = False | |
655 | |
656 # Check for a cached value to avoid executing commands, or generating | |
657 # file lists more than once. | |
658 # TODO(http://code.google.com/p/gyp/issues/detail?id=112): It is | |
659 # possible that the command being invoked depends on the current | |
660 # directory. For that case the syntax needs to be extended so that the | |
661 # directory is also used in cache_key (it becomes a tuple). | |
662 # TODO(http://code.google.com/p/gyp/issues/detail?id=111): In theory, | |
663 # someone could author a set of GYP files where each time the command | |
664 # is invoked it produces different output by design. When the need | |
665 # arises, the syntax should be extended to support no caching off a | |
666 # command's output so it is run every time. | |
667 cache_key = str(contents) | |
668 cached_value = cached_command_results.get(cache_key, None) | |
669 if cached_value is None: | |
670 gyp.DebugOutput(gyp.DEBUG_VARIABLES, | |
671 "Executing command '%s' in directory '%s'" % | |
672 (contents,build_file_dir)) | |
673 | |
674 replacement = '' | |
675 | |
676 if command_string == 'pymod_do_main': | |
677 # <!pymod_do_main(modulename param eters) loads |modulename| as a | |
678 # python module and then calls that module's DoMain() function, | |
679 # passing ["param", "eters"] as a single list argument. For modules | |
680 # that don't load quickly, this can be faster than | |
681 # <!(python modulename param eters). Do this in |build_file_dir|. | |
682 oldwd = os.getcwd() # Python doesn't like os.open('.'): no fchdir. | |
683 os.chdir(build_file_dir) | |
684 | |
685 parsed_contents = shlex.split(contents) | |
686 py_module = __import__(parsed_contents[0]) | |
687 replacement = str(py_module.DoMain(parsed_contents[1:])).rstrip() | |
688 | |
689 os.chdir(oldwd) | |
690 assert replacement != None | |
691 elif command_string: | |
692 raise Exception("Unknown command string '%s' in '%s'." % | |
693 (command_string, contents)) | |
694 else: | |
695 # Fix up command with platform specific workarounds. | |
696 contents = FixupPlatformCommand(contents) | |
697 p = subprocess.Popen(contents, shell=use_shell, | |
698 stdout=subprocess.PIPE, | |
699 stderr=subprocess.PIPE, | |
700 stdin=subprocess.PIPE, | |
701 cwd=build_file_dir) | |
702 | |
703 p_stdout, p_stderr = p.communicate('') | |
704 | |
705 if p.wait() != 0 or p_stderr: | |
706 sys.stderr.write(p_stderr) | |
707 # Simulate check_call behavior, since check_call only exists | |
708 # in python 2.5 and later. | |
709 raise Exception("Call to '%s' returned exit status %d." % | |
710 (contents, p.returncode)) | |
711 replacement = p_stdout.rstrip() | |
712 | |
713 cached_command_results[cache_key] = replacement | |
714 else: | |
715 gyp.DebugOutput(gyp.DEBUG_VARIABLES, | |
716 "Had cache value for command '%s' in directory '%s'" % | |
717 (contents,build_file_dir)) | |
718 replacement = cached_value | |
719 | |
720 else: | |
721 if not contents in variables: | |
722 if contents[-1] in ['!', '/']: | |
723 # In order to allow cross-compiles (nacl) to happen more naturally, | |
724 # we will allow references to >(sources/) etc. to resolve to | |
725 # and empty list if undefined. This allows actions to: | |
726 # 'action!': [ | |
727 # '>@(_sources!)', | |
728 # ], | |
729 # 'action/': [ | |
730 # '>@(_sources/)', | |
731 # ], | |
732 replacement = [] | |
733 else: | |
734 raise KeyError, 'Undefined variable ' + contents + \ | |
735 ' in ' + build_file | |
736 else: | |
737 replacement = variables[contents] | |
738 | |
739 if isinstance(replacement, list): | |
740 for item in replacement: | |
741 if (not contents[-1] == '/' and | |
742 not isinstance(item, str) and not isinstance(item, int)): | |
743 raise TypeError, 'Variable ' + contents + \ | |
744 ' must expand to a string or list of strings; ' + \ | |
745 'list contains a ' + \ | |
746 item.__class__.__name__ | |
747 # Run through the list and handle variable expansions in it. Since | |
748 # the list is guaranteed not to contain dicts, this won't do anything | |
749 # with conditions sections. | |
750 ProcessVariablesAndConditionsInList(replacement, phase, variables, | |
751 build_file) | |
752 elif not isinstance(replacement, str) and \ | |
753 not isinstance(replacement, int): | |
754 raise TypeError, 'Variable ' + contents + \ | |
755 ' must expand to a string or list of strings; ' + \ | |
756 'found a ' + replacement.__class__.__name__ | |
757 | |
758 if expand_to_list: | |
759 # Expanding in list context. It's guaranteed that there's only one | |
760 # replacement to do in |input_str| and that it's this replacement. See | |
761 # above. | |
762 if isinstance(replacement, list): | |
763 # If it's already a list, make a copy. | |
764 output = replacement[:] | |
765 else: | |
766 # Split it the same way sh would split arguments. | |
767 output = shlex.split(str(replacement)) | |
768 else: | |
769 # Expanding in string context. | |
770 encoded_replacement = '' | |
771 if isinstance(replacement, list): | |
772 # When expanding a list into string context, turn the list items | |
773 # into a string in a way that will work with a subprocess call. | |
774 # | |
775 # TODO(mark): This isn't completely correct. This should | |
776 # call a generator-provided function that observes the | |
777 # proper list-to-argument quoting rules on a specific | |
778 # platform instead of just calling the POSIX encoding | |
779 # routine. | |
780 encoded_replacement = gyp.common.EncodePOSIXShellList(replacement) | |
781 else: | |
782 encoded_replacement = replacement | |
783 | |
784 output = output[:replace_start] + str(encoded_replacement) + \ | |
785 output[replace_end:] | |
786 # Prepare for the next match iteration. | |
787 input_str = output | |
788 | |
789 # Look for more matches now that we've replaced some, to deal with | |
790 # expanding local variables (variables defined in the same | |
791 # variables block as this one). | |
792 gyp.DebugOutput(gyp.DEBUG_VARIABLES, | |
793 "Found output %s, recursing." % repr(output)) | |
794 if isinstance(output, list): | |
795 if output and isinstance(output[0], list): | |
796 # Leave output alone if it's a list of lists. | |
797 # We don't want such lists to be stringified. | |
798 pass | |
799 else: | |
800 new_output = [] | |
801 for item in output: | |
802 new_output.append( | |
803 ExpandVariables(item, phase, variables, build_file)) | |
804 output = new_output | |
805 else: | |
806 output = ExpandVariables(output, phase, variables, build_file) | |
807 | 811 |
808 # Convert all strings that are canonically-represented integers into integers. | 812 # Convert all strings that are canonically-represented integers into integers. |
809 if isinstance(output, list): | 813 if isinstance(output, list): |
810 for index in xrange(0, len(output)): | 814 for index in xrange(0, len(output)): |
811 if IsStrCanonicalInt(output[index]): | 815 if IsStrCanonicalInt(output[index]): |
812 output[index] = int(output[index]) | 816 output[index] = int(output[index]) |
813 elif IsStrCanonicalInt(output): | 817 elif IsStrCanonicalInt(output): |
814 output = int(output) | 818 output = int(output) |
815 | 819 |
816 return output | 820 return output |
(...skipping 1657 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2474 ValidateRunAsInTarget(target, target_dict, build_file) | 2478 ValidateRunAsInTarget(target, target_dict, build_file) |
2475 ValidateActionsInTarget(target, target_dict, build_file) | 2479 ValidateActionsInTarget(target, target_dict, build_file) |
2476 | 2480 |
2477 # Generators might not expect ints. Turn them into strs. | 2481 # Generators might not expect ints. Turn them into strs. |
2478 TurnIntIntoStrInDict(data) | 2482 TurnIntIntoStrInDict(data) |
2479 | 2483 |
2480 # TODO(mark): Return |data| for now because the generator needs a list of | 2484 # TODO(mark): Return |data| for now because the generator needs a list of |
2481 # build files that came in. In the future, maybe it should just accept | 2485 # build files that came in. In the future, maybe it should just accept |
2482 # a list, and not the whole data dict. | 2486 # a list, and not the whole data dict. |
2483 return [flat_list, targets, data] | 2487 return [flat_list, targets, data] |
OLD | NEW |