|
29 | 29 | from bson.tz_util import utc
|
30 | 30 |
|
31 | 31 | _MAX_COUNTER_VALUE = 0xFFFFFF
|
| 32 | +_PACK_INT = struct.Struct(">I").pack |
| 33 | +_PACK_INT_RANDOM = struct.Struct(">I5s").pack |
| 34 | +_UNPACK_INT = struct.Struct(">I").unpack |
32 | 35 |
|
33 | 36 |
|
34 | 37 | def _raise_invalid_id(oid: str) -> NoReturn:
|
@@ -132,7 +135,7 @@ def from_datetime(cls: Type[ObjectId], generation_time: datetime.datetime) -> Ob
|
132 | 135 | if offset is not None:
|
133 | 136 | generation_time = generation_time - offset
|
134 | 137 | timestamp = calendar.timegm(generation_time.timetuple())
|
135 |
| - oid = struct.pack(">I", int(timestamp)) + b"\x00\x00\x00\x00\x00\x00\x00\x00" |
| 138 | + oid = _PACK_INT(int(timestamp)) + b"\x00\x00\x00\x00\x00\x00\x00\x00" |
136 | 139 | return cls(oid)
|
137 | 140 |
|
138 | 141 | @classmethod
|
@@ -163,18 +166,12 @@ def _random(cls) -> bytes:
|
163 | 166 |
|
164 | 167 | def __generate(self) -> None:
|
165 | 168 | """Generate a new value for this ObjectId."""
|
166 |
| - # 4 bytes current time |
167 |
| - oid = struct.pack(">I", int(time.time())) |
168 |
| - |
169 |
| - # 5 bytes random |
170 |
| - oid += ObjectId._random() |
171 |
| - |
172 |
| - # 3 bytes inc |
173 | 169 | with ObjectId._inc_lock:
|
174 |
| - oid += struct.pack(">I", ObjectId._inc)[1:4] |
175 |
| - ObjectId._inc = (ObjectId._inc + 1) % (_MAX_COUNTER_VALUE + 1) |
| 170 | + inc = ObjectId._inc |
| 171 | + ObjectId._inc = (inc + 1) % (_MAX_COUNTER_VALUE + 1) |
176 | 172 |
|
177 |
| - self.__id = oid |
| 173 | + # 4 bytes current time, 5 bytes random, 3 bytes inc. |
| 174 | + self.__id = _PACK_INT_RANDOM(int(time.time()), ObjectId._random()) + _PACK_INT(inc)[1:4] |
178 | 175 |
|
179 | 176 | def __validate(self, oid: Any) -> None:
|
180 | 177 | """Validate and use the given id for this ObjectId.
|
@@ -212,7 +209,7 @@ def generation_time(self) -> datetime.datetime:
|
212 | 209 | represents the generation time in UTC. It is precise to the
|
213 | 210 | second.
|
214 | 211 | """
|
215 |
| - timestamp = struct.unpack(">I", self.__id[0:4])[0] |
| 212 | + timestamp = _UNPACK_INT(self.__id[0:4])[0] |
216 | 213 | return datetime.datetime.fromtimestamp(timestamp, utc)
|
217 | 214 |
|
218 | 215 | def __getstate__(self) -> bytes:
|
|
0 commit comments