Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
A
ansible
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
OpenEdx
ansible
Commits
5f0f5363
Commit
5f0f5363
authored
Sep 23, 2015
by
Toshio Kuratomi
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #12487 from mgedmin/py3k
Fix one more failing test on Python 3
parents
2898e000
95e655eb
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
78 additions
and
33 deletions
+78
-33
lib/ansible/inventory/__init__.py
+4
-2
lib/ansible/module_utils/basic.py
+74
-31
No files found.
lib/ansible/inventory/__init__.py
View file @
5f0f5363
...
@@ -26,6 +26,8 @@ import re
...
@@ -26,6 +26,8 @@ import re
import
stat
import
stat
import
itertools
import
itertools
from
six
import
string_types
from
ansible
import
constants
as
C
from
ansible
import
constants
as
C
from
ansible.errors
import
AnsibleError
from
ansible.errors
import
AnsibleError
...
@@ -78,7 +80,7 @@ class Inventory(object):
...
@@ -78,7 +80,7 @@ class Inventory(object):
def
parse_inventory
(
self
,
host_list
):
def
parse_inventory
(
self
,
host_list
):
if
isinstance
(
host_list
,
basestring
):
if
isinstance
(
host_list
,
string_types
):
if
","
in
host_list
:
if
","
in
host_list
:
host_list
=
host_list
.
split
(
","
)
host_list
=
host_list
.
split
(
","
)
host_list
=
[
h
for
h
in
host_list
if
h
and
h
.
strip
()
]
host_list
=
[
h
for
h
in
host_list
if
h
and
h
.
strip
()
]
...
@@ -589,7 +591,7 @@ class Inventory(object):
...
@@ -589,7 +591,7 @@ class Inventory(object):
def
is_file
(
self
):
def
is_file
(
self
):
""" did inventory come from a file? """
""" did inventory come from a file? """
if
not
isinstance
(
self
.
host_list
,
basestring
):
if
not
isinstance
(
self
.
host_list
,
string_types
):
return
False
return
False
return
self
.
_loader
.
path_exists
(
self
.
host_list
)
return
self
.
_loader
.
path_exists
(
self
.
host_list
)
...
...
lib/ansible/module_utils/basic.py
View file @
5f0f5363
...
@@ -66,7 +66,12 @@ import grp
...
@@ -66,7 +66,12 @@ import grp
import
pwd
import
pwd
import
platform
import
platform
import
errno
import
errno
from
itertools
import
imap
,
repeat
from
itertools
import
repeat
try
:
from
itertools
import
imap
# Python 2
except
ImportError
:
imap
=
map
# Python 3
try
:
try
:
import
json
import
json
...
@@ -162,6 +167,22 @@ except ImportError:
...
@@ -162,6 +167,22 @@ except ImportError:
raise
ValueError
(
'malformed string'
)
raise
ValueError
(
'malformed string'
)
return
_convert
(
node_or_string
)
return
_convert
(
node_or_string
)
def
get_exception
():
"""Get the current exception.
This code needs to work on Python 2.4 through 3.x, so we cannot use
"except Exception, e:" (SyntaxError on Python 3.x) nor
"except Exception as e:" (SyntaxError on Python 2.4-2.5).
Instead we must use ::
except Exception:
e = get_exception()
"""
return
sys
.
exc_info
()[
1
]
FILE_COMMON_ARGUMENTS
=
dict
(
FILE_COMMON_ARGUMENTS
=
dict
(
src
=
dict
(),
src
=
dict
(),
mode
=
dict
(),
mode
=
dict
(),
...
@@ -184,6 +205,11 @@ FILE_COMMON_ARGUMENTS=dict(
...
@@ -184,6 +205,11 @@ FILE_COMMON_ARGUMENTS=dict(
PASSWD_ARG_RE
=
re
.
compile
(
r'^[-]{0,2}pass[-]?(word|wd)?'
)
PASSWD_ARG_RE
=
re
.
compile
(
r'^[-]{0,2}pass[-]?(word|wd)?'
)
# Can't use 07777 on Python 3, can't use 0o7777 on Python 2.4
PERM_BITS
=
int
(
'07777'
,
8
)
# file mode permission bits
EXEC_PERM_BITS
=
int
(
'00111'
,
8
)
# execute permission bits
DEFAULT_PERM
=
int
(
'0666'
,
8
)
# default file permission bits
def
get_platform
():
def
get_platform
():
''' what's the platform? example: Linux is a platform. '''
''' what's the platform? example: Linux is a platform. '''
return
platform
.
system
()
return
platform
.
system
()
...
@@ -527,7 +553,8 @@ class AnsibleModule(object):
...
@@ -527,7 +553,8 @@ class AnsibleModule(object):
return
context
return
context
try
:
try
:
ret
=
selinux
.
lgetfilecon_raw
(
self
.
_to_filesystem_str
(
path
))
ret
=
selinux
.
lgetfilecon_raw
(
self
.
_to_filesystem_str
(
path
))
except
OSError
,
e
:
except
OSError
:
e
=
get_exception
()
if
e
.
errno
==
errno
.
ENOENT
:
if
e
.
errno
==
errno
.
ENOENT
:
self
.
fail_json
(
path
=
path
,
msg
=
'path
%
s does not exist'
%
path
)
self
.
fail_json
(
path
=
path
,
msg
=
'path
%
s does not exist'
%
path
)
else
:
else
:
...
@@ -607,7 +634,8 @@ class AnsibleModule(object):
...
@@ -607,7 +634,8 @@ class AnsibleModule(object):
return
True
return
True
rc
=
selinux
.
lsetfilecon
(
self
.
_to_filesystem_str
(
path
),
rc
=
selinux
.
lsetfilecon
(
self
.
_to_filesystem_str
(
path
),
str
(
':'
.
join
(
new_context
)))
str
(
':'
.
join
(
new_context
)))
except
OSError
,
e
:
except
OSError
:
e
=
get_exception
()
self
.
fail_json
(
path
=
path
,
msg
=
'invalid selinux context:
%
s'
%
str
(
e
),
new_context
=
new_context
,
cur_context
=
cur_context
,
input_was
=
context
)
self
.
fail_json
(
path
=
path
,
msg
=
'invalid selinux context:
%
s'
%
str
(
e
),
new_context
=
new_context
,
cur_context
=
cur_context
,
input_was
=
context
)
if
rc
!=
0
:
if
rc
!=
0
:
self
.
fail_json
(
path
=
path
,
msg
=
'set selinux context failed'
)
self
.
fail_json
(
path
=
path
,
msg
=
'set selinux context failed'
)
...
@@ -671,7 +699,8 @@ class AnsibleModule(object):
...
@@ -671,7 +699,8 @@ class AnsibleModule(object):
except
Exception
:
except
Exception
:
try
:
try
:
mode
=
self
.
_symbolic_mode_to_octal
(
path_stat
,
mode
)
mode
=
self
.
_symbolic_mode_to_octal
(
path_stat
,
mode
)
except
Exception
,
e
:
except
Exception
:
e
=
get_exception
()
self
.
fail_json
(
path
=
path
,
self
.
fail_json
(
path
=
path
,
msg
=
"mode must be in octal or symbolic form"
,
msg
=
"mode must be in octal or symbolic form"
,
details
=
str
(
e
))
details
=
str
(
e
))
...
@@ -698,14 +727,16 @@ class AnsibleModule(object):
...
@@ -698,14 +727,16 @@ class AnsibleModule(object):
new_underlying_stat
=
os
.
stat
(
path
)
new_underlying_stat
=
os
.
stat
(
path
)
if
underlying_stat
.
st_mode
!=
new_underlying_stat
.
st_mode
:
if
underlying_stat
.
st_mode
!=
new_underlying_stat
.
st_mode
:
os
.
chmod
(
path
,
stat
.
S_IMODE
(
underlying_stat
.
st_mode
))
os
.
chmod
(
path
,
stat
.
S_IMODE
(
underlying_stat
.
st_mode
))
except
OSError
,
e
:
except
OSError
:
e
=
get_exception
()
if
os
.
path
.
islink
(
path
)
and
e
.
errno
==
errno
.
EPERM
:
# Can't set mode on symbolic links
if
os
.
path
.
islink
(
path
)
and
e
.
errno
==
errno
.
EPERM
:
# Can't set mode on symbolic links
pass
pass
elif
e
.
errno
in
(
errno
.
ENOENT
,
errno
.
ELOOP
):
# Can't set mode on broken symbolic links
elif
e
.
errno
in
(
errno
.
ENOENT
,
errno
.
ELOOP
):
# Can't set mode on broken symbolic links
pass
pass
else
:
else
:
raise
e
raise
e
except
Exception
,
e
:
except
Exception
:
e
=
get_exception
()
self
.
fail_json
(
path
=
path
,
msg
=
'chmod failed'
,
details
=
str
(
e
))
self
.
fail_json
(
path
=
path
,
msg
=
'chmod failed'
,
details
=
str
(
e
))
path_stat
=
os
.
lstat
(
path
)
path_stat
=
os
.
lstat
(
path
)
...
@@ -743,7 +774,7 @@ class AnsibleModule(object):
...
@@ -743,7 +774,7 @@ class AnsibleModule(object):
elif
user
==
'o'
:
mask
=
stat
.
S_IRWXO
|
stat
.
S_ISVTX
elif
user
==
'o'
:
mask
=
stat
.
S_IRWXO
|
stat
.
S_ISVTX
# mask out u, g, or o permissions from current_mode and apply new permissions
# mask out u, g, or o permissions from current_mode and apply new permissions
inverse_mask
=
mask
^
07777
inverse_mask
=
mask
^
PERM_BITS
new_mode
=
(
current_mode
&
inverse_mask
)
|
mode_to_apply
new_mode
=
(
current_mode
&
inverse_mask
)
|
mode_to_apply
elif
operator
==
'+'
:
elif
operator
==
'+'
:
new_mode
=
current_mode
|
mode_to_apply
new_mode
=
current_mode
|
mode_to_apply
...
@@ -755,7 +786,7 @@ class AnsibleModule(object):
...
@@ -755,7 +786,7 @@ class AnsibleModule(object):
prev_mode
=
stat
.
S_IMODE
(
path_stat
.
st_mode
)
prev_mode
=
stat
.
S_IMODE
(
path_stat
.
st_mode
)
is_directory
=
stat
.
S_ISDIR
(
path_stat
.
st_mode
)
is_directory
=
stat
.
S_ISDIR
(
path_stat
.
st_mode
)
has_x_permissions
=
(
prev_mode
&
00111
)
>
0
has_x_permissions
=
(
prev_mode
&
EXEC_PERM_BITS
)
>
0
apply_X_permission
=
is_directory
or
has_x_permissions
apply_X_permission
=
is_directory
or
has_x_permissions
# Permission bits constants documented at:
# Permission bits constants documented at:
...
@@ -882,7 +913,8 @@ class AnsibleModule(object):
...
@@ -882,7 +913,8 @@ class AnsibleModule(object):
# setting the locale to '' uses the default locale
# setting the locale to '' uses the default locale
# as it would be returned by locale.getdefaultlocale()
# as it would be returned by locale.getdefaultlocale()
locale
.
setlocale
(
locale
.
LC_ALL
,
''
)
locale
.
setlocale
(
locale
.
LC_ALL
,
''
)
except
locale
.
Error
,
e
:
except
locale
.
Error
:
e
=
get_exception
()
# fallback to the 'C' locale, which may cause unicode
# fallback to the 'C' locale, which may cause unicode
# issues but is preferable to simply failing because
# issues but is preferable to simply failing because
# of an unknown locale
# of an unknown locale
...
@@ -890,7 +922,8 @@ class AnsibleModule(object):
...
@@ -890,7 +922,8 @@ class AnsibleModule(object):
os
.
environ
[
'LANG'
]
=
'C'
os
.
environ
[
'LANG'
]
=
'C'
os
.
environ
[
'LC_CTYPE'
]
=
'C'
os
.
environ
[
'LC_CTYPE'
]
=
'C'
os
.
environ
[
'LC_MESSAGES'
]
=
'C'
os
.
environ
[
'LC_MESSAGES'
]
=
'C'
except
Exception
,
e
:
except
Exception
:
e
=
get_exception
()
self
.
fail_json
(
msg
=
"An unknown error was encountered while attempting to validate the locale:
%
s"
%
e
)
self
.
fail_json
(
msg
=
"An unknown error was encountered while attempting to validate the locale:
%
s"
%
e
)
def
_handle_aliases
(
self
):
def
_handle_aliases
(
self
):
...
@@ -1035,7 +1068,8 @@ class AnsibleModule(object):
...
@@ -1035,7 +1068,8 @@ class AnsibleModule(object):
return
(
result
,
None
)
return
(
result
,
None
)
else
:
else
:
return
result
return
result
except
Exception
,
e
:
except
Exception
:
e
=
get_exception
()
if
include_exceptions
:
if
include_exceptions
:
return
(
str
,
e
)
return
(
str
,
e
)
return
str
return
str
...
@@ -1325,7 +1359,7 @@ class AnsibleModule(object):
...
@@ -1325,7 +1359,7 @@ class AnsibleModule(object):
if
not
'changed'
in
kwargs
:
if
not
'changed'
in
kwargs
:
kwargs
[
'changed'
]
=
False
kwargs
[
'changed'
]
=
False
self
.
do_cleanup_files
()
self
.
do_cleanup_files
()
print
self
.
jsonify
(
kwargs
)
print
(
self
.
jsonify
(
kwargs
)
)
sys
.
exit
(
0
)
sys
.
exit
(
0
)
def
fail_json
(
self
,
**
kwargs
):
def
fail_json
(
self
,
**
kwargs
):
...
@@ -1334,7 +1368,7 @@ class AnsibleModule(object):
...
@@ -1334,7 +1368,7 @@ class AnsibleModule(object):
assert
'msg'
in
kwargs
,
"implementation error -- msg to explain the error is required"
assert
'msg'
in
kwargs
,
"implementation error -- msg to explain the error is required"
kwargs
[
'failed'
]
=
True
kwargs
[
'failed'
]
=
True
self
.
do_cleanup_files
()
self
.
do_cleanup_files
()
print
self
.
jsonify
(
kwargs
)
print
(
self
.
jsonify
(
kwargs
)
)
sys
.
exit
(
1
)
sys
.
exit
(
1
)
def
is_executable
(
self
,
path
):
def
is_executable
(
self
,
path
):
...
@@ -1403,7 +1437,8 @@ class AnsibleModule(object):
...
@@ -1403,7 +1437,8 @@ class AnsibleModule(object):
try
:
try
:
shutil
.
copy2
(
fn
,
backupdest
)
shutil
.
copy2
(
fn
,
backupdest
)
except
(
shutil
.
Error
,
IOError
),
e
:
except
(
shutil
.
Error
,
IOError
):
e
=
get_exception
()
self
.
fail_json
(
msg
=
'Could not make backup of
%
s to
%
s:
%
s'
%
(
fn
,
backupdest
,
e
))
self
.
fail_json
(
msg
=
'Could not make backup of
%
s to
%
s:
%
s'
%
(
fn
,
backupdest
,
e
))
return
backupdest
return
backupdest
...
@@ -1412,7 +1447,8 @@ class AnsibleModule(object):
...
@@ -1412,7 +1447,8 @@ class AnsibleModule(object):
if
os
.
path
.
exists
(
tmpfile
):
if
os
.
path
.
exists
(
tmpfile
):
try
:
try
:
os
.
unlink
(
tmpfile
)
os
.
unlink
(
tmpfile
)
except
OSError
,
e
:
except
OSError
:
e
=
get_exception
()
sys
.
stderr
.
write
(
"could not cleanup
%
s:
%
s"
%
(
tmpfile
,
e
))
sys
.
stderr
.
write
(
"could not cleanup
%
s:
%
s"
%
(
tmpfile
,
e
))
def
atomic_move
(
self
,
src
,
dest
):
def
atomic_move
(
self
,
src
,
dest
):
...
@@ -1424,9 +1460,10 @@ class AnsibleModule(object):
...
@@ -1424,9 +1460,10 @@ class AnsibleModule(object):
if
os
.
path
.
exists
(
dest
):
if
os
.
path
.
exists
(
dest
):
try
:
try
:
dest_stat
=
os
.
stat
(
dest
)
dest_stat
=
os
.
stat
(
dest
)
os
.
chmod
(
src
,
dest_stat
.
st_mode
&
07777
)
os
.
chmod
(
src
,
dest_stat
.
st_mode
&
PERM_BITS
)
os
.
chown
(
src
,
dest_stat
.
st_uid
,
dest_stat
.
st_gid
)
os
.
chown
(
src
,
dest_stat
.
st_uid
,
dest_stat
.
st_gid
)
except
OSError
,
e
:
except
OSError
:
e
=
get_exception
()
if
e
.
errno
!=
errno
.
EPERM
:
if
e
.
errno
!=
errno
.
EPERM
:
raise
raise
if
self
.
selinux_enabled
():
if
self
.
selinux_enabled
():
...
@@ -1452,7 +1489,8 @@ class AnsibleModule(object):
...
@@ -1452,7 +1489,8 @@ class AnsibleModule(object):
try
:
try
:
# Optimistically try a rename, solves some corner cases and can avoid useless work, throws exception if not atomic.
# Optimistically try a rename, solves some corner cases and can avoid useless work, throws exception if not atomic.
os
.
rename
(
src
,
dest
)
os
.
rename
(
src
,
dest
)
except
(
IOError
,
OSError
),
e
:
except
(
IOError
,
OSError
):
e
=
get_exception
()
# only try workarounds for errno 18 (cross device), 1 (not permitted), 13 (permission denied)
# only try workarounds for errno 18 (cross device), 1 (not permitted), 13 (permission denied)
# and 26 (text file busy) which happens on vagrant synced folders
# and 26 (text file busy) which happens on vagrant synced folders
if
e
.
errno
not
in
[
errno
.
EPERM
,
errno
.
EXDEV
,
errno
.
EACCES
,
errno
.
ETXTBSY
]:
if
e
.
errno
not
in
[
errno
.
EPERM
,
errno
.
EXDEV
,
errno
.
EACCES
,
errno
.
ETXTBSY
]:
...
@@ -1463,7 +1501,8 @@ class AnsibleModule(object):
...
@@ -1463,7 +1501,8 @@ class AnsibleModule(object):
try
:
try
:
tmp_dest
=
tempfile
.
NamedTemporaryFile
(
tmp_dest
=
tempfile
.
NamedTemporaryFile
(
prefix
=
".ansible_tmp"
,
dir
=
dest_dir
,
suffix
=
dest_file
)
prefix
=
".ansible_tmp"
,
dir
=
dest_dir
,
suffix
=
dest_file
)
except
(
OSError
,
IOError
),
e
:
except
(
OSError
,
IOError
):
e
=
get_exception
()
self
.
fail_json
(
msg
=
'The destination directory (
%
s) is not writable by the current user.'
%
dest_dir
)
self
.
fail_json
(
msg
=
'The destination directory (
%
s) is not writable by the current user.'
%
dest_dir
)
try
:
# leaves tmp file behind when sudo and not root
try
:
# leaves tmp file behind when sudo and not root
...
@@ -1480,11 +1519,13 @@ class AnsibleModule(object):
...
@@ -1480,11 +1519,13 @@ class AnsibleModule(object):
tmp_stat
=
os
.
stat
(
tmp_dest
.
name
)
tmp_stat
=
os
.
stat
(
tmp_dest
.
name
)
if
dest_stat
and
(
tmp_stat
.
st_uid
!=
dest_stat
.
st_uid
or
tmp_stat
.
st_gid
!=
dest_stat
.
st_gid
):
if
dest_stat
and
(
tmp_stat
.
st_uid
!=
dest_stat
.
st_uid
or
tmp_stat
.
st_gid
!=
dest_stat
.
st_gid
):
os
.
chown
(
tmp_dest
.
name
,
dest_stat
.
st_uid
,
dest_stat
.
st_gid
)
os
.
chown
(
tmp_dest
.
name
,
dest_stat
.
st_uid
,
dest_stat
.
st_gid
)
except
OSError
,
e
:
except
OSError
:
e
=
get_exception
()
if
e
.
errno
!=
errno
.
EPERM
:
if
e
.
errno
!=
errno
.
EPERM
:
raise
raise
os
.
rename
(
tmp_dest
.
name
,
dest
)
os
.
rename
(
tmp_dest
.
name
,
dest
)
except
(
shutil
.
Error
,
OSError
,
IOError
),
e
:
except
(
shutil
.
Error
,
OSError
,
IOError
):
e
=
get_exception
()
self
.
cleanup
(
tmp_dest
.
name
)
self
.
cleanup
(
tmp_dest
.
name
)
self
.
fail_json
(
msg
=
'Could not replace file:
%
s to
%
s:
%
s'
%
(
src
,
dest
,
e
))
self
.
fail_json
(
msg
=
'Could not replace file:
%
s to
%
s:
%
s'
%
(
src
,
dest
,
e
))
...
@@ -1493,7 +1534,7 @@ class AnsibleModule(object):
...
@@ -1493,7 +1534,7 @@ class AnsibleModule(object):
# based on the current value of umask
# based on the current value of umask
umask
=
os
.
umask
(
0
)
umask
=
os
.
umask
(
0
)
os
.
umask
(
umask
)
os
.
umask
(
umask
)
os
.
chmod
(
dest
,
0666
&
~
umask
)
os
.
chmod
(
dest
,
DEFAULT_PERM
&
~
umask
)
if
switched_user
:
if
switched_user
:
os
.
chown
(
dest
,
os
.
getuid
(),
os
.
getgid
())
os
.
chown
(
dest
,
os
.
getuid
(),
os
.
getgid
())
...
@@ -1609,7 +1650,8 @@ class AnsibleModule(object):
...
@@ -1609,7 +1650,8 @@ class AnsibleModule(object):
if
cwd
and
os
.
path
.
isdir
(
cwd
):
if
cwd
and
os
.
path
.
isdir
(
cwd
):
try
:
try
:
os
.
chdir
(
cwd
)
os
.
chdir
(
cwd
)
except
(
OSError
,
IOError
),
e
:
except
(
OSError
,
IOError
):
e
=
get_exception
()
self
.
fail_json
(
rc
=
e
.
errno
,
msg
=
"Could not open
%
s,
%
s"
%
(
cwd
,
str
(
e
)))
self
.
fail_json
(
rc
=
e
.
errno
,
msg
=
"Could not open
%
s,
%
s"
%
(
cwd
,
str
(
e
)))
try
:
try
:
...
@@ -1662,7 +1704,8 @@ class AnsibleModule(object):
...
@@ -1662,7 +1704,8 @@ class AnsibleModule(object):
cmd
.
stderr
.
close
()
cmd
.
stderr
.
close
()
rc
=
cmd
.
returncode
rc
=
cmd
.
returncode
except
(
OSError
,
IOError
),
e
:
except
(
OSError
,
IOError
):
e
=
get_exception
()
self
.
fail_json
(
rc
=
e
.
errno
,
msg
=
str
(
e
),
cmd
=
clean_args
)
self
.
fail_json
(
rc
=
e
.
errno
,
msg
=
str
(
e
),
cmd
=
clean_args
)
except
:
except
:
self
.
fail_json
(
rc
=
257
,
msg
=
traceback
.
format_exc
(),
cmd
=
clean_args
)
self
.
fail_json
(
rc
=
257
,
msg
=
traceback
.
format_exc
(),
cmd
=
clean_args
)
...
@@ -1684,13 +1727,13 @@ class AnsibleModule(object):
...
@@ -1684,13 +1727,13 @@ class AnsibleModule(object):
def
pretty_bytes
(
self
,
size
):
def
pretty_bytes
(
self
,
size
):
ranges
=
(
ranges
=
(
(
1
<<
70
L
,
'ZB'
),
(
1
<<
70
,
'ZB'
),
(
1
<<
60
L
,
'EB'
),
(
1
<<
60
,
'EB'
),
(
1
<<
50
L
,
'PB'
),
(
1
<<
50
,
'PB'
),
(
1
<<
40
L
,
'TB'
),
(
1
<<
40
,
'TB'
),
(
1
<<
30
L
,
'GB'
),
(
1
<<
30
,
'GB'
),
(
1
<<
20
L
,
'MB'
),
(
1
<<
20
,
'MB'
),
(
1
<<
10
L
,
'KB'
),
(
1
<<
10
,
'KB'
),
(
1
,
'Bytes'
)
(
1
,
'Bytes'
)
)
)
for
limit
,
suffix
in
ranges
:
for
limit
,
suffix
in
ranges
:
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment