Skip to content

Commit

Permalink
Configuration from a ini formated file
Browse files Browse the repository at this point in the history
  • Loading branch information
mmulich committed Nov 16, 2011
1 parent a04a664 commit 9c0cf9b
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 22 deletions.
8 changes: 5 additions & 3 deletions docs/source/config.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,20 @@ Configuration (pkgmeta.cfg)
In order to setup a repository, one needs to configure using a basic INI file.

The configuration fairly simple. There is one INI section that is special,
it is called ``pkgmeta``. This section is used to configure ``pkgmeta``
itself. Any other sections in the file are repository definitions.
it is called ``pkgmeta``. This section is used to configure globals.
Any other sections in the file are repository definitions.

Configuration example
Example configuration
---------------------

The following configuration selects the ``myrepo`` as the default repository. The ``myrepo`` repository using the filesystem storage type and sources from ``pkgmeta.org``.
::

[pkgmeta]
default = myrepo

[myrepo]
type = fs
sources =
http://repo.pkgmeta.org/ pypi
http://repo.pkgmeta.org/ private
69 changes: 50 additions & 19 deletions pkgmeta/config.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,30 @@
# -*- coding: utf-8 -*-
from configparser import ConfigParser
from pkgmeta.exceptions import PkgMetaConfigFileError
from pkgmeta.storage import lookup_storage_by_type
__all__ = ('PkgMetaConfig',
'RepositoryConfig', 'FileSystemRepositoryConfig',
)


class RepositoryConfig:
"""A repository configuration"""

def __init__(self, name, type=None, sources=None,
**kwargs):
self.name = name
self.type = type
self.sources = sources
if self.sources is None:
self.sources = []
for name, value in kwargs.items():
setattr(self, name, value)
storage_factory = lookup_storage_by_type(self.type)
self.storage = storage_factory(self)


class PkgMetaConfig(object):
"""Configuration
"""
"""Main pkgmeta configuration object"""

def __init__(self, repositories, default=None):
if not hasattr(repositories, '__iter__'):
Expand All @@ -16,9 +33,39 @@ def __init__(self, repositories, default=None):
for repo in self.repositories:
if not isinstance(repo, RepositoryConfig):
raise TypeError("%s is not a RepsitoryConfig" % repr(repo))
if default is None:
self.default = default
if self.default is None:
self.default = repositories[0].name

@classmethod
def from_file(cls, file):
cfg = ConfigParser(allow_no_value=True)
cfg.read(file)
if cfg.has_section('pkgmeta') and cfg.has_option('pkgmeta', 'default'):
default = cfg.get('pkgmeta', 'default')
else:
default = None
repositories = []
for section in cfg.sections():
if section == 'pkgmeta':
continue
# TODO Wrap config init errors with a PkgMetaConfigFileError
config = RepositoryConfig(section, **dict(cfg.items(section)))
repositories.append(config)
if len(repositories) == 0:
raise PkgMetaConfigFileError("Missing a repository definition")
# Find the default repositories index
if default is not None:
repo_keys = [r.name for r in repositories]
try:
repo_keys.index(default)
except ValueError as err:
raise PkgMetaConfigFileError("Invalid default repository")
inst = cls(repositories, default=default)
setattr(inst, '__from__', 'from_file')
setattr(inst, '_file', file)
return inst

def __iter__(self):
return iter(self.repositories)

Expand All @@ -32,19 +79,3 @@ def get_repository_config(self, name=None):
except IndexError:
raise LookupError("Could not find '%s'" % name)
return repo_config


class RepositoryConfig:
"""A repository configuration"""

def __init__(self, name, type=None, sources=None,
**kwargs):
self.name = name
self.type = type
self.sources = sources
if self.sources is None:
self.sources = []
for name, value in kwargs.items():
setattr(self, name, value)
storage_factory = lookup_storage_by_type(self.type)
self.storage = storage_factory(self)
6 changes: 6 additions & 0 deletions pkgmeta/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
'InvalidVersion',
'RepositoryIsNotMutable', 'RepositoryNotFound',
'ReleaseNotFound',
'PkgMetaConfigFileError',
)


Expand All @@ -25,3 +26,8 @@ class ReleaseNotFound(KeyError):

class UnknownRepositoryStorageType(Exception):
"""Raised when an unknown storage type is requested."""


class PkgMetaConfigFileError(Exception):
"""Raised when there is an issue with reading/writing a pkgmeta.cfg file.
"""
60 changes: 60 additions & 0 deletions pkgmeta/tests/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,19 @@
import tempfile
from pkgmeta.tests import unittest

TEST_PKGMETA_CFG = """\
[pkgmeta]
default = repo2
[repo1]
[repo2]
[repo3]
type = filesystem
location = %(location)s
"""


class PkgMetaConfigTestCase(unittest.TestCase):

Expand Down Expand Up @@ -89,3 +102,50 @@ def test_arbitrary_attributes(self):
config = self.make_one('repo', foo='foo', bar='foobar')
self.assertEqual(config.foo, 'foo')
self.assertEqual(config.bar, 'foobar')


class ConfigurationFromAFileTest(unittest.TestCase):
"""Read in the configuration from a pkgmeta.cfg file."""

def write_config(self, content):
dummy, file = tempfile.mkstemp()
with open(file, 'w') as f:
f.write(content)
return file

def make_one(self, file):
from pkgmeta.config import PkgMetaConfig
return PkgMetaConfig.from_file(file)

def test_blank_file(self):
from pkgmeta.exceptions import PkgMetaConfigFileError
file = self.write_config('\n')
with self.assertRaises(PkgMetaConfigFileError) as error:
self.make_one(file)
self.assertEqual(str(error.exception),
"Missing a repository definition")

def test_invalid_default_value(self):
from pkgmeta.exceptions import PkgMetaConfigFileError
content = """\
[pkgmeta]
default = nothere
[repo]
"""
file = self.write_config(content)
with self.assertRaises(PkgMetaConfigFileError) as error:
self.make_one(file)
self.assertEqual(str(error.exception),
"Invalid default repository")

def test_correct_init_values(self):
location = tempfile.mkdtemp()
file = self.write_config(TEST_PKGMETA_CFG % dict(location=location))
config = self.make_one(file)
default_repo = config.get_repository_config()
self.assertEqual(default_repo.name, 'repo2')
# Check to see if the configuration variables made it through
from pkgmeta.storage import FileSystemStorage
repo3 = config.get_repository_config('repo3')
self.assertTrue(isinstance(repo3.storage, FileSystemStorage))

0 comments on commit 9c0cf9b

Please sign in to comment.