| 67 | |
| 68 | @contextlib.contextmanager |
| 69 | def tzpath_context(self, tzpath, block_tzdata=True, lock=TZPATH_LOCK): |
| 70 | def pop_tzdata_modules(): |
| 71 | tzdata_modules = {} |
| 72 | for modname in list(sys.modules): |
| 73 | if modname.split(".", 1)[0] != "tzdata": # pragma: nocover |
| 74 | continue |
| 75 | |
| 76 | tzdata_modules[modname] = sys.modules.pop(modname) |
| 77 | |
| 78 | return tzdata_modules |
| 79 | |
| 80 | with lock: |
| 81 | if block_tzdata: |
| 82 | # In order to fully exclude tzdata from the path, we need to |
| 83 | # clear the sys.modules cache of all its contents — setting the |
| 84 | # root package to None is not enough to block direct access of |
| 85 | # already-imported submodules (though it will prevent new |
| 86 | # imports of submodules). |
| 87 | tzdata_modules = pop_tzdata_modules() |
| 88 | sys.modules["tzdata"] = None |
| 89 | |
| 90 | old_path = self.module.TZPATH |
| 91 | try: |
| 92 | self.module.reset_tzpath(tzpath) |
| 93 | yield |
| 94 | finally: |
| 95 | if block_tzdata: |
| 96 | sys.modules.pop("tzdata") |
| 97 | for modname, module in tzdata_modules.items(): |
| 98 | sys.modules[modname] = module |
| 99 | |
| 100 | self.module.reset_tzpath(old_path) |