summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkali <kali@leap.se>2012-08-29 04:50:17 +0900
committerkali <kali@leap.se>2012-08-29 04:50:17 +0900
commit2be70492beb7212fdc585601c9e9939be6803acd (patch)
tree5f0e8e0bf3a8977254684e1cb41e962553692fca
parent7a8f4db1a4743582c34a52ab448eece0e7689bc8 (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.py50
-rw-r--r--src/leap/base/providers.py101
-rw-r--r--src/leap/base/specs.py49
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
+ },
+}