ImageLoader: spawn one thread per image. fix #93
In the process of fixing #93, I realized that we were spawning new threads to fetch images for each update (we only need one).
This commit is contained in:
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -1,3 +1,3 @@
|
|||||||
docs/ export-ignore
|
docs/ export-ignore
|
||||||
resources/
|
resources/
|
||||||
!resources/*.base64
|
!resources/*.base64
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
# Why?
|
# Why?
|
||||||
Why do you want to use fancy symbols in your standard monospace font? Obviously to have a fancy prompt like mine :-)
|
Why do you want to use fancy symbols in your standard monospace font? Obviously to have a fancy prompt like mine :-)
|
||||||
|
|
||||||

|
<!--  -->
|
||||||
|
|
||||||
And because when you live in a terminal a symbol can convey more informations in less space creating a dense and beautiful (for those who have a certain aesthetic taste) informative workspace
|
And because when you live in a terminal a symbol can convey more informations in less space creating a dense and beautiful (for those who have a certain aesthetic taste) informative workspace
|
||||||
|
|
||||||
|
|||||||
@ -25,13 +25,6 @@ markdowner = Markdown(extras=["fenced-code-blocks", "cuddled-lists"])
|
|||||||
# does it stupidly throw them out? (we could implement something of our own)
|
# does it stupidly throw them out? (we could implement something of our own)
|
||||||
executor = concurrent.futures.ThreadPoolExecutor(max_workers=5)
|
executor = concurrent.futures.ThreadPoolExecutor(max_workers=5)
|
||||||
|
|
||||||
images_cache = {}
|
|
||||||
|
|
||||||
|
|
||||||
class LoadingError(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def markdown2html(markdown, basepath, re_render, resources, viewport_width):
|
def markdown2html(markdown, basepath, re_render, resources, viewport_width):
|
||||||
""" converts the markdown to html, loads the images and puts in base64 for sublime
|
""" converts the markdown to html, loads the images and puts in base64 for sublime
|
||||||
to understand them correctly. That means that we are responsible for loading the
|
to understand them correctly. That means that we are responsible for loading the
|
||||||
@ -59,12 +52,7 @@ def markdown2html(markdown, basepath, re_render, resources, viewport_width):
|
|||||||
# realpath: simplify that paths so that we don't have duplicated caches
|
# realpath: simplify that paths so that we don't have duplicated caches
|
||||||
path = os.path.realpath(os.path.expanduser(os.path.join(basepath, src)))
|
path = os.path.realpath(os.path.expanduser(os.path.join(basepath, src)))
|
||||||
|
|
||||||
try:
|
base64, (width, height) = get_base64_image(path, re_render, resources)
|
||||||
base64, (width, height) = get_base64_image(path, re_render)
|
|
||||||
except FileNotFoundError as e:
|
|
||||||
base64, (width, height) = resources["base64_404_image"]
|
|
||||||
except LoadingError:
|
|
||||||
base64, (width, height) = resources["base64_loading_image"]
|
|
||||||
|
|
||||||
img_element["src"] = base64
|
img_element["src"] = base64
|
||||||
if width > viewport_width:
|
if width > viewport_width:
|
||||||
@ -100,8 +88,10 @@ def markdown2html(markdown, basepath, re_render, resources, viewport_width):
|
|||||||
"<br/>", "<br />"
|
"<br/>", "<br />"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
images_cache = {}
|
||||||
|
images_loading = []
|
||||||
|
|
||||||
def get_base64_image(path, re_render):
|
def get_base64_image(path, re_render, resources):
|
||||||
""" Gets the base64 for the image (local and remote images). re_render is a
|
""" Gets the base64 for the image (local and remote images). re_render is a
|
||||||
callback which is called when we finish loading an image from the internet
|
callback which is called when we finish loading an image from the internet
|
||||||
to trigger an update of the preview (the image will then be loaded from the cache)
|
to trigger an update of the preview (the image will then be loaded from the cache)
|
||||||
@ -109,13 +99,20 @@ def get_base64_image(path, re_render):
|
|||||||
return base64_data, (width, height)
|
return base64_data, (width, height)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def callback(path, future):
|
def callback(path, resources, future):
|
||||||
# altering images_cache is "safe" to do because callback is called in the same
|
# altering images_cache is "safe" to do because callback is called in the same
|
||||||
# thread as add_done_callback:
|
# thread as add_done_callback:
|
||||||
# > Added callables are called in the order that they were added and are always
|
# > Added callables are called in the order that they were added and are always
|
||||||
# > called in a thread belonging to the process that added them
|
# > called in a thread belonging to the process that added them
|
||||||
# > --- Python docs
|
# > --- Python docs
|
||||||
images_cache[path] = future.result()
|
try:
|
||||||
|
images_cache[path] = future.result()
|
||||||
|
except urllib.error.HTTPError as e:
|
||||||
|
images_cache[path] = resources['base64_404_image']
|
||||||
|
print("Error loading {!r}: {!r}".format(path, e))
|
||||||
|
|
||||||
|
images_loading.remove(path)
|
||||||
|
|
||||||
# we render, which means this function will be called again, but this time, we
|
# we render, which means this function will be called again, but this time, we
|
||||||
# will read from the cache
|
# will read from the cache
|
||||||
re_render()
|
re_render()
|
||||||
@ -124,8 +121,11 @@ def get_base64_image(path, re_render):
|
|||||||
return images_cache[path]
|
return images_cache[path]
|
||||||
|
|
||||||
if path.startswith("http://") or path.startswith("https://"):
|
if path.startswith("http://") or path.startswith("https://"):
|
||||||
executor.submit(load_image, path).add_done_callback(partial(callback, path))
|
# FIXME: submiting a load of loaders, we should only have one
|
||||||
raise LoadingError()
|
if path not in images_loading:
|
||||||
|
executor.submit(load_image, path).add_done_callback(partial(callback, path, resources))
|
||||||
|
images_loading.append(path)
|
||||||
|
return resources['base64_loading_image']
|
||||||
|
|
||||||
with open(path, "rb") as fhandle:
|
with open(path, "rb") as fhandle:
|
||||||
image_content = fhandle.read()
|
image_content = fhandle.read()
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@ -26,6 +26,7 @@ def make_cache(image_name):
|
|||||||
width, height = get_image_size(png)
|
width, height = get_image_size(png)
|
||||||
png.seek(0)
|
png.seek(0)
|
||||||
base64.write(bytes("{}\n{}\n".format(width, height), encoding="utf-8"))
|
base64.write(bytes("{}\n{}\n".format(width, height), encoding="utf-8"))
|
||||||
|
base64.write(b'data:image/png;base64,')
|
||||||
base64.write(b64encode(png.read()))
|
base64.write(b64encode(png.read()))
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user