1
+ import asyncio
1
2
import os
2
3
import tempfile
3
4
4
5
from fontTools .ttLib import TTFont
5
6
7
+ from fdiff .remote import (
8
+ _get_filepath_from_url ,
9
+ create_async_get_request_session_and_run ,
10
+ )
6
11
from fdiff .utils import get_file_modtime
7
12
from fdiff .thirdparty .fdifflib import unified_diff
8
13
@@ -25,38 +30,75 @@ def u_diff(
25
30
:returns: Generator of ordered diff line strings that include newline line endings
26
31
:raises: KeyError if include_tables or exclude_tables includes a mis-specified table
27
32
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
-
59
33
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
+
60
102
tt_left .saveXML (
61
103
os .path .join (tmpdirname , "left.ttx" ),
62
104
tables = include_tables ,
@@ -76,8 +118,8 @@ def u_diff(
76
118
return unified_diff (
77
119
fromlines ,
78
120
tolines ,
79
- filepath_a ,
80
- filepath_b ,
121
+ pre_pathname ,
122
+ post_pathname ,
81
123
fromdate ,
82
124
todate ,
83
125
n = context_lines ,
0 commit comments