diff --git a/mathics/builtin/files.py b/mathics/builtin/files.py
index 434e3937ea..7d1e537f1a 100644
--- a/mathics/builtin/files.py
+++ b/mathics/builtin/files.py
@@ -3812,6 +3812,8 @@ class FileHash(Builtin):
'FileHash[$file$, $type$]'
returns an integer hash of the specified $type$ for the given $file$.
The types supported are "MD5", "Adler32", "CRC32", "SHA", "SHA224", "SHA256", "SHA384", and "SHA512".
+ 'FileHash[$file$, $type$, $format$]'
+ gives a hash code in the specified format.
>> FileHash["ExampleData/sunflowers.jpg"]
@@ -3840,19 +3842,20 @@ class FileHash(Builtin):
#> FileHash["ExampleData/sunflowers.jpg", xyzsymbol]
= FileHash[ExampleData/sunflowers.jpg, xyzsymbol]
#> FileHash["ExampleData/sunflowers.jpg", "xyzstr"]
- = FileHash[ExampleData/sunflowers.jpg, xyzstr]
+ = FileHash[ExampleData/sunflowers.jpg, xyzstr, Integer]
#> FileHash[xyzsymbol]
= FileHash[xyzsymbol]
"""
rules = {
- "FileHash[filename_String]": 'FileHash[filename, "MD5"]',
+ "FileHash[filename_String]": 'FileHash[filename, "MD5", "Integer"]',
+ "FileHash[filename_String, hashtype_String]": 'FileHash[filename, hashtype, "Integer"]',
}
attributes = ("Protected", "ReadProtected")
- def apply(self, filename, hashtype, evaluation):
- "FileHash[filename_String, hashtype_String]"
+ def apply(self, filename, hashtype, format, evaluation):
+ "FileHash[filename_String, hashtype_String, format_String]"
py_filename = filename.get_string_value()
try:
@@ -3865,7 +3868,7 @@ def apply(self, filename, hashtype, evaluation):
e.message(evaluation)
return
- return Hash.compute(lambda update: update(dump), hashtype.get_string_value())
+ return Hash.compute(lambda update: update(dump), hashtype.get_string_value(), format.get_string_value())
class FileDate(Builtin):
@@ -4803,6 +4806,7 @@ def apply(self, pathname, evaluation):
return SymbolTrue
return SymbolFalse
+
class Needs(Builtin):
"""
@@ -4922,7 +4926,6 @@ def apply(self, context, evaluation):
curr_ctxt = evaluation.definitions.get_current_context()
contextstr = curr_ctxt + contextstr[1:]
context = String(contextstr)
-
if not valid_context_name(contextstr):
evaluation.message('Needs', 'ctx', Expression(
'Needs', context), 1, '`')
@@ -4932,15 +4935,6 @@ def apply(self, context, evaluation):
if test_loaded.is_true():
# Already loaded
return SymbolNull
-
- # TODO: Figure out why this raises the message:
- # "Select::normal: Nonatomic expression expected."
- already_loaded = Expression('MemberQ',
- Symbol('System`$Packages'), context)
- already_loaded = already_loaded.evaluate(evaluation).is_true()
- if already_loaded:
- return SymbolNull
-
result = Expression('Get', context).evaluate(evaluation)
if result == SymbolFailed:
@@ -4948,3 +4942,4 @@ def apply(self, context, evaluation):
return SymbolFailed
return SymbolNull
+
diff --git a/mathics/builtin/numeric.py b/mathics/builtin/numeric.py
index 7724f06a85..99e639bb36 100644
--- a/mathics/builtin/numeric.py
+++ b/mathics/builtin/numeric.py
@@ -1340,6 +1340,8 @@ class Hash(Builtin):
- 'Hash[$expr$, $type$]'
- returns an integer hash of the specified $type$ for the given $expr$.
- The types supported are "MD5", "Adler32", "CRC32", "SHA", "SHA224", "SHA256", "SHA384", and "SHA512".
+ - 'Hash[$expr$, $type$, $format$]'
+
- Returns the hash in the especified format.
> Hash["The Adventures of Huckleberry Finn"]
@@ -1358,11 +1360,12 @@ class Hash(Builtin):
= 58042316473471877315442015469706095084
>> Hash[{a, b, c}, "xyzstr"]
- = Hash[{a, b, c}, xyzstr]
+ = Hash[{a, b, c}, xyzstr, Integer]
"""
rules = {
- "Hash[expr_]": 'Hash[expr, "MD5"]',
+ "Hash[expr_]": 'Hash[expr, "MD5", "Integer"]',
+ "Hash[expr_, type_String]": 'Hash[expr, type, "Integer"]',
}
attributes = ("Protected", "ReadProtected")
@@ -1380,17 +1383,30 @@ class Hash(Builtin):
}
@staticmethod
- def compute(user_hash, py_hashtype):
+ def compute(user_hash, py_hashtype, py_format):
hash_func = Hash._supported_hashes.get(py_hashtype)
if hash_func is None: # unknown hash function?
return # in order to return original Expression
h = hash_func()
user_hash(h.update)
- return from_python(int(h.hexdigest(), 16))
-
- def apply(self, expr, hashtype, evaluation):
- "Hash[expr_, hashtype_String]"
- return Hash.compute(expr.user_hash, hashtype.get_string_value())
+ res = h.hexdigest()
+ if py_format in ('HexString', "HexStringLittleEndian") :
+ return from_python(res)
+ res = int(res, 16)
+ if py_format == "DecimalString":
+ return from_python(str(res))
+ elif py_format == "ByteArray":
+ print("Not implemented. Return a string")
+ return from_python(str(res))
+ # Default: Integer
+ return from_python(res)
+
+
+ def apply(self, expr, hashtype, outformat, evaluation):
+ "Hash[expr_, hashtype_String, outformat_String]"
+ return Hash.compute(expr.user_hash,
+ hashtype.get_string_value(),
+ outformat.get_string_value())
class TypeEscalation(Exception):