Skip to content
This repository was archived by the owner on Jul 18, 2024. It is now read-only.

Commit 5723294

Browse files
authored
Merge pull request #41 from alfpark/v2
1.0.0b1
2 parents 45ef468 + af53ea7 commit 5723294

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+5469
-751
lines changed

.travis.yml

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,14 @@ language: python
22
cache: pip
33
python:
44
- 2.7
5-
- 3.3
65
- 3.4
76
- 3.5
87
- 3.6
98
install:
109
- travis_retry pip install --upgrade pip
11-
- travis_retry pip install --upgrade setuptools wheel coveralls
10+
- travis_retry pip install --upgrade setuptools wheel
11+
- travis_retry pip install --upgrade coveralls tox-travis
1212
script:
13-
- |
14-
if [[ $TRAVIS_PYTHON_VERSION == '2.7' ]] || [[ $TRAVIS_PYTHON_VERSION == '3.3' ]] || [[ $TRAVIS_PYTHON_VERSION == '3.4' ]]; then
15-
travis_retry pip install tox
16-
tox -e $(echo py$TRAVIS_PYTHON_VERSION | tr -d .)
17-
else
18-
travis_retry pip install tox-travis
19-
tox
20-
fi
13+
- tox
2114
after_success:
2215
- coveralls --rcfile=.coveragerc --verbose

CHANGELOG.md

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,27 @@
22

33
## [Unreleased]
44

5+
## [1.0.0b1] - 2017-08-28
6+
### Added
7+
- Cross-mode synchronous copy support
8+
- Duplicate detection (different local source paths mapping to the same
9+
destination) on upload
10+
11+
### Changed
12+
- Python 3.3 is no longer supported (due to `cryptography` dropping support
13+
for 3.3).
14+
- `--strip-components` now defaults to `0`
15+
- `timeout_sec` YAML property is now named `timeout` and is a complex property
16+
comprised of `connect` and `read` values expressed in seconds
17+
- Test coverage improved
18+
- Dependencies updated to latest
19+
20+
### Fixed
21+
- Properly merge CLI options with YAML config options. You can now override
22+
most YAML config settings with CLI options at runtime.
23+
- Issue with zero-byte uploads
24+
- Check for max page blob size
25+
526
## [1.0.0a5] - 2017-06-09
627
### Added
728
- Synchronous copy support with the `synccopy` command. This command supports
@@ -210,7 +231,8 @@ usage documentation carefully when upgrading from 0.12.1.
210231
`--no-skiponmatch`.
211232
- 0.8.2: performance regression fixes
212233

213-
[Unreleased]: https://github.com/Azure/blobxfer/compare/1.0.0a5...HEAD
234+
[Unreleased]: https://github.com/Azure/blobxfer/compare/1.0.0b1...HEAD
235+
[1.0.0b1]: https://github.com/Azure/blobxfer/compare/1.0.0a5...1.0.0b1
214236
[1.0.0a5]: https://github.com/Azure/blobxfer/compare/1.0.0a4...1.0.0a5
215237
[1.0.0a4]: https://github.com/Azure/blobxfer/compare/0.12.1...1.0.0a4
216238
[0.12.1]: https://github.com/Azure/blobxfer/compare/0.12.0...0.12.1

CODE_OF_CONDUCT.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Code of Conduct
2+
3+
This project has adopted the
4+
[Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
5+
For more information see the
6+
[Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
7+
or contact [<[email protected]>](mailto:[email protected]) with any
8+
additional questions or comments.

CONTRIBUTING.md

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,4 @@
1-
Contributing Code
2-
-----------------
3-
4-
This project has adopted the
5-
[Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
6-
For more information see the
7-
[Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
8-
or contact [[email protected]](mailto:[email protected]) with any
9-
additional questions or comments.
1+
# Contributing
102

113
If you would like to contribute to this project, please view the
124
[Microsoft Contribution guidelines](https://azure.github.io/guidelines/).

README.md

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ from Azure Blob and File Storage
2424
throughput limits
2525
* `replica` mode allows replication of a file across multiple destinations
2626
including to multiple storage accounts
27-
* Synchronous copy with replication support (including block-level copies
28-
for Block blobs)
27+
* Synchronous copy with cross-mode replication support (including block-level
28+
copies for Block blobs)
2929
* Client-side encryption support
3030
* Support all Azure Blob types and Azure Files for both upload and download
3131
* Advanced skip options for rsync-like operations
@@ -39,6 +39,7 @@ for Block blobs)
3939
* Include and exclude filtering support
4040
* Rsync-like delete support
4141
* No clobber support in either direction
42+
* Automatic content type tagging
4243
* File logging support
4344

4445
## Installation
@@ -56,11 +57,6 @@ For recent changes, please refer to the
5657
[CHANGELOG.md](https://github.com/Azure/blobxfer/blob/master/CHANGELOG.md)
5758
file.
5859

59-
------------------------------------------------------------------------
60-
61-
This project has adopted the
62-
[Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
63-
For more information see the
64-
[Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
65-
or contact [<[email protected]>](mailto:[email protected]) with any
66-
additional questions or comments.
60+
* * *
61+
Please see this project's [Code of Conduct](CODE_OF_CONDUCT.md) and
62+
[Contributing](CONTRIBUTING.md) guidelines.

blobxfer/__init__.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,12 @@
3030
azure.storage._constants.USER_AGENT_STRING = 'blobxfer/{} {}'.format(
3131
__version__, azure.storage._constants.USER_AGENT_STRING)
3232

33-
# monkeypatch SOCKET_TIMEOUT value in Azure Storage SDK
34-
azure.storage._constants.SOCKET_TIMEOUT = (5, 300)
35-
3633
# set stdin source
37-
if sys.version_info >= (3, 0):
34+
if sys.version_info >= (3, 0): # noqa
3835
STDIN = sys.stdin.buffer
39-
else:
36+
else: # noqa
4037
# set stdin to binary mode on Windows
41-
if sys.platform == 'win32': # noqa
38+
if sys.platform == 'win32':
4239
import msvcrt
4340
import os
4441
msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)

blobxfer/models/download.py

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ class Descriptor(object):
191191
_AES_BLOCKSIZE = blobxfer.models.crypto.AES256_BLOCKSIZE_BYTES
192192

193193
def __init__(self, lpath, ase, options, resume_mgr):
194-
# type: (Descriptior, pathlib.Path,
194+
# type: (Descriptor, pathlib.Path,
195195
# blobxfer.models.azure.StorageEntity,
196196
# blobxfer.models.options.Download,
197197
# blobxfer.operations.resume.DownloadResumeManager) -> None
@@ -321,10 +321,10 @@ def compute_allocated_size(size, is_encrypted):
321321
size //
322322
blobxfer.models.download.Descriptor._AES_BLOCKSIZE - 1
323323
) * blobxfer.models.download.Descriptor._AES_BLOCKSIZE
324+
if allocatesize < 0:
325+
raise RuntimeError('allocatesize is negative')
324326
else:
325327
allocatesize = size
326-
if allocatesize < 0:
327-
allocatesize = 0
328328
else:
329329
allocatesize = 0
330330
return allocatesize
@@ -364,10 +364,9 @@ def convert_vectored_io_slice_to_final_path_name(local_path, ase):
364364
:rtype: pathlib.Path
365365
:return: converted final path
366366
"""
367-
name = local_path.name
368367
name = blobxfer.models.metadata.\
369368
remove_vectored_io_slice_suffix_from_name(
370-
name, ase.vectored_io.slice_id)
369+
local_path.name, ase.vectored_io.slice_id)
371370
_tmp = list(local_path.parts[:-1])
372371
_tmp.append(name)
373372
return pathlib.Path(*_tmp)
@@ -460,7 +459,7 @@ def _resume(self):
460459
return None
461460
self._allocate_disk_space()
462461
# check if final path exists
463-
if not self.final_path.exists():
462+
if not self.final_path.exists(): # noqa
464463
logger.warning('download path {} does not exist'.format(
465464
self.final_path))
466465
return None
@@ -493,7 +492,7 @@ def _resume(self):
493492
if rr.md5hexdigest != hexdigest:
494493
logger.warning(
495494
'MD5 mismatch resume={} computed={} for {}'.format(
496-
rr.md5hexdigest, hexdigest, self.final_path))
495+
rr.md5hexdigest, hexdigest, self.final_path))
497496
# reset hasher
498497
self.md5 = blobxfer.util.new_md5_hasher()
499498
return None
@@ -768,12 +767,12 @@ def _restore_file_attributes(self):
768767
if self._ase.file_attributes is None:
769768
return
770769
# set file uid/gid and mode
771-
if blobxfer.util.on_windows():
770+
if blobxfer.util.on_windows(): # noqa
772771
# TODO not implemented yet
773772
pass
774773
else:
775774
self.final_path.chmod(int(self._ase.file_attributes.mode, 8))
776-
if os.getuid() == 0:
775+
if os.getuid() == 0: # noqa
777776
os.chown(
778777
str(self.final_path),
779778
self._ase.file_attributes.uid,

blobxfer/models/metadata.py

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -164,18 +164,6 @@ def fileattr_from_metadata(md):
164164
return fileattr
165165

166166

167-
def restore_fileattr(path, metadata):
168-
# type: (pathlib.Path, dict) -> None
169-
"""Restore file attributes from metadata
170-
:param pathlib.Path path: path to modify
171-
:param dict metadata: existing metadata dict
172-
"""
173-
if blobxfer.util.on_windows():
174-
logger.warning(
175-
'file attributes store/restore on Windows is not supported yet')
176-
raise NotImplementedError()
177-
178-
179167
def create_vectored_io_next_entry(ase):
180168
# type: (blobxfer.models.azure.StorageEntity) -> str
181169
"""Create Vectored IO next entry id

blobxfer/models/options.py

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@
4343

4444
# create logger
4545
logger = logging.getLogger(__name__)
46+
# global defines
47+
_DEFAULT_REQUESTS_TIMEOUT = (3.1, 12.1)
4648

4749
# named tuples
4850
VectoredIo = collections.namedtuple(
@@ -95,13 +97,56 @@
9597
SyncCopy = collections.namedtuple(
9698
'SyncCopy', [
9799
'delete_extraneous_destination',
100+
'dest_mode',
98101
'mode',
99102
'overwrite',
100103
'recursive',
101104
]
102105
)
103106

104107

108+
class Timeout(object):
109+
"""Timeout Options"""
110+
def __init__(self, connect, read):
111+
"""Ctor for Timeout options
112+
:param Timeout self: this
113+
:param float connect: connect timeout
114+
:param float read: read timeout
115+
"""
116+
if connect is None or connect <= 0:
117+
self._connect = _DEFAULT_REQUESTS_TIMEOUT[0]
118+
else:
119+
self._connect = connect
120+
if read is None or read <= 0:
121+
self._read = _DEFAULT_REQUESTS_TIMEOUT[1]
122+
else:
123+
self._read = read
124+
125+
@property
126+
def connect(self):
127+
"""Connect timeout
128+
:rtype: float
129+
:return: connect timeout
130+
"""
131+
return self._connect
132+
133+
@property
134+
def read(self):
135+
"""Read timeout
136+
:rtype: float
137+
:return: read timeout
138+
"""
139+
return self._read
140+
141+
@property
142+
def timeout(self):
143+
"""Timeout property in requests format
144+
:rtype: tuple
145+
:return: (connect, read) timeout tuple
146+
"""
147+
return (self._connect, self._read)
148+
149+
105150
class Concurrency(object):
106151
"""Concurrency Options"""
107152
def __init__(
@@ -157,14 +202,14 @@ class General(object):
157202
"""General Options"""
158203
def __init__(
159204
self, concurrency, log_file=None, progress_bar=True,
160-
resume_file=None, timeout_sec=None, verbose=False):
205+
resume_file=None, timeout=None, verbose=False):
161206
"""Ctor for General Options
162207
:param General self: this
163208
:param Concurrency concurrency: concurrency options
164209
:param bool progress_bar: progress bar
165210
:param str log_file: log file
166211
:param str resume_file: resume file
167-
:param int timeout_sec: timeout in seconds
212+
:param Timeout timeout: timeout options
168213
:param bool verbose: verbose output
169214
"""
170215
if concurrency is None:
@@ -176,5 +221,5 @@ def __init__(
176221
self.resume_file = pathlib.Path(resume_file)
177222
else:
178223
self.resume_file = None
179-
self.timeout_sec = timeout_sec
224+
self.timeout = timeout
180225
self.verbose = verbose

blobxfer/models/resume.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,7 @@ def __repr__(self):
156156
'next_integrity_chunk={} completed={} md5={}>').format(
157157
self.final_path, self.length, self.chunk_size,
158158
self.next_integrity_chunk, self.completed,
159-
self.md5hexdigest,
160-
)
159+
self.md5hexdigest)
161160

162161

163162
class Upload(object):
@@ -295,8 +294,7 @@ def __repr__(self):
295294
'md5={}>').format(
296295
self.local_path, self.length, self.chunk_size,
297296
self.total_chunks, self.completed_chunks, self.completed,
298-
self.md5hexdigest,
299-
)
297+
self.md5hexdigest)
300298

301299

302300
class SyncCopy(object):
@@ -428,5 +426,4 @@ def __repr__(self):
428426
return ('SyncCopy<length={} chunk_size={} total_chunks={} '
429427
'completed_chunks={} completed={}>').format(
430428
self.length, self.chunk_size, self.total_chunks,
431-
self.completed_chunks, self.completed,
432-
)
429+
self.completed_chunks, self.completed)

0 commit comments

Comments
 (0)