-
Jan Kotanski authoredJan Kotanski authored
cache.py 7.42 KiB
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#-----------------------------------------------------------------------------
# :author: Pete R. Jemian
# :email: prjemian@gmail.com
# :copyright: (c) 2016, Pete R. Jemian
#
# Distributed under the terms of the Creative Commons Attribution 4.0 International Public License.
#
# The full license is in the file LICENSE.txt, distributed with this software.
#-----------------------------------------------------------------------------
'''
maintain the local cache of NeXus NXDL and XML Schema files
.. autosummary::
~NoCacheDirectory
~get_nxdl_dir
~update_NXDL_Cache
~qsettings
~user_cache_settings
~UserCacheSettings
~abs_NXDL_filename
~get_XML_Schema
~get_nxdl_xsd
~get_nxdlTypes_xsd
A key component necessary to validate both NeXus data files and
NXDL class files is a current set of the NXDL definitions.
This code maintains two sets of the definitions.
One is the set provided with the package at installation.
This set is updated by the developer prior to packaging the
source for distribution.
Since the source cache is already installed with the package,
it provides a version of the NeXus definitions available for
fallback use when network access to the GitHub
repository is not available.
The second set is updated into a directory that can be written by
the user. This set is updated on demand by the user and only
when a network connection allows the code to contact the GitHub
source code repository. The update process will update content
from the repository.
.. rubric:: Public Interface
:settings object: :meth:`~punx.cache.qsettings`
:get new NXDL definitions from GitHub: :meth:`~punx.cache.update_NXDL_Cache`
'''
import lxml.etree
import os
import sys
from PyQt4 import QtCore
_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
if _path not in sys.path:
sys.path.insert(0, _path)
from punx import settings
import punx
orgName = punx.__settings_organization__
appName = punx.__settings_package__
PKG_DIR = os.path.abspath(os.path.dirname(__file__))
NXDL_SCHEMA_FILE = 'nxdl.xsd'
NXDL_TYPES_SCHEMA_FILE = 'nxdlTypes.xsd'
NXDL_NAMESPACE = 'http://definition.nexusformat.org/nxdl/3.1'
XSD_NAMESPACE = 'http://www.w3.org/2001/XMLSchema'
NX_DICT = dict(xs=XSD_NAMESPACE, nx=NXDL_NAMESPACE)
__singleton_cache_settings_user__ = None
__singleton_settings__ = None
__singleton_xml_schema__ = None
__singleton_nxdl_xsd__ = None
__singleton_nxdlTypes_xsd__ = None
class NoCacheDirectory(Exception):
'custom exception: no cache directory was found'
pass
class No_NXDL_files_available(Exception):
'custom exception: no NXDL files are available'
pass
def get_nxdl_dir():
'''
the path of the directory with the files containing NeXus definitions
Note: This directory, and the files it contains, are **only** used during
the process of updating the cache.
'''
import punx.cache_manager
cm = punx.cache_manager.CacheManager()
if cm.default_file_set is None:
raise No_NXDL_files_available()
path = cm.default_file_set.path
return os.path.abspath(path)
def update_NXDL_Cache(force_update=False):
'''
update the cache of NeXus NXDL files
:param bool force_update: (optional, default: False) update if GitHub is available
'''
import punx.cache_manager, punx.github_handler
punx.LOG_MESSAGE('update_NXDL_Cache(force_update=%s)' % str(force_update))
cm = punx.cache_manager.CacheManager()
grr = punx.github_handler.GitHub_Repository_Reference()
grr.connect_repo()
cm.install_NXDL_file_set(grr, user_cache=True, ref='master')
qset = qsettings()
info = dict(git_sha=grr.sha, git_time=grr.last_modified, zip_url=grr.zip_url)
info['file'] = str(qset.fileName())
punx.LOG_MESSAGE('update .ini file: ' + str(qset.fileName()), punx.INFO)
qset.updateGroupKeys(info)
def qsettings():
'''
return the QSettings instance, chosen from user cache
'''
global __singleton_settings__
if __singleton_settings__ is None:
__singleton_settings__ = user_cache_settings()
if not os.path.exists(__singleton_settings__.cache_dir()):
raise NoCacheDirectory('no cache found')
return __singleton_settings__
def user_cache_settings():
'''manage the user cache info file as an .ini file'''
global __singleton_cache_settings_user__
if __singleton_cache_settings_user__ is None:
__singleton_cache_settings_user__ = UserCacheSettings()
return __singleton_cache_settings_user__
class UserCacheSettings(QtCore.QSettings, settings.QSettingsMixin):
'''
manage and preserve default settings for this application using QSettings
Use the .ini file format and save under user directory
:see: http://doc.qt.io/qt-4.8/qsettings.html
'''
def __init__(self):
QtCore.QSettings.__init__(self,
QtCore.QSettings.IniFormat,
QtCore.QSettings.UserScope,
orgName,
appName)
path = self.cache_dir()
if not os.path.exists(path):
os.mkdir(path)
self.init_global_keys()
def abs_NXDL_filename(file_name):
'''return absolute path to file_name, within NXDL directory'''
import punx.cache_manager
cm = punx.cache_manager.CacheManager()
punx.LOG_MESSAGE('file_name: ' + str(file_name), punx.DEBUG)
punx.LOG_MESSAGE('cm.default_file_set: ' + str(cm.default_file_set), punx.DEBUG)
if cm.default_file_set is None:
raise ValueError('no default file set')
absolute_name = os.path.abspath(os.path.join(cm.default_file_set.path, file_name))
if not os.path.exists(absolute_name):
msg = 'file does not exist: ' + absolute_name
raise punx.FileNotFound(msg)
punx.LOG_MESSAGE('user cache: ' + absolute_name, punx.DEBUG)
return absolute_name
def get_XML_Schema():
'''
parse & cache the XML Schema file (nxdl.xsd) as an **XML Schema** only once
Uses :class:`lxml.etree.XMLSchema` and :meth:`~get_nxdl_xsd`
'''
global __singleton_xml_schema__
if __singleton_xml_schema__ is None:
__singleton_xml_schema__ = lxml.etree.XMLSchema(get_nxdl_xsd())
return __singleton_xml_schema__
def get_nxdl_xsd():
'''
parse and cache the XML Schema file (nxdl.xsd) as an XML document only once
Uses :meth:`lxml.etree.parse`
'''
global __singleton_nxdl_xsd__
if __singleton_nxdl_xsd__ is None:
try:
xsd_file_name = abs_NXDL_filename(NXDL_SCHEMA_FILE)
except punx.FileNotFound as _exc:
raise punx.SchemaNotFound(_exc)
if not os.path.exists(xsd_file_name):
msg = 'Could not find XML Schema file: ' + xsd_file_name
raise punx.SchemaNotFound(msg)
__singleton_nxdl_xsd__ = lxml.etree.parse(xsd_file_name)
return __singleton_nxdl_xsd__
def get_nxdlTypes_xsd():
'''
parse and cache the XML Schema file (nxdlTypes.xsd) as an XML document only once
'''
global __singleton_nxdlTypes_xsd__
if __singleton_nxdlTypes_xsd__ is None:
xsd_file_name = abs_NXDL_filename(NXDL_TYPES_SCHEMA_FILE)
if not os.path.exists(xsd_file_name):
msg = 'Could not find XML Schema file: ' + xsd_file_name
raise IOError(msg)
__singleton_nxdlTypes_xsd__ = lxml.etree.parse(xsd_file_name)
return __singleton_nxdlTypes_xsd__