[Python-Dev] New and Improved Import Hooks

Just van Rossum just@letterror.com
Tue, 3 Dec 2002 01:29:28 +0100


--41333375-49397760-3247867773=:9006
Content-Type: text/plain; Charset=US-ASCII
Content-Transfer-Encoding: 7bit

Folks,

I've attached a proof-of-concept patch to import.c that implements the
sys.import_hooks idea I outlined earlier. Here's an updated description.

  - sys.import_hooks is a list of hooks.
  - A hook is a callable object taking two arguments:
    'modulename' and 'path'. 'path' is either the parents package's
    __path__ or None, 'modulename' is *always* a "simple" name: no
    dots.
  - Hooks are never called for modules already in sys.modules.
  - A hook either returns None ("module not found") or a two-tuple:
    (loadfunc, data). loadfunc is a callable object that will
    be called with two arguments: the 'fullname' and 'data'. 'data'
    is just an arbitrary object, private to the hook. The loaderfunc
    must return the imported module. It _may_ add the module to
    sys.modules, but it doesn't need to.
  - A hook is not supposed to fail: it should return None or a
    (loader, data) tuple. If a hook _does_ fail with an exception,
    the import is aborted and subsequent hooks won't get called.
    The exception will be propagated to the caller. (XXX this is
    perhaps brittle; maybe errors need to be ignored by default,
    or a warning should be issued instead.)

sys.import_hooks currently gets filled with a default hook:
imp.builtin_import_hook. This is simply a wrapper around find_module() and
friends. Perhaps it's an idea to split it into discrete hooks for builtin,
frozen, and file system imports. This can be done later.

An alternative to the current default hook would be to keep sys.import_hooks
empty by default and fall back to find_module/load_module if no hook managed to
find/load the module. Pro: this would allow for some optimizations, as the hook
mechanism would be bypassed (and therefore less code in import.c). Con: it would
then be awkward to completely disable the builtin import mechanism, it's less
transparent, less elegant. (Ok, I thought a bit more about this: I don't like it
at all. All imports should be done by a hook on sys.import_hooks. If
sys.import_hooks is empty, _any_ new import will fail.)

Rationale:
- Make writing import hooks simpler; this new scheme avoids much of the
complexity involved in writing a traditional __import__ hook.

Real rationale:
- Allow the "Import from Zip archive" patch to be rewritten as an external
module, avoiding the huge mess it is right now, as it touches more or less all
of import.c and then some. Paul Moore is doing an admirable job to get it
working and cleaned up, but I honestly don't see this getting into the core:
it's such a huge and complex patch that it's almost impossible to properly
review. It's a maintainance nightmare waiting to happen. And let's face it,
import.c isn't all that maintainable as it is...

Longer term rationale:
- It would allow us to refactor the builtin import mechanism(s) by writing
specialized hooks, replacing the current monolithic find_module/load_module
code.

Con:
It is slower for first-time imports. If you care, go ahead and measure ;-)

Comments?

Just
--41333375-49397760-3247867773=:9006
Content-Type: application/octet-stream; Name="newimporthook.patch"; X-Mac-Type="54455854"; X-Mac-Creator="522A6368"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; Filename="newimporthook.patch"

SW5kZXg6IFB5dGhvbi9pbXBvcnQuYwo9PT09PT09PT09PT09PT09PT09PT09PT09
PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09ClJDUyBm
aWxlOiAvY3Zzcm9vdC9weXRob24vcHl0aG9uL2Rpc3Qvc3JjL1B5dGhvbi9pbXBv
cnQuYyx2CnJldHJpZXZpbmcgcmV2aXNpb24gMi4yMTEKZGlmZiAtYyAtcjIuMjEx
IGltcG9ydC5jCioqKiBQeXRob24vaW1wb3J0LmMJMjkgTm92IDIwMDIgMjA6NDc6
NDAgLTAwMDAJMi4yMTEKLS0tIFB5dGhvbi9pbXBvcnQuYwkyIERlYyAyMDAyIDIz
OjQwOjUwIC0wMDAwCioqKioqKioqKioqKioqKgoqKiogMTA1LDExMCAqKioqCi0t
LSAxMDUsMTI4IC0tLS0KICB9OwogICNlbmRpZgogIAorIC8qIGltcG9ydF9ob29r
cyBzdHVmZiwgcHJvYmFibHkgbmVlZHMgcmVvcmdhbml6YXRpb24gKi8KKyAvKiBm
b3J3YXJkIGRlY2xzICovCisgc3RhdGljIEZJTEUgKmdldF9maWxlKGNoYXIgKnBh
dGhuYW1lLCBQeU9iamVjdCAqZm9iLCBjaGFyICptb2RlKTsKKyBzdGF0aWMgUHlP
YmplY3QgKmNhbGxfZmluZF9tb2R1bGUoY2hhciAqbmFtZSwgUHlPYmplY3QgKnBh
dGgpOworIAorIC8qICJtYW51YWwiIGNvbnN0cnVjdGlvbiBvZiB0d28gQ0Z1bmN0
aW9uIG9iamVjdHM7IGNhbid0IHVzZSB0aGUKKyAgICByZWd1bGFyIG1lY2hhbmlz
bSBhcyB3ZSBuZWVkIHRoZXNlIGZ1bmN0aW9uIG9iamVjdHMgZXZlbiBpZiB0aGUK
KyAgICBpbXAgbW9kdWxlIGlzbid0IGltcG9ydGVkLiAqLworIHN0YXRpYyBQeU9i
amVjdCAqaW1wX2J1aWx0aW5faW1wb3J0X2hvb2soUHlPYmplY3QgKnNlbGYsIFB5
T2JqZWN0ICphcmdzKTsKKyBzdGF0aWMgUHlNZXRob2REZWYgYnVpbHRpbl9pbXBv
cnRfaG9va19kZWYgPSAKKyAJeyJidWlsdGluX2ltcG9ydF9ob29rIiwgaW1wX2J1
aWx0aW5faW1wb3J0X2hvb2ssIE1FVEhfVkFSQVJHUywgIlhYWCJ9OworIHN0YXRp
YyBQeU9iamVjdCAqYnVpbHRpbl9pbXBvcnRfaG9va19mdW5jID0gTlVMTDsKKyAK
KyBzdGF0aWMgUHlPYmplY3QgKmltcF9idWlsdGluX2xvYWRlcihQeU9iamVjdCAq
c2VsZiwgUHlPYmplY3QgKmFyZ3MpOworIHN0YXRpYyBQeU1ldGhvZERlZiBidWls
dGluX2xvYWRlcl9kZWYgPSAKKyAJeyJidWlsdGluX2xvYWRlciIsIGltcF9idWls
dGluX2xvYWRlciwgTUVUSF9WQVJBUkdTLCAiWFhYIn07Cisgc3RhdGljIFB5T2Jq
ZWN0ICpidWlsdGluX2xvYWRlcl9mdW5jID0gTlVMTDsKKyAKICAvKiBJbml0aWFs
aXplIHRoaW5ncyAqLwogIAogIHZvaWQKKioqKioqKioqKioqKioqCioqKiAxMTQs
MTE5ICoqKioKLS0tIDEzMiwxMzggLS0tLQogIAlzdHJ1Y3QgZmlsZWRlc2NyICpm
aWxldGFiOwogIAlpbnQgY291bnREID0gMDsKICAJaW50IGNvdW50UyA9IDA7Cisg
CVB5T2JqZWN0ICppbXBvcnRfaG9va3M7CiAgCiAgCS8qIHByZXBhcmUgX1B5SW1w
b3J0X0ZpbGV0YWI6IGNvcHkgZW50cmllcyBmcm9tCiAgCSAgIF9QeUltcG9ydF9E
eW5Mb2FkRmlsZXRhYiBhbmQgX1B5SW1wb3J0X1N0YW5kYXJkRmlsZXRhYi4KKioq
KioqKioqKioqKioqCioqKiAxNTAsMTU1ICoqKioKLS0tIDE2OSwxODUgLS0tLQog
IAkJICAgY29kZSBjcmVhdGVkIGluIG5vcm1hbCBvcGVyYXRpb24gbW9kZS4gKi8K
ICAJCXB5Y19tYWdpYyA9IE1BR0lDICsgMTsKICAJfQorIAorIAkvKiBTZXR1cCBz
eXMuaW1wb3J0X2hvb2tzOyBjcmVhdGUgZnVuY3Rpb24gb2JqZWN0cyBmb3IgdGhl
CisgCSAgIGRlZmF1bHQgaG9vayBhbmQgbWF0Y2hpbmcgbG9hZGVyIGZ1bmN0aW9u
cy4gKi8KKyAJYnVpbHRpbl9pbXBvcnRfaG9va19mdW5jID0gUHlDRnVuY3Rpb25f
TmV3KCZidWlsdGluX2ltcG9ydF9ob29rX2RlZiwKKyAJCQkJCQkgICBOVUxMKTsK
KyAJYnVpbHRpbl9sb2FkZXJfZnVuYyA9IFB5Q0Z1bmN0aW9uX05ldygmYnVpbHRp
bl9sb2FkZXJfZGVmLCBOVUxMKTsKKyAJaW1wb3J0X2hvb2tzID0gUHlfQnVpbGRW
YWx1ZSgiW09dIiwgYnVpbHRpbl9pbXBvcnRfaG9va19mdW5jKTsKKyAJaWYgKGlt
cG9ydF9ob29rcyAhPSBOVUxMKSB7CisgCQlQeVN5c19TZXRPYmplY3QoImltcG9y
dF9ob29rcyIsIGltcG9ydF9ob29rcyk7CisgCQlQeV9ERUNSRUYoaW1wb3J0X2hv
b2tzKTsKKyAJfQogIH0KICAKICB2b2lkCioqKioqKioqKioqKioqKgoqKiogMjQ2
LDI1MiAqKioqCiAgCSJwYXRoIiwgImFyZ3YiLCAicHMxIiwgInBzMiIsICJleGl0
ZnVuYyIsCiAgCSJleGNfdHlwZSIsICJleGNfdmFsdWUiLCAiZXhjX3RyYWNlYmFj
ayIsCiAgCSJsYXN0X3R5cGUiLCAibGFzdF92YWx1ZSIsICJsYXN0X3RyYWNlYmFj
ayIsCiEgCU5VTEwKICB9OwogIAogIHN0YXRpYyBjaGFyKiBzeXNfZmlsZXNbXSA9
IHsKLS0tIDI3NiwyODIgLS0tLQogIAkicGF0aCIsICJhcmd2IiwgInBzMSIsICJw
czIiLCAiZXhpdGZ1bmMiLAogIAkiZXhjX3R5cGUiLCAiZXhjX3ZhbHVlIiwgImV4
Y190cmFjZWJhY2siLAogIAkibGFzdF90eXBlIiwgImxhc3RfdmFsdWUiLCAibGFz
dF90cmFjZWJhY2siLAohIAkiaW1wb3J0X2hvb2tzIiwgTlVMTAogIH07CiAgCiAg
c3RhdGljIGNoYXIqIHN5c19maWxlc1tdID0gewoqKioqKioqKioqKioqKioKKioq
IDE5NjEsMTk2NiAqKioqCi0tLSAxOTkxLDIxMTAgLS0tLQogIH0KICAKICBzdGF0
aWMgUHlPYmplY3QgKgorIGltcF9idWlsdGluX2ltcG9ydF9ob29rKFB5T2JqZWN0
ICpzZWxmLCBQeU9iamVjdCAqYXJncykgeworIAljaGFyICpuYW1lOworIAlQeU9i
amVjdCAqcGF0aCwgKnJlczsKKyAJCisgCWlmICghUHlBcmdfUGFyc2VUdXBsZShh
cmdzLCAic08iLCAmbmFtZSwgJnBhdGgpKQorIAkJcmV0dXJuIE5VTEw7CisgCWlm
IChwYXRoID09IFB5X05vbmUpCisgCQlwYXRoID0gTlVMTDsKKyAJcmVzID0gY2Fs
bF9maW5kX21vZHVsZShuYW1lLCBwYXRoKTsKKyAJaWYgKHJlcyA9PSBOVUxMKSB7
CisgCQlpZiAoIVB5RXJyX0V4Y2VwdGlvbk1hdGNoZXMoUHlFeGNfSW1wb3J0RXJy
b3IpKQorIAkJCXJldHVybiBOVUxMOworIAkJUHlFcnJfQ2xlYXIoKTsKKyAJCVB5
X0lOQ1JFRihQeV9Ob25lKTsKKyAJCXJldHVybiBQeV9Ob25lOworIAl9CisgCXJl
dHVybiBQeV9CdWlsZFZhbHVlKCIoT08pIiwgYnVpbHRpbl9sb2FkZXJfZnVuYywg
cmVzKTsKKyB9CisgCisgc3RhdGljIFB5T2JqZWN0ICoKKyBpbXBfYnVpbHRpbl9s
b2FkZXIoUHlPYmplY3QgKnNlbGYsIFB5T2JqZWN0ICphcmdzKSB7CisgCWNoYXIg
KmZ1bGxuYW1lLCAqcGF0aG5hbWUsICpzdWZmaXgsICptb2RlOworIAlpbnQgdHlw
ZTsKKyAJUHlPYmplY3QgKmRhdGEsICpmb2IsICptb2Q7CisgCUZJTEUgKmZwOwor
IAorIAlpZiAoIVB5QXJnX1BhcnNlVHVwbGUoYXJncywgInNPOmJ1aWx0aW5fbG9h
ZGVyIiwKKyAJCQkgICAgICAmZnVsbG5hbWUsICZkYXRhKSkKKyAJCXJldHVybiBO
VUxMOworIAlpZiAoIVB5QXJnX1BhcnNlVHVwbGUoZGF0YSwgIk9zKHNzaSk6YnVp
bHRpbl9sb2FkZXIiLAorIAkJCSAgICAgICZmb2IsICZwYXRobmFtZSwgJnN1ZmZp
eCwKKyAJCQkgICAgICAmbW9kZSwgJnR5cGUpKQorIAkJcmV0dXJuIE5VTEw7Cisg
CS8qIFhYWCBjaGVjayBtb2RlLCBhcyBpbiBsb2FkX21vZHVsZSwgYnV0IHRoZSBj
b2RlIG5lZWRzIHJlZmFjdG9yaW5nICovCisgCWlmIChmb2IgPT0gUHlfTm9uZSkK
KyAJCWZwID0gTlVMTDsKKyAJZWxzZSB7CisgCQlpZiAoIVB5RmlsZV9DaGVjayhm
b2IpKSB7CisgCQkJUHlFcnJfU2V0U3RyaW5nKFB5RXhjX1ZhbHVlRXJyb3IsCisg
CQkJCSJsb2FkX21vZHVsZSBhcmcjMiBzaG91bGQgYmUgYSBmaWxlIG9yIE5vbmUi
KTsKKyAJCQlyZXR1cm4gTlVMTDsKKyAJCX0KKyAJCWZwID0gZ2V0X2ZpbGUocGF0
aG5hbWUsIGZvYiwgbW9kZSk7CisgCQlpZiAoZnAgPT0gTlVMTCkKKyAJCQlyZXR1
cm4gTlVMTDsKKyAJfQorIAltb2QgPSBsb2FkX21vZHVsZShmdWxsbmFtZSwgZnAs
IHBhdGhuYW1lLCB0eXBlKTsKKyAJaWYgKGZwKQorIAkJZmNsb3NlKGZwKTsKKyAJ
cmV0dXJuIG1vZDsKKyB9CisgCisgc3RhdGljIFB5T2JqZWN0ICoKKyBmaW5kX21v
ZHVsZTIoY2hhciAqc3VibmFtZSwgUHlPYmplY3QgKnBhdGgpCisgeworIAlpbnQg
aSwgbmhvb2tzOworIAlQeU9iamVjdCAqYXJncywgKnJlcyA9IE5VTEw7CisgCVB5
T2JqZWN0ICppbXBvcnRfaG9va3MgPSBQeVN5c19HZXRPYmplY3QoImltcG9ydF9o
b29rcyIpOworIAorIAlpZiAoaW1wb3J0X2hvb2tzID09IE5VTEwgfHwgIVB5TGlz
dF9DaGVjayhpbXBvcnRfaG9va3MpKSB7CisgCQlQeUVycl9TZXRTdHJpbmcoUHlF
eGNfSW1wb3J0RXJyb3IsCisgCQkJCSJzeXMuaW1wb3J0X2hvb2tzIG11c3QgYmUg
YSBsaXN0IG9mIGltcG9ydCBob29rcyIpOworIAkJcmV0dXJuIE5VTEw7CisgCX0K
KyAJaWYgKHBhdGggPT0gTlVMTCkKKyAJCXBhdGggPSBQeV9Ob25lOworIAlhcmdz
ID0gUHlfQnVpbGRWYWx1ZSgiKHNPKSIsIHN1Ym5hbWUsIHBhdGgpOworIAlpZiAo
YXJncyA9PSBOVUxMKQorIAkJcmV0dXJuIE5VTEw7CisgCW5ob29rcyA9IFB5TGlz
dF9TaXplKGltcG9ydF9ob29rcyk7CisgCWZvciAoaSA9IDA7IGkgPCBuaG9va3M7
IGkrKykgeworIAkJUHlPYmplY3QgKmhvb2sgPSBQeUxpc3RfR2V0SXRlbShpbXBv
cnRfaG9va3MsIGkpOworIAkJaWYgKGhvb2sgPT0gTlVMTCkKKyAJCQlnb3RvIGVy
cm9yOworIAkJcmVzID0gUHlPYmplY3RfQ2FsbChob29rLCBhcmdzLCBOVUxMKTsK
KyAJCWlmIChyZXMgPT0gTlVMTCkKKyAJCQlnb3RvIGVycm9yOworIAkJaWYgKHJl
cyAhPSBQeV9Ob25lKQorIAkJCWJyZWFrOworIAkJUHlfREVDUkVGKHJlcyk7Cisg
CQlyZXMgPSBOVUxMOworIAkJY29udGludWU7CisgCX0KKyAJaWYgKHJlcyA9PSBO
VUxMKSB7CisgCQlQeV9JTkNSRUYoUHlfTm9uZSk7CisgCQlyZXMgPSBQeV9Ob25l
OworIAl9CisgZXJyb3I6CisgCVB5X0RFQ1JFRihhcmdzKTsKKyAJcmV0dXJuIHJl
czsKKyB9CisgCisgc3RhdGljIFB5T2JqZWN0ICoKKyBsb2FkX21vZHVsZTIoY2hh
ciAqZnVsbG5hbWUsIFB5T2JqZWN0ICpmaW5kZXJfcmVzdWx0KQorIHsKKyAJUHlP
YmplY3QgKmxvYWRlcmZ1bmMsICpkYXRhLCAqYXJncywgKm1vZDsKKyAJCisgCWlm
ICghUHlBcmdfUGFyc2VUdXBsZShmaW5kZXJfcmVzdWx0LCAiT08iLCAmbG9hZGVy
ZnVuYywgJmRhdGEpKQorIAkJcmV0dXJuIE5VTEw7CisgCWFyZ3MgPSBQeV9CdWls
ZFZhbHVlKCIoc08pIiwgZnVsbG5hbWUsIGRhdGEpOworIAlpZiAoYXJncyA9PSBO
VUxMKQorIAkJcmV0dXJuIE5VTEw7CisgCW1vZCA9IFB5T2JqZWN0X0NhbGwobG9h
ZGVyZnVuYywgYXJncywgTlVMTCk7CisgCVB5X0RFQ1JFRihhcmdzKTsKKyAJaWYg
KG1vZCAhPSBOVUxMICYmIG1vZCAhPSBQeV9Ob25lKSB7CisgCQkvKiBpbnNlcnQg
bW9kdWxlIGluIHN5cy5tb2R1bGVzLCBpZiBpdCBpc24ndCB0aGVyZSB5ZXQgKi8K
KyAJCVB5T2JqZWN0ICptb2R1bGVzID0gUHlJbXBvcnRfR2V0TW9kdWxlRGljdCgp
OworIAkJaWYgKFB5RGljdF9HZXRJdGVtU3RyaW5nKG1vZHVsZXMsIGZ1bGxuYW1l
KSA9PSBOVUxMKQorIAkJCVB5RGljdF9TZXRJdGVtU3RyaW5nKG1vZHVsZXMsIGZ1
bGxuYW1lLCBtb2QpOworIAl9CisgCXJldHVybiBtb2Q7CisgfQorIAorIHN0YXRp
YyBQeU9iamVjdCAqCiAgaW1wb3J0X3N1Ym1vZHVsZShQeU9iamVjdCAqbW9kLCBj
aGFyICpzdWJuYW1lLCBjaGFyICpmdWxsbmFtZSkKICB7CiAgCVB5T2JqZWN0ICpt
b2R1bGVzID0gUHlJbXBvcnRfR2V0TW9kdWxlRGljdCgpOwoqKioqKioqKioqKioq
KioKKioqIDE5NzYsMTk4NCAqKioqCiAgCX0KICAJZWxzZSB7CiAgCQlQeU9iamVj
dCAqcGF0aDsKLSAJCWNoYXIgYnVmW01BWFBBVEhMRU4rMV07Ci0gCQlzdHJ1Y3Qg
ZmlsZWRlc2NyICpmZHA7Ci0gCQlGSUxFICpmcCA9IE5VTEw7CiAgCiAgCQlpZiAo
bW9kID09IFB5X05vbmUpCiAgCQkJcGF0aCA9IE5VTEw7Ci0tLSAyMTIwLDIxMjUg
LS0tLQoqKioqKioqKioqKioqKioKKioqIDE5OTEsMjAwOSAqKioqCiAgCQkJfQog
IAkJfQogIAohIAkJYnVmWzBdID0gJ1wwJzsKISAJCWZkcCA9IGZpbmRfbW9kdWxl
KHN1Ym5hbWUsIHBhdGgsIGJ1ZiwgTUFYUEFUSExFTisxLCAmZnApOwohIAkJUHlf
WERFQ1JFRihwYXRoKTsKISAJCWlmIChmZHAgPT0gTlVMTCkgewohIAkJCWlmICgh
UHlFcnJfRXhjZXB0aW9uTWF0Y2hlcyhQeUV4Y19JbXBvcnRFcnJvcikpCiEgCQkJ
CXJldHVybiBOVUxMOwohIAkJCVB5RXJyX0NsZWFyKCk7CiAgCQkJUHlfSU5DUkVG
KFB5X05vbmUpOwogIAkJCXJldHVybiBQeV9Ob25lOwogIAkJfQohIAkJbSA9IGxv
YWRfbW9kdWxlKGZ1bGxuYW1lLCBmcCwgYnVmLCBmZHAtPnR5cGUpOwohIAkJaWYg
KGZwKQohIAkJCWZjbG9zZShmcCk7CiAgCQlpZiAobW9kICE9IFB5X05vbmUpIHsK
ICAJCQkvKiBJcnJlc3BlY3RpdmUgb2YgdGhlIHN1Y2Nlc3Mgb2YgdGhpcyBsb2Fk
LCBtYWtlIGEKICAJCQkgICByZWZlcmVuY2UgdG8gaXQgaW4gdGhlIHBhcmVudCBw
YWNrYWdlIG1vZHVsZS4KLS0tIDIxMzIsMjE0OCAtLS0tCiAgCQkJfQogIAkJfQog
IAohIAkJcmVzID0gZmluZF9tb2R1bGUyKHN1Ym5hbWUsIHBhdGgpOwohIAkJaWYg
KHJlcyA9PSBOVUxMKQohIAkJCS8qIGZpbmRpbmcgcmFpc2VkIGFuIGVycm9yICov
CiEgCQkJcmV0dXJuIE5VTEw7CiEgCQlpZiAocmVzID09IFB5X05vbmUpIHsKISAJ
CQkvKiB0aGUgbW9kdWxlIHdhc24ndCBmb3VuZCAqLwogIAkJCVB5X0lOQ1JFRihQ
eV9Ob25lKTsKICAJCQlyZXR1cm4gUHlfTm9uZTsKICAJCX0KISAJCW0gPSBsb2Fk
X21vZHVsZTIoZnVsbG5hbWUsIHJlcyk7CiEgCiAgCQlpZiAobW9kICE9IFB5X05v
bmUpIHsKICAJCQkvKiBJcnJlc3BlY3RpdmUgb2YgdGhlIHN1Y2Nlc3Mgb2YgdGhp
cyBsb2FkLCBtYWtlIGEKICAJCQkgICByZWZlcmVuY2UgdG8gaXQgaW4gdGhlIHBh
cmVudCBwYWNrYWdlIG1vZHVsZS4KKioqKioqKioqKioqKioqCioqKiAyNzI0LDI3
MjkgKioqKgotLS0gMjg2MywyODcyIC0tLS0KICAJaWYgKHNldGludChkLCAiUFlf
RlJPWkVOIiwgUFlfRlJPWkVOKSA8IDApIGdvdG8gZmFpbHVyZTsKICAJaWYgKHNl
dGludChkLCAiUFlfQ09ERVJFU09VUkNFIiwgUFlfQ09ERVJFU09VUkNFKSA8IDAp
IGdvdG8gZmFpbHVyZTsKICAKKyAJaWYgKFB5RGljdF9TZXRJdGVtU3RyaW5nKGQs
ICJidWlsdGluX2ltcG9ydF9ob29rIiwgYnVpbHRpbl9pbXBvcnRfaG9va19mdW5j
KSA8IDApCisgCQlnb3RvIGZhaWx1cmU7CisgCWlmIChQeURpY3RfU2V0SXRlbVN0
cmluZyhkLCAiYnVpbHRpbl9sb2FkZXIiLCBidWlsdGluX2xvYWRlcl9mdW5jKSA8
IDApCisgCQlnb3RvIGZhaWx1cmU7CiAgICBmYWlsdXJlOgogIAk7CiAgfQo=
--41333375-49397760-3247867773=:9006--