- Initially, I'm only concerned with using a MySQL back-end, so that's going to be the primary focus for the database side of things.
- It will use the current version of Fuse for Python available on my Ubuntu installations (0.2 or so);
The
DBFSpy
packageThis should provide any global constants, definitions of interfaces and the like, and anything else that the various database-specific modules would require.
There are a couple of custom exceptions that are already defined (since they are very basic):
ConnectionChangeError
and FilsystemChangeError
. They will serve to provide specific exception-throwing capabilities in cases where the filesystem or the database underlying the filesystem are being changed. This, in my mind, would be something to avoid, since the underlying filesystem data could then be left in a corrupted or unusable state.There are also a couple of constants defined here:
GUIDCHECKER
- A regular expression that will be used elsewhere to determine whether a string is a GUID/UUID-formatted value (which I'll be using extensively to provide unique identifiers in the filesystem database); and
LOGFORMAT
- A string that defines the format for an output line in the system's log-file, if any is generated.
With no other implementation details, then, the package-header will look something like this:
# DBFSpy package header (__init__.py) """Provides global constants, interfaces and functionality for the database-specific DBFSpy implementations in various member modules.""" # Define __all__ list, so that we can use "from DBFSpy import *" # syntax elsewhere. __all__ = [] ######################################################################## # Required imports # ######################################################################## import fuse, logging, os, re, stat, types, uuid ######################################################################## # Package constants # ######################################################################## # A regular expression that we can use to verify GUID/UUID structure. GUIDCHECKER = re.compile( '[0-9a-fA-F]{,8}-[0-9a-fA-F]{,4}-[0-9a-fA-F]{,4}-[0-9a-fA-F]{,4}-[0-9a-fA-F]{,12}' ) __all__ += [ 'GUIDCHECKER' ] # logging output format: LOGFORMAT = '%(name)s:%(asctime)s:%(levelname)s:%(message)s' __all__ += [ 'LOGFORMAT' ] ######################################################################## # Custom Exceptions # ######################################################################## class ConnectionChangeError( Exception ): """Custom exception to be raised when a change is made to connection properties of an IDatabaseConnected instance that would break or corrupt the virtual filesystem if the change were allowed.""" pass __all__ += [ 'ConnectionChangeError' ] class FilesystemChangeError( Exception ): """Custom exception to be raised when a change is made to an IFilesystem instance that would break or corrupt the virtual filesystem if the change were allowed.""" pass __all__ += [ 'FilesystemChangeError' ] ######################################################################## # Definitions of (nominal) interfaces and abstract classes # ######################################################################## class BaseDatabaseConnection( object ): """Nominal abstract class, provides baseline functionality and interface requirements for objects that can connect to and execute queries, procedures, and/or functions against a back-end data-source""" ########################### # Class Attributes # ########################### ########################### # Class Property Getters # ########################### ########################### # Class Property Setters # ########################### ########################### # Class Property Deleters # ########################### ########################### # Class Properties # ########################### ########################### # Object Constructor # ########################### ########################### # Object Destructor # ########################### ########################### # Class Methods # ########################### ########################### # Static Class Methods # ########################### pass __all__ += [ 'BaseDatabaseConnection' ] class BaseDataObject( object ): """Nominal abstract class, provides baseline functionality and interface requirements for objects whose state data is persisted in a back-end data-store.""" pass __all__ += [ 'BaseDataObject' ] class IFilesystemItem( object ): """Nominal interface, provides functional requirements for objects that can represent items in the virtual filesystem.""" pass __all__ += [ 'IFilesystemItem' ] class BaseFilesystemItemCache( object ): """Nominal abstract class, provides functional requirements for objects that can cache virtual filesystem items.""" pass __all__ += [ 'BaseFilesystemItemCache' ] class IFilesystemOperators( object ): """Nominal interface, provides functional requirements for objects that can respond to filesystem commands.""" pass __all__ += [ 'IFilesystemOperators' ] class IFilesystem( object ): """Nominal interface, provides functional requirements for objects that provide the logic-bridge between the virtual filesystemand the back-end data-store.""" pass __all__ += [ 'IFilesystem' ] ######################################################################## # Instantiable classes # ######################################################################## # No instantiable classes are anticipated at this level of the package...
The
DBFSpy.MySQL
moduleThe main DBFSpy package-header is not expected to provide any instantiable classes, just nominal interface and abstract-class definitions. The database-specific implementations will be broken out into separate modules (one for each back-end database-connection type), in order to allow for as much separation of code as we can manage across the different back-end implementations. Since I'm planning on starting with a MySQL back-end, that will be the first concrete-implementation module. Others should be similarly structured.
# DBFSpy.MySQL module (MySQL.py) """Provides instantiable classes that can be used to create a virtual filesystem that uses a MySQL back-end to store filesystem information.""" # Define __all__ list, so that we can use "from DBFSpy import *" # syntax elsewhere. __all__ = [] ######################################################################## # Required imports # ######################################################################## import fuse, MySQLdb from DBFSpy import GUIDCHECKER, LOGFORMAT, ConnectionChangeError, FilesystemChangeError, BaseDatabaseConnection, BaseDataObject, IFilesystemItem, IFilesystemOperators, IFilesystem ######################################################################## # Package constants # ######################################################################## ######################################################################## # Custom Exceptions # ######################################################################## ######################################################################## # Definitions of (nominal) interfaces and abstract classes # ######################################################################## ######################################################################## # Instantiable classes # ######################################################################## class MySQLFileItem( BaseDataObject, IFileSystemItem, object ): """Represents an item in a virtual filesystem, whose state-information is persisted in a MySQL back-end data-store.""" pass __all__ += [ 'MySQLFileItem' ] class MySQLDatasource( BaseDatabaseConnection, BaseFilesystemItemCache, IFilesystemOperators, object ): """Represents a connection to a MySQL back-end data-store, with an in-memory cache of filesystem objects, and actual implementations of filesystem operations to return item-data from the cached or live-data state of filesystem objects.""" pass __all__ += [ 'MySQLDatasource' ] class MySQLFilesystem( IFilesystem, IFilesystemOperators, fuse.Fuse, object ): """Provides the virtual filesystem, and provides filesystem operations (which are delegated to a MySQLDatasource instance).""" pass __all__ += [ 'MySQLFilesystem' ]
Other database modules
Ultimately, as the project grows, there should be other database-specific modules added to provide support for other back-end database systems (PostgreSQL and ODBC connections, at the very least, possibly others as well). They should provide a very similar set of concrete classes.
The main executable
Though the main intended use for the final codebase is intended to support a CMS system that I'm thinking through (PicaCMS), there is no reason that it couldn't be used for other purposes as well. With my intended goal in mind, however, the typical use-case would involve the main CMS starting one or more instances of the database filesystem, probably as a service on the machine(s) it is installed on. To that end, the invocation to start the filesystem would likely look something like this:
dbfspy -m mountpoint -t database-type -s server -d database -u user -p password -l log-file -g logging-level
where:
- mountpoint
- is the "real" filesystem mount-point for the virtual filesystem;
- database-type;
- is the type of back-end database (e.g., MySQL, PostgreSQL, ODBC, etc.) that the filesystem's data will be stored in;
- server
- is the machine (by name or IP-address) that the virtual filesystem database resides on;
- database
- is the name of the database that the virtual filesystem's data is stored in;
- user
- is the user-name that will be used to connect to the specified database;
- password
- is the password that will be used to connect to the specified database;
- log-file
- is the file-path to the virtual filesystem's log-file (if any); and
- logging-level
- is the logging-level for the system.
There is also a strong possibility that separate executables for each database-type would be of some use (e.g., a "
mysqlfspy
," "pgsqlfspy
," and "odbcfspy
"). If I decide to develop those as well, I would expect them to use the same command-line arguments as the base dbfspy
command shown above, without the database-type specifier.That should cover all of the expected code, at least until/unless something else comes to mind.
I'll cover each class-definition in it's own post, but since there may be a lot of interrelationship, particularly early on, these links resolve to all items tagged as related to the class:
No comments:
Post a Comment