+
+class WLURI(object):
+ """Represents a WL URI. Extracts slug and language from it."""
+ DEFAULT_LANGUAGE = u'pol'
+
+ slug = None
+ language = None
+
+ example = 'http://wolnelektury.pl/katalog/lektura/template/'
+ _re_wl_uri = re.compile('http://wolnelektury.pl/katalog/lektura/'
+ '(?P<slug>[-a-z]+)(/(?P<lang>[a-z]{3})/?)?')
+
+ def __init__(self, uri=None):
+ if uri is not None:
+ self.uri = uri
+ match = self._re_wl_uri.match(uri)
+ assert match
+ self.slug = match.group('slug')
+ self.language = match.group('lang') or self.DEFAULT_LANGUAGE
+
+ @classmethod
+ def from_slug_and_lang(cls, slug, lang):
+ """Contructs an URI from slug and language code.
+
+ >>> WLURI.from_slug_and_lang('a-slug', WLURI.DEFAULT_LANGUAGE).uri
+ 'http://wolnelektury.pl/katalog/lektura/a-slug/'
+ >>> WLURI.from_slug_and_lang('a-slug', 'deu').uri
+ 'http://wolnelektury.pl/katalog/lektura/a-slug/deu/'
+
+ """
+ if lang is None:
+ lang = self.DEFAULT_LANGUAGE
+ uri = 'http://wolnelektury.pl/katalog/lektura/%s/' % slug
+ if lang is not None and lang != cls.DEFAULT_LANGUAGE:
+ uri += lang + '/'
+ instance = cls()
+ instance.slug = slug
+ instance.language = lang
+ instance.uri = uri
+ return instance
+
+ def __unicode__(self):
+ return self.uri
+
+ def __eq__(self, other):
+ return self.slug, self.language == other.slug, other.language
+
+ def filename_stem(self):
+ stem = self.slug
+ if self.language != self.DEFAULT_LANGUAGE:
+ stem += '_' + self.language
+ return stem
+
+ def validate_language(self, language):
+ if language != self.language:
+ raise ValidationError("Incorrect language definition in URI")
+
+
+class DocProvider(object):
+ """Base class for a repository of XML files.
+
+ Used for generating joined files, like EPUBs.
+ """
+
+ def by_slug_and_lang(self, slug, lang=None):
+ """Should return a file-like object with a WL document XML."""
+ raise NotImplementedError
+
+ def by_slug(self, slug):
+ """Should return a file-like object with a WL document XML."""
+ return self.by_slug_and_lang(slug)
+
+ def by_uri(self, uri):
+ """Should return a file-like object with a WL document XML."""
+ wluri = WLURI(uri)
+ return self.by_slug_and_lang(wluri.slug, wluri.language)
+
+
+class DirDocProvider(DocProvider):
+ """ Serve docs from a directory of files in form <slug>.xml """
+
+ def __init__(self, dir_):
+ self.dir = dir_
+ self.files = {}
+ return super(DirDocProvider, self).__init__()
+
+ def by_slug_and_lang(self, slug, lang=None):
+ fname = WLURI.from_slug_and_lang(slug, lang).filename_stem() + '.xml'
+ return open(os.path.join(self.dir, fname))
+
+