Merge pull request #16 from wanadev/8-unicode-paths

Handling unicode paths
This commit is contained in:
Fabien LOISON 2018-06-13 14:16:43 +02:00 committed by GitHub
commit ebe7bbaee2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 56 additions and 80 deletions

View File

@ -36,38 +36,38 @@ class Test_model_helpers(object):
assert helpers.normalize_path(
u"somE_valid-caractères of files.png") == "some_valid-caracteres of files.png" # noqa
def test_normalize_textures(self):
textures = helpers.normalize_textures({
def test_normalize_paths(self):
paths = helpers.normalize_paths({
"./images\\texture-1.png": True,
"images/texture-2.png": True,
})
assert "images/texture-1.png" in textures
assert "images/texture-2.png" in textures
assert "images/texture-1.png" in paths
assert "images/texture-2.png" in paths
with pytest.raises(ValueError):
helpers.normalize_textures({
helpers.normalize_paths({
"images/texture.png": True,
"./images/texture.png": True,
})
def test_find_valid_texture_path(self):
textures = dict({
def test_find_valid_path(self):
paths = dict({
"images/texture.png": True,
"images/texture.jpg": True,
"other_images/texture.jpg": True,
"texture.gif": True,
})
assert helpers.find_valid_texture_path(
"images/texture.png", textures) == "images/texture.png"
assert helpers.find_valid_texture_path(
"images/texture.jpg", textures) == "images/texture.jpg"
assert helpers.find_valid_texture_path(
"texture.png", textures) == "images/texture.png"
assert helpers.find_valid_path(
"images/texture.png", paths) == "images/texture.png"
assert helpers.find_valid_path(
"images/texture.jpg", paths) == "images/texture.jpg"
assert helpers.find_valid_path(
"texture.png", paths) == "images/texture.png"
assert helpers.find_valid_texture_path(
"texture.jpg", textures) is None
assert helpers.find_valid_texture_path(
"non-existing.png", textures) is None
assert helpers.find_valid_texture_path(
"exture.png", textures) is None
assert helpers.find_valid_path(
"texture.jpg", paths) is None
assert helpers.find_valid_path(
"non-existing.png", paths) is None
assert helpers.find_valid_path(
"exture.png", paths) is None

View File

@ -23,7 +23,7 @@ def optimize(input_file, output_file, options={}, textures=None,
if not hasattr(input_file, "read"):
input_file = open(input_file, "rb")
root_path = "."
root_path = None
if hasattr(input_file, "name"):
root_path = os.path.dirname(os.path.abspath(input_file.name))

View File

@ -1,6 +1,7 @@
from ._assimp import ffi
import io
import sys
import os.path
import unidecode
@ -35,65 +36,30 @@ def normalize_path(path):
return "/".join(normalized_path[::-1]).lower()
def normalize_textures(textures):
if textures is None:
def normalize_paths(paths):
if paths is None:
return None
# Normalizes all the paths in the texture dict.
normalized_textures = dict()
for path in textures:
normalized_paths = dict()
for path in paths:
normalized_path = normalize_path(path)
if normalized_path in normalized_textures:
raise ValueError("Multiple textures are resolved to the same path %s." % normalized_path) # noqa
normalized_textures[normalized_path] = textures[path]
if normalized_path in normalized_paths:
raise ValueError("Multiple paths are resolved to the same path %s." % normalized_path) # noqa
normalized_paths[normalized_path] = paths[path]
return normalized_textures
return normalized_paths
def find_valid_path(path, root_path):
# Note: we cannot use normalized paths here,
# because we need to find a file on the system.
def find_valid_path(path, paths):
if paths is None:
return None
tested_path = path
if os.path.isfile(tested_path):
return tested_path
tested_path = os.path.join(root_path, path)
if os.path.isfile(tested_path):
return tested_path
tested_path = os.path.join(root_path, os.path.basename(path))
if os.path.isfile(tested_path):
return tested_path
# Still not able to find it, it might be a Windows path,
# while this program is executed on Linux.
# So paths like "..\\image.png" are seen as entire filename,
# we try some trick.
path = path.replace("\\", "/")
tested_path = path
if os.path.isfile(tested_path):
return tested_path
tested_path = os.path.join(root_path, path)
if os.path.isfile(tested_path):
return tested_path
tested_path = os.path.join(root_path, os.path.basename(path))
if os.path.isfile(tested_path):
return tested_path
return None
def find_valid_texture_path(path, textures):
# The path and the textures' paths are supposed to have
# The path and the paths are supposed to have
# already been normalized.
split_path = path.split("/")[::-1]
split_paths = map(lambda p: p.split("/")[::-1], textures.keys())
split_paths = map(lambda p: p.split("/")[::-1], paths.keys())
for i, name in enumerate(split_path):
split_paths = list(filter(lambda sp: len(sp) > i and sp[i] == name, split_paths)) # noqa
@ -106,11 +72,24 @@ def find_valid_texture_path(path, textures):
return None
def extract_files_dictionary(root_path):
if root_path is None:
return None
if sys.version_info.major == 2 and type(root_path) is str:
root_path = root_path.decode("utf-8")
# Recursive walk of root_path files
files = [os.path.join(dp, f) for dp, dn, filenames in os.walk(root_path) for f in filenames] # noqa
return normalize_paths(dict(zip(files, files)))
def model_embed_images(images, images_bytes,
optimize_textures, fallback_texture, root_path,
image_options, textures, quiet):
optimized_textures = {}
normalized_textures = normalize_textures(textures)
normalized_textures = normalize_paths(textures)
files = extract_files_dictionary(root_path)
image = images
while image:
@ -120,23 +99,20 @@ def model_embed_images(images, images_bytes,
image_path = ffi.string(image.path).decode("utf-8")
# If textures exists, we don't look for files on the file system
valid_image_path = None
normalized_image_path = normalize_path(image_path)
if normalized_textures is not None:
valid_image_path = normalize_path(image_path)
valid_image_path = find_valid_texture_path(valid_image_path, normalized_textures) # noqa
valid_image_path = find_valid_path(normalized_image_path, normalized_textures) # noqa
else:
valid_image_path = find_valid_path(image_path, root_path)
if valid_image_path is not None:
valid_image_path = os.path.abspath(valid_image_path)
valid_image_path = find_valid_path(normalized_image_path, files)
# Unable to find a valid image path
if valid_image_path is None:
if fallback_texture is not None:
if not quiet:
print("Warning: Cannot resolve file %s, using the fallback texture instead." % image_path) # noqa
valid_image_path = None
if not quiet:
print("Warning: Cannot resolve %s, using the fallback texture instead." % normalized_image_path) # noqa
else:
raise ValueError("Cannot resolve file %s" % image_path)
raise ValueError("Cannot resolve %s" % normalized_image_path)
# If valid_image_path have already been seen, do not reoptimize...
if valid_image_path in optimized_textures:
@ -154,13 +130,13 @@ def model_embed_images(images, images_bytes,
elif textures is not None:
image_io = textures[valid_image_path]
else:
image_io = io.BytesIO(open(valid_image_path, "rb").read())
image_io = io.BytesIO(open(files[valid_image_path], "rb").read())
# Optimizing the texture if requested
if optimize_textures:
if not quiet:
if valid_image_path is not None:
print("Optimizing texture %s..." % valid_image_path)
print("Optimizing texture %s..." % normalized_image_path)
else:
print("Optimizing fallback texture...")
output_io = io.BytesIO()