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 """Xcode project file generator. | 5 """Xcode project file generator. |
6 | 6 |
7 This module is both an Xcode project file generator and a documentation of the | 7 This module is both an Xcode project file generator and a documentation of the |
8 Xcode project file format. Knowledge of the project file format was gained | 8 Xcode project file format. Knowledge of the project file format was gained |
9 based on extensive experience with Xcode, and by making changes to projects in | 9 based on extensive experience with Xcode, and by making changes to projects in |
10 Xcode.app and observing the resultant changes in the associated project files. | 10 Xcode.app and observing the resultant changes in the associated project files. |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
147 # and other secure hashes. In 2.6, sha is deprecated. Import hashlib if | 147 # and other secure hashes. In 2.6, sha is deprecated. Import hashlib if |
148 # available, avoiding a deprecation warning under 2.6. Import sha otherwise, | 148 # available, avoiding a deprecation warning under 2.6. Import sha otherwise, |
149 # preserving 2.4 compatibility. | 149 # preserving 2.4 compatibility. |
150 try: | 150 try: |
151 import hashlib | 151 import hashlib |
152 _new_sha1 = hashlib.sha1 | 152 _new_sha1 = hashlib.sha1 |
153 except ImportError: | 153 except ImportError: |
154 import sha | 154 import sha |
155 _new_sha1 = sha.new | 155 _new_sha1 = sha.new |
156 | 156 |
| 157 try: |
| 158 basestring = basestring |
| 159 except NameError: |
| 160 basestring = str |
157 | 161 |
158 # See XCObject._EncodeString. This pattern is used to determine when a string | 162 # See XCObject._EncodeString. This pattern is used to determine when a string |
159 # can be printed unquoted. Strings that match this pattern may be printed | 163 # can be printed unquoted. Strings that match this pattern may be printed |
160 # unquoted. Strings that do not match must be quoted and may be further | 164 # unquoted. Strings that do not match must be quoted and may be further |
161 # transformed to be properly encoded. Note that this expression matches the | 165 # transformed to be properly encoded. Note that this expression matches the |
162 # characters listed with "+", for 1 or more occurrences: if a string is empty, | 166 # characters listed with "+", for 1 or more occurrences: if a string is empty, |
163 # it must not match this pattern, because it needs to be encoded as "". | 167 # it must not match this pattern, because it needs to be encoded as "". |
164 _unquoted = re.compile('^[A-Za-z0-9$./_]+$') | 168 _unquoted = re.compile('^[A-Za-z0-9$./_]+$') |
165 | 169 |
166 # Strings that match this pattern are quoted regardless of what _unquoted says. | 170 # Strings that match this pattern are quoted regardless of what _unquoted says. |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
307 """Make a copy of this object. | 311 """Make a copy of this object. |
308 | 312 |
309 The new object will have its own copy of lists and dicts. Any XCObject | 313 The new object will have its own copy of lists and dicts. Any XCObject |
310 objects owned by this object (marked "strong") will be copied in the | 314 objects owned by this object (marked "strong") will be copied in the |
311 new object, even those found in lists. If this object has any weak | 315 new object, even those found in lists. If this object has any weak |
312 references to other XCObjects, the same references are added to the new | 316 references to other XCObjects, the same references are added to the new |
313 object without making a copy. | 317 object without making a copy. |
314 """ | 318 """ |
315 | 319 |
316 that = self.__class__(id=self.id, parent=self.parent) | 320 that = self.__class__(id=self.id, parent=self.parent) |
317 for key, value in self._properties.iteritems(): | 321 for key, value in self._properties.items(): |
318 is_strong = self._schema[key][2] | 322 is_strong = self._schema[key][2] |
319 | 323 |
320 if isinstance(value, XCObject): | 324 if isinstance(value, XCObject): |
321 if is_strong: | 325 if is_strong: |
322 new_value = value.Copy() | 326 new_value = value.Copy() |
323 new_value.parent = that | 327 new_value.parent = that |
324 that._properties[key] = new_value | 328 that._properties[key] = new_value |
325 else: | 329 else: |
326 that._properties[key] = value | 330 that._properties[key] = value |
327 elif isinstance(value, str) or isinstance(value, unicode) or \ | 331 elif isinstance(value, basestring) or isinstance(value, int): |
328 isinstance(value, int): | |
329 that._properties[key] = value | 332 that._properties[key] = value |
330 elif isinstance(value, list): | 333 elif isinstance(value, list): |
331 if is_strong: | 334 if is_strong: |
332 # If is_strong is True, each element is an XCObject, so it's safe to | 335 # If is_strong is True, each element is an XCObject, so it's safe to |
333 # call Copy. | 336 # call Copy. |
334 that._properties[key] = [] | 337 that._properties[key] = [] |
335 for item in value: | 338 for item in value: |
336 new_item = item.Copy() | 339 new_item = item.Copy() |
337 new_item.parent = that | 340 new_item.parent = that |
338 that._properties[key].append(new_item) | 341 that._properties[key].append(new_item) |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
442 _HashUpdate(child_hash, hashable) | 445 _HashUpdate(child_hash, hashable) |
443 | 446 |
444 for child in self.Children(): | 447 for child in self.Children(): |
445 child.ComputeIDs(recursive, overwrite, child_hash) | 448 child.ComputeIDs(recursive, overwrite, child_hash) |
446 | 449 |
447 if overwrite or self.id is None: | 450 if overwrite or self.id is None: |
448 # Xcode IDs are only 96 bits (24 hex characters), but a SHA-1 digest is | 451 # Xcode IDs are only 96 bits (24 hex characters), but a SHA-1 digest is |
449 # is 160 bits. Instead of throwing out 64 bits of the digest, xor them | 452 # is 160 bits. Instead of throwing out 64 bits of the digest, xor them |
450 # into the portion that gets used. | 453 # into the portion that gets used. |
451 assert hash.digest_size % 4 == 0 | 454 assert hash.digest_size % 4 == 0 |
452 digest_int_count = hash.digest_size / 4 | 455 digest_int_count = hash.digest_size // 4 |
453 digest_ints = struct.unpack('>' + 'I' * digest_int_count, hash.digest()) | 456 digest_ints = struct.unpack('>' + 'I' * digest_int_count, hash.digest()) |
454 id_ints = [0, 0, 0] | 457 id_ints = [0, 0, 0] |
455 for index in xrange(0, digest_int_count): | 458 for index in range(0, digest_int_count): |
456 id_ints[index % 3] ^= digest_ints[index] | 459 id_ints[index % 3] ^= digest_ints[index] |
457 self.id = '%08X%08X%08X' % tuple(id_ints) | 460 self.id = '%08X%08X%08X' % tuple(id_ints) |
458 | 461 |
459 def EnsureNoIDCollisions(self): | 462 def EnsureNoIDCollisions(self): |
460 """Verifies that no two objects have the same ID. Checks all descendants. | 463 """Verifies that no two objects have the same ID. Checks all descendants. |
461 """ | 464 """ |
462 | 465 |
463 ids = {} | 466 ids = {} |
464 descendants = self.Descendants() | 467 descendants = self.Descendants() |
465 for descendant in descendants: | 468 for descendant in descendants: |
466 if descendant.id in ids: | 469 if descendant.id in ids: |
467 other = ids[descendant.id] | 470 other = ids[descendant.id] |
468 raise KeyError( | 471 raise KeyError( |
469 'Duplicate ID %s, objects "%s" and "%s" in "%s"' % \ | 472 'Duplicate ID %s, objects "%s" and "%s" in "%s"' % \ |
470 (descendant.id, str(descendant._properties), | 473 (descendant.id, str(descendant._properties), |
471 str(other._properties), self._properties['rootObject'].Name())) | 474 str(other._properties), self._properties['rootObject'].Name())) |
472 ids[descendant.id] = descendant | 475 ids[descendant.id] = descendant |
473 | 476 |
474 def Children(self): | 477 def Children(self): |
475 """Returns a list of all of this object's owned (strong) children.""" | 478 """Returns a list of all of this object's owned (strong) children.""" |
476 | 479 |
477 children = [] | 480 children = [] |
478 for property, attributes in self._schema.iteritems(): | 481 for property, attributes in self._schema.items(): |
479 (is_list, property_type, is_strong) = attributes[0:3] | 482 (is_list, property_type, is_strong) = attributes[0:3] |
480 if is_strong and property in self._properties: | 483 if is_strong and property in self._properties: |
481 if not is_list: | 484 if not is_list: |
482 children.append(self._properties[property]) | 485 children.append(self._properties[property]) |
483 else: | 486 else: |
484 children.extend(self._properties[property]) | 487 children.extend(self._properties[property]) |
485 return children | 488 return children |
486 | 489 |
487 def Descendants(self): | 490 def Descendants(self): |
488 """Returns a list of all of this object's descendants, including this | 491 """Returns a list of all of this object's descendants, including this |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
596 else: | 599 else: |
597 sep = '\n' | 600 sep = '\n' |
598 element_tabs = '\t' * (tabs + 1) | 601 element_tabs = '\t' * (tabs + 1) |
599 end_tabs = '\t' * tabs | 602 end_tabs = '\t' * tabs |
600 | 603 |
601 if isinstance(value, XCObject): | 604 if isinstance(value, XCObject): |
602 printable += value.id | 605 printable += value.id |
603 comment = value.Comment() | 606 comment = value.Comment() |
604 elif isinstance(value, str): | 607 elif isinstance(value, str): |
605 printable += self._EncodeString(value) | 608 printable += self._EncodeString(value) |
606 elif isinstance(value, unicode): | 609 # A python3 compatible way of saying isinstance(value, unicode). |
| 610 # basestring is str in python3 so this is equivalent to the above isinstance
. |
| 611 # Thus if it failed above it will fail here. |
| 612 # In python2 we test against str and unicode at this point. str has already |
| 613 # failed in the above isinstance so we test against unicode. |
| 614 elif isinstance(value, basestring): |
607 printable += self._EncodeString(value.encode('utf-8')) | 615 printable += self._EncodeString(value.encode('utf-8')) |
608 elif isinstance(value, int): | 616 elif isinstance(value, int): |
609 printable += str(value) | 617 printable += str(value) |
610 elif isinstance(value, list): | 618 elif isinstance(value, list): |
611 if flatten_list and len(value) <= 1: | 619 if flatten_list and len(value) <= 1: |
612 if len(value) == 0: | 620 if len(value) == 0: |
613 printable += self._EncodeString('') | 621 printable += self._EncodeString('') |
614 else: | 622 else: |
615 printable += self._EncodeString(value[0]) | 623 printable += self._EncodeString(value[0]) |
616 else: | 624 else: |
617 printable = '(' + sep | 625 printable = '(' + sep |
618 for item in value: | 626 for item in value: |
619 printable += element_tabs + \ | 627 printable += element_tabs + \ |
620 self._XCPrintableValue(tabs + 1, item, flatten_list) + \ | 628 self._XCPrintableValue(tabs + 1, item, flatten_list) + \ |
621 ',' + sep | 629 ',' + sep |
622 printable += end_tabs + ')' | 630 printable += end_tabs + ')' |
623 elif isinstance(value, dict): | 631 elif isinstance(value, dict): |
624 printable = '{' + sep | 632 printable = '{' + sep |
625 for item_key, item_value in sorted(value.iteritems()): | 633 for item_key, item_value in sorted(value.items()): |
626 printable += element_tabs + \ | 634 printable += element_tabs + \ |
627 self._XCPrintableValue(tabs + 1, item_key, flatten_list) + ' = ' + \ | 635 self._XCPrintableValue(tabs + 1, item_key, flatten_list) + ' = ' + \ |
628 self._XCPrintableValue(tabs + 1, item_value, flatten_list) + ';' + \ | 636 self._XCPrintableValue(tabs + 1, item_value, flatten_list) + ';' + \ |
629 sep | 637 sep |
630 printable += end_tabs + '}' | 638 printable += end_tabs + '}' |
631 else: | 639 else: |
632 raise TypeError("Can't make " + value.__class__.__name__ + ' printable') | 640 raise TypeError("Can't make " + value.__class__.__name__ + ' printable') |
633 | 641 |
634 if comment != None: | 642 if comment != None: |
635 printable += ' ' + self._EncodeComment(comment) | 643 printable += ' ' + self._EncodeComment(comment) |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
684 flatten_list = False | 692 flatten_list = False |
685 | 693 |
686 try: | 694 try: |
687 printable_key = self._XCPrintableValue(tabs, key, flatten_list) | 695 printable_key = self._XCPrintableValue(tabs, key, flatten_list) |
688 printable_value = self._XCPrintableValue(tabs, value_to_print, | 696 printable_value = self._XCPrintableValue(tabs, value_to_print, |
689 flatten_list) | 697 flatten_list) |
690 if strip_value_quotes and len(printable_value) > 1 and \ | 698 if strip_value_quotes and len(printable_value) > 1 and \ |
691 printable_value[0] == '"' and printable_value[-1] == '"': | 699 printable_value[0] == '"' and printable_value[-1] == '"': |
692 printable_value = printable_value[1:-1] | 700 printable_value = printable_value[1:-1] |
693 printable += printable_key + ' = ' + printable_value + ';' + after_kv | 701 printable += printable_key + ' = ' + printable_value + ';' + after_kv |
694 except TypeError, e: | 702 except TypeError as e: |
695 gyp.common.ExceptionAppend(e, | 703 gyp.common.ExceptionAppend(e, |
696 'while printing key "%s"' % key) | 704 'while printing key "%s"' % key) |
697 raise | 705 raise |
698 | 706 |
699 self._XCPrint(file, 0, printable) | 707 self._XCPrint(file, 0, printable) |
700 | 708 |
701 def Print(self, file=sys.stdout): | 709 def Print(self, file=sys.stdout): |
702 """Prints a reprentation of this object to file, adhering to Xcode output | 710 """Prints a reprentation of this object to file, adhering to Xcode output |
703 formatting. | 711 formatting. |
704 """ | 712 """ |
(...skipping 18 matching lines...) Expand all Loading... |
723 | 731 |
724 # Start the object. For example, '\t\tPBXProject = {\n'. | 732 # Start the object. For example, '\t\tPBXProject = {\n'. |
725 self._XCPrint(file, 2, self._XCPrintableValue(2, self) + ' = {' + sep) | 733 self._XCPrint(file, 2, self._XCPrintableValue(2, self) + ' = {' + sep) |
726 | 734 |
727 # "isa" isn't in the _properties dictionary, it's an intrinsic property | 735 # "isa" isn't in the _properties dictionary, it's an intrinsic property |
728 # of the class which the object belongs to. Xcode always outputs "isa" | 736 # of the class which the object belongs to. Xcode always outputs "isa" |
729 # as the first element of an object dictionary. | 737 # as the first element of an object dictionary. |
730 self._XCKVPrint(file, 3, 'isa', self.__class__.__name__) | 738 self._XCKVPrint(file, 3, 'isa', self.__class__.__name__) |
731 | 739 |
732 # The remaining elements of an object dictionary are sorted alphabetically. | 740 # The remaining elements of an object dictionary are sorted alphabetically. |
733 for property, value in sorted(self._properties.iteritems()): | 741 for property, value in sorted(self._properties.items()): |
734 self._XCKVPrint(file, 3, property, value) | 742 self._XCKVPrint(file, 3, property, value) |
735 | 743 |
736 # End the object. | 744 # End the object. |
737 self._XCPrint(file, end_tabs, '};\n') | 745 self._XCPrint(file, end_tabs, '};\n') |
738 | 746 |
739 def UpdateProperties(self, properties, do_copy=False): | 747 def UpdateProperties(self, properties, do_copy=False): |
740 """Merge the supplied properties into the _properties dictionary. | 748 """Merge the supplied properties into the _properties dictionary. |
741 | 749 |
742 The input properties must adhere to the class schema or a KeyError or | 750 The input properties must adhere to the class schema or a KeyError or |
743 TypeError exception will be raised. If adding an object of an XCObject | 751 TypeError exception will be raised. If adding an object of an XCObject |
744 subclass and the schema indicates a strong relationship, the object's | 752 subclass and the schema indicates a strong relationship, the object's |
745 parent will be set to this object. | 753 parent will be set to this object. |
746 | 754 |
747 If do_copy is True, then lists, dicts, strong-owned XCObjects, and | 755 If do_copy is True, then lists, dicts, strong-owned XCObjects, and |
748 strong-owned XCObjects in lists will be copied instead of having their | 756 strong-owned XCObjects in lists will be copied instead of having their |
749 references added. | 757 references added. |
750 """ | 758 """ |
751 | 759 |
752 if properties is None: | 760 if properties is None: |
753 return | 761 return |
754 | 762 |
755 for property, value in properties.iteritems(): | 763 for property, value in properties.items(): |
756 # Make sure the property is in the schema. | 764 # Make sure the property is in the schema. |
757 if not property in self._schema: | 765 if not property in self._schema: |
758 raise KeyError(property + ' not in ' + self.__class__.__name__) | 766 raise KeyError(property + ' not in ' + self.__class__.__name__) |
759 | 767 |
760 # Make sure the property conforms to the schema. | 768 # Make sure the property conforms to the schema. |
761 (is_list, property_type, is_strong) = self._schema[property][0:3] | 769 (is_list, property_type, is_strong) = self._schema[property][0:3] |
762 if is_list: | 770 if is_list: |
763 if value.__class__ != list: | 771 if value.__class__ != list: |
764 raise TypeError( | 772 raise TypeError( |
765 property + ' of ' + self.__class__.__name__ + \ | 773 property + ' of ' + self.__class__.__name__ + \ |
766 ' must be list, not ' + value.__class__.__name__) | 774 ' must be list, not ' + value.__class__.__name__) |
767 for item in value: | 775 for item in value: |
768 if not isinstance(item, property_type) and \ | 776 if not isinstance(item, property_type) and \ |
769 not (item.__class__ == unicode and property_type == str): | 777 not (isinstance(item, basestring) and property_type == str): |
770 # Accept unicode where str is specified. str is treated as | 778 # Accept unicode where str is specified. str is treated as |
771 # UTF-8-encoded. | 779 # UTF-8-encoded. |
772 raise TypeError( | 780 raise TypeError( |
773 'item of ' + property + ' of ' + self.__class__.__name__ + \ | 781 'item of ' + property + ' of ' + self.__class__.__name__ + \ |
774 ' must be ' + property_type.__name__ + ', not ' + \ | 782 ' must be ' + property_type.__name__ + ', not ' + \ |
775 item.__class__.__name__) | 783 item.__class__.__name__) |
776 elif not isinstance(value, property_type) and \ | 784 elif not isinstance(value, property_type) and \ |
777 not (value.__class__ == unicode and property_type == str): | 785 not (isinstance(value, basestring) and property_type == str): |
778 # Accept unicode where str is specified. str is treated as | 786 # Accept unicode where str is specified. str is treated as |
779 # UTF-8-encoded. | 787 # UTF-8-encoded. |
780 raise TypeError( | 788 raise TypeError( |
781 property + ' of ' + self.__class__.__name__ + ' must be ' + \ | 789 property + ' of ' + self.__class__.__name__ + ' must be ' + \ |
782 property_type.__name__ + ', not ' + value.__class__.__name__) | 790 property_type.__name__ + ', not ' + value.__class__.__name__) |
783 | 791 |
784 # Checks passed, perform the assignment. | 792 # Checks passed, perform the assignment. |
785 if do_copy: | 793 if do_copy: |
786 if isinstance(value, XCObject): | 794 if isinstance(value, XCObject): |
787 if is_strong: | 795 if is_strong: |
788 self._properties[property] = value.Copy() | 796 self._properties[property] = value.Copy() |
789 else: | 797 else: |
790 self._properties[property] = value | 798 self._properties[property] = value |
791 elif isinstance(value, str) or isinstance(value, unicode) or \ | 799 elif isinstance(value, basestring) or isinstance(value, int): |
792 isinstance(value, int): | |
793 self._properties[property] = value | 800 self._properties[property] = value |
794 elif isinstance(value, list): | 801 elif isinstance(value, list): |
795 if is_strong: | 802 if is_strong: |
796 # If is_strong is True, each element is an XCObject, so it's safe | 803 # If is_strong is True, each element is an XCObject, so it's safe |
797 # to call Copy. | 804 # to call Copy. |
798 self._properties[property] = [] | 805 self._properties[property] = [] |
799 for item in value: | 806 for item in value: |
800 self._properties[property].append(item.Copy()) | 807 self._properties[property].append(item.Copy()) |
801 else: | 808 else: |
802 self._properties[property] = value[:] | 809 self._properties[property] = value[:] |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
858 # Store the item. | 865 # Store the item. |
859 self._properties[key].append(value) | 866 self._properties[key].append(value) |
860 | 867 |
861 def VerifyHasRequiredProperties(self): | 868 def VerifyHasRequiredProperties(self): |
862 """Ensure that all properties identified as required by the schema are | 869 """Ensure that all properties identified as required by the schema are |
863 set. | 870 set. |
864 """ | 871 """ |
865 | 872 |
866 # TODO(mark): A stronger verification mechanism is needed. Some | 873 # TODO(mark): A stronger verification mechanism is needed. Some |
867 # subclasses need to perform validation beyond what the schema can enforce. | 874 # subclasses need to perform validation beyond what the schema can enforce. |
868 for property, attributes in self._schema.iteritems(): | 875 for property, attributes in self._schema.items(): |
869 (is_list, property_type, is_strong, is_required) = attributes[0:4] | 876 (is_list, property_type, is_strong, is_required) = attributes[0:4] |
870 if is_required and not property in self._properties: | 877 if is_required and not property in self._properties: |
871 raise KeyError(self.__class__.__name__ + ' requires ' + property) | 878 raise KeyError(self.__class__.__name__ + ' requires ' + property) |
872 | 879 |
873 def _SetDefaultsFromSchema(self): | 880 def _SetDefaultsFromSchema(self): |
874 """Assign object default values according to the schema. This will not | 881 """Assign object default values according to the schema. This will not |
875 overwrite properties that have already been set.""" | 882 overwrite properties that have already been set.""" |
876 | 883 |
877 defaults = {} | 884 defaults = {} |
878 for property, attributes in self._schema.iteritems(): | 885 for property, attributes in self._schema.items(): |
879 (is_list, property_type, is_strong, is_required) = attributes[0:4] | 886 (is_list, property_type, is_strong, is_required) = attributes[0:4] |
880 if is_required and len(attributes) >= 5 and \ | 887 if is_required and len(attributes) >= 5 and \ |
881 not property in self._properties: | 888 not property in self._properties: |
882 default = attributes[4] | 889 default = attributes[4] |
883 | 890 |
884 defaults[property] = default | 891 defaults[property] = default |
885 | 892 |
886 if len(defaults) > 0: | 893 if len(defaults) > 0: |
887 # Use do_copy=True so that each new object gets its own copy of strong | 894 # Use do_copy=True so that each new object gets its own copy of strong |
888 # objects, lists, and dicts. | 895 # objects, lists, and dicts. |
(...skipping 530 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1419 # obtain additional hashables specific to this XCFileLikeElement. Don't | 1426 # obtain additional hashables specific to this XCFileLikeElement. Don't |
1420 # just use this object's hashables, they're not specific and unique enough | 1427 # just use this object's hashables, they're not specific and unique enough |
1421 # on their own (without access to the parent hashables.) Instead, provide | 1428 # on their own (without access to the parent hashables.) Instead, provide |
1422 # hashables that identify this object by path by getting its hashables as | 1429 # hashables that identify this object by path by getting its hashables as |
1423 # well as the hashables of ancestor XCHierarchicalElement objects. | 1430 # well as the hashables of ancestor XCHierarchicalElement objects. |
1424 | 1431 |
1425 hashables = [] | 1432 hashables = [] |
1426 xche = self | 1433 xche = self |
1427 while xche != None and isinstance(xche, XCHierarchicalElement): | 1434 while xche != None and isinstance(xche, XCHierarchicalElement): |
1428 xche_hashables = xche.Hashables() | 1435 xche_hashables = xche.Hashables() |
1429 for index in xrange(0, len(xche_hashables)): | 1436 for index, xche_hashable in enumerate(xche_hashables): |
1430 hashables.insert(index, xche_hashables[index]) | 1437 hashables.insert(index, xche_hashable) |
1431 xche = xche.parent | 1438 xche = xche.parent |
1432 return hashables | 1439 return hashables |
1433 | 1440 |
1434 | 1441 |
1435 class XCContainerPortal(XCObject): | 1442 class XCContainerPortal(XCObject): |
1436 # Abstract base for objects that can be used as the containerPortal property | 1443 # Abstract base for objects that can be used as the containerPortal property |
1437 # of PBXContainerItemProxy. | 1444 # of PBXContainerItemProxy. |
1438 pass | 1445 pass |
1439 | 1446 |
1440 | 1447 |
(...skipping 953 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2394 return the_phase | 2401 return the_phase |
2395 | 2402 |
2396 def HeadersPhase(self): | 2403 def HeadersPhase(self): |
2397 headers_phase = self.GetBuildPhaseByType(PBXHeadersBuildPhase) | 2404 headers_phase = self.GetBuildPhaseByType(PBXHeadersBuildPhase) |
2398 if headers_phase is None: | 2405 if headers_phase is None: |
2399 headers_phase = PBXHeadersBuildPhase() | 2406 headers_phase = PBXHeadersBuildPhase() |
2400 | 2407 |
2401 # The headers phase should come before the resources, sources, and | 2408 # The headers phase should come before the resources, sources, and |
2402 # frameworks phases, if any. | 2409 # frameworks phases, if any. |
2403 insert_at = len(self._properties['buildPhases']) | 2410 insert_at = len(self._properties['buildPhases']) |
2404 for index in xrange(0, len(self._properties['buildPhases'])): | 2411 for index, phase in enumerate(self._properties['buildPhases']): |
2405 phase = self._properties['buildPhases'][index] | |
2406 if isinstance(phase, PBXResourcesBuildPhase) or \ | 2412 if isinstance(phase, PBXResourcesBuildPhase) or \ |
2407 isinstance(phase, PBXSourcesBuildPhase) or \ | 2413 isinstance(phase, PBXSourcesBuildPhase) or \ |
2408 isinstance(phase, PBXFrameworksBuildPhase): | 2414 isinstance(phase, PBXFrameworksBuildPhase): |
2409 insert_at = index | 2415 insert_at = index |
2410 break | 2416 break |
2411 | 2417 |
2412 self._properties['buildPhases'].insert(insert_at, headers_phase) | 2418 self._properties['buildPhases'].insert(insert_at, headers_phase) |
2413 headers_phase.parent = self | 2419 headers_phase.parent = self |
2414 | 2420 |
2415 return headers_phase | 2421 return headers_phase |
2416 | 2422 |
2417 def ResourcesPhase(self): | 2423 def ResourcesPhase(self): |
2418 resources_phase = self.GetBuildPhaseByType(PBXResourcesBuildPhase) | 2424 resources_phase = self.GetBuildPhaseByType(PBXResourcesBuildPhase) |
2419 if resources_phase is None: | 2425 if resources_phase is None: |
2420 resources_phase = PBXResourcesBuildPhase() | 2426 resources_phase = PBXResourcesBuildPhase() |
2421 | 2427 |
2422 # The resources phase should come before the sources and frameworks | 2428 # The resources phase should come before the sources and frameworks |
2423 # phases, if any. | 2429 # phases, if any. |
2424 insert_at = len(self._properties['buildPhases']) | 2430 insert_at = len(self._properties['buildPhases']) |
2425 for index in xrange(0, len(self._properties['buildPhases'])): | 2431 for index, phase in enumerate(self._properties['buildPhases']): |
2426 phase = self._properties['buildPhases'][index] | |
2427 if isinstance(phase, PBXSourcesBuildPhase) or \ | 2432 if isinstance(phase, PBXSourcesBuildPhase) or \ |
2428 isinstance(phase, PBXFrameworksBuildPhase): | 2433 isinstance(phase, PBXFrameworksBuildPhase): |
2429 insert_at = index | 2434 insert_at = index |
2430 break | 2435 break |
2431 | 2436 |
2432 self._properties['buildPhases'].insert(insert_at, resources_phase) | 2437 self._properties['buildPhases'].insert(insert_at, resources_phase) |
2433 resources_phase.parent = self | 2438 resources_phase.parent = self |
2434 | 2439 |
2435 return resources_phase | 2440 return resources_phase |
2436 | 2441 |
(...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2837 # present in the remote_products list. | 2842 # present in the remote_products list. |
2838 x_remote = x._properties['remoteRef']._properties['remoteGlobalIDString'] | 2843 x_remote = x._properties['remoteRef']._properties['remoteGlobalIDString'] |
2839 y_remote = y._properties['remoteRef']._properties['remoteGlobalIDString'] | 2844 y_remote = y._properties['remoteRef']._properties['remoteGlobalIDString'] |
2840 x_index = remote_products.index(x_remote) | 2845 x_index = remote_products.index(x_remote) |
2841 y_index = remote_products.index(y_remote) | 2846 y_index = remote_products.index(y_remote) |
2842 | 2847 |
2843 # Use the order of each remote PBXFileReference in remote_products to | 2848 # Use the order of each remote PBXFileReference in remote_products to |
2844 # determine the sort order. | 2849 # determine the sort order. |
2845 return cmp(x_index, y_index) | 2850 return cmp(x_index, y_index) |
2846 | 2851 |
2847 for other_pbxproject, ref_dict in self._other_pbxprojects.iteritems(): | 2852 for other_pbxproject, ref_dict in self._other_pbxprojects.items(): |
2848 # Build up a list of products in the remote project file, ordered the | 2853 # Build up a list of products in the remote project file, ordered the |
2849 # same as the targets that produce them. | 2854 # same as the targets that produce them. |
2850 remote_products = [] | 2855 remote_products = [] |
2851 for target in other_pbxproject._properties['targets']: | 2856 for target in other_pbxproject._properties['targets']: |
2852 if not isinstance(target, PBXNativeTarget): | 2857 if not isinstance(target, PBXNativeTarget): |
2853 continue | 2858 continue |
2854 remote_products.append(target._properties['productReference']) | 2859 remote_products.append(target._properties['productReference']) |
2855 | 2860 |
2856 # Sort the PBXReferenceProxy children according to the list of remote | 2861 # Sort the PBXReferenceProxy children according to the list of remote |
2857 # products. | 2862 # products. |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2918 self._XCPrint(file, 0, '/* Begin ' + class_name + ' section */\n') | 2923 self._XCPrint(file, 0, '/* Begin ' + class_name + ' section */\n') |
2919 for object in sorted(objects_by_class[class_name], | 2924 for object in sorted(objects_by_class[class_name], |
2920 cmp=lambda x, y: cmp(x.id, y.id)): | 2925 cmp=lambda x, y: cmp(x.id, y.id)): |
2921 object.Print(file) | 2926 object.Print(file) |
2922 self._XCPrint(file, 0, '/* End ' + class_name + ' section */\n') | 2927 self._XCPrint(file, 0, '/* End ' + class_name + ' section */\n') |
2923 | 2928 |
2924 if self._should_print_single_line: | 2929 if self._should_print_single_line: |
2925 self._XCPrint(file, 0, '}; ') | 2930 self._XCPrint(file, 0, '}; ') |
2926 else: | 2931 else: |
2927 self._XCPrint(file, 1, '};\n') | 2932 self._XCPrint(file, 1, '};\n') |
OLD | NEW |