Skip to content

Commit

Permalink
Added a sorted flag to FactBase.asp_str() for sorted output
Browse files Browse the repository at this point in the history
  • Loading branch information
daveraja committed Oct 26, 2021
1 parent 7e1be72 commit 927249e
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 7 deletions.
45 changes: 38 additions & 7 deletions clorm/orm/factbase.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
# PEP 257 (modified for Python 3): https://www.python.org/dev/peps/pep-0257/
# ------------------------------------------------------------------------------

_builtin_sorted=sorted

def _format_asp_facts(iterator,output,width):
tmp1=""
for f in iterator:
Expand Down Expand Up @@ -360,22 +362,51 @@ def facts(self):
tmp = [ fm.factset for fm in self._factmaps.values() if fm]
return list(itertools.chain(*tmp))

def asp_str(self,width=0,commented=False):
"""Return a string representation of the fact base that is suitable for adding
to an ASP program
def asp_str(self,*,width=0,commented=False,sorted=False):
"""Return a ASP string representation of the fact base.
This ASP string representation is syntactically correct ASP code so is
suitable for adding as the input to to an ASP program (or writing to a
file for later use in an ASP program).
By default the order of the facts in the string is arbitrary. Because
`FactBase` is built on a `OrderedDict` (which preserves insertion
order) the order of the facts will be deterministic between runs of the
same program. However two FactBases containing the same facts but
constructed in different ways will not produce the same output
string. In order to guarantee the same output the `sorted` flag can be
specified.
Args (keyword arguments only):
width=0: tries to fill to a given width by putting more than one
fact on a line if necessary.
commented=False: produces commented ASP code by adding a predicate
signature and turning the Predicate sub-class
docstring into a ASP comments.
sorted=False: sort the output facts
"""
self._check_init() # Check for delayed init
out = io.StringIO()

if not commented:
_format_asp_facts(self,out,width)
first=True
if sorted:
names = _builtin_sorted(self._factmaps.keys(),key=lambda pt:
(pt.meta.name, pt.meta.arity,pt.__name__))
fms = [self._factmaps[n] for n in names]
else:
first=True
for fm in self._factmaps.values():
fms = self._factmaps.values()
for fm in fms:
if commented:
if first: first=False
else: print("",file=out)
_format_commented(fm,out)
if sorted:
_format_asp_facts(_builtin_sorted(fm.factset),out,width)
else:
_format_asp_facts(fm.factset,out,width)

data = out.getvalue()
Expand Down
46 changes: 46 additions & 0 deletions tests/test_orm_factbase.py
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,52 @@ class Meta: name="a_very_long_predicate_name_that_cause_wrapping_well"
cfactspre="% Predicate signature:\n% {}(n,s)\n".format(C.meta.name)
self.assertTrue(aspstr.startswith(cfactspre))

#--------------------------------------------------------------------------
# Test the asp output string with the sorted flag
# --------------------------------------------------------------------------
def test_factbase_aspstr_sorted(self):
class A(Predicate):
a = IntegerField
class Meta: name="bb"
class B(Predicate):
a = IntegerField
class Meta: name="aa"
class C(Predicate):
a = IntegerField
b = IntegerField
class Meta: name="aa"

def tostr(facts):
return ".\n".join([str(f) for f in facts])

def sig(ptype):
cstr = ("% -------------------\n"
"% Predicate signature\n"
"% {}(a)\n"
"% -------------------\n").format(ptype.__name__)
return cstr

afacts = [A(100),A(50),A(99)]
bfacts = [B(100),B(50),B(99)]
cfacts = [C(100,100),C(50,50),C(99,99)]
fb=FactBase()
fb.add(cfacts)
fb.add(bfacts)
fb.add(afacts)

expected1 = tostr(cfacts) + ".\n" + tostr(bfacts) + ".\n" + \
tostr(afacts) + ".\n"
self.assertEqual(fb.asp_str(), expected1)

expected2 = tostr(sorted(bfacts)) + ".\n" + tostr(sorted(cfacts)) + \
".\n" + tostr(sorted(afacts)) + ".\n"
self.assertEqual(fb.asp_str(sorted=True), expected2)

expected3 = \
sig(A) + tostr(sorted(bfacts)) + ".\n" + \
sig(B) + tostr(sorted(bfacts)) + ".\n" + \
sig(C) + tostr(sorted(afacts)) + ".\n"
self.assertTrue(fb.asp_str(commented=True,sorted=True), expected3)

#------------------------------------------------------------------------------
# Test QueryAPI version 1 (called via FactBase.select() and FactBase.delete())
Expand Down

0 comments on commit 927249e

Please sign in to comment.