[Zope-CMF] Historical revisions in CMF (was Re: CMF newbiequestions)

Dieter Maurer dieter@handshake.de
Sun, 30 Mar 2003 09:22:32 +0200


--5WQbovnOO0
Content-Type: text/plain; charset=us-ascii
Content-Description: message body text
Content-Transfer-Encoding: 7bit

Ausum Studio wrote at 2003-3-29 07:58 -0500:
 > ....
 > ----- Original Message -----
 > From: "Dieter Maurer" <dieter@handshake.de>
 > > ....
 > > I also have a "historical connection" that automatically
 > > loads subobjects as of a given historical time.
 > > This makes the history mechanism available for structured
 > > object, such as folders.
 > >
 > >
 > > If someone it interested, I can make code available.
 > >
 > 
 > I am interested. :)

I attach the module.

Use its "Historical" the same way you would use "OFS.History.Historical".

It behaves like the original with the exception that access to
a persistent subobject does not return the current version
of the subobject but that which was current at the historical time.
The same holds true for indirect access to persistent descendants:
you see the subhierarchy as it was at the historical time.


The "_hasSmartHistory" function is part of my "ReadCommited" ZODB patch.
If applied (there is one known problem with respect to transaction
abortion; thus, you may want to wait until this has been sorted out),
you will get more efficient history operations (by a factor of 2)
for "FileStorage".


Dieter


--5WQbovnOO0
Content-Type: application/x-python
Content-Description: "History" module -- an extension to "OFS.History" to provide historical access to persistent subobjects
Content-Disposition: attachment;
	filename="History.py"
Content-Transfer-Encoding: base64

IyAgICAgICAkSWQ6IEhpc3RvcnkucHksdiAxLjUgMjAwMy8wMy8yMCAxNDoyNzozNyBkaWV0
ZXIgRXhwICQKJycnSGlzdG9yeSBleHRlbnNpb25zLicnJwoKZnJvbSBPRlMuSGlzdG9yeSBp
bXBvcnQgSHlzdG9yeUphciwgSGlzdG9yaWFuLCBIaXN0b3JpY2FsCmZyb20gc3RydWN0IGlt
cG9ydCBwYWNrLCB1bnBhY2sKZnJvbSBjU3RyaW5nSU8gaW1wb3J0IFN0cmluZ0lPCmZyb20g
Y1BpY2tsZSBpbXBvcnQgVW5waWNrbGVyCmZyb20gWk9EQi5Db25uZWN0aW9uIGltcG9ydCBD
b25uZWN0aW9uCmZyb20gWk9EQi5QT1NFeGNlcHRpb24gaW1wb3J0IFBPU0tleUVycm9yCmZy
b20gWk9EQi5UaW1lU3RhbXAgaW1wb3J0IFRpbWVTdGFtcApmcm9tIHN5cyBpbXBvcnQgbWF4
aW50CgoKIyBDb2RlIG1vc3RseSBzdG9sZW4gZnJvbSAiT0ZTLkhpc3RvcnkiCmRlZiBoaXN0
b3JpY2FsUmV2aXNpb24oc2VsZixzZXJpYWwpOgogICcnJ3JldHVybiB0aGUgc3RhdGUgb2Yg
KnNlbGYqIGN1cnJlbnQgYXQgKnNlcmlhbCogYW5kIHNldCAiX3BfamFyIgogIHVwIGluIGEg
d2F5IHRoYXQgYWxsIHN1Ym9iamVjdCBhY2Nlc3MgaGFzIHRoZSBzYW1lIHByb3BlcnR5Licn
JwogIGphcj0gSGlzdG9yeUphcihzZWxmLl9wX2phcixzZXJpYWwpCiAgcmV2PSBqYXJbc2Vs
Zi5fcF9vaWRdCiAgcGFyZW50PSBnZXRhdHRyKHNlbGYsJ2FxX3BhcmVudCcsTm9uZSkKICBv
Zj0gZ2V0YXR0cihyZXYsJ19fb2ZfXycsTm9uZSkKICBpZiBwYXJlbnQgaXMgbm90IE5vbmUg
YW5kIG9mIGlzIG5vdCBOb25lOiByZXY9IG9mKHBhcmVudCkKICByZXR1cm4gcmV2CgoKY2xh
c3MgSGlzdG9yeUphcihIeXN0b3J5SmFyKToKICAnJydhIHJlbGF5aW5nIGNvbm5lY3Rpb24g
c2VsZWN0aW5nIGFuIG9iamVjdCBjdXJyZW50IGF0IGEgc2VyaWFsIChyZXByZXNlbnRpbmcg
YSB0aW1lKS4nJycKICBkZWYgX19pbml0X18oc2VsZixiYXNlLHNlcmlhbCk6CiAgICBIeXN0
b3J5SmFyLl9faW5pdF9fKHNlbGYsYmFzZSkKICAgIHNlbGYuX2phcj0gYmFzZTsgc2VsZi5f
c2VyaWFsPSBzZXJpYWwKICAgIHNlbGYuX2NhY2hlPSB7fQoKICBkZWYgX19nZXRpdGVtX18o
c2VsZixvaWQpOgogICAgJycncmV0dXJuIHRoZSBzdGF0ZSBmb3IgKm9pZCogY3VycmVudCBm
b3IgKl9zZXJpYWwqLicnJwogICAgIyBkZXRlcm1pbmUgd2hpY2ggaGlzdG9yeSByZWNvcmRz
IGFyZSBhdmFpbGFibGUKICAgICMgQVRUOiB0aGlzIGluZm9ybWF0aW9uIHNob3VsZCBiZSBj
YWNoZWQKICAgICMgICAgICBldmVuIGJldHRlciwgd2hlbiBaT0RCIHdvdWxkIHN1cHBvcnQg
bG9hZGluZyBhbiBvYmplY3QgdmFsaWQgYXQgc2VyaWFsCiAgICBqYXI9IHNlbGYuX2phcjsg
b2JqPSBqYXJbb2lkXQogICAgcmV2PSBvYmouX19jbGFzc19fLl9fYmFzaWNuZXdfXygpCiAg
ICByZXYuX3BfamFyPSBzZWxmCiAgICByZXYuX3Bfb2lkPSBvaWQKICAgIHNlbGYuc2V0c3Rh
dGUocmV2KQogICAgcmV0dXJuIHJldgoKICBkZWYgc2V0c3RhdGUoc2VsZixvYmopOgogICAg
c2VyaWFsPSBzZWxmLl9zZXJpYWw7IGphcj0gc2VsZi5famFyOyBvaWQ9IG9iai5fcF9vaWQK
ICAgIFM9IGphci5fc3RvcmFnZQogICAgZmlsdGVyPSBsYW1iZGEgdCwgc2VyaWFsPSBzZXJp
YWw6IHRbJ3NlcmlhbCddIDw9IHNlcmlhbCAjIHRoaXMgbWlnaHQgbmVlZCB0byBiZWNvbWUg
YSBwaWNrbGFibGUgb2JqZWN0LCBvbmNlIFpFTyBzdXBwb3J0cyAnZmlsdGVyJy4KICAgIGlm
IF9oYXNTbWFydEhpc3RvcnkoUyk6CiAgICAgIHRzPSBTLmhpc3Rvcnkob2lkLE5vbmUsMSwg
ZmlsdGVyPSBmaWx0ZXIsICkKICAgIGVsc2U6CiAgICAgIGhmPSBIaXN0b3J5RmV0Y2hlcihq
YXIsb2lkLE5vbmUsbGFzdD0xLCBmaWx0ZXI9ZmlsdGVyKQogICAgICB0cz0gaGYubmV4dCgp
CiAgICBpZiBub3QgdHM6IHJhaXNlIFBPU0tleUVycm9yLCAob2lkLHNlcmlhbCkKICAgIHQ9
IHRzWzBdCiAgICBvc2VyaWFsPSB0WydzZXJpYWwnXQogICAgc3RhdGU9IHNlbGYub2xkc3Rh
dGUob2JqLG9zZXJpYWwpCiAgICBvYmouX3Bfc2VyaWFsPSBvc2VyaWFsCiAgICBvYmouX19z
ZXRzdGF0ZV9fKHN0YXRlKQogICAgaHQ9IFRpbWVTdGFtcCh1bnBhY2soJzhzJyxzZXJpYWwp
WzBdKS50aW1lVGltZSgpCiAgICB0cnk6IG9iai5fcF9oaXN0b3JpY2FsPSBodAogICAgZXhj
ZXB0IEF0dHJpYnV0ZUVycm9yOgogICAgICAjIHRoaXMgbWF5IG5vdCBiZSBwb3NzaWJsZSwg
ZS5nLiBmb3IgX19kaWN0X18gbGVzcyBpbnN0YW5jZXMgKHN1Y2ggYXMgIkJUcmVlcyIKICAg
ICAgcGFzcwogICAgb2JqLl9wX2NoYW5nZWQ9IDAKCiAgIyB0YWtlIG92ZXIgbWV0aG9kcyBm
cm9tICJDb25uZWN0aW9uIiwgYmVjYXVzZSB3ZSBkbyBub3QgZGVyaXZlCiAgIyAgIGZyb20g
dGhpcyBjbGFzcywgd2UgbXVzdCB1c2UgImltX2Z1bmMiLgogIG9sZHN0YXRlPSBDb25uZWN0
aW9uLm9sZHN0YXRlLmltX2Z1bmMKICBfcGVyc2lzdGVudF9sb2FkPSBDb25uZWN0aW9uLl9w
ZXJzaXN0ZW50X2xvYWQuaW1fZnVuYwogICAgCgoKY2xhc3MgSGlzdG9yaWFuKEhpc3Rvcmlh
bik6CiAgJycnZGVsaXZlciBoaXN0b3JpY2FsIHJldmlzaW9ucy4nJycKICBkZWYgX19nZXRp
dGVtX18oc2VsZixrZXkpOgogICAgc2VsZj0gc2VsZi5hcV9wYXJlbnQKICAgIHNlcmlhbD1f
ZGVjb2RlU2VyaWFsKGtleSkKICAgIGlmIHNlcmlhbCA9PSBzZWxmLl9wX3NlcmlhbDogcmV0
dXJuIHNlbGYKICAgIHJldHVybiBoaXN0b3JpY2FsUmV2aXNpb24oc2VsZixzZXJpYWwpCgpj
bGFzcyBIaXN0b3JpY2FsKEhpc3RvcmljYWwpOgogIEhpc3RvcmljYWxSZXZpc2lvbnM9IEhp
c3RvcmlhbigpCgogICMgcHJvdmlkZSBpbmZvcm1hdGlvbiBvbiB3aGV0aGVyIG9yIG5vdCB0
aGlzIGlzIGEgaGlzdG9yaWNhbCB2ZXJzaW9uCiAgZGVmIGlzSGlzdG9yaWNhbChzZWxmKToK
ICAgICcnJ2ZhbHNlIChpbiBmYWN0ICdOb25lJyksIGlmICpzZWxmKiBpcyBub3QgaGlzdG9y
aWNhbDsKICAgIG90aGVyd2lzZSwgdGhlIHRpbWUgZm9yIHdoaWNoICpzZWxmKiBoYXMgYmVl
biByZXF1ZXN0ZWQuJycnCiAgICByZXR1cm4gZ2V0YXR0cihzZWxmLCdfcF9oaXN0b3JpY2Fs
JyxOb25lKQoKICBkZWYgZ2V0SGlzdG9yaWNhbFN1YnBhdGgoc2VsZik6CiAgICAnJydyZXR1
cm5zIGFuIFVSTCBzdWJwYXRoIHRvIHJlZmVyZW5jZSBhIGhpc3RvcmljYWwgdmVyc2lvbiBj
b3JyZXNwb25kaW5nIHRvIHRoaXMgdGltZS4nJycKICAgIGh0PSBzZWxmLmlzSGlzdG9yaWNh
bCgpCiAgICBpZiBodCBpcyBOb25lOiByZXR1cm4gJycKICAgIHJldHVybiAnL0hpc3Rvcmlj
YWxSZXZpc2lvbnMvJyArIF9lbmNvZGVTZXJpYWwoc2VsZi5fcF9zZXJpYWwpCgoKICAjIG11
c3Qgb3ZlcnJpZGUgdG8gdXNlIG91ciAiaGlzdG9yaWNhbFJldmlzaW9uIgogIGRlZiBtYW5h
Z2VfaGlzdG9yaWNhbENvbXBhcmlzb24oc2VsZiwgUkVRVUVTVCwga2V5cz1bXSk6CiAgICAg
ICAgIkNvbXBhcmUgdHdvIHNlbGVjdGVkIHJldmlzaW9ucyIKICAgICAgICBpZiBub3Qga2V5
czoKICAgICAgICAgICAgcmFpc2UgSGlzdG9yeVNlbGVjdGlvbkVycm9yLCAoCiAgICAgICAg
ICAgICAgICAiTm8gaGlzdG9yaWNhbCByZXZpc2lvbiB3YXMgc2VsZWN0ZWQuPHA+IikKICAg
ICAgICBpZiBsZW4oa2V5cykgPiAyOgogICAgICAgICAgICByYWlzZSBIaXN0b3J5U2VsZWN0
aW9uRXJyb3IsICgKICAgICAgICAgICAgICAgICJPbmx5IHR3byBoaXN0b3JpY2FsIHJldmlz
aW9uIGNhbiBiZSBjb21wYXJlZDxwPiIpCgogICAgICAgIHJldjE9aGlzdG9yaWNhbFJldmlz
aW9uKHNlbGYsIF9kZWNvZGVTZXJpYWwoa2V5c1stMV0pKQoKICAgICAgICBpZiBsZW4oa2V5
cyk9PTI6CiAgICAgICAgICAgIHJldjI9aGlzdG9yaWNhbFJldmlzaW9uKHNlbGYsIF9kZWNv
ZGVTZXJpYWwoa2V5c1swXSkpCiAgICAgICAgZWxzZToKICAgICAgICAgICAgcmV2Mj1zZWxm
CgogICAgICAgIHJldHVybiBzZWxmLm1hbmFnZV9oaXN0b3J5Q29tcGFyZShyZXYxLCByZXYy
LCBSRVFVRVNUKQogIAoKY2xhc3MgSGlzdG9yeUZldGNoZXI6CiAgJycnYXV4aWxpYXJ5IGNs
YXNzIHRvIGluY3JlbWVudGFsbHkgZmV0Y2ggaGlzdG9yeS4nJycKICBfY3Vycj0gMAogIF9p
bmM9IDEKICBfY29tcGxldGU9IDAKCiAgZGVmIF9faW5pdF9fKHNlbGYsamFyLG9pZCx2ZXJz
aW9uPU5vbmUsZmlyc3Q9MCxsYXN0PU5vbmUsZmlsdGVyPU5vbmUpOgogICAgJycncHJlcGFy
ZSBmZXRjaGluZyBoaXN0b3JpY2FsIHJlY29yZHMgZm9yICpvaWQqIGluICp2ZXJzaW9uKi4K
CiAgICBUcmllcyB0byBmaW5kIHJlY29yZHMgc2F0aXNmeWluZyAqZmlsdGVyKi4gUmVjb3Jk
cyAqZmlyc3QqCiAgICB0aHJvdWdoICpsYXN0KiBhcmUgcmV0dXJuZWQuCiAgICAnJycKICAg
IFM9IGphci5fc3RvcmFnZQogICAgaGlzdG9yeT0gUy5oaXN0b3J5CiAgICBpZiBfaGFzU21h
cnRIaXN0b3J5KFMpOiBzZWxmLl9zbWFydEhpc3Rvcnk9IGhpc3RvcnkKICAgIGVsc2U6IHNl
bGYuX2dldFJhd0hpc3Rvcnk9IGhpc3RvcnkKICAgIHNlbGYuX29pZD0gb2lkCiAgICBzZWxm
Ll92ZXJzaW9uPSB2ZXJzaW9uCiAgICBzZWxmLl9maXJzdD0gZmlyc3QKICAgIHNlbGYuX2xh
c3Q9IGxhc3QKICAgIHNlbGYuX2ZpbHRlcj0gX0ZpbHRlcihmaWx0ZXIpCgogIGRlZiBmZXRj
aChzZWxmKToKICAgICcnJ3JldHVybiB0aGUgcmVsZXZhbnQgaGlzdG9yeSByZWNvcmRzLicn
JwogICAgc2VsZi5yZXNldCgpCiAgICBuPSBzZWxmLl9sYXN0CiAgICBpZiBuIGlzIE5vbmU6
IG49IG1heGludAogICAgcmV0dXJuIHNlbGYubmV4dChuLXNlbGYuX2ZpcnN0KQoKICBkZWYg
bmV4dChzZWxmLG49MSk6CiAgICAnJydyZXR1cm4gdXAgdG8gbiBtb3JlIHJlbGV2YW50IGhp
c3RvcnkgcmVjb3Jkcy4nJycKICAgIGw9IFtdCiAgICB3aGlsZSBuID4gMDoKICAgICAgeD0g
c2VsZi5fbmV4dCgpCiAgICAgIGlmIHggaXMgTm9uZTogYnJlYWsKICAgICAgbC5hcHBlbmQo
eCk7IG4tPSAxCiAgICByZXR1cm4gbAoKICBkZWYgcmVzZXQoc2VsZik6CiAgICBzZWxmLl9i
aT0gc2VsZi5fY29tcGxldGU9IHNlbGYuX2ZpbHRlci5zdG9wcGVkPSAwCiAgICBpZiBzZWxm
Ll9idWZmZXIgaXMgTm9uZSBvciBzZWxmLl9sYXN0IGlzIG5vdCBOb25lIG9yIHNlbGYuX2N1
cnIgPT0gc2VsZi5fZmlyc3Q6CiAgICAgIHJldHVybiAjIGp1c3QgcmVzZXQgdGhlIGJ1ZmZl
ciBpbmRleAogICAgZGVsIHNlbGYuX2J1ZmZlciAjIGRlbGV0ZSB0aGUgYnVmZmVyIGFzIHdl
bGwKCiAgX2J1ZmZlcj0gTm9uZQogIGRlZiBfbmV4dChzZWxmKToKICAgIGlmIHNlbGYuX2Nv
bXBsZXRlOiByZXR1cm4KICAgIGJ1ZmZlcj0gc2VsZi5fYnVmZmVyCiAgICBpZiBidWZmZXIg
aXMgTm9uZSBvciBzZWxmLl9iaSA+PSBsZW4oYnVmZmVyKTogYnVmZmVyPSBzZWxmLl9wcmVm
ZXRjaCgpCiAgICBpZiBub3QgYnVmZmVyOiBzZWxmLl9jb21wbGV0ZT0gMTsgcmV0dXJuCiAg
ICB4PSBidWZmZXJbc2VsZi5fYmldOyBzZWxmLl9iaSs9IDEKICAgIHJldHVybiB4CgogIGRl
ZiBfcHJlZmV0Y2goc2VsZik6CiAgICAnJydwcmVmZXRjaCBoaXN0b3J5IGluZm9ybWF0aW9u
LicnJwogICAgYnVmZmVyPSBzZWxmLl9idWZmZXIKICAgIHNlbGYuX2JpPSAwCiAgICAjIGlm
IHdlIGtub3cgbGFzdCwgd2UgZmV0Y2ggdGhlbSBpbiBhIHNpbmdsZSBzdGVwCiAgICBsYXN0
PSBzZWxmLl9sYXN0CiAgICBpZiBsYXN0IGlzIG5vdCBOb25lOgogICAgICBpZiBidWZmZXIg
aXMgbm90IE5vbmU6IHJldHVybiAjIHdlIGFscmVhZHkgcmVhZCBldmVyeXRoaW5nCiAgICAg
IHNlbGYuX2J1ZmZlcj0gYnVmZmVyPSBzZWxmLl9mZXRjaEhpc3Rvcnkoc2VsZi5fZmlyc3Qs
bGFzdCkKICAgICAgcmV0dXJuIGJ1ZmZlcgogICAgaWYgYnVmZmVyIGlzIE5vbmU6CiAgICAg
ICMgdGhlIGZpcnN0IHJvdW5kCiAgICAgIGN1cnI9IHNlbGYuX2ZpcnN0CiAgICBlbHNlOiBj
dXJyPSBzZWxmLl9jdXJyPSBzZWxmLl9jdXJyICsgbGVuKGJ1ZmZlcikKICAgIGluYz0gc2Vs
Zi5faW5jCiAgICBidWZmZXI9IHNlbGYuX2ZldGNoSGlzdG9yeShjdXJyLGN1cnIraW5jKQog
ICAgc2VsZi5faW5jPDw9IDEKICAgIHNlbGYuX2J1ZmZlcj0gYnVmZmVyCiAgICByZXR1cm4g
YnVmZmVyCgogIGRlZiBfZmV0Y2hIaXN0b3J5KHNlbGYsZmlyc3QsbGFzdCk6CiAgICBmaWx0
ZXI9IHNlbGYuX2ZpbHRlcgogICAgaWYgZmlsdGVyLnN0b3BwZWQ6IHJldHVybgogICAgZmls
dGVyLnNldElnbm9yZShmaXJzdCkKICAgIGluYz0gbGFzdC1maXJzdAogICAgcj0gc2VsZi5f
c21hcnRIaXN0b3J5KHNlbGYuX29pZCwgc2VsZi5fdmVyc2lvbixpbmMsZmlsdGVyKQogICAg
aWYgbGVuKHIpICE9IGluYzogZmlsdGVyLnN0b3BwZWQ9IDEKICAgIHJldHVybiByCgogIGRl
ZiBfc21hcnRIaXN0b3J5KHNlbGYsb2lkLHZlcnNpb24sc2l6ZSxmaWx0ZXIpOgogICAgJycn
ZW11bGF0ZSBhIHNtYXJ0IChpLmUuIGZpbHRlcmVkKSBoaXN0b3J5IGZldGNoaW5nIGZvcgog
ICAgc3RvcmFnZXMgdGhhdCBwcm92aWRlIG9ubHkgYSBzaW1wbGUgb25lLicnJwogICAgcj0g
W10gIyB0aGUgcmVzdWx0IGxpc3QKICAgIGlmIHNpemUgPD0gMDogcmV0dXJuIHIKICAgIGw9
IDA7IGg9IHNpemUrZmlsdGVyLl9pZ25jb3VudCAjIEFUVDogdGhpcyBpcyBhIHZlcnkgY3J1
ZGUgYXBwcm94aW1hdGlvbiAtLSB3ZSBtYXkgZG8gbXVjaCBiZXR0ZXIgd2hlbiB3ZSBjYWNo
ZSBhIGJpdC4KICAgIGhpc3Rvcnk9IHNlbGYuX2dldFJhd0hpc3RvcnkKICAgIHdoaWxlIDE6
CiAgICAgIHRzPSBoaXN0b3J5KG9pZCx2ZXJzaW9uLGgpCiAgICAgIGlmIGxlbih0cykgPD0g
bDogYnJlYWsKICAgICAgZm9yIHQgaW4gdHNbbDpoXToKICAgICAgICBpZiBmaWx0ZXIodCk6
CiAgICAgICAgICByLmFwcGVuZCh0KQogICAgICAgICAgaWYgbGVuKHIpID49IHNpemU6IHJl
dHVybiByICMgQVRUOiB3ZSBtYXkgd2FudCB0byBjYWNoZSB0aGUgcmVtYWluaW5nIGVsZW1l
bnRzIGFuZCBob3cgZmFyIHdlIGhhZCB0byBmZXRjaCBhaGVhZAogICAgICBpZiBsZW4odHMp
IDwgaDogYnJlYWsKICAgICAgbD0gaDsgaDw8PSAxCiAgICBmaWx0ZXIuc3RvcHBlZD0gMQog
ICAgcmV0dXJuIHIKCgpjbGFzcyBfRmlsdGVyOgogICcnJ0EgZmlsdGVyIGlnbm9yaW5nIGFu
IGluaXRpYWwgc2VnbWVudCBvZiBhIHNlcXVlbmNlIGFjY2VwdGVkIGJ5IGEgKmJhc2VGaWx0
ZXIqLicnJwogIHN0b3BwZWQ9IE5vbmUKICBfaWduY291bnQ9IDAgICMgaWdub3JlIHRoYXQg
bWFueSBldmVudHMKCiAgZGVmIF9faW5pdF9fKHNlbGYsYmFzZUZpbHRlcik6CiAgICBzZWxm
Ll9iYXNlPSBiYXNlRmlsdGVyCgogIGRlZiBzZXRJZ25vcmUoc2VsZixubyk6CiAgICBzZWxm
Ll9pZ25jb3VudD0gbm8KCiAgZGVmIF9fY2FsbF9fKHNlbGYsb2JqKToKICAgICcnJ2NoZWNr
IHdoZXRoZXIgKm9iaiogc2hvdWxkIHBhc3MuJycnCiAgICBiYXNlPSBzZWxmLl9iYXNlCiAg
ICBmZD0gYmFzZSBpcyBOb25lIG9yIGJhc2Uob2JqKQogICAgaWYgZmQ6CiAgICAgIGlmIHNl
bGYuX2lnbmNvdW50OiBzZWxmLl9pZ25jb3VudC09IDE7IHJldHVybgogICAgcmV0dXJuIGZk
CgoKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj
IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojIyBIaXN0b3J5UHJvZHVjZXIKIyMgYW4gaW5j
cmVtZW50YWwgcHJvZHVjZXIgb2YgaGlzdG9yeSByZWNvcmRzCmNsYXNzIEhpc3RvcnlQcm9k
dWNlcjoKICAnJydhIGhpc3RvcnkgcHJvZHVjZXIgdG8gYmUgdXNlZCB0b2dldGhlciB3aXRo
IGFuIGluY3JlbWVudGFsIG1lcmdlci4KICBUaGUgZWxlbWVudHMgYXJlIGNvbXBhcmVkIHdp
dGggcmVzcGVjdCB0byB0aW1lIGFuZCBjb250YWluCiAgYm90aCB0aGUgb2JqZWN0cyBhcyB3
ZWxsIGFzIHRoZSBoaXN0b3J5IHJlY29yZC4nJycKICBkZWYgX19pbml0X18oc2VsZixvYmop
OgogICAgc2VsZi5fb2JqPSBvYmoKICAgIHNlbGYuX2ZldGNoZXI9IEhpc3RvcnlGZXRjaGVy
KG9iai5fcF9qYXIsb2JqLl9wX29pZCkKCiAgZGVmIHBvcChzZWxmKToKICAgIGg9IHNlbGYu
X2ZldGNoZXIubmV4dCgpCiAgICBpZiBub3QgaDogcmV0dXJuCiAgICByZXR1cm4gX0hpc3Rv
cnlSZWNvcmQoaFswXSxzZWxmLl9vYmopCgpjbGFzcyBfSGlzdG9yeVJlY29yZDoKICBkZWYg
X19pbml0X18oc2VsZixkYXRhLG9iaik6CiAgICBzZWxmLl9kYXRhPSBkYXRhCiAgICBzZWxm
Ll9vYmo9IG9iagoKICBkZWYgX19jbXBfXyhzZWxmLG90aGVyKToKICAgIHJldHVybiBjbXAo
b3RoZXIuX2RhdGFbJ3RpbWUnXSxzZWxmLl9kYXRhWyd0aW1lJ10pCgoKCiMjIyMjIyMjIyMj
IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj
IyMjIyMjIyMjIwojIyBBdXhpbGlhcmllcwpkZWYgX2VuY29kZVNlcmlhbChzZXJpYWwpOgog
ICcnJ2VuY29kZSBhIHNlcmlhbCBpbnRvIGEgJy4nIHNlcGFyYXRlZCBzZXF1ZW5jZSBvZiBp
bnRzLicnJwogIHJldHVybiAnLicuam9pbihtYXAoc3RyLCB1bnBhY2soIj5ISEhIIiwgc2Vy
aWFsKSkpCgpkZWYgX2RlY29kZVNlcmlhbChjb2RlKToKICAnJydkZWNvZGUgYSBzZXJpYWwg
ZW5jb2RlZCBhcyBhICcuJyBzZXBhcmF0ZWQgc2VxdWVuY2Ugb2YgaW50cy4nJycKICByZXR1
cm4gYXBwbHkocGFjaywgKCc+SEhISCcsKSt0dXBsZShtYXAoaW50LGNvZGUuc3BsaXQoJy4n
KSkpKQoKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj
IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojIyBub24gc3RhbmRhcmQgWk9EQiBleHRl
bnNpb24gaGFuZGxpbmcKdHJ5OiBmcm9tIFpPREIuQ29ubmVjdGlvbiBpbXBvcnQgX2hhc1Nt
YXJ0SGlzdG9yeQpleGNlcHQgSW1wb3J0RXJyb3I6CiAgZGVmIF9oYXNTbWFydEhpc3Rvcnko
c3RvcmFnZSk6IHJldHVybiAwCg==
--5WQbovnOO0--