@@ -1557,59 +1557,113 @@ def DetectTarBombCatFileArray(listarrayfiles,
15571557 }
15581558
15591559
1560- def MkTempFile(data=None, inmem=__use_inmemfile__, isbytes=True, prefix=__project__,
1561- delete=True, encoding="utf-8"):
1560+ def _normalize_initial_data(data, isbytes, encoding):
15621561 """
1563- Return a file-like handle.
1564- - If inmem=True: returns StringIO (text) or BytesIO (bytes).
1565- - If inmem=False: returns a NamedTemporaryFile opened in text or binary mode.
1566- Args:
1567- data: optional initial content; if provided, it's written and the handle is seek(0)
1568- inmem: bool — return in-memory handle if True
1569- isbytes: bool — choose bytes (True) or text (False)
1570- prefix: str — tempfile prefix
1571- delete: bool — whether the tempfile is deleted on close (NamedTemporaryFile)
1572- encoding: str — used for text mode (and for conversions when needed)
1562+ Coerce `data` to the correct type for the chosen mode:
1563+ - bytes mode: return `bytes` (Py2: str; Py3: bytes)
1564+ - text mode : return unicode/str (Py2: unicode; Py3: str)
15731565 """
1574- init = _normalize_initial_data(data, isbytes, encoding)
1575-
1576- if inmem:
1577- buf = BytesIO() if isbytes else StringIO()
1578- if init is not None:
1579- buf.write(init)
1580- buf.seek(0)
1581- return buf
1582-
1583- mode = "wb+" if isbytes else "w+"
1584- kwargs = {"prefix": prefix or "", "delete": delete, "mode": mode}
1566+ if data is None:
1567+ return None
15851568
1586- # Only Python 3's text-mode files accept encoding/newline explicitly
1587- if not isbytes and sys.version_info[0] >= 3:
1588- kwargs["encoding"] = encoding
1589- kwargs["newline"] = ""
1569+ if isbytes:
1570+ # Need a byte sequence
1571+ if isinstance(data, bytes):
1572+ return data
1573+ if isinstance(data, bytearray):
1574+ return bytes(data)
1575+ # memoryview may not exist on very old Py2 builds; guard dynamically
1576+ mv_t = getattr(__builtins__, 'memoryview', type(None))
1577+ if isinstance(data, mv_t):
1578+ return bytes(data)
1579+ if isinstance(data, str):
1580+ # Py2 str is already bytes; Py3 str must be encoded
1581+ return data if PY2 else data.encode(encoding)
1582+ if PY2 and isinstance(data, unicode): # noqa: F821 (unicode only in Py2)
1583+ return data.encode(encoding)
1584+ raise TypeError("data must be bytes-like or text for isbytes=True (got %r)" % (type(data),))
1585+ else:
1586+ # Need text (unicode in Py2, str in Py3)
1587+ if PY2:
1588+ if isinstance(data, unicode): # noqa: F821
1589+ return data
1590+ if isinstance(data, str):
1591+ return data.decode(encoding)
1592+ if isinstance(data, bytearray):
1593+ return bytes(data).decode(encoding)
1594+ mv_t = getattr(__builtins__, 'memoryview', type(None))
1595+ if isinstance(data, mv_t):
1596+ return bytes(data).decode(encoding)
1597+ raise TypeError("data must be unicode or bytes-like for text mode (got %r)" % (type(data),))
1598+ else:
1599+ if isinstance(data, str):
1600+ return data
1601+ if isinstance(data, (bytes, bytearray, memoryview)):
1602+ return bytes(data).decode(encoding)
1603+ raise TypeError("data must be str or bytes-like for text mode (got %r)" % (type(data),))
1604+
1605+ def MkTempFile(data=None,
1606+ inmem=True,
1607+ isbytes=True,
1608+ prefix="",
1609+ delete=True,
1610+ encoding="utf-8",
1611+ newline=None, # Py3 text only; ignored by Py2 temp classes
1612+ dir=None,
1613+ suffix="",
1614+ # spooled option (RAM until threshold, then rolls to disk)
1615+ use_spool=False,
1616+ spool_max=8 * 1024 * 1024,
1617+ spool_dir=None):
1618+ """
1619+ Return a file-like handle with consistent behavior on Py2.7 and Py3.x.
15901620
1591- f = tempfile.NamedTemporaryFile(**kwargs)
1621+ - inmem=True -> BytesIO (bytes) or StringIO (text)
1622+ - inmem=False, use_spool=True -> SpooledTemporaryFile (RAM -> disk after spool_max)
1623+ - inmem=False, use_spool=False -> NamedTemporaryFile (on disk)
15921624
1593- if init is not None:
1594- f.write(init)
1595- f.seek(0)
1596- return f
1625+ If `data` is provided, it's written and the handle is rewound to position 0.
1626+ """
1627+ init = _normalize_initial_data(data, isbytes, encoding)
15971628
1629+ # -------- In-memory --------
1630+ if inmem:
1631+ if isbytes:
1632+ return BytesIO(init if init is not None else b"")
1633+ else:
1634+ # Py2 needs unicode literal for empty default
1635+ return StringIO(init if init is not None else (u"" if PY2 else ""))
15981636
1599- def MkTempFileSmart(data=None, isbytes=True, prefix=__project__, max_mem=1024*1024, encoding="utf-8"):
1600- """
1601- Spooled temp file: starts in memory and spills to disk past max_mem.
1602- Behaves like BytesIO/StringIO for small data, with the same preload+seek(0) behavior.
1603- """
1604- mode = "wb+" if isbytes else "w+"
1605- kwargs = {"mode": mode, "max_size": max_mem, "prefix": prefix or ""}
1606- if not isbytes and sys.version_info[0] >= 3:
1607- kwargs["encoding"] = encoding
1608- kwargs["newline"] = ""
1637+ # -------- Spooled (RAM then disk) --------
1638+ if use_spool:
1639+ if isbytes:
1640+ f = tempfile.SpooledTemporaryFile(max_size=spool_max, mode="w+b", dir=spool_dir)
1641+ else:
1642+ if PY2:
1643+ # Py2 SpooledTemporaryFile doesn't accept encoding/newline
1644+ f = tempfile.SpooledTemporaryFile(max_size=spool_max, mode="w+", dir=spool_dir)
1645+ else:
1646+ f = tempfile.SpooledTemporaryFile(max_size=spool_max, mode="w+",
1647+ dir=spool_dir, encoding=encoding, newline=newline)
1648+ if init is not None:
1649+ f.write(init)
1650+ f.seek(0)
1651+ return f
16091652
1610- f = tempfile.SpooledTemporaryFile(**kwargs)
1653+ # -------- On-disk temp --------
1654+ if isbytes:
1655+ f = tempfile.NamedTemporaryFile(mode="w+b", prefix=prefix or "", suffix=suffix,
1656+ dir=dir, delete=delete)
1657+ else:
1658+ if PY2:
1659+ # Py2 temp files don't accept encoding/newline; writes of unicode will be encoded
1660+ # using the default encoding. If you need strict control, wrap with codecs/io.open.
1661+ f = tempfile.NamedTemporaryFile(mode="w+", prefix=prefix or "", suffix=suffix,
1662+ dir=dir, delete=delete)
1663+ else:
1664+ f = tempfile.NamedTemporaryFile(mode="w+", prefix=prefix or "", suffix=suffix,
1665+ dir=dir, delete=delete, encoding=encoding, newline=newline)
16111666
1612- init = _normalize_initial_data(data, isbytes, encoding)
16131667 if init is not None:
16141668 f.write(init)
16151669 f.seek(0)
0 commit comments