diff options
author | kali <kali@leap.se> | 2012-08-29 04:50:17 +0900 |
---|---|---|
committer | kali <kali@leap.se> | 2012-08-29 04:50:17 +0900 |
commit | 2be70492beb7212fdc585601c9e9939be6803acd (patch) | |
tree | 5f0e8e0bf3a8977254684e1cb41e962553692fca | |
parent | 7a8f4db1a4743582c34a52ab448eece0e7689bc8 (diff) |
spec creation moved to JSONLeapConfig __metaclass__
now we expect spec to be a dict for all the JSONLeapConfig instances.
-rw-r--r-- | src/leap/base/config.py | 50 | ||||
-rw-r--r-- | src/leap/base/providers.py | 101 | ||||
-rw-r--r-- | src/leap/base/specs.py | 49 |
3 files changed, 101 insertions, 99 deletions
diff --git a/src/leap/base/config.py b/src/leap/base/config.py index 93a89638..1ced471b 100644 --- a/src/leap/base/config.py +++ b/src/leap/base/config.py @@ -1,7 +1,6 @@ """ Configuration Base Class """ -import configuration # python configuration module, not local! import grp import json import logging @@ -12,6 +11,8 @@ import os logger = logging.getLogger(name=__name__) logger.setLevel('DEBUG') +import configuration + from leap.base import exceptions from leap.base import constants from leap.util.fileutil import (mkdir_p) @@ -45,8 +46,54 @@ class BaseLeapConfig(object): raise NotImplementedError("abstract base class") +class MetaConfigWithSpec(type): + """ + metaclass for JSONLeapConfig classes. + It creates a configuration spec out of + the `spec` dictionary. + """ + # XXX in the near future, this is the + # place where we want to enforce + # singletons, read-only and stuff. + def __new__(meta, classname, bases, classDict): + spec_options = classDict.get('spec', None) + # XXX if not spec_options, raise BadConfiguration or something + # we create a configuration spec attribute from the spec dict + config_class = type( + classname + "Spec", + (configuration.Configuration, object), + {'options': spec_options}) + classDict['spec'] = config_class + + return type.__new__(meta, classname, bases, classDict) + +########################################################## +# hacking in progress: + +# Configs have: +# - a slug (from where a filename/folder is derived) +# - a spec (for validation and defaults). +# this spec is basically a dict that will be used +# for type casting and validation, and defaults settings. + +# all config objects, since they are derived from BaseConfig, implement basic +# useful methods: +# - save +# - load +# - get_config (returns a optparse.OptionParser object) + +# TODO: +# - have a good type cast repertory (uris, version, hashes...) +# - raise validation errors +# - multilingual objects + +########################################################## + + class JSONLeapConfig(BaseLeapConfig): + __metaclass__ = MetaConfigWithSpec + def __init__(self, *args, **kwargs): # sanity check assert self.slug is not None @@ -94,6 +141,7 @@ class JSONLeapConfig(BaseLeapConfig): config_file = get_config_file(filename, folder) return config_file + # # utility functions # diff --git a/src/leap/base/providers.py b/src/leap/base/providers.py index 1f6ab54b..e2075264 100644 --- a/src/leap/base/providers.py +++ b/src/leap/base/providers.py @@ -1,110 +1,15 @@ """all dealing with leap-providers: definition files, updating""" -import configuration - from leap.base.config import JSONLeapConfig - -########################################################## -# hacking in progress: - -# Specs are instances of configuration.Configuration class -# -yeah, that's an external app, not ours- -# and have to carry an options attr. -# -# Configs have: -# - a slug (from where a filename/folder is derived) -# - a spec (for validation and defaults). - -# all config objects, as BaseConfig derived, implment basic -# useful methods: -# - save -# - load -# - get_config (returns a optparse.OptionParser object) - -# TODO: -# - have a good type cast repertory (uris, version, hashes...) -# - raise validation errors -# - multilingual objects - -########################################################## - - -class LeapProviderSpec(configuration.Configuration): - options = { - 'serial': { - 'type': int, - 'default': 1, - 'required': True, - }, - 'version': { - 'type': unicode, - 'default': '0.1.0' - #'required': True - }, - 'domain': { - 'type': unicode, # XXX define uri type - 'default': 'testprovider.example.org' - #'required': True, - }, - 'display_name': { - 'type': unicode, # XXX multilingual object? - 'default': 'test provider' - #'required': True - }, - 'description': { - 'default': 'test provider' - }, - 'enrollment_policy': { - 'type': unicode, # oneof ?? - 'default': 'open' - }, - 'services': { - 'type': list, # oneof ?? - 'default': ['eip'] - }, - 'api_version': { - 'type': unicode, - 'default': '0.1.0' # version regexp - }, - 'api_uri': { - 'type': unicode # uri - }, - 'public_key': { - 'type': unicode # fingerprint - }, - 'ca_cert': { - 'type': unicode - }, - 'ca_cert_uri': { - 'type': unicode - }, - } +from leap.base import specs class LeapProviderDefinition(JSONLeapConfig): slug = 'definition.json' - spec = LeapProviderSpec - - -class LeapProvider(object): - # bring slug here (property) - # constructor: pass name - - # constructor: init definition class - # (__cls__.__name__ + Definition) - # initializes a JSONLeapConfig with slug and - # initializes also cls.name + Spec - - # and Abstract this thing out! - - # how can we hook here the network fetching stuff? - # maybe (bstorming a little bit): - - # config = LeapProviderDefinition - # fetcher = foo.FetcherClass - pass + spec = specs.leap_provider_spec class LeapProviderSet(object): # we gather them from the filesystem + # TODO: (MVS+) def __init__(self): self.count = 0 diff --git a/src/leap/base/specs.py b/src/leap/base/specs.py new file mode 100644 index 00000000..d88dc63f --- /dev/null +++ b/src/leap/base/specs.py @@ -0,0 +1,49 @@ +leap_provider_spec = { + 'serial': { + 'type': int, + 'default': 1, + 'required': True, + }, + 'version': { + 'type': unicode, + 'default': '0.1.0' + #'required': True + }, + 'domain': { + 'type': unicode, # XXX define uri type + 'default': 'testprovider.example.org' + #'required': True, + }, + 'display_name': { + 'type': unicode, # XXX multilingual object? + 'default': 'test provider' + #'required': True + }, + 'description': { + 'default': 'test provider' + }, + 'enrollment_policy': { + 'type': unicode, # oneof ?? + 'default': 'open' + }, + 'services': { + 'type': list, # oneof ?? + 'default': ['eip'] + }, + 'api_version': { + 'type': unicode, + 'default': '0.1.0' # version regexp + }, + 'api_uri': { + 'type': unicode # uri + }, + 'public_key': { + 'type': unicode # fingerprint + }, + 'ca_cert': { + 'type': unicode + }, + 'ca_cert_uri': { + 'type': unicode + }, +} |