Repository: MaineKuehn/classad

Issue:
Support evaluation of two classads in context
Until now only one classad can be evaluated, so the reference with ``my`` and ``target`` is not supported yet. This should be implemented.

Discussion:

Patch:
diff --git a/classad/_expression.py b/classad/_expression.py
index 14f2d3e..f63d257 100644
--- a/classad/_expression.py
+++ b/classad/_expression.py
@@ -206,19 +206,23 @@ class AttributeExpression(Expression):
         my: "Optional[ClassAd]" = None,
         target: "Optional[ClassAd]" = None,
     ) -> Any:
-        def find_scope(current_key):
+        def find_scope(current_key, classad=my):
             if len(current_key) > 0:
-                return my[current_key]
-            return my
+                return classad[current_key]
+            return classad
 
+        selected_classad = my
         value = Undefined()
         if self._expression[0] == ".":
             key = scope_up(self._expression[1])
             expression = self._expression[1][-1]
+        elif self._expression[0] == "target":
+            selected_classad = target
+            expression = self._expression[1]
         else:
             expression = self._expression
         try:
-            context = find_scope(key)
+            context = find_scope(key, classad=selected_classad)
         except TypeError:
             return Error()
         while isinstance(value, Undefined):
@@ -227,7 +231,7 @@ class AttributeExpression(Expression):
                 if len(key) == 0:
                     return Undefined()
                 key = scope_up(key)
-                context = find_scope(key)
+                context = find_scope(key, classad=selected_classad)
         if isinstance(value, AttributeExpression):
             return value._evaluate(key=key, my=my, target=target)
         return value
diff --git a/classad/_grammar.py b/classad/_grammar.py
index ef1413a..b08d4f5 100644
--- a/classad/_grammar.py
+++ b/classad/_grammar.py
@@ -41,6 +41,9 @@ undefined_literal = pp.CaselessKeyword("undefined").setParseAction(lambda: Undef
 parent_literal = pp.CaselessKeyword("parent").setParseAction(
     lambda s, l, t: NamedExpression.from_grammar(t[0])
 )
+my_literal = pp.CaselessKeyword("my").setParseAction(
+    lambda s, l, t: NamedExpression.from_grammar(t[0])
+)
 target_literal = pp.CaselessKeyword("target").setParseAction(
     lambda s, l, t: NamedExpression.from_grammar(t[0])
 )
diff --git a/docs/source/change/11.target_evaluation.yaml b/docs/source/change/11.target_evaluation.yaml
new file mode 100644
index 0000000..a3a46f8
--- /dev/null
+++ b/docs/source/change/11.target_evaluation.yaml
@@ -0,0 +1,10 @@
+category: added
+summary: "Evaluation of target classad"
+description: |
+  The project can now evaluate two classads in context. For this, the evaluation
+  of :py:class:`~.AttributeExpression`s implements the evaluation of the
+  :py:class:`~.NamedExpression` *target*.
+issues:
+  - 9
+pull requests:
+  - 11
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000..89faa06
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,9 @@
+[aliases]
+test=pytest
+
+[flake8]
+statistics = True
+max-line-length = 80
+ignore = E501, B008, B011, W503
+select = C,E,F,W,B,B9
+exclude = docs,.svn,CVS,.bzr,.hg,.git,__pycache__,.tox,.eggs,*.egg


Test patch:
diff --git a/classad_tests/test_matchmaking.py b/classad_tests/test_matchmaking.py
new file mode 100644
index 0000000..0403d2e
--- /dev/null
+++ b/classad_tests/test_matchmaking.py
@@ -0,0 +1,23 @@
+from classad import parse
+from classad._primitives import HTCInt
+
+
+def test_simple():
+    my_classad = parse("""rank = TARGET.Memory + TARGET.Mips """)
+    target_classad = parse(
+        """
+    Memory = 8
+    Mips = 10
+    """
+    )
+    assert my_classad.evaluate(
+        key="rank", my=my_classad, target=target_classad
+    ) == HTCInt(18)
+
+
+def test_nested():
+    my_classad = parse("""rank = TARGET.a.b + TARGET.c""")
+    target_classad = parse("""[c = 1; a = [b = 2; d = 1]]""")
+    assert my_classad.evaluate(
+        key="rank", my=my_classad, target=target_classad
+    ) == HTCInt(3)