The BSFS stack can be coarsely divided into four parts (see the image below).

  • Envelope: Essentials and utils used throughout the whole codebase.

  • Front: End-user applications and APIs.

  • Center: The core interfaces and functionality.

  • Back: The triple store backends.

Details of these components are given in the sections below.

_images/arch_light.png _images/arch_dark.png


Most notably, the envelope covers the Schema and the Query syntax trees (AST). Both of them essential for all parts of the BSFS stack. For example, the schema is specified by the user via the Migrate command, checked and extended by the Graph, and ultimately stored by a Triple Store backend. Similarly, the Query AST may be provided by a caller and is translated to a database query by a backend. In addition, the envelope also contains some classes to handle URIs: URI defines the URI base class, Namespace provides shortcuts to generate URIs, and UUID is used to generate unique URIs.


The front consists of exposed interfaces such as end-user applications or APIs, and all utils needed to offer this functionality. See bsfs.apps and bsfs.front.


The heart of BSFS is grouped around the bsfs.graph module. These classes provide the interface to navigate and manipulate the file graph in a safe and programmer friendly manner. Some of them are indirectly exposed through the higher-level APIs.

The two core design principles of BSFS are the focus on nodes and batch processing. They are realized in the the Graph and Nodes classes. The Graph class manages the graph as a whole, and offers methods to get a specific set of Nodes. In turn, the Nodes class represents such a set of nodes, and performs operations on the whole node set at once. Besides, the bsfs.graph module also comes with some syntactic sugar.


# Open a file graph.
from bsfs import Open, ns
graph = Open(...)
# Get all nodes of type File.
nodes = graph.all(ns.bsfs.File)
# Set the author of all nodes at once.
nodes.set(, 'Myself')
# Retrieve the author of all nodes at once.
set(nodes.get(, node=False))
# Same as above, but shorter.


There are various graph databases (e.g., RDFLib, Blazegraph, Titan, etc.) and it would be foolish to replicate the work that others have done. Instead, we use third-party stores that take care of how to store and manage the data. The Backend base class defines the interface to integrate any such third-party store to BSFS. Besides storing the data, a triple store backend also need to track the current schema.