|
@@ -1,7 +1,5 @@
|
|
|
import argparse
|
|
|
-from datetime import datetime, timedelta
|
|
|
-from fnmatch import fnmatchcase
|
|
|
-from operator import attrgetter
|
|
|
+import binascii
|
|
|
import grp
|
|
|
import msgpack
|
|
|
import os
|
|
@@ -10,10 +8,12 @@ import re
|
|
|
import stat
|
|
|
import sys
|
|
|
import time
|
|
|
-import urllib
|
|
|
+from datetime import datetime, timedelta
|
|
|
+from fnmatch import fnmatchcase
|
|
|
+from operator import attrgetter
|
|
|
|
|
|
|
|
|
-class Manifest(object):
|
|
|
+class Manifest:
|
|
|
|
|
|
MANIFEST_ID = b'\0' * 32
|
|
|
|
|
@@ -62,7 +62,7 @@ def prune_split(archives, pattern, n, skip=[]):
|
|
|
return keep
|
|
|
|
|
|
|
|
|
-class Statistics(object):
|
|
|
+class Statistics:
|
|
|
|
|
|
def __init__(self):
|
|
|
self.osize = self.csize = self.usize = self.nfiles = 0
|
|
@@ -112,7 +112,7 @@ def exclude_path(path, patterns):
|
|
|
return False
|
|
|
|
|
|
|
|
|
-class IncludePattern(object):
|
|
|
+class IncludePattern:
|
|
|
"""--include PATTERN
|
|
|
"""
|
|
|
def __init__(self, pattern):
|
|
@@ -345,12 +345,23 @@ def decode_dict(d, keys, encoding='utf-8', errors='surrogateescape'):
|
|
|
|
|
|
|
|
|
def remove_surrogates(s, errors='replace'):
|
|
|
+ """Replace surrogates generated by fsdecode with '?'
|
|
|
+ """
|
|
|
return s.encode('utf-8', errors).decode('utf-8')
|
|
|
|
|
|
|
|
|
if sys.version < '3.3':
|
|
|
+ # st_mtime_ns attribute only available in 3.3+
|
|
|
def st_mtime_ns(st):
|
|
|
return int(st.st_mtime * 10**9)
|
|
|
+
|
|
|
+ # unhexlify in < 3.3 incorrectly only accepts bytes input
|
|
|
+ def unhexlify(data):
|
|
|
+ if isinstance(data, str):
|
|
|
+ data = data.encode('ascii')
|
|
|
+ return binascii.unhexlify(data)
|
|
|
else:
|
|
|
def st_mtime_ns(st):
|
|
|
return st.st_mtime_ns
|
|
|
+
|
|
|
+ unhexlify = binascii.unhexlify
|