Repository: MaineKuehn/classad

Issue:
Evaluation of ArithmetricExpression in context of ClassAd not working
There still seems to be an issue when evaluating an ArithmetricExpression in the context of a ClassAd, e.g.

`parse("my.a + 2").evluate(my=parse("a=4")))`

This should result in a value of `6`.

Discussion:

Patch:
diff --git a/classad/_expression.py b/classad/_expression.py
index 7885788..11647b1 100644
--- a/classad/_expression.py
+++ b/classad/_expression.py
@@ -232,18 +232,21 @@ class AttributeExpression(CompoundExpression):
             the_key = scope_up(self._expression[1])
             expression = self._expression[1][-1]
         elif self._expression[0] == "target":
-            if my is None or target is None:
+            if target is None:
                 return Undefined()
             selected_classad = target
             expression = self._expression[1]
         elif self._expression[0] == "my":
-            if my is None or target is None:
+            if my is None:
                 return Undefined()
-            expression = self._expression
+            expression = self._expression[1]
         else:
             expression = self._expression
         try:
-            context = find_scope(the_key, classad=selected_classad)
+            if the_key is None and selected_classad is not None:
+                context = selected_classad
+            else:
+                context = find_scope(the_key, classad=selected_classad)
         except TypeError:
             return Error()
         while isinstance(value, Undefined):
diff --git a/classad/_primitives.py b/classad/_primitives.py
index 6709e61..166ea71 100644
--- a/classad/_primitives.py
+++ b/classad/_primitives.py
@@ -63,9 +63,6 @@ class Undefined(PrimitiveExpression):
     def __repr__(self):
         return f"<{self.__class__.__name__}>"
 
-    def __hash__(self):
-        return hash("undefined")
-
 
 class Error(PrimitiveExpression):
     """
@@ -118,9 +115,6 @@ class Error(PrimitiveExpression):
     def __repr__(self):
         return f"<{self.__class__.__name__}>"
 
-    def __hash__(self):
-        return hash("error")
-
 
 class HTCInt(int, PrimitiveExpression):
     __slots__ = ()
@@ -229,9 +223,6 @@ class HTCInt(int, PrimitiveExpression):
     def __repr__(self):
         return f"<{self.__class__.__name__}>: {self}"
 
-    def __hash__(self):
-        return super().__hash__()
-
 
 class HTCList(tuple, PrimitiveExpression):
     __slots__ = ()
@@ -277,9 +268,6 @@ class HTCStr(str, PrimitiveExpression):
     def __repr__(self):
         return f"<{self.__class__.__name__}>: {self}"
 
-    def __hash__(self):
-        return super().__hash__()
-
 
 class HTCFloat(float, PrimitiveExpression):
     __slots__ = ()
@@ -326,9 +314,6 @@ class HTCFloat(float, PrimitiveExpression):
     def __repr__(self):
         return f"<{self.__class__.__name__}>: {self}"
 
-    def __hash__(self):
-        return super().__hash__()
-
 
 class HTCBool(PrimitiveExpression):
     __slots__ = ("_value",)
@@ -392,6 +377,3 @@ class HTCBool(PrimitiveExpression):
 
     def __repr__(self):
         return f"<{self.__class__.__name__}>: {self._value}"
-
-    def __hash__(self):
-        return hash(self._value)
diff --git a/docs/source/change/16.primitive_hash.yaml b/docs/source/change/16.primitive_hash.yaml
deleted file mode 100644
index 2528330..0000000
--- a/docs/source/change/16.primitive_hash.yaml
+++ /dev/null
@@ -1,7 +0,0 @@
-category: added
-summary: "Primitives now implement __hash__"
-description: |
-  So far, the primitives including `Undefined`, `Error`, `HTCInt`, `HTCFloat`,
-  `HTCBool` and `HTCStr` did not implement `__hash__`. This was added.
-pull requests:
-  - 16
diff --git a/docs/source/change/18.expression_evaluation.yaml b/docs/source/change/18.expression_evaluation.yaml
new file mode 100644
index 0000000..3507d6c
--- /dev/null
+++ b/docs/source/change/18.expression_evaluation.yaml
@@ -0,0 +1,8 @@
+category: added
+summary: "Evaluation of expression in context of classad"
+description: |
+  The project can now evaluate an expression in the context of a classads.
+issues:
+  - 17
+pull requests:
+  - 18


Test patch:
diff --git a/classad_tests/test_builtins.py b/classad_tests/test_builtins.py
index de2b57d..9ed21d0 100644
--- a/classad_tests/test_builtins.py
+++ b/classad_tests/test_builtins.py
@@ -8,8 +8,8 @@ from classad._primitives import (
     HTCInt,
     HTCFloat,
     # HTCList,
+    # HTCStr,
     HTCBool,
-    HTCStr,
 )
 from classad._operator import eq_operator, ne_operator
 
@@ -60,17 +60,3 @@ def test_numbers(num_type):
             assert_similar(operation, HTCBool(False), num_type, value)
             assert_similar(operation, Error(), num_type, value)
             assert_similar(operation, Undefined(), num_type, value)
-
-
-def test_hashable():
-    test = set()
-    try:
-        test.add(Undefined())
-        test.add(Error())
-        test.add(HTCInt(1))
-        test.add(HTCFloat(0.0))
-        test.add(HTCStr("test"))
-        test.add(HTCBool(True))
-    except TypeError:
-        pytest.fail("Hashing not supported")
-    assert len(test) == 6
diff --git a/classad_tests/test_evaluation.py b/classad_tests/test_evaluation.py
new file mode 100644
index 0000000..17bbd9b
--- /dev/null
+++ b/classad_tests/test_evaluation.py
@@ -0,0 +1,8 @@
+from classad import parse
+from classad._primitives import HTCInt
+
+
+def test_simple():
+    first_part = parse("my.a + 2")
+    my_classad = parse("a = 4")
+    assert first_part.evaluate(my=my_classad) == HTCInt(6)