forked from Sinbu/WebGL-Unity-AWS-CD
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathutil.py
120 lines (98 loc) · 3.16 KB
/
util.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import os
def stringify(s):
"""In Py3k, unicode are strings, so we mustn't encode it.
However it is necessary in Python 2.x, since Unicode strings are
unicode, not str."""
if type(s) != str and type(s) != bytes:
s = s.encode('utf-8')
return s
class LenWrapperStream(object):
"""
A simple class to wrap a stream and provide length capability
for streams like cStringIO
We do it because requests will try to fallback to chuncked transfer if
it can't extract the len attribute of the object it gets, and S3 doesn't
support chuncked transfer.
In some cases, like cStringIO, it may cause some issues, so we wrap the
stream with a class of our own, that will proxy the stream and provide a
proper len attribute
"""
def __init__(self, stream):
"""
Creates a new wrapper from the given stream
Params:
- stream The baseline stream
"""
self.stream = stream
def read(self, n=-1):
"""
Proxy for reading the stream
"""
return self.stream.read(n)
def __iter__(self):
"""
Proxy for iterating the stream
"""
return self.stream
def seek(self, pos, mode=0):
"""
Proxy for the `seek` method of the underlying stream
"""
return self.stream.seek(pos, mode)
def tell(self):
"""
Proxy for the `tell` method of the underlying stream
"""
return self.stream.tell()
def __len__(self):
"""
Calculate the stream length in a fail-safe way
"""
o = self.stream
# If we have a '__len__' method
if hasattr(o, '__len__'):
return len(o)
# If we have a len property
if hasattr(o, 'len'):
return o.len
# If we have a fileno property
# (EAFP here, because some file-like objs like
# tarfile "ExFileObject" will pass a hasattr test
# but still not work)
try:
return os.fstat(o.fileno()).st_size
except (IOError, AttributeError):
# fallback to the manual way,
# this is useful when using something like BytesIO
pass
# calculate based on bytes to end of content
# get our start position
start_pos = o.tell()
# move to the end
o.seek(0, os.SEEK_END)
# Our len is end - start position
size = o.tell() - start_pos
# Seek the stream back to the start position
o.seek(start_pos)
# Return the size
return size
def __eq__(self, other):
"""
Make sure equal method works as expected (comparing the underlying
stream and not the wrapper)
"""
if self.stream == other:
return True
if isinstance(other, LenWrapperStream) and other.stream == self.stream:
return True
@property
def closed(self):
"""
Proxy for the underlying stream closed property
"""
return self.stream.closed
def __repr__(self):
"""
Proxy for the repr of the stream
"""
return repr(self.stream)