Buckets are used to store the bytecode for one template. It's created and initialized by the bytecode cache and passed to the loading functions. The buckets get an internal checksum from the cache assigned and use this to automatically reject outdated cache material. Individual byteco
| 44 | |
| 45 | |
| 46 | class Bucket: |
| 47 | """Buckets are used to store the bytecode for one template. It's created |
| 48 | and initialized by the bytecode cache and passed to the loading functions. |
| 49 | |
| 50 | The buckets get an internal checksum from the cache assigned and use this |
| 51 | to automatically reject outdated cache material. Individual bytecode |
| 52 | cache subclasses don't have to care about cache invalidation. |
| 53 | """ |
| 54 | |
| 55 | def __init__(self, environment: "Environment", key: str, checksum: str) -> None: |
| 56 | self.environment = environment |
| 57 | self.key = key |
| 58 | self.checksum = checksum |
| 59 | self.reset() |
| 60 | |
| 61 | def reset(self) -> None: |
| 62 | """Resets the bucket (unloads the bytecode).""" |
| 63 | self.code: t.Optional[CodeType] = None |
| 64 | |
| 65 | def load_bytecode(self, f: t.BinaryIO) -> None: |
| 66 | """Loads bytecode from a file or file like object.""" |
| 67 | # make sure the magic header is correct |
| 68 | magic = f.read(len(bc_magic)) |
| 69 | if magic != bc_magic: |
| 70 | self.reset() |
| 71 | return |
| 72 | # the source code of the file changed, we need to reload |
| 73 | checksum = pickle.load(f) |
| 74 | if self.checksum != checksum: |
| 75 | self.reset() |
| 76 | return |
| 77 | # if marshal_load fails then we need to reload |
| 78 | try: |
| 79 | self.code = marshal.load(f) |
| 80 | except (EOFError, ValueError, TypeError): |
| 81 | self.reset() |
| 82 | return |
| 83 | |
| 84 | def write_bytecode(self, f: t.IO[bytes]) -> None: |
| 85 | """Dump the bytecode into the file or file like object passed.""" |
| 86 | if self.code is None: |
| 87 | raise TypeError("can't write empty bucket") |
| 88 | f.write(bc_magic) |
| 89 | pickle.dump(self.checksum, f, 2) |
| 90 | marshal.dump(self.code, f) |
| 91 | |
| 92 | def bytecode_from_string(self, string: bytes) -> None: |
| 93 | """Load bytecode from bytes.""" |
| 94 | self.load_bytecode(BytesIO(string)) |
| 95 | |
| 96 | def bytecode_to_string(self) -> bytes: |
| 97 | """Return the bytecode as bytes.""" |
| 98 | out = BytesIO() |
| 99 | self.write_bytecode(out) |
| 100 | return out.getvalue() |
| 101 | |
| 102 | |
| 103 | class BytecodeCache: |
no outgoing calls