[prev in list] [next in list] [prev in thread] [next in thread] 

List:       fuse-devel
Subject:    [fuse-devel] fuse-python api version support could be done better.
From:       Donovan Baarda <abo () minkirri ! apana ! org ! au>
Date:       2011-10-14 2:06:45
Message-ID: CAKfm1dsTpU5C2ORH=zQhPyaL-SJR4xt6FA-YQG7sKydpHd-kbw () mail ! gmail ! com
[Download RAW message or body]

G'day fuse-devel,

New subscriber... please forgive my ignorance of the past on this
list. I just started fiddling around with the fuse-python stuff and
thought I'd throw in my 2c. I've got an old hgfs mercurial fuse
backend that I'm updating and extending using the new fuse-python API.

The way fuse.py is doing API versioning is kinda clumsy. It requires
applications to import fuse.py and then set fuse.fuse_python_api to
specify which version of the API they want to use. This kind of
approach will eventually make fuse.py into a tangled mess of every
historical API with messy API selection code. There is a much
simpler/better way to handle this based on the idea of
major.minor.micro versioning. The version is made up of three numbers;
the major version, the minor version, and the micro version, like
2.3.13.

The major version gets a bump whenever the API changes in a
non-backwards compatible way. If code that used fuse-2.3.13 will not
work with the new fuse, then the new version should be fuse-3.0.0.

The minor version gets a bump whenever the API changes in a forwards
compatible way. If code that worked with 2.3.13 will work with the new
fuse, but code written for the new fuse might not work with
fuse-2.3.13, then the new version should be fuse-2.4.0

The micro version gets a bump whenever the API has not changed at
all... ie bugfixes, implementation improvements, etc. In that case
fuse-2.3.13 becomes fuse-2.3.14.

You then need to implement something to support this version numbering
system in a way that will allow programs to specify what version they
require without making them break when a new version is released, and
do it in a way that prevents the implementation code from becoming a
tangled mess of legacy API support.

1) The major version is critical to identifying what version of the
API you want. You also absolutely need old major versions to hang
around for backwards compatibility. So put the major version number in
the file name; ie fuse2.py for fuse-2.x.x versions. This way older
applications can "import fuse1" if they want the 1.x.x version of the
API, and new applications can "import fuse2" secure in the knowledge
that they will continue to work when fuse-3.0.0 is released. It also
ensures code for older, incompatible versions of the API are kept in a
separate files and don't mess up the newer versions of the API.

2)  The minor version is not critical for what version of that major
API you want, and you probably just want the latest minor version of
whatever major release you require. This means you don't need older
minor versions to hang around for backwards compatibility. You also
don't need to clutter up the code with backwards compatibility support
since by definition minor releases are backwards compatible. However,
applications typically do want to specify that you require a minimum
minor number because they require a feature introduced in fuse-2.3.0.
So you need a mechanism to assert you require minor version >=3.

3) The micro version is not required at all for identifying what
version of the API you require. You'll never need older micro versions
to hang around. However, it might still be useful to assert that you
require micro version >=6 if you know that fuse-2.3.6 fixed an
important bug.

Asserting minor and micro versions can be done by applications using a
simple helper function.

in fuse2.py:
  fuse_python_api = (2, 3, 13)

  def python_api_assert(major, minor, micro=0):
    if major != fuse_python_api[0]:
      raise RuntimeError("FUSE Python API major version wrong.")
    if (major, minor, micro) < fuse_python_api:
      raise RuntimeError("FUSE Python API too old.")

If you really really want a single fuse.py with backwards
compatibility and version assertion support, you can do it by having
fuse1.py, fuse2.py etc be major version API implementations, and then
have fuse.py (or maybe fuse/__init__.py) be a simple frontend that
does this;

def api_assert(major, minor, micro=0):
  fuse = __import__('fuse%d' % major)
  globals().update(fuse.__dict__)
  if (major, minor, micro) < fuse_python_api:
      raise RuntimeError("FUSE Python API too old.")

On another unrelated note, I think the Xmp.py example should be
included in the source not just as an example. There are plenty of
filesystems which are based on the idea of overlaying on top of other
files, and this class would be convenient to inherit and extend for
those applications. If it is only provided as an example then I cannot
just "import fuse.xmp" on distro's with python-fuse installed.

-- 
Donovan Baarda <abo@minkirri.apana.org.au>

------------------------------------------------------------------------------
All the data continuously generated in your IT infrastructure contains a
definitive record of customers, application performance, security
threats, fraudulent activity and more. Splunk takes this data and makes
sense of it. Business sense. IT sense. Common sense.
http://p.sf.net/sfu/splunk-d2d-oct
_______________________________________________
fuse-devel mailing list
fuse-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/fuse-devel

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic