Skip to content

Commit

Permalink
Added more documentation to the example code.
Browse files Browse the repository at this point in the history
  • Loading branch information
thobe committed Mar 24, 2010
1 parent ef1c96e commit a0c705d
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 3 deletions.
25 changes: 25 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,28 @@ Neo4j Python example
====================

Implementation of a shop domain model with categories and products.


Requirements
============

This application requires Python (CPython or Jython) version 2.5 or later.
It also requires the `Neo4j Python bindings`_ and its dependencies.

.. _Neo4j Python bindings: http://components.neo4j.org/neo4j.py/


Running the application
=======================

Running with Python/Jython 2.5::

git clone git://github.com/neo4j-examples/python-shop-categories.git
cd python-shop-categories
jython -m shop

Running with Python/Jython 2.6::

git clone git://github.com/neo4j-examples/python-shop-categories.git
cd python-shop-categories
python shop
41 changes: 38 additions & 3 deletions shop/cmdui.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# -*- coding: utf-8 -*-
"""
This module defines a command line interface for working with this shop model.
"""

from __future__ import with_statement

Expand All @@ -16,11 +19,17 @@ def __init__(self, store):
self.prompt = "%s> " % (store.name,)
self.category = store.root

def help_help(self):
print("""With no arguments help lists all available commands,
If a command is given as an argument the help for that command is displayed.""")

def do_EOF(self, line):
"Exit the application on end of file."
print(" ") # Cover up the ^D char
self.do_exit()

def do_exit(self, line=None):
"Exit the application."
print("bye.")
sys.exit()

Expand All @@ -32,12 +41,17 @@ def default(self, line):
print("unknown command: %s" % command)

def do_list(self, line):
"list all available products"
"list all available products in the current category"
with self.store.graphdb.transaction:
for product in self.category:
print(product)

def do_cat(self, line=None):
"""Change the current category and list all subcategories.
The parameter to this command is the name of the subcategory
to change to, .. changes to the parent category.
If no parameter is given cat only lists the subcategories.
"""
if line:
if line == '..':
self.category = self.category.parent
Expand Down Expand Up @@ -87,7 +101,7 @@ def do_sample(self, line):
**{'Shipping weight': 6.3,
'CPU frequency': 2000.0})

_make_usage = "USAGE: make %s [<key>:<attr type> ...]"
_make_usage = "USAGE: make %s [<key>:<value> ...]"
def do_make(self, line):
command, args, line = self.parseline(line)
if command:
Expand All @@ -100,7 +114,14 @@ def do_make(self, line):
except ValueError:
print(self._make_usage % (command,))
else:
print(self._make_usage % ("category|product|type",))
print(self._make_usage % ("|".join(self._makers),))

def help_make(self):
print(self._make_usage % ("|".join(self._makers),))
print("")
for maker in self._makers:
print("make %s:" % (maker,))
print(" " + getattr(self, 'make_'+maker).__doc__)

_make_pattern = re.compile(r'^\s*(\w+):((?:"(?:[^"]*(?:\\")?)*")|(?:\w+))')
def _make_attributes(self, line):
Expand Down Expand Up @@ -128,6 +149,11 @@ def _make_required(self, attributes, *keys):
return value

def make_category(self, attributes):
"""Creates a new category.
A 'Name' parameter must be specified for the category.
The rest of the parameters are names and types of the attributes of
the products in the category.
"""
try:
name = self._make_required(attributes, 'name', 'Name')
except KeyError:
Expand All @@ -142,12 +168,18 @@ def make_category(self, attributes):
self.do_cat()

def make_product(self, attributes):
"""Creates a new product.
The supplied key value pairs are the attribute values for the product.
"""
try:
self.category.new_product(**attributes)
except:
import traceback; traceback.print_exc()

def make_type(self, attributes):
"""Creates a new attribute type.
A 'Name' parameter must be specified for the attribute type.
"""
try:
name = self._make_required(attributes, 'name', 'Name')
except KeyError:
Expand All @@ -158,7 +190,10 @@ def make_type(self, attributes):
_,val,_ = sys.exc_info()
print(val)

_makers = tuple(name[5:] for name in dir() if name.startswith('make_'))

def do_types(self, line):
"List all available attribute types."
pass

def start(*args, **params):
Expand Down
14 changes: 14 additions & 0 deletions shop/model.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,18 @@
# -*- coding: utf-8 -*-
"""
Defines the domain model for a shop with categories and products.
Each product in a category is of a type defined by the category. Therefore
the Category type in the domain model is the metaclass of the Product type.
Each category is an instance of the Category class. Each category object is
also the class of the products that are contained in that category.
The Product class is the base class for all product classes (the Category
objects). While metaprogramming can easily get tricky, this is a perfect
example of where it is actually useful, this allows us to store the metadata
of the domain in the database with the actual data. The metadata here being
the definitions of the categories, with the attribute constraints the
categories carry, and the data being the actual products in the categories.
"""

from __future__ import with_statement

Expand Down

0 comments on commit a0c705d

Please sign in to comment.