Skip to content
Permalink
Browse files

Merge 114d415 into 710daf2

  • Loading branch information...
willmcgugan committed Jan 30, 2019
2 parents 710daf2 + 114d415 commit 04e53a4caf1e346237aa44816889430a6967e1f5
Showing with 66 additions and 3 deletions.
  1. +5 −1 CHANGELOG.md
  2. +2 −1 docs/source/implementers.rst
  3. +1 −0 docs/source/interface.rst
  4. +1 −1 fs/_version.py
  5. +38 −0 fs/base.py
  6. +9 −0 fs/errors.py
  7. +2 −0 fs/info.py
  8. +7 −0 fs/test.py
  9. +1 −0 tests/test_new_name.py
@@ -5,12 +5,16 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).

## [2.2.2] - Unreleased
## [2.3.0] - 2018-01-30

### Fixed

- IllegalBackReference had mangled error message

### Added

- FS.hash method

## [2.2.1] - 2018-01-06

### Fixed
@@ -130,8 +130,9 @@ These methods SHOULD NOT be implemented.

Implementing these is highly unlikely to be worthwhile.

* :meth:`~fs.base.FS.check`
* :meth:`~fs.base.FS.getbasic`
* :meth:`~fs.base.FS.getdetails`
* :meth:`~fs.base.FS.check`
* :meth:`~fs.base.FS.hash`
* :meth:`~fs.base.FS.match`
* :meth:`~fs.base.FS.tree`
@@ -25,6 +25,7 @@ The following is a complete list of methods on PyFilesystem objects.
* :meth:`~fs.base.FS.gettype` Get the type of a resource.
* :meth:`~fs.base.FS.geturl` Get a URL to a resource, if one exists.
* :meth:`~fs.base.FS.hassyspath` Check if a resource maps to the OS filesystem.
* :meth:`~fs.base.FS.hash` Get the hash of a file's contents.
* :meth:`~fs.base.FS.hasurl` Check if a resource has a URL.
* :meth:`~fs.base.FS.isclosed` Check if the filesystem is closed.
* :meth:`~fs.base.FS.isempty` Check if a directory is empty.
@@ -1,3 +1,3 @@
"""Version, used in module and setup.py.
"""
__version__ = "2.2.2a0"
__version__ = "2.3.0"
@@ -9,6 +9,7 @@
from __future__ import absolute_import, print_function, unicode_literals

import abc
import hashlib
import itertools
import os
import threading
@@ -65,6 +66,7 @@
def _new_name(method, old_name):
"""Return a method with a deprecation warning."""
# Looks suspiciously like a decorator, but isn't!

@wraps(method)
def _method(*args, **kwargs):
warnings.warn(
@@ -75,6 +77,14 @@ def _method(*args, **kwargs):
)
return method(*args, **kwargs)

_method.__doc__ += """
Note:
.. deprecated:: 2.2.0
Please use `~{}`
""".format(
method.__name__
)

return _method


@@ -1593,3 +1603,31 @@ def tree(self, **kwargs):
from .tree import render

render(self, **kwargs)

def hash(self, path, name):
# type: (Text, Text) -> Text
"""Get the hash of a file's contents.
Arguments:
path(str): A path on the filesystem.
name(str): One of the algorithms supported by the hashlib module, e.g. `"md5"`
Returns:
str: The hex digest of the hash.
Raises:
fs.errors.UnsupportedHash: If the requested hash is not supported.
"""
_path = self.validatepath(path)
try:
hash_object = hashlib.new(name)
except ValueError:
raise errors.UnsupportedHash("hash '{}' is not supported".format(name))
with self.openbin(path) as binary_file:
while True:
chunk = binary_file.read(1024 * 1024)
if not chunk:
break
hash_object.update(chunk)
return hash_object.hexdigest()
@@ -364,3 +364,12 @@ def __init__(self, path):

def __reduce__(self):
return type(self), (self.path,)


class UnsupportedHash(ValueError):
"""The requested hash algorithm is not supported.
This exception will be thrown if a hash algorithm is requested that is
not supported by hashlib.
"""
@@ -45,6 +45,8 @@ class Info(object):
"""

__slots__ = ["raw", "_to_datetime", "namespaces"]

def __init__(self, raw_info, to_datetime=epoch_to_datetime):
# type: (RawInfo, ToDatetime) -> None
"""Create a resource info object from a raw info dict.
@@ -1834,3 +1834,10 @@ def test_case_sensitive(self):
def test_glob(self):
self.assertIsInstance(self.fs.glob, glob.BoundGlobber)

def test_hash(self):
self.fs.writebytes("hashme.txt", b"foobar" * 1024)
self.assertEqual(
self.fs.hash("hashme.txt", "md5"), "9fff4bb103ab8ce4619064109c54cb9c"
)
with self.assertRaises(errors.UnsupportedHash):
self.fs.hash("hashme.txt", "nohash")
@@ -9,6 +9,7 @@

class TestNewNameDecorator(unittest.TestCase):
def double(self, n):
"Double a number"
return n * 2

times_2 = _new_name(double, "times_2")

0 comments on commit 04e53a4

Please sign in to comment.
You can’t perform that action at this time.