Skip to content

Commit 3a215b0

Browse files
committed
[fdiff.diff] initial implementation of remote font file support via URL
1 parent 6f3924c commit 3a215b0

File tree

1 file changed

+75
-33
lines changed

1 file changed

+75
-33
lines changed

lib/fdiff/diff.py

Lines changed: 75 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1+
import asyncio
12
import os
23
import tempfile
34

45
from fontTools.ttLib import TTFont
56

7+
from fdiff.remote import (
8+
_get_filepath_from_url,
9+
create_async_get_request_session_and_run,
10+
)
611
from fdiff.utils import get_file_modtime
712
from fdiff.thirdparty.fdifflib import unified_diff
813

@@ -25,38 +30,75 @@ def u_diff(
2530
:returns: Generator of ordered diff line strings that include newline line endings
2631
:raises: KeyError if include_tables or exclude_tables includes a mis-specified table
2732
that is not included in filepath_a OR filepath_b"""
28-
tt_left = TTFont(filepath_a)
29-
tt_right = TTFont(filepath_b)
30-
31-
# Validation: include_tables request should be for tables that are in one of
32-
# the two fonts. This otherwise silently passes with exit status code 0 which
33-
# could lead to the interpretation of no diff between two files when the table
34-
# entry is incorrectly defined or is a typo. Let's be conservative and consider
35-
# this an error, force user to use explicit definitions that include tables in
36-
# one of the two files, and understand that the diff request was for one or more
37-
# tables that are not present.
38-
if include_tables is not None:
39-
for table in include_tables:
40-
if table not in tt_left and table not in tt_right:
41-
raise KeyError(
42-
f"'{table}' table was not identified for inclusion in either font"
43-
)
44-
45-
# Validation: exclude_tables request should be for tables that are in one of
46-
# the two fonts. Mis-specified OT table definitions could otherwise result
47-
# in the presence of a table in the diff when the request was to exclude it.
48-
# For example, when an "OS/2" table request is entered as "OS2".
49-
if exclude_tables is not None:
50-
for table in exclude_tables:
51-
if table not in tt_left and table not in tt_right:
52-
raise KeyError(
53-
f"'{table}' table was not identified for exclusion in either font"
54-
)
55-
56-
fromdate = get_file_modtime(filepath_a)
57-
todate = get_file_modtime(filepath_b)
58-
5933
with tempfile.TemporaryDirectory() as tmpdirname:
34+
# define the file paths with either local file requests
35+
# or pulls of remote files based on the command line request
36+
urls = []
37+
if filepath_a.startswith("http"):
38+
urls.append(filepath_a)
39+
prepath = _get_filepath_from_url(filepath_a, tmpdirname)
40+
# keep URL as path name for remote file requests
41+
pre_pathname = filepath_a
42+
else:
43+
prepath = filepath_a
44+
pre_pathname = filepath_a
45+
46+
if filepath_b.startswith("http"):
47+
urls.append(filepath_b)
48+
postpath = _get_filepath_from_url(filepath_b, tmpdirname)
49+
# keep URL as path name for remote file requests
50+
post_pathname = filepath_b
51+
else:
52+
postpath = filepath_b
53+
post_pathname = filepath_b
54+
55+
# Async IO fetch and write of any remote file requests
56+
if len(urls) > 0:
57+
loop = asyncio.get_event_loop()
58+
tasks = loop.run_until_complete(
59+
create_async_get_request_session_and_run(urls, tmpdirname)
60+
)
61+
for task in tasks:
62+
if task.exception():
63+
# raise exception here to notify calling code that something
64+
# did not work
65+
# TODO: handle exceptions
66+
pass
67+
elif task.result().http_status != 200:
68+
# TODO: handle non-200 HTTP response status codes + file write fails
69+
pass
70+
71+
tt_left = TTFont(prepath)
72+
tt_right = TTFont(postpath)
73+
74+
# Validation: include_tables request should be for tables that are in one of
75+
# the two fonts. This otherwise silently passes with exit status code 0 which
76+
# could lead to the interpretation of no diff between two files when the table
77+
# entry is incorrectly defined or is a typo. Let's be conservative and consider
78+
# this an error, force user to use explicit definitions that include tables in
79+
# one of the two files, and understand that the diff request was for one or more
80+
# tables that are not present.
81+
if include_tables is not None:
82+
for table in include_tables:
83+
if table not in tt_left and table not in tt_right:
84+
raise KeyError(
85+
f"'{table}' table was not identified for inclusion in either font"
86+
)
87+
88+
# Validation: exclude_tables request should be for tables that are in one of
89+
# the two fonts. Mis-specified OT table definitions could otherwise result
90+
# in the presence of a table in the diff when the request was to exclude it.
91+
# For example, when an "OS/2" table request is entered as "OS2".
92+
if exclude_tables is not None:
93+
for table in exclude_tables:
94+
if table not in tt_left and table not in tt_right:
95+
raise KeyError(
96+
f"'{table}' table was not identified for exclusion in either font"
97+
)
98+
99+
fromdate = get_file_modtime(prepath)
100+
todate = get_file_modtime(postpath)
101+
60102
tt_left.saveXML(
61103
os.path.join(tmpdirname, "left.ttx"),
62104
tables=include_tables,
@@ -76,8 +118,8 @@ def u_diff(
76118
return unified_diff(
77119
fromlines,
78120
tolines,
79-
filepath_a,
80-
filepath_b,
121+
pre_pathname,
122+
post_pathname,
81123
fromdate,
82124
todate,
83125
n=context_lines,

0 commit comments

Comments
 (0)