From ad2da44cb1cffac8ec8b45d38bc0fde3773023c1 Mon Sep 17 00:00:00 2001
From: Calen Pennington <cale@edx.org>
Date: Thu, 19 Sep 2013 13:06:55 -0400
Subject: [PATCH] Make Textbooks properly lazy

---
 common/lib/xmodule/xmodule/course_module.py   | 15 +++++---
 common/lib/xmodule/xmodule/util/decorators.py | 37 -------------------
 requirements/edx/base.txt                     |  1 +
 3 files changed, 11 insertions(+), 42 deletions(-)
 delete mode 100644 common/lib/xmodule/xmodule/util/decorators.py

diff --git a/common/lib/xmodule/xmodule/course_module.py b/common/lib/xmodule/xmodule/course_module.py
index 24e6995ae10..6d6d204eb81 100644
--- a/common/lib/xmodule/xmodule/course_module.py
+++ b/common/lib/xmodule/xmodule/course_module.py
@@ -6,10 +6,10 @@ from path import path  # NOTE (THK): Only used for detecting presence of syllabu
 import requests
 from datetime import datetime
 import dateutil.parser
+from lazy import lazy
 
 from xmodule.modulestore import Location
 from xmodule.seq_module import SequenceDescriptor, SequenceModule
-from xmodule.util.decorators import lazyproperty
 from xmodule.graders import grader_from_conf
 import json
 
@@ -62,17 +62,22 @@ class Textbook(object):
     def __init__(self, title, book_url):
         self.title = title
         self.book_url = book_url
-        self.start_page = int(self.table_of_contents[0].attrib['page'])
 
+    @lazy
+    def start_page(self):
+        return int(self.table_of_contents[0].attrib['page'])
+
+    @lazy
+    def end_page(self):
         # The last page should be the last element in the table of contents,
         # but it may be nested. So recurse all the way down the last element
         last_el = self.table_of_contents[-1]
         while last_el.getchildren():
             last_el = last_el[-1]
 
-        self.end_page = int(last_el.attrib['page'])
+        return int(last_el.attrib['page'])
 
-    @lazyproperty
+    @lazy
     def table_of_contents(self):
         """
         Accesses the textbook's table of contents (default name "toc.xml") at the URL self.book_url
@@ -738,7 +743,7 @@ class CourseDescriptor(CourseFields, SequenceDescriptor):
 
         return announcement, start, now
 
-    @lazyproperty
+    @lazy
     def grading_context(self):
         """
         This returns a dictionary with keys necessary for quickly grading
diff --git a/common/lib/xmodule/xmodule/util/decorators.py b/common/lib/xmodule/xmodule/util/decorators.py
deleted file mode 100644
index e827b74ef17..00000000000
--- a/common/lib/xmodule/xmodule/util/decorators.py
+++ /dev/null
@@ -1,37 +0,0 @@
-
-
-def lazyproperty(fn):
-    """
-    Use this decorator for lazy generation of properties that
-    are expensive to compute. From http://stackoverflow.com/a/3013910/86828
-
-
-    Example:
-    class Test(object):
-
-        @lazyproperty
-        def a(self):
-            print 'generating "a"'
-            return range(5)
-
-    Interactive Session:
-    >>> t = Test()
-    >>> t.__dict__
-    {}
-    >>> t.a
-    generating "a"
-    [0, 1, 2, 3, 4]
-    >>> t.__dict__
-    {'_lazy_a': [0, 1, 2, 3, 4]}
-    >>> t.a
-    [0, 1, 2, 3, 4]
-    """
-
-    attr_name = '_lazy_' + fn.__name__
-
-    @property
-    def _lazyprop(self):
-        if not hasattr(self, attr_name):
-            setattr(self, attr_name, fn(self))
-        return getattr(self, attr_name)
-    return _lazyprop
diff --git a/requirements/edx/base.txt b/requirements/edx/base.txt
index 62515f74450..addef7b629c 100644
--- a/requirements/edx/base.txt
+++ b/requirements/edx/base.txt
@@ -34,6 +34,7 @@ feedparser==5.1.3
 fs==0.4.0
 GitPython==0.3.2.RC1
 glob2==0.3
+lazy==1.1
 lxml==3.0.1
 mako==0.7.3
 Markdown==2.2.1
-- 
GitLab