[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [HTCondor-users] matchmaking with python bindings changes behavior depending on the imports



On 11/15/2018 2:35 PM, Jose Caballero wrote:
> Hi,
> is this behavior expected?
> 
>>>> import classad
>>>> c = classad.ClassAd()
>>>> c['foo'] = 5
>>>> req = classad.ClassAd()
>>>> req['Requirements'] = classad.ExprTree('foo > 0')
>>>> c.matches(req)
> False
> 
>>>> import htcondor
>>>> c.matches(req)
> True
> 
> 

Hi Jose,

Yes, for better or worse, this is currently the expected behavior.

The explanation can be found by understanding the "old" vs "new" ClassAd semantics.  Details on this can be found in the HTCondor Manual here:
  http://htcondor.org/manual/v8.7/HTCondorsClassAdMechanism.html#x48-3990004.1.1

But in a nutshell, when you do 'import classad' on its own, you get "new" semantics.  When you do 'import htcondor', you get "old" classad semantics, because HTCondor itself uses the old semantics. One difference between old and new classads that explains the behavior you see above is when expressions refer to ClassAd attributes. These attribute references work differently in Old ClassAds as compared with New ClassAds. In New ClassAds, an unscoped reference is looked for only in the local ClassAd. An unscoped reference is an attribute that does not have a MY. or TARGET. prefix.  In Old classads, the reference will first be looked for in the MY ad, and if it is not found, then it will automatically also be looked for in the TARGET ad.

Some examples below to help explain via demonstrative code.

Hope the above and below help!
regards,
Todd

Example One.  This shows the same result you got above.  The issue here is 'foo' is only looked up in ad req:

In:  import classad
     c = classad.ClassAd()
     c['foo'] = 5
     req = classad.ClassAd()
     req['Requirements'] = classad.ExprTree('foo > 0')
     c.matches(req)
Out: False

Example Two.  Here we explicitly scope foo to be target.foo, and now we get a match:

In:  import classad
     c = classad.ClassAd()
     c['foo'] = 5
     req = classad.ClassAd()
     req['Requirements'] = classad.ExprTree('TARGET.foo > 0')
     c.matches(req)
Out: True

Example Three.  Because we import htcondor here, we will get the 'old' semantics which will first lookup 
attribute foo in MY scope and then automatically lookup attribute foo in TARGET, resulting in
the True output:

In:  import classad
     import htcondor
     c = classad.ClassAd()
     c['foo'] = 5
     req = classad.ClassAd()
     req['Requirements'] = classad.ExprTree('foo > 0')
     c.matches(req)
Out: True

Example Four.  So this example is same as Example Three, but we first set config knob 
STRICT_CLASSAD_EVALUATION=True (it defaults to False). As explained in the Manual section I listed 
above, you can set config knob STRICT_CLASSAD_EVALUATION=True to tell HTCondor (and thus 
the htcondor python package) to use 'new' style semantics instead of defaulting to the 'old' style.  

In:  import os
     os.environ['_condor_STRICT_CLASSAD_EVALUATION']='True'
     import classad
     import htcondor
     c = classad.ClassAd()
     c['foo'] = 5
     req = classad.ClassAd()
     req['Requirements'] = classad.ExprTree('foo > 0')
     c.matches(req)
Out: False