[BioPython] PDB parser

Thomas Hamelryck thamelry@vub.ac.be
Tue, 23 Apr 2002 14:57:02 +0200


--------------Boundary-00=_1NU0N6IAKIYE2PZXXBUG
Content-Type: text/plain;
  charset="iso-8859-1"
Content-Transfer-Encoding: 8bit


Hi Catherine,

I've attached a PDBParser class that you can probably use. An example of its 
use can be found in the file test.py.

PDBParser uses an aggregated StructureBuilder class, which you are supposed 
to implement for your specific purpose (it's easy). This class needs to have 
a set of standard methods (init_atom, init_residue, init_chain, 
init_model,...) that are called each time a new atom, residue, chain, model, 
etc. is encountered. 

Cheers,
 
---
Thomas Hamelryck      Vrije Universiteit Brussel (VUB)
Intitute for Molecular Biology            ULTR Department
Paardenstraat 65    1640 Sint-Gensius-Rode, Belgium
                http://ultr.vub.ac.be/~thomas
--------------Boundary-00=_1NU0N6IAKIYE2PZXXBUG
Content-Type: text/english;
  name="PDBParser.py"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="PDBParser.py"

IiIiClBEQlBhcnNlcjogcGFyc2VyIGZvciBQREIgZmlsZXMKQ29weXJpZ2h0IChDKSAyMDAyIFRo
b21hcyBIYW1lbHJ5Y2sKIApUaGlzIHByb2dyYW0gaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiBy
ZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeQppdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdO
VSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieQp0aGUgRnJlZSBTb2Z0d2Fy
ZSBGb3VuZGF0aW9uOyBlaXRoZXIgdmVyc2lvbiAyIG9mIHRoZSBMaWNlbnNlLCBvcgooYXQgeW91
ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLgogClRoaXMgcHJvZ3JhbSBpcyBkaXN0cmlidXRl
ZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLApidXQgV0lUSE9VVCBBTlkgV0FS
UkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZgpNRVJDSEFOVEFCSUxJ
VFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlCkdOVSBHZW5l
cmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuCiAKWW91IHNob3VsZCBoYXZlIHJl
Y2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UKYWxvbmcgd2l0
aCB0aGlzIHByb2dyYW07IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmUKRm91bmRh
dGlvbiwgSW5jLiwgNTkgVGVtcGxlIFBsYWNlLCBTdWl0ZSAzMzAsIEJvc3RvbiwgTUEgIDAyMTEx
LTEzMDcgIFVTQQoiIiIKCiMgUHl0aG9uIHN0dWZmCmltcG9ydCBzdHJpbmcKZnJvbSBOdW1lcmlj
IGltcG9ydCBhcnJheSwgRmxvYXQwCgojIFJlbWFyazogaWYgdGhlIFBEQiBzcGVjIHNheXMgIndo
YXRldmVyPUNPTFVNTlMgMTgtMjAiCiMgdGhpcyBjb3JyZXNwb25kcyB0byAid2hhdGV2ZXI9bGlu
ZVsxNzoyMF0iIGluIHRoaXMgZmlsZQoKY2xhc3MgUERCUGFyc2VyOgoJZGVmIF9faW5pdF9fKHNl
bGYsIHN0cnVjdHVyZV9idWlsZGVyKToKCQlzZWxmLnN0cnVjdHVyZV9idWlsZGVyPXN0cnVjdHVy
ZV9idWlsZGVyCgoJIyBQdWJsaWMgbWV0aG9kcwoKCWRlZiBnZXQoc2VsZiwgaWQsIGZpbGVuYW1l
KToKCQkjIE1ha2UgYSBTdHJ1Y3R1cmVCdWlsZGVyIGluc3RhbmNlIChwYXNzIGlkIG9mIHN0cnVj
dHVyZSBhcyBwYXJhbWV0ZXIpCgkJc2VsZi5zdHJ1Y3R1cmVfYnVpbGRlci5zZXRfaWQoaWQpCgkJ
ZmlsZT1vcGVuKGZpbGVuYW1lKQoJCXNlbGYuX3BhcnNlKGZpbGUucmVhZGxpbmVzKCkpCgkJZmls
ZS5jbG9zZSgpCgkJIyBSZXR1cm4gdGhlIFN0cnVjdHVyZSBpbnN0YW5jZQoJCXJldHVybiBzZWxm
LnN0cnVjdHVyZV9idWlsZGVyLmdldCgpCgoJIyBQcml2YXRlIG1ldGhvZHMKCQoJZGVmIF9wYXJz
ZShzZWxmLCBidWZmZXIpOgoJCSMgUGFyc2UgdGhlIGhlYWRlcjsgcmV0dXJuIHRoZSByZXN0IG9m
IHRoZSBmaWxlCgkJbmV3QnVmZmVyPXNlbGYuX3BhcnNlSGVhZGVyKGJ1ZmZlcikKCQkjIFBhcnNl
IHRoZSBhdG9taWMgZGF0YTsgcmV0dXJuIHRoZSByZXN0IG9mIHRoZSBmaWxlCgkJbmV3QnVmZmVy
PXNlbGYuX3BhcnNlQ29vcmRpbmF0ZXMobmV3QnVmZmVyKQoJCSMgUGFyc2UgdGhlIHRyYWlsZXIg
KENPTkVDVCByZWNvcmRzIGV0Yy4pCgkJc2VsZi5fcGFyc2VUcmFpbGVyKG5ld0J1ZmZlcikKCQoJ
ZGVmIF9wYXJzZUhlYWRlcihzZWxmLCBidWZmZXIpOgoJCWF0b2Y9c3RyaW5nLmF0b2YKCQlhdG9p
PXN0cmluZy5hdG9pCgkJbGluZUNvdW50ZXI9MAoJCWZvciBpIGluIHJhbmdlKDAsIGxlbihidWZm
ZXIpKToKCQkJbGluZT1idWZmZXJbaV0KCQkJcmVjb3JkVHlwZT1saW5lWzA6Nl0gCgkJCWlmKHJl
Y29yZFR5cGU9PSdBVE9NICAnIG9yIHJlY29yZFR5cGU9PSdIRVRBVE0nIG9yIHJlY29yZFR5cGU9
PSdNT0RFTCAnKToKCQkJCWJyZWFrCgkJCWVsaWYocmVjb3JkVHlwZT09J0hFQURFUicpOgoJCQkJ
c2VsZi5zdHJ1Y3R1cmVfYnVpbGRlci5zZXRfcGRiX2lkZW50KHN0cmluZy5sb3dlcihsaW5lWzYy
OjY2XSkpCgkJCWVsaWYocmVjb3JkVHlwZT09J0NSWVNUMScpOgoJCQkJIyBnZXQgdGhlIHN5bW1l
dHJ5ICYgdGhlIGNlbGwgcGFyYW1ldGVycwoJCQkJYT1hdG9mKGxpbmVbNjoxNV0pCgkJCQliPWF0
b2YobGluZVsxNToyNF0pCgkJCQljPWF0b2YobGluZVsyNDozM10pCgkJCQlhbHBoYT1hdG9mKGxp
bmVbMzM6NDBdKQoJCQkJYmV0YT1hdG9mKGxpbmVbNDA6NDddKQoJCQkJZ2FtbWE9YXRvZihsaW5l
WzQ3OjU0XSkKCQkJCXNwYWNlZ3JvdXA9bGluZVs1NTo2Nl0KCQkJCSMgbWFrZSBudW1weSBhcnJh
eSBjb250YWluaW5nIGNlbGwgcGFyYW1ldGVycwoJCQkJY2VsbD1hcnJheSgoYSwgYiwgYywgYWxw
aGEsIGJldGEsIGdhbW1hKSwgRmxvYXQwKQoJCQkJc2VsZi5zdHJ1Y3R1cmVfYnVpbGRlci5zZXRf
c3ltbWV0cnkoc3BhY2Vncm91cCwgY2VsbCkKCQkJbGluZUNvdW50ZXI9bGluZUNvdW50ZXIrMQoJ
CXNlbGYuaGVhZGVyPWJ1ZmZlclswOmxpbmVDb3VudGVyXQoJCSMgUmV0dXJuIHRoZSByZXN0IG9m
IHRoZSBmaWxlIGZvciBmdXJ0aGVyIHByb2Nlc3NpbmcKCQlzZWxmLl9saW5lX2NvdW50ZXI9bGlu
ZUNvdW50ZXIKCQlyZXR1cm4gYnVmZmVyW2xpbmVDb3VudGVyOl0KCQoJZGVmIF9wYXJzZVRyYWls
ZXIoc2VsZiwgYnVmZmVyKToKCQlzZWxmLnRyYWlsZXI9YnVmZmVyCgkKCWRlZiBfcGFyc2VDb29y
ZGluYXRlcyhzZWxmLCBidWZmZXIpOgoJCWxpbmVfY291bnRlcj0wCgkJc3RydWN0dXJlX2J1aWxk
ZXI9c2VsZi5zdHJ1Y3R1cmVfYnVpbGRlcgoJCWN1cnJlbnRfbW9kZWxfaWQ9MAoJCXN0cnVjdHVy
ZV9idWlsZGVyLmluaXRfbW9kZWwoY3VycmVudF9tb2RlbF9pZCkKCQljdXJyZW50X2NoYWluX2lk
PU5vbmUKCQljdXJyZW50X3Jlc2lkdWVfaWQ9Tm9uZQoJCSMgU29tZSBsb2NhbCBjb3BpZXMgZm9y
IHNwZWVkCgkJYXRvaT1zdHJpbmcuYXRvaQoJCWF0b2Y9c3RyaW5nLmF0b2YKCQlzcGxpdD1zdHJp
bmcuc3BsaXQKCQlmb3IgaSBpbiByYW5nZSgwLCBsZW4oYnVmZmVyKSk6CgkJCWxpbmU9YnVmZmVy
W2ldCgkJCXJlY29yZFR5cGU9bGluZVswOjZdCgkJCWlmKHJlY29yZFR5cGU9PSdBVE9NICAnIG9y
IHJlY29yZFR5cGU9PSdIRVRBVE0nKToKCQkJCSMgZ2V0IHJpZCBvZiB3aGl0ZXNwYWNlIGluIGF0
b20gbmFtZXMKCQkJCWVsZW1lbnQ9bGluZVsxMjoxNl0KCQkJCXRyeToKCQkJCQluYW1lPXNwbGl0
KGxpbmVbMTI6MTZdKVswXQoJCQkJZXhjZXB0OgoJCQkJCSMgbWlzc2luZyBhdG9tIG5hbWUKCQkJ
CQluYW1lPSJYWCIKCQkJCWFsdGxvYz1saW5lWzE2OjE3XQoJCQkJcmVzbmFtZT1saW5lWzE3OjIw
XQoJCQkJY2hhaW5pZD1saW5lWzIxOjIyXQoJCQkJc2ltcGxlX3Jlc3NlcT1zcGxpdChsaW5lWzIy
OjI2XSlbMF0JIyBrZWVwIGFzIHN0cmluZyEKCQkJCXJlc3NlcT1zaW1wbGVfcmVzc2VxCgkJCQlp
Y29kZT1saW5lWzI2OjI3XQkJCSMgaW5zZXJ0aW9uIGNvZGUKCQkJCWlmIGljb2RlIT0iICI6CgkJ
CQkJcmVzc2VxPXJlc3NlcSsiaSIraWNvZGUKCQkJCWlmIHJlY29yZFR5cGU9PSdIRVRBVE0nOgoJ
CQkJCWZpZWxkX2ZsYWc9IkgiCQkJCQoJCQkJZWxzZToKCQkJCQlmaWVsZF9mbGFnPSIgIgoJCQkJ
eD1hdG9mKGxpbmVbMzA6MzhdKSAKCQkJCXk9YXRvZihsaW5lWzM4OjQ2XSkgCgkJCQl6PWF0b2Yo
bGluZVs0Njo1NF0pCgkJCQljb29yZD1hcnJheSgoeCwgeSwgeiksIEZsb2F0MCkKCQkJCW9jY3Vw
YW5jeT1hdG9mKGxpbmVbNTQ6NjBdKQoJCQkJdGVtcGZhY3Rvcj1hdG9mKGxpbmVbNjA6NjZdKQoJ
CQkJc2VnaWQ9bGluZVs3Mjo3Nl0KCQkJCWlmIGN1cnJlbnRfY2hhaW5faWQhPWNoYWluaWQ6CgkJ
CQkJY3VycmVudF9jaGFpbl9pZD1jaGFpbmlkCgkJCQkJc3RydWN0dXJlX2J1aWxkZXIuaW5pdF9j
aGFpbihjdXJyZW50X2NoYWluX2lkKQoJCQkJCWN1cnJlbnRfcmVzaWR1ZV9pZD1yZXNzZXEKCQkJ
CQlzdHJ1Y3R1cmVfYnVpbGRlci5pbml0X3Jlc2lkdWUocmVzbmFtZSwgZmllbGRfZmxhZywgYXRv
aShzaW1wbGVfcmVzc2VxKSwgaWNvZGUpCgkJCQllbGlmIGN1cnJlbnRfcmVzaWR1ZV9pZCE9cmVz
c2VxOgoJCQkJCWN1cnJlbnRfcmVzaWR1ZV9pZD1yZXNzZXEKCQkJCQkjIGdldCByaWQgb2Ygd2hp
dGVzcGFjZSBpbiByZXNpZHVlIG5hbWVzCgkJCQkJbm9ibGFua19yZXNuYW1lPXNwbGl0KHJlc25h
bWUpWzBdCgkJCQkJc3RydWN0dXJlX2J1aWxkZXIuaW5pdF9yZXNpZHVlKG5vYmxhbmtfcmVzbmFt
ZSwgZmllbGRfZmxhZywgYXRvaShzaW1wbGVfcmVzc2VxKSwgaWNvZGUpCgkJCQkjIE5PVyBBREQg
VEhFIEFUT00JCQoJCQkJc3RydWN0dXJlX2J1aWxkZXIuaW5pdF9hdG9tKG5hbWUsIGNvb3JkLCB0
ZW1wZmFjdG9yLCBvY2N1cGFuY3ksIGFsdGxvYywgZWxlbWVudCkKCQkJZWxpZihyZWNvcmRUeXBl
PT0nRU5ETURMJyk6CgkJCQljdXJyZW50X21vZGVsX2lkPWN1cnJlbnRfbW9kZWxfaWQrMQoJCQkJ
c3RydWN0dXJlX2J1aWxkZXIuaW5pdF9tb2RlbChjdXJyZW50X21vZGVsX2lkKQoJCQkJY3VycmVu
dF9jaGFpbl9pZD1Ob25lCgkJCQljdXJyZW50X3Jlc2lkdWVfaWQ9Tm9uZQoJCQllbGlmKHJlY29y
ZFR5cGU9PSdURVIgICAnKToKCQkJCSMgdGhpcyBpcyBib2xkbHkgaWdub3JlZDsgY29ubmVjdGl2
aXR5IGlzIGJ1aWxkIGxhdGVyIGJhc2VkIG9uIAoJCQkJIyBhIGRpc3RhbmNlIGNyaXRlcml1bSwg
c28gVEVSIHNob3VsZCBub3QgYmUgbmVjZXNzYXJ5CgkJCQlwYXNzCgkJCWVsaWYocmVjb3JkVHlw
ZT09J0VORCAgICcgb3IgcmVjb3JkVHlwZT09J0NPTkVDVCcpOgoJCQkJIyBFbmQgb2YgYXRvbWlj
IGRhdGEKCQkJCSMgUmV0dXJuIHRoZSB0cmFpbGVyCgkJCQlyZXR1cm4gYnVmZmVyW2xpbmVfY291
bnRlcjpdCgkJCWVsaWYocmVjb3JkVHlwZT09J0FOSVNPVScpOgoJCQkJYW5pc291PShsaW5lWzI4
OjM1XSwgbGluZVszNTo0Ml0sIGxpbmVbNDM6NDldLCBsaW5lWzQ5OjU2XSwgbGluZVs1Njo2M10s
IGxpbmVbNjM6NzBdKQoJCQkJbWFwcGVkX2FuaXNvdT1tYXAoYXRvZiwgYW5pc291KQoJCQkJIyBV
J3MgYXJlIHNjYWxlZCBieSAxMF40IGZvciBzb21lIHJlYXNvbgoJCQkJYW5pc291X2FycmF5PWFy
cmF5KG1hcHBlZF9hbmlzb3UsIEZsb2F0MCkvMTAwMDAuMAoJCQkJc3RydWN0dXJlX2J1aWxkZXIu
c2V0X2FuaXNvdShhbmlzb3VfYXJyYXkpCgkJCWVsaWYocmVjb3JkVHlwZT09J1NJR0FUTScpOgoJ
CQkJIyBzdGFuZGFyZCBkZXZpYXRpb24gb2YgYXRvbWljIHBhcmFtZXRlcnMKCQkJCXNpZ2F0bT0o
bGluZVszMDozOF0sIGxpbmVbMzg6NDVdLCBsaW5lWzQ2OjU0XSwgbGluZVs1NDo2MF0sIGxpbmVb
NjA6NjZdKQoJCQkJbWFwcGVkX3NpZ2F0bT1tYXAoYXRvZiwgc2lnYXRtKQoJCQkJc2lnYXRtX2Fy
cmF5PWFycmF5KG1hcHBlZF9zaWdhdG0sIEZsb2F0MCkKCQkJCXN0cnVjdHVyZV9idWlsZGVyLnNl
dF9zaWdhdG0oc2lnYXRtX2FycmF5KQoJCQllbGlmKHJlY29yZFR5cGU9PSdTSUdVSUonKToKCQkJ
CSMgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIGFuaXNvdHJvcGljIHRlbXBlcmF0dXJlIGZhY3RvcgoJ
CQkJc2lndWlqPShsaW5lWzI4OjM1XSwgbGluZVszNTo0Ml0sIGxpbmVbNDI6NDldLCBsaW5lWzQ5
OjU2XSwgbGluZVs1Njo2M10sIGxpbmVbNjM6NzBdKQoJCQkJbWFwcGVkX3NpZ3Vpaj1tYXAoYXRv
Ziwgc2lndWlqKQoJCQkJIyBVIHNpZ21hJ3MgYXJlIHNjYWxlZCBieSAxMF40IGZvciBzb21lIHJl
YXNvbgoJCQkJc2lndWlqX2FycmF5PWFycmF5KG1hcHBlZF9zaWd1aWosIEZsb2F0MCkvMTAwMDAu
MAoJCQkJc3RydWN0dXJlX2J1aWxkZXIuc2V0X3NpZ3VpaihzaWd1aWpfYXJyYXkpCgkJCWxpbmVf
Y291bnRlcj1saW5lX2NvdW50ZXIrMQoJCSMgV2UndmUgcmVhY2hlZCB0aGUgZW5kIG9mIHRoZSBm
aWxlIChObyBFTkQgb3IgQ09ORUNUIHJlY29yZCBmb3VuZCkKCQlyZXR1cm4gTm9uZQoJCg==

--------------Boundary-00=_1NU0N6IAKIYE2PZXXBUG
Content-Type: text/english;
  name="test.py"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="test.py"

IiIiClBEQlBhcnNlcjogcGFyc2VyIGZvciBQREIgZmlsZXMKQ29weXJpZ2h0IChDKSAgMjAwMiBU
aG9tYXMgSGFtZWxyeWNrCiAKVGhpcyBwcm9ncmFtIGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4g
cmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnkKaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBH
TlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkKdGhlIEZyZWUgU29mdHdh
cmUgRm91bmRhdGlvbjsgZWl0aGVyIHZlcnNpb24gMiBvZiB0aGUgTGljZW5zZSwgb3IKKGF0IHlv
dXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi4KIApUaGlzIHByb2dyYW0gaXMgZGlzdHJpYnV0
ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwKYnV0IFdJVEhPVVQgQU5ZIFdB
UlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YKTUVSQ0hBTlRBQklM
SVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZQpHTlUgR2Vu
ZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLgogCllvdSBzaG91bGQgaGF2ZSBy
ZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlCmFsb25nIHdp
dGggdGhpcyBwcm9ncmFtOyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlCkZvdW5k
YXRpb24sIEluYy4sIDU5IFRlbXBsZSBQbGFjZSwgU3VpdGUgMzMwLCBCb3N0b24sIE1BICAwMjEx
MS0xMzA3ICBVU0EKIiIiCgpmcm9tIFBEQlBhcnNlciBpbXBvcnQgUERCUGFyc2VyCgpjbGFzcyBT
dHJ1Y3R1cmVCdWlsZGVyRXhhbXBsZToKCSIiIgoJUERCUGFyc2VyIHVzZXMgYW4gYWdncmVnYXRl
ZCBjbGFzcyB0byBidWlsZCB0aGUgc3RydWN0dXJlcy4KCUl0IGNhbGxzIHN0YW5kYXJkIG1ldGhv
ZHMgb2YgdGhpcyBjbGFzcyB0byBpbml0aWF0ZSBuZXcgbW9kZWxzLAoJY2hhaW5zLCByZXNpZHVl
cyBhbmQgYXRvbXMuIFlvdSBjYW4gYnVpbGQgeW91ciBvd24gU3RydWN0dXJlIAoJaW5zdGFuY2Ug
YnkgaW1wbGVtZW50aW5nIHlvdXIgb3duIFN0cnVjdHVyZUJ1aWxkZXIgY2xhc3MuIAoJIiIiCglk
ZWYgc2V0X2lkKHNlbGYsIHN0cnVjdHVyZV9pZCk6CgkJIlNldCB0aGUgdXNlciBkZWZpbmVkIGlk
IG9mIHRoZSBzdHJ1Y3R1cmUiCgkJcHJpbnQgIlN0cnVjdHVyZSBpZCBpcyAiLCBzdHJ1Y3R1cmVf
aWQKCglkZWYgc2V0X3BkYl9pZGVudChzZWxmLCBwZGJfaWRlbnQpOgoJCSJTZXQgdGhlIHBkYiBp
ZCIKCQlwcmludCAiUERCIGlkZW50aWZpZXIgaXMgIiwgcGRiX2lkZW50CgoJZGVmIHNldF9zeW1t
ZXRyeShzZWxmLCBzcGFjZWdyb3VwLCBjZWxsKToKCQkiU2V0IHN5bW1ldHJ5ICYgY2VsbCBwYXJh
bWV0ZXJzIgoJCXByaW50ICJTcGFjZWdyb3VwIGlzICIsIHNwYWNlZ3JvdXAKCQlwcmludCAiQ2Vs
bCBpcyAiLCBjZWxsCgoJZGVmIGluaXRfbW9kZWwoc2VsZiwgbW9kZWxfaWQpOgoJCSIiIgoJCUNh
bGxlZCB3aGVuIGEgbmV3IG1vZGVsIGlzIGVuY291bnRlcmVkCgkJCW1vZGVsX2lkIC0tLSBpbnRl
Z2VyIAoJCSIiIgoJCXByaW50ICJNb2RlbCAlaSIgJSBtb2RlbF9pZAoKCWRlZiBpbml0X2NoYWlu
KHNlbGYsIGNoYWluX2lkKToKCQkiIiIKCQlDYWxsZWQgd2hlbiBhIG5ldyBjaGFpbiBpcyBlbmNv
dW50ZXJlZCAKCQkJY2hhaW5faWQgLS0tIGNoYXIKCQkiIiIKCQlwcmludCAiXHRDaGFpbiAlYyIg
JSBjaGFpbl9pZAoKCWRlZiBpbml0X3Jlc2lkdWUoc2VsZiwgcmVzbmFtZSwgZmllbGQsIHJlc3Nl
cSwgaWNvZGUpOgoJCSIiIgoJCUNhbGxlZCB3aGVuIGEgbmV3IHJlc2lkdWUgaXMgZW5jb3VudGVy
ZWQKCQkJcmVzbmFtZSAtLS0gMyBsZXR0ZXIgc3RyaW5nLCBhbWlubyBhY2lkLCBlLmcuIEFTTgoJ
CQlmaWVsZCAtLS0gJ0gnIGlmIGl0IGlzIGEgaGV0ZXJvIHJlc2lkdWUsICcgJyBpZiBub3QKCQkJ
cmVzc2VxIC0tLSBpbnQsIGNoYWluIGlkZW50aWZpZXIKCQkJaWNvZGUgLS0tIGNoYXIsIGluc2Vy
dGlvbiBjb2RlCgkJIiIiIAoJCWlmIGZpZWxkPT0nSCc6CgkJCWxhYmVsPSIoSEVURVJPKSIKCQll
bHNlOgoJCQlsYWJlbD0iIgoJCXByaW50ICJcdFx0UmVzaWR1ZSAlcyAlaSAlYyAlcyIgJSAocmVz
bmFtZSwgcmVzc2VxLCBpY29kZSwgbGFiZWwpCgkJCglkZWYgaW5pdF9hdG9tKHNlbGYsIG5hbWUs
IGNvb3JkLCB0ZW1wZmFjdG9yLCBvY2N1cGFuY3ksIGFsdGxvYywgZWxlbWVudCk6CgkJIiIiCgkJ
Q2FsbGVkIHdoZW4gYSBuZXcgYXRvbSBpcyBlbmNvdW50ZXJlZAoJCQluYW1lIC0tLSAKCQkJY29v
cmQgLS0tIE51bXB5IGFycmF5LCB4eXogY29vcmRpbmF0ZXMKCQkJdGVtcGZhY3RvciAtLS0gZmxv
YXQsIHRlbXBlcmF0dXJlIGZhY3RvcgoJCQlvY2N1cGFuY3kgLS0tIGZsb2F0CgkJCWFsdGxvYyAt
LS0gY2hhciwgYWx0ZXJuYXRpdmUgbG9jYXRpb24gc3BlY2lmaWVyCgkJCWVsZW1lbnQgLS0tIHN0
cmluZwoJCSIiIgoJCXByaW50ICJcdFx0XHRBdG9tICVzIiAlIG5hbWUKCQkKCWRlZiBzZXRfYW5p
c291KHNlbGYsIGFuaXNvdSk6CgkJIlNldCBhbmlzb3Ryb3BpYyBCLWZhY3RvcnMiCgkJcGFzcwoK
CWRlZiBzZXRfc2lnYXRtKHNlbGYsIHNpZ2F0bSk6CgkJIlNldCBzdGFuZGFyZCBkZXZpYXRpb24g
b2YgYXRvbWljIGNvb3JkaW5hdGVzIgoJCXBhc3MKCglkZWYgc2V0X3NpZ3VpaihzZWxmLCBzaWd1
aWopOgoJCSJTZXQgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIGFuaXNvdHJvcGljIEItZmFjdG9yIgoJ
CXBhc3MKCglkZWYgZ2V0KHNlbGYpOgoJCSJSZXR1cm4gdGhlIFN0cnVjdHVyZSBpbnN0YW5jZSIK
CQlyZXR1cm4gIkRvbmUuIgoKCmlmIF9fbmFtZV9fPT0iX19tYWluX18iOgoKCWltcG9ydCBzeXMK
CglpZiBsZW4oc3lzLmFyZ3YpIT0yOgoJCXByaW50ICJVc2FnZTogcHl0aG9uIHRlc3QucHkgcGRi
ZmlsZSIKCQlzeXMuZXhpdCgpCgoJc2I9U3RydWN0dXJlQnVpbGRlckV4YW1wbGUoKQoKCXA9UERC
UGFyc2VyKHNiKQoKCXByaW50IHAuZ2V0KCJzY3JhdGNoIiwgc3lzLmFyZ3ZbMV0pCgoK

--------------Boundary-00=_1NU0N6IAKIYE2PZXXBUG--