Coverage for src/lektor_ng/filecontents.py: 43%
72 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-08-03 16:19 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-08-03 16:19 +0000
1import base64
2import codecs
3import hashlib
4import mimetypes
5import os
7from lektor_ng.utils import deprecated
10class FileContents:
11 @deprecated(name="FileContents", version="3.4.0")
12 def __init__(self, filename):
13 self.filename = filename
14 self._md5 = None
15 self._sha1 = None
16 self._integrity = None
17 self._mimetype = mimetypes.guess_type(filename)[0] or "application/octet-stream"
19 @property
20 def sha1(self):
21 self._ensure_hashes()
22 return self._sha1
24 @property
25 def md5(self):
26 self._ensure_hashes()
27 return self._md5
29 @property
30 def integrity(self):
31 self._ensure_hashes()
32 return self._integrity
34 @property
35 def mimetype(self):
36 return self._mimetype
38 @property
39 def bytes(self):
40 try:
41 return os.stat(self.filename).st_size
42 except OSError:
43 return 0
45 def as_data_url(self, mediatype=None):
46 if mediatype is None:
47 mediatype = self.mimetype
48 return f"data:{mediatype};base64,{self.as_base64()}"
50 def as_text(self):
51 with self.open() as f:
52 return f.read()
54 def as_bytes(self):
55 with self.open("rb") as f:
56 return f.read()
58 def as_base64(self):
59 return base64.b64encode(self.as_bytes())
61 def open(self, mode="r", encoding=None):
62 if mode == "rb":
63 return open(self.filename, "rb")
64 if mode != "r":
65 raise TypeError("Can only open files for reading")
66 # pylint: disable=deprecated-method
67 return codecs.open(self.filename, encoding=encoding or "utf-8")
69 def _ensure_hashes(self):
70 if self._md5 is not None:
71 return
72 with self.open("rb") as f:
73 md5 = hashlib.md5()
74 sha1 = hashlib.sha1()
75 sha384 = hashlib.sha384()
76 while 1:
77 chunk = f.read(16384)
78 if not chunk:
79 break
80 md5.update(chunk)
81 sha1.update(chunk)
82 sha384.update(chunk)
83 self._md5 = md5.hexdigest()
84 self._sha1 = sha1.hexdigest()
85 self._integrity = "sha384-" + base64.b64encode(sha384.digest()).decode("ascii")
87 def __repr__(self):
88 return f"<FileContents {self.filename!r} md5={self.md5!r}>"