Permalink
Browse files

added docs on validation and polymorphism

  • Loading branch information...
1 parent be66eeb commit bbd2e0142bee77e23478fbf23f0d6ddb5b9129d0 @zbyte64 committed Mar 22, 2013
Showing with 188 additions and 0 deletions.
  1. +117 −0 build_docs.py
  2. +2 −0 doc_requirements.txt
  3. +2 −0 docs/source/index.rst
  4. +62 −0 docs/source/manual/multiplerecordtypes.rst
  5. +5 −0 docs/source/manual/validation.rst
View
@@ -0,0 +1,117 @@
+#!/usr/bin/env python
+
+import logging
+import subprocess
+import os
+
+try:
+ from cStringIO import StringIO
+except ImportError:
+ from StringIO import StringIO
+
+class LogStream(object):
+ def __init__(self, log_func):
+ self.log_func = log_func
+
+ def log_line(self, line):
+ self.log_func(line)
+
+ def writelines(self, sequence):
+ for line in sequence:
+ self.log_line(line)
+
+ def write(self, string):
+ self.log_line(string)
+
+class TaskLogger(logging.Logger):
+ def __init__(self, *args, **kwargs):
+ logging.Logger.__init__(self, *args, **kwargs)
+ self.log_stream = StringIO()
+ handler = logging.StreamHandler(self.log_stream)
+ handler.setLevel(logging.INFO)
+ formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
+ handler.setFormatter(formatter)
+ self.addHandler(handler)
+
+ def read_log(self):
+ return self.log_stream.getvalue()
+
+ def get_stdout_object(self):
+ return LogStream(self.info)
+
+ def get_stderr_object(self):
+ return LogStream(self.error)
+
+class CommandResponse(object):
+ def __init__(self, session, cmd, popen, block, logger):
+ self.session = session
+ self.cmd = cmd
+ self.popen = popen
+ self.joined = False
+ self.logger = logger
+ if block:
+ self.join()
+
+ def join(self):
+ if self.joined:
+ return
+ self.joined = True
+ self.stdout, self.stderr = self.popen.communicate()
+ if self.stdout:
+ self.logger.info(self.stdout)
+ if self.stderr:
+ self.logger.error(self.stderr)
+ self.logger.debug('Return Code: %s' % self.returncode)
+
+ @property
+ def returncode(self):
+ return self.popen.returncode
+
+class CommandFailure(Exception):
+ pass
+
+class ShellSession(object):
+ def __init__(self, logger, cwd=None, **popen_kwargs):
+ self.popen_kwargs = {
+ 'cwd': cwd or os.getcwd(),
+ 'stdout': subprocess.PIPE,
+ 'stderr': subprocess.PIPE,
+ }
+ self.popen_kwargs.update(popen_kwargs)
+ self.logger = logger
+
+ def run(self, cmd, block=True):
+ kwargs = dict(self.popen_kwargs)
+ if isinstance(cmd, basestring):
+ kwargs['shell'] = True
+ self.logger.info(cmd)
+ result = subprocess.Popen(cmd, **kwargs)
+ return CommandResponse(self, cmd, result, block, self.logger)
+
+ def run_with_retries(self, cmd, retries=3):
+ attempts = list()
+ while retries:
+ response = self.run(cmd)
+ if response.returncode:
+ retries -= 1
+ attempts.append(response)
+ else:
+ return response
+ raise CommandFailure('Failed to run command, # of attempts: %s' % len(attempts), attempts)
+
+ def cd(self, directory):
+ if directory.startswith('/'):
+ self.popen_kwargs['cwd'] = directory
+ else:
+ self.popen_kwargs['cwd'] = os.path.join(self.popen_kwargs['cwd'], directory)
+ self.logger.info('cd %s' % self.popen_kwargs['cwd'])
+
+if __name__ == '__main__':
+ import sys
+ logger = TaskLogger('docbuilder')
+ shell = ShellSession(logger, stdout=sys.stdout, stderr=sys.stderr)
+ shell.run('virtualenv --system-site-packages .')
+ shell.run_with_retries('bin/pip install -q -r doc_requirements.txt')
+ shell.run_with_retries('bin/pip install -q Sphinx')
+ shell.run('bin/python setup.py build_sphinx -E')
+
@@ -0,0 +1,2 @@
+django>=1.4
+
@@ -15,6 +15,8 @@ Welcome to Django DocKits's documentation!
manual/forms
manual/views
manual/indexers
+ manual/validation
+ manual/multiplerecordtypes
Download: http://github.com/webcube/django-dockit
@@ -0,0 +1,62 @@
+=====================
+Multiple Record Types
+=====================
+
+Documents and Schemas maybe subclassed to provide polymorphic functionality. For this to work the base class must define `typed_field` in its Meta class which specifies a field name to store the type of schema. The subclasses must define `typed_key` which is to be a unique string value identifying that sublcass.
+
+Here is an example where a collection contains multiple record types::
+
+ class ParentDocument(schema.Document):
+ slug = schema.SlugField()
+
+ class Meta:
+ typed_field = '_doctype'
+
+ class Blog(ParentDocument):
+ author = schema.CharField()
+ body = schema.TextField()
+
+ class Meta:
+ typed_key = 'blog'
+
+ class Video(ParentDocument):
+ url = schema.CharField()
+ thumbnail = schema.ImageField(blank=True, null=True)
+
+ class Meta:
+ typed_key = 'video'
+
+ Blog(slug='blog-entry', author='John Smith', body='large description').save()
+ Video(slug='a-video', url='http://videos/url').save()
+
+ ParentDocument.objects.all() #an iterator containing a Blog and Video entry
+
+Embedded schemas may also take advantage of this functionality as well::
+
+ class Download(schema.Schema):
+ class Meta:
+ typed_field = '_dltype'
+
+ class Bucket(schema.Document):
+ slug = schema.SlugField()
+ downloads = schema.ListField(schema.SchemaField(Download))
+
+ class Image(Download):
+ full_image = schema.ImageField()
+
+ class Meta:
+ typed_key = 'image'
+
+ class Video(Download):
+ url = schema.CharField()
+ thumbnail = schema.ImageField(blank=True, null=True)
+
+ class Meta:
+ typed_key = 'video'
+
+ bucket = Bucket(slug='my-bucket')
+ bucket.downloads.append(Image(full_image=myfile))
+ bucket.downloads.append(Video(url='http://videos/url'))
+ bucket.save()
+
+When we retrieve our bucket later we can expect the entries in downloads to be appropriately mapped to Image and Video. Outside applications may also add other Download record types and our Bucket class will be made aware of those types.
@@ -0,0 +1,5 @@
+==========
+Validation
+==========
+
+Documents and Schemas support validation that mimics Django's models. Given a document instance you may call `full_clean` to validate the document structure and have a `ValidationError` raised if the document does not conform. Documents and schemas may define their own `clean_<fieldname>` method to validate each entry.

0 comments on commit bbd2e01

Please sign in to comment.