Merge lp:~leonardr/launchpadlib/delay-http-requests into lp:launchpadlib

Proposed by Leonard Richardson
Status: Merged
Merged at revision: 89
Proposed branch: lp:~leonardr/launchpadlib/delay-http-requests
Merge into: lp:launchpadlib
Diff against target: 198 lines (+94/-19)
5 files modified
setup.py (+1/-1)
src/launchpadlib/NEWS.txt (+6/-0)
src/launchpadlib/__init__.py (+1/-1)
src/launchpadlib/docs/toplevel.txt (+54/-14)
src/launchpadlib/launchpad.py (+32/-3)
To merge this branch: bzr merge lp:~leonardr/launchpadlib/delay-http-requests
Reviewer Review Type Date Requested Status
Henning Eggers (community) code Approve
Review via email: mp+27759@code.launchpad.net

Description of the change

This branch makes launchpadlib use the new performance optimization introduced by https://code.edge.launchpad.net/~leonardr/lazr.restfulclient/shim-objects/. Basically, if you write launchpad.bugs[1] we can now delay the GET to "/bugs/1" until you actually need some data from that bug. If you're invoking a named operation on the bug, the GET doesn't need to happen at all.

Since it's pretty common for scripts to look up an object in a top-level collection and immediately invoke a named operation on it, this has a good chance of giving a modest performance boost to any given script.

The one top-level collection that doesn't have this feature is the collection of users. Without making that GET request, there's no way to know whether launchpad.user['foo'] is a 'person' or a 'team' type object, so I punted.

To post a comment you must log in.
Revision history for this message
Henning Eggers (henninge) wrote :

Thanks!

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'setup.py'
--- setup.py 2010-02-15 16:34:26 +0000
+++ setup.py 2010-06-16 19:58:22 +0000
@@ -60,7 +60,7 @@
60 license='LGPL v3',60 license='LGPL v3',
61 install_requires=[61 install_requires=[
62 'httplib2',62 'httplib2',
63 'lazr.restfulclient>=0.9.11',63 'lazr.restfulclient>=0.9.18',
64 'lazr.uri',64 'lazr.uri',
65 'oauth',65 'oauth',
66 'setuptools',66 'setuptools',
6767
=== modified file 'src/launchpadlib/NEWS.txt'
--- src/launchpadlib/NEWS.txt 2010-04-06 19:54:35 +0000
+++ src/launchpadlib/NEWS.txt 2010-06-16 19:58:22 +0000
@@ -2,6 +2,12 @@
2NEWS for launchpadlib2NEWS for launchpadlib
3=====================3=====================
44
51.6.1 (2010-06-16)
6==================
7
8- Added an optimization that lets launchpadlib avoid making an HTTP
9 request in some situations.
10
51.6.0 (2010-04-07)111.6.0 (2010-04-07)
6==================12==================
713
814
=== modified file 'src/launchpadlib/__init__.py'
--- src/launchpadlib/__init__.py 2010-04-06 19:54:35 +0000
+++ src/launchpadlib/__init__.py 2010-06-16 19:58:22 +0000
@@ -14,4 +14,4 @@
14# You should have received a copy of the GNU Lesser General Public License14# You should have received a copy of the GNU Lesser General Public License
15# along with launchpadlib. If not, see <http://www.gnu.org/licenses/>.15# along with launchpadlib. If not, see <http://www.gnu.org/licenses/>.
1616
17__version__ = '1.6.0'17__version__ = '1.6.1'
1818
=== modified file 'src/launchpadlib/docs/toplevel.txt'
--- src/launchpadlib/docs/toplevel.txt 2009-04-16 19:30:01 +0000
+++ src/launchpadlib/docs/toplevel.txt 2010-06-16 19:58:22 +0000
@@ -1,31 +1,71 @@
1The launchpad web service's top-level collections provide access to1The launchpad web service's top-level collections provide access to
2Launchpad-wide objects like projects and people.2Launchpad-wide objects like projects and people.
33
4 >>> import httplib2
5 >>> httplib2.debuglevel = 1
6
4 >>> from launchpadlib.testing.helpers import salgado_with_full_permissions7 >>> from launchpadlib.testing.helpers import salgado_with_full_permissions
5 >>> launchpad = salgado_with_full_permissions.login()8 >>> launchpad = salgado_with_full_permissions.login()
9 connect: ...
10 ...
611
7It's possible to do key-based lookups on the top-level12It's possible to do key-based lookups on the top-level
8collections. The bug collection does lookups by bug ID.13collections. The bug collection does lookups by bug ID.
914
10 >>> launchpad.bugs[1].id15 >>> bug = launchpad.bugs[1]
16
17For most top-level collections, simply looking up an object will not
18trigger an HTTP request. The HTTP request happens when you try to
19access one of the object's properties.
20
21 >>> print bug.id
22 send: 'GET /.../bugs/1 ...'
23 ...
11 124 1
1225
13The person collection does lookups by a person's Launchpad name.26Let's look at some more collections. The project collection does
1427lookups by project name.
15 >>> launchpad.people['salgado'].name28
16 u'salgado'29 >>> project = launchpad.projects['firefox']
1730 >>> print project.name
18The project collection does lookups by project name.31 send: 'GET /.../firefox ...'
1932 ...
20 >>> launchpad.projects['firefox'].name33 firefox
21 u'firefox'
2234
23The project group collection does lookups by project group name.35The project group collection does lookups by project group name.
2436
25 >>> launchpad.project_groups['firefox'].name37 >>> group = launchpad.project_groups['gnome']
26 u'firefox'38 >>> print group.name
39 send: 'GET /.../gnome ...'
40 ...
41 gnome
2742
28The distribution collection does lookups by distribution name.43The distribution collection does lookups by distribution name.
2944
30 >>> launchpad.distributions['ubuntu'].name45 >>> distribution = launchpad.distributions['ubuntu']
31 u'ubuntu'46 >>> print distribution.name
47 send: 'GET /.../ubuntu ...'
48 ...
49 ubuntu
50
51The person collection does lookups by a person's Launchpad
52name. Looking up a person from the top-level collection of people
53*does* trigger an HTTP request, since there's no other way to tell
54whether a given person should be represented by a 'person' object or a
55'team' object.
56
57 >>> person = launchpad.people['salgado']
58 send: 'GET /.../~salgado ...'
59 ...
60 >>> print person.name
61 salgado
62
63 >>> team = launchpad.people['rosetta-admins']
64 send: 'GET /1.0/~rosetta-admins ...'
65 ...
66 >>> print team.name
67 rosetta-admins
68
69Cleanup.
70
71 >>> httplib2.debuglevel = None
3272
=== modified file 'src/launchpadlib/launchpad.py'
--- src/launchpadlib/launchpad.py 2010-03-24 16:09:40 +0000
+++ src/launchpadlib/launchpad.py 2010-06-16 19:58:22 +0000
@@ -47,6 +47,11 @@
47 """Transform a username into the URL to a person resource."""47 """Transform a username into the URL to a person resource."""
48 return str(self._root._root_uri.ensureSlash()) + '~' + str(key)48 return str(self._root._root_uri.ensureSlash()) + '~' + str(key)
4949
50 # The only way to determine whether a string corresponds to a
51 # person or a team object is to ask the server, so looking up an
52 # entry from the PersonSet always requires making an HTTP request.
53 collection_of = None
54
5055
51class BugSet(CollectionWithKeyBasedLookup):56class BugSet(CollectionWithKeyBasedLookup):
52 """A custom subclass capable of bug lookup by bug ID."""57 """A custom subclass capable of bug lookup by bug ID."""
@@ -55,6 +60,8 @@
55 """Transform a bug ID into the URL to a bug resource."""60 """Transform a bug ID into the URL to a bug resource."""
56 return str(self._root._root_uri.ensureSlash()) + 'bugs/' + str(key)61 return str(self._root._root_uri.ensureSlash()) + 'bugs/' + str(key)
5762
63 collection_of = 'bug'
64
5865
59class PillarSet(CollectionWithKeyBasedLookup):66class PillarSet(CollectionWithKeyBasedLookup):
60 """A custom subclass capable of lookup by pillar name.67 """A custom subclass capable of lookup by pillar name.
@@ -66,6 +73,28 @@
66 """Transform a project name into the URL to a project resource."""73 """Transform a project name into the URL to a project resource."""
67 return str(self._root._root_uri.ensureSlash()) + str(key)74 return str(self._root._root_uri.ensureSlash()) + str(key)
6875
76 # The subclasses for projects, project groups, and distributions
77 # all define this property differently.
78 collection_of = None
79
80
81class ProjectSet(PillarSet):
82 """A custom subclass for accessing the collection of projects."""
83
84 collection_of = 'project'
85
86
87class ProjectGroupSet(PillarSet):
88 """A custom subclass for accessing the collection of project groups."""
89
90 collection_of = 'project_group'
91
92
93class DistributionSet(PillarSet):
94 """A custom subclass for accessing the collection of project groups."""
95
96 collection_of = 'distribution'
97
6998
70class Launchpad(ServiceRoot):99class Launchpad(ServiceRoot):
71 """Root Launchpad API class.100 """Root Launchpad API class.
@@ -78,11 +107,11 @@
78107
79 RESOURCE_TYPE_CLASSES = {108 RESOURCE_TYPE_CLASSES = {
80 'bugs': BugSet,109 'bugs': BugSet,
81 'distributions': PillarSet,110 'distributions': DistributionSet,
82 'HostedFile': HostedFile,111 'HostedFile': HostedFile,
83 'people': PersonSet,112 'people': PersonSet,
84 'project_groups': PillarSet,113 'project_groups': ProjectGroupSet,
85 'projects': PillarSet,114 'projects': ProjectSet,
86 }115 }
87116
88 def __init__(self, credentials, service_root=uris.STAGING_SERVICE_ROOT,117 def __init__(self, credentials, service_root=uris.STAGING_SERVICE_ROOT,

Subscribers

People subscribed via source and target branches