diff --git a/docs/conf.py b/docs/conf.py index 9f29c4a..9d4aeb7 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -38,7 +38,7 @@ # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] -# The suffix of source filenames.git +# The suffix of source filenames.git source_suffix = '.rst' # The encoding of source files. diff --git a/farg/apps/seqsee/tests/test_workspace2.py b/farg/apps/seqsee/tests/test_workspace2.py index 9b909b5..37a3b93 100644 --- a/farg/apps/seqsee/tests/test_workspace2.py +++ b/farg/apps/seqsee/tests/test_workspace2.py @@ -10,7 +10,7 @@ from farg.apps.seqsee.relation import Relation class TestWorkspace(unittest.TestCase): - + def setUp(self): self.ws = ws = Workspace() ws.InsertElements((5, 6, 7, 8)) @@ -42,24 +42,24 @@ def test_group_overlap(self): gp_cp = SAnchored.Create((ws.elements[0], ws.elements[1])) self.assertNotIn(gp_cp, ws.groups, "gp_cp not yet part of workspace") self.assertNotEqual(gp, gp_cp, "The two groups differ") - + gp2 = SAnchored.Create(ws.elements[:]) self.assertIn(gp, ws.GetConflictingGroups(gp2)) - + gp3 = SAnchored.Create((ws.elements[1], ws.elements[2])) # Overlap does not constitute conflict. self.assertNotIn(gp, ws.GetConflictingGroups(gp3)) - + # Also, groups do not conflict with others at exactly the same location if their structures are # identical. self.assertNotIn(gp, ws.GetConflictingGroups(gp_cp)) - + # However, [[X, Y], Z] SHOULD conflict [X, [Y, Z]] gp_XY_Z = ws.InsertGroup(SAnchored.Create((gp, ws.elements[2]))) gp_X_YZ = SAnchored.Create((ws.elements[0], gp3)) self.assertIn(gp_XY_Z, ws.GetConflictingGroups(gp_X_YZ)) - - + + def test_ltm_storability(self): gp = list(self.ws.groups)[0] @@ -68,7 +68,7 @@ def test_ltm_storability(self): self.assertIsInstance(storable, LTMStorableSObject) self.assertEqual((5, 6), storable.structure) self.assertEqual(gp.GetLTMStorableContent(), storable, "Repeated call gives same value.") - + # A different group with the same structure will also give the same storable. self.assertEqual(SAnchored.Create((self.ws.elements[0], self.ws.elements[1])).GetLTMStorableContent(), storable) @@ -89,7 +89,7 @@ def test_relations(self): rel.InsertSelf() self.assertIn(rel, gp.relations, "Ends contain relation") self.assertIn(rel, gp2.relations, "Ends contain relation") - + # Now let's delete gp2: gp should have no relations left. self.assertEqual(2, len(self.ws.groups)) self.ws.DeleteGroup(gp2) diff --git a/farg/core/ltm/graph.py b/farg/core/ltm/graph.py index 1e6743a..4879ab3 100644 --- a/farg/core/ltm/graph.py +++ b/farg/core/ltm/graph.py @@ -26,7 +26,7 @@ class LTMGraph(object): Keyword Args: filename: If present, loads data from file. master_graph must not be present. master_graph: If present, copies data from master graph. filename must not be present. - + Attributes: nodes: A list of :py:class:`~farg.core.ltm.node.LTMNode` objects. _content_to_node: A dictionary mapping content (each an instance of :py:class:`~farg.core.ltm.storable.LTMStorableMixin`) @@ -38,7 +38,7 @@ class LTMGraph(object): This contains nodes and edges. **Nodes** - + Nodes are instances of :py:class:`~farg.core.ltm.node.LTMNode`. A node has the attribute .content, (which is the concept being stored in the node, the very reason for the existence of the node), as well as other metadata such as activation level. @@ -47,18 +47,18 @@ class LTMGraph(object): A particular instance may depend for its definition on content of other graph nodes. **Storing to and retrieving from disk** - + Graphs can be stored on disk and retrieved. Given arbitrary dependencies between nodes, we rely on :py:mod:`pickle` to do the heavy-duty lifting of serialization and deserialization. - + There are two main ways to construct this graph: it can be loaded from a file, or it can be copied from another graph. - + In a given run, a graph is loaded from disk (let's call this graph O), and a copy made from it (Graph W). Graph W is the working copy which the app can update, and at the end, some salient items will make their way back to O, and it will be written to disk. - - The class LTM Manager handles this workflow. + + The class LTM Manager handles this workflow. """ def __init__(self, *, filename=None, master_graph=None, empty_ok_for_test=False): @@ -98,7 +98,7 @@ def DumpToFile(self): self._Mangle(node.content.__dict__) pickler.dump(node) self._Unmangle(node.content.__dict__) - + # TODO: rename to GetNode(self, *, content) def GetNode(self, *, content): """Returns node for content; creates one if it does not exist.""" @@ -135,13 +135,13 @@ def UploadToMaster(self, *, threshold=0.05): def _LoadFromFile(self): """Loads graph nodes from file. - + The file contains pickled nodes, and dependent data has been replaced with nodes. All this needs to be undone to load from file.""" if hasattr(self, 'filename'): filename = self.filename else: - filename = self.master_graph.filename + filename = self.master_graph.filename with open(filename, "rb") as ltmfile: unpickler = pickle.Unpickler(ltmfile) while True: @@ -153,7 +153,7 @@ def _LoadFromFile(self): except ValueError: # Hit in Py3 for empty input file... break - + def _AddNode(self, node): """Adds node to graph.""" assert(isinstance(node, LTMNode)) @@ -195,4 +195,3 @@ def StrengthenEdge(self, from_content, to_content, *, edge.utility += 1 return node.outgoing_edges.append(LTMEdge(to_node, edge_type=edge_type, utility=1)) - \ No newline at end of file diff --git a/farg/core/main.py b/farg/core/main.py index 04d13d6..15c966b 100644 --- a/farg/core/main.py +++ b/farg/core/main.py @@ -29,11 +29,11 @@ class Main: Based on flags, it sets up the appropriate run mode (which start GUIs if needed). It also does a sanity check on flags and creates certain directories if needed. - + Arguments: unprocessed_flags: These are the flags returned by argparse that are yet to be sanity checked and processed. That work is done here, and the processed flags are put in self.flags. - + Notes: * Many attributes here are classes that do the actual work. Subclasses will override several of these. These include the following. @@ -196,12 +196,12 @@ def _CreateRunModeInstance(self): def ProcessFlags(self): """Sanity checks and does some flag-related and flag-triggered house-keeping. - + This includes creating directories, starting logging, and so forth. """ if self.flags.debug_config: logging.config.fileConfig(self.flags.debug_config) - + if self.flags.debug: numeric_level = getattr(logging, self.flags.debug.upper(), None) if not isinstance(numeric_level, int): @@ -233,7 +233,7 @@ def ProcessFlags(self): def ProcessCustomFlags(self): """Process custom flags defined by the app. - + If an app needs post-processing of some flags it defines, it can be put here. The current flags (including any changes made to the core flags is available as self.flags. """ diff --git a/farg/core/ui/gui/central_pane.py b/farg/core/ui/gui/central_pane.py index 25f67bd..c84bb9b 100644 --- a/farg/core/ui/gui/central_pane.py +++ b/farg/core/ui/gui/central_pane.py @@ -25,22 +25,22 @@ class CentralPane(Canvas): # Pylint thinks this has 9 ancestrors. pylint:disabl """The central area of the UI based display. **ViewPorts** and **Views** - + A Viewport is a small window through which to look at some aspects the activity of the app. Examples of viewports that come packaged with PySeqsee include :py:class:`~farg.core.ui.gui.views.coderack_view.CoderackView`, which displays the current codelets waiting to run. Other already supplied views can be found in the :py:mod:`~farg.core.ui.gui.views` module. - + A View, on the other hand, is a tiling of a few such views into a display. A View may consist of just a single viewport, or two or more viewports. This class provides methods to create views and to maintain a set of named views. - + **Setting up views** - + A view may be set up by calling one of the following methods of this class. SetFullView, which takes a viewport class as argument, creates a view with that single, full-sized viewport. The names SetVerticallySplitView and SetThreeWaySplit should be self-explanatory. - + **Example Usage** For an example of how a subclass may set up the views, take a look at the code for diff --git a/farg/tools/print_ltm.py b/farg/tools/print_ltm.py index 203a141..677ae18 100644 --- a/farg/tools/print_ltm.py +++ b/farg/tools/print_ltm.py @@ -28,9 +28,9 @@ def PrintLTM(args): filename = GetLTMPath(args.app_name, args.ltm_name) ltm = LTMGraph(filename=filename) print("LTM contains %d nodes" % len(ltm.nodes)) - for idx, node in enumerate(ltm.nodes): - print('-- %d [dep=%5.3f] --' % (idx, 1.0 / node.depth_reciprocal), node.content.BriefLabel()) + for node in ltm.nodes: + print('%s\t\t[dep=%5.3f]' % (node.content.BriefLabel(), 1.0 / node.depth_reciprocal)) for edge in node.GetOutgoingEdges(): other_node = edge.to_node - print('\tEdge:%s to %s [Utility=%d]' % (edge.edge_type, other_node.content.BriefLabel(), - edge.utility)) \ No newline at end of file + print('\t--> %s [%s, Utility=%d]' % (other_node.content.BriefLabel(), edge.edge_type, + edge.utility)) \ No newline at end of file diff --git a/setup.py b/setup.py index acccede..2e9a8e6 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,6 @@ from setuptools import setup import os, sys - + def fullsplit(path, result=None): """ Split a pathname into components (the opposite of os.path.join) in a @@ -68,4 +68,4 @@ def fullsplit(path, result=None): 'farg=farg.tools:main', ], }, -) \ No newline at end of file +)