Sprinting on GetPaid: a plan

1 view
Skip to first unread message

Brandon Craig Rhodes

unread,
Oct 30, 2009, 2:47:16 PM10/30/09
to getpaid-dev
I have an important outstanding branch of GetPaid which needs to be
merged, but I would like some help with it before merging.

Christopher Johnson asked me to describe the tasks that need to be
completed, in a format convenient for sprinters. Hence this email! If
you are sprinting on GetPaid, try reading through this whole email, then
seeing whether one of the issues is one within your range of competence
to tackle!

Briefly, here is the process to get started on if you are a sprinter:

1. Build out my "no-overrides" branch.
2. Verify that buttons now appear and disappear.
3. Practice running tests.
4. Choose a task.
5. Sprint!

For each of these five items, I've written an extended explanation
below. Read through it carefully, and let me know if you have any
questions!

Build out my "no-overrides" branch
----------------------------------

Unlike the main GetPaid buildout, which pulls in the official version of
each GetPaid package, my buildout pulls in the branches from SVN where I
have been working on the new functionality. You will need Python 2.4 to
work on it; if you do not have that version of Python on your system and
are unsure how to install it, please ask a more experienced sprinter how!

Here are the commands for creating your own copy of my buildout; there
are only four of them, but they can take quite a while to run. I have
shown the amount of time that they take on my own laptop, but I think my
laptop already has many packages installed that the buildout needed; if
these packages need to be downloaded for the first time on your own
computer, then the times below could run much longer:

(5 minutes)
svn co https://getpaid.googlecode.com/svn/getpaid.buildout/branches/brandon-no-overrides no-overrides

(Immediate)
cd no-overrides

(10 seconds)
python2.4 bootstrap.py -c 316.cfg

(4 minutes)
bin/buildout -c 316.cfg -v

Once these commands have finished, you should then be able to run a
Plone instance very simply:

bin/instance fg

You *might* at this point receive the error "ImportError: No module
named PIL". If you do, simply ask someone more experienced how to
install the Python Imaging Library for Python 2.4 on your system. Once
it is installed, you should be able to run the above command successfully.

Once the instance is up and running:

* Visit the URL:

http://localhost:8080/manage_main

and log in as "admin" with the password "admin". Then select "Plone
site" from the pull-down menu next to "Add", press Enter, give it the
Id "Plone" and select "PloneGetPaid" from the "Extension Profiles"
down at the bottom, and press "Add Plone Site". You should now be
able to visit your new Plone site at:

http://localhost:8080/Plone

* Make a "Page" a buyable type by visiting the following URL and moving
"Page" into the right column at the top and clicking "Apply":

http://localhost:8080/Plone/@@manage-getpaid-content-types

* Create a buyable Page by returning to your home page:

http://localhost:8080/Plone/

and selecting "Add new…" "Page". Give it a title of "Sweater" and
click "Save". Then select "Actions…" "Make buyable", give it a
product code of "1001" and a price of "59.95", and click "Activate".

* Add the page to your shopping cart by finding the "Product details"
portlet in the lower-right of the Sweater page and clicking "Add to
Cart".

Verify that buttons now appear and disappear
--------------------------------------------

After following the instructions above, and with your Plone instance
running, you are ready to check out the new features of my branch. It
is designed to allow multiple off-site payment processors to live
happily together on the screen at the same time, and also to allow
on-site payment processing to be an option that can be turned on or off.
Here is how to try out my new features:

* Visit your shopping cart at:

http://localhost:8080/Plone/@@getpaid-cart

The cart should have a single checkout button, beneath the "Continue
Shopping" button, and it should be labeled "Checkout". Try clicking
on it; it should send you to the first page of the built-in checkout
process.

* The first feature of my branch that you should try out is that onsite
checkout can now be enabled or disabled, separately from the offsite
payment options. To see this, visit:

http://localhost:8080/Plone/@@manage-getpaid-payment-options

and un-check the "Activate On-site Payment" button and click "apply".
Now return to and re-load your shopping cart page. You should note
that no "Checkout" button now appears.

* The next feature you should try out is the fact that off-site payment
buttons can be made to appear. Return to the payment options screen
and move "Google Checkout" into the right column and press "Apply".
Re-load your cart and you should now see a Google Checkout button
appear. Now return to the payment options screen and add the "PayPal"
processor to the list on the right as well; now, your cart should show
two checkout buttons. Now return to the payment options and turn the
"Activate On-site Payment" check box back on; your cart should now
show all three buttons for the user to choose from.

There; that's, essentially, what the branch accomplishes. Rather than
require every off-site payment solution to perform messy ZCML overrides
to hijack the main GetPaid checkout button, my branch lets them each
cleanly offer their own button that appears or disappears under the
control of the site owner, not the programmer.

Actually, there's another effect that you can observe - the Payment
Processor options page at:

http://localhost:8080/Plone/@@manage-getpaid-payment-processor

provides a block of options for each active payment processor, but makes
them disappear if the payment processor is turned off. Isn't that cool?

Practice running tests
----------------------

Good programmers always try to include comprehensive unit and
integration tests as part of a package. Test can verify, as we keep
"improving" our products, that all of their old features actually keep
working even as we are busy adding new ones.

Most of the work I have done has been in four packages. Here is the
status of their tests:

* Products.PloneGetPaid - Working
* getpaid.core - Working
* getpaid.paypal - Broken!
* getpaid.googlecheckout - Broken (package might not even completely work)!

As you can guess, those last two statuses have a lot to do with what I
would like to see accomplished during the sprint. :-)

Here is how to run the two working sets of tests, so that you can see
that they indeed succeed - and so that you can also learn the pattern,
in case the sprint task you choose involves running the tests for any of
the other GetPaid packages:

bin/instance test --package Products.PloneGetPaid
bin/instance test --package getpaid.core

You should see lots of crazy warning and deprecation messages scroll
past (ah, Plone!) then the dots "...." that are printed as each test
runs. Once the ordeal is over, you should receive a report telling you
that, despite all of those scary messages, the tests actually passed:

Ran 147 tests with 0 failures and 0 errors in 96.076 seconds.

If they pass, then your buildout is a safe place for you to begin work.

Look at all you've accomplished! You now have a working development
instance of GetPaid, you can run its Plone, you can explore its
features, and you can run its tests. It's now about time to choose a
task and start sprinting!

Choose a task
-------------

If you are new to Plone development, there is one issue that might not
have been thought about ahead of time: establishing your legal ability
to contribute code back to GetPaid. I know that contributing to Plone
requires signing and returning a form to the foundation, but you should
talk to Christopher Johnson as you get started on this sprint to make
sure that code or patches you generate can indeed be legally contributed
back to the effort.

So, how can you choose a task?

What I would like to see the sprint accomplish is to get both the PayPal
and the GoogleCheckout mechanisms working great with my new branch.
That would bring about two great results:

1. Just the fact that everyone would have worked with and tried out my
branch for hours and hours would hopefully make us all comfortable
that my "Products.PloneGetPaid" and "getpaid.core" innovates can now
be merged back into trunk.

2. Instead of my new feature appearing for the first time in trunk with
its "Offsite Payment Processors" setup option blank, we could now
include both PayPal and GoogleCheckout in the default GetPaid build.

To help people communicate during this sprint, I will here invent a
little rating system for GetPaid off-site payment processors:

"Tin" - the off-site payment processor does not even use my new plug-in
mechanism, but relies on an "overrides.zcml" file instead.

"Bronze" - the processor has been rewritten to use my new plug-in
mechanism and can therefore live peacefully with other off-site
payment processors.

"Silver" - the processor's tests have been re-written (or written for
the first time, if it lacked them before) to demonstrate that it
plugs in fine with my new mechanism.

"Gold" - the processor supports a callback mechanism that lets the
off-site payment solution report back to Plone about which orders
users actually carried through with.

"Platinum" - tests are written, and work, for the callback mechanism.

Given the above ratings, here is now I would rate the two payment
processors I have touched:

PayPal - Bronze
GoogleCheckout - on the way to Bronze

The goal that I would suggest for the sprint is to work on these two
change processors to get them both at least to "Silver", because that is
a tolerable working state: while shop owners can't use "Silver"-level
processors and expect to be able to manage orders on their Plone site,
many won't need to because they can do their management on PayPal or
Google Checkout's own site. Of course, if sprinters are available to
start working on going Gold, then please do so!

So, having given that background, what are the available projects for
the sprint? Here are some projects that I think could be divvied up
among you.

Easy Tasks - require only basic knowledge of Plone
..................................................

* Add "Available" and "Selected" headings to the "Off-site Payment
Processors" controller on the @@manage-getpaid-payment-options page.

Take a look at the @@manage-getpaid-payment-options page; do you see
something funny about the off-site selection boxes up at the top?
That's right! They contain absolutely no indication of which box is
for the ones you *do* want to use, and which box is for the ones you
*don't*. :-)

That's because I couldn't figure out how to label them, and after
one or two tries I ran out of time and had to turn to other things.

The odd thing is that the "Accepted Credit Cards" setting just below
it on the same page *does* have headings; but I couldn't figure out
what the difference was!

This whole form is powered by the "IGetPaidManagementPaymentOptions"
interface in:

Products.PloneGetPaid/Products/PloneGetPaid/interfaces.py

Somehow there's a way to turn those little headings on; go find it!
If you're new to Plone, this should be a great little project.


* Fix the fact that checkout buttons are too close to each other.

You probably noticed this already: the checkout buttons run right up
against each other (in Firefox, at least) where they are sitting
beneath the shopping cart. If you know a little HTML and CSS, then
please consider jumping in and fixing this! I am probably just
failing to put a <div> around them with the right class to tell the
default Plone stylesheets that they're buttons and need some room
around them.

The (admittedly primitive) template that I use for the stack of
buttons is here:

Products.PloneGetPaid/Products/PloneGetPaid/browser/templates/checkout-buttons.pt

What am I doing wrong? You will want to compare my HTML to other
buttons around the Plone site, that are presumably done the "right"
and "standard" way, and then try modifying the above template until
things look better.

It's annoying that the checkout buttons are different sizes, isn't
it? But we have to use the logos for user recognition of these
common services, right? You might also think about whether there's
any way to improve the appearance when the Google button is so much
bigger than the PayPal one!


* Disable the checkout process if "Activate On-site Payment" is
unchecked.

Okay, you might have noticed something of a flaw in my design: if
the store owner un-checks the "Activate On-site Payment" box at

http://localhost:8080/Plone/@@manage-getpaid-payment-options

then, as planned, the normal "Checkout" button disappears. But,
behind the scenes, the view is still there and ready to let the user
check out! It should really be disabled. To be more exact, if the
"Activate On-site Payment" box is unchecked by the store owner, then
any attempt to access:

http://localhost:8080/Plone/@@getpaid-checkout-wizard

(whether by a user who knows GetPaid, or because an old link to the
checkout has been left in a site template somewhere) should be met
with some sort of refusal. Maybe it should redirect back to the
main cart view? Or should it show an error and provide a link back
to the rest of the site? First, write the logic. Then you can
debate with other GetPaid people about what action the logic should
trigger.

You will probably accomplish this by finding the class that runs the
"getpaid-checkout-wizard" view (look through the ZCML to find the
module and class that run that view), and putting an "if" statement
inside of it somewhere that grabs the GetPaid global options (you
can find the pattern for this in several places; look for the portal
root being adapted to an options interface from getpaid.core!) and
then looks to make sure that onsite checkout is enabled.

Intermediate Tasks
..................

* Write tests for PayPal

The PayPal processor in "trunk" lacks tests entirely, from what I
can see, and it needs some! You can verify that it works by hand by
creating a PayPal sandbox account and entering its username into
your PayPal Processor Options (if PayPal is turned on!) at:

http://localhost:8080/Plone/@@manage-getpaid-payment-processor

By "works", I mean that you'll indeed be forwarded to PayPal which
will display the total of your shopping cart, and if you click on
the pull-down arrow on the margin just below the total you'll see
all of the "line items" appear that detail the objects that were in
your shopping cart. This all demonstrates that information is
making it through from GetPaid to PayPal correctly.

But this is the world of Python, and testing things by hand is not
enough for us! The PayPal change processor needs tests. How can
you add them?

First, look at the trunk of "getpaid.googlecheckout":

http://code.google.com/p/getpaid/source/browse#svn/getpaid.googlecheckout/trunk/src/getpaid/googlecheckout/tests

You will see that its tests.test_suite() function runs two doctests
that you'll find one level up, outside the test directory: one test
just named "googlecheckout.txt" and another that is named
"googlecheckout-browser.txt". If you checked out the project trunk
and ran these tests, you'd even see that they pass!

To give PayPal tests, copy these tests as an example and adapt them
to PayPal: have them create some purchasable objects,


* Get the Google Checkout button working.

Though the Google Checkout button will appear when that payment
processor is activated, the form that surrounds the button is pretty
much empty. Unlike the PayPal checkout button, which I've been able
to spend more time on, the Google Checkout button is pretty much
blank.

It needs someone to go in and add all of the hidden fields that will
make it an effective button. If you choose to tackle this problem,
you will have the advantage of having the PayPal branch to work off
of: it will show you how an effective form can be generated that is
full of information about the current shopping cart.

You will have succeeded if, when you are done, the Google Checkout
button - like the PayPal button - actually takes the person clicking
it off-site and if, upon arrival, Google Checkout knows what items
were in their cart. Expect to need to bring up the Google Checkout
docs to complete this task; but use the PayPal branch to see
examples of how to get to the information (like payment processor
settings and cart contents) that you'll need to fill out the form.


* BONUS: Tests for Google Checkout.

If the previous item is actually accomplished, and the Google
Checkout button becomes useful, then write working tests for it -
check out the instructions in the first item in this Intermediate
section for thoughts on testing.

Advanced Tasks
..............

* Get PayPal notification working.
* Get Google Checkout notification working.

Okay, here is a real challenge in case some serious Plone hackers
show up and the above items don't provide enough entertainment.

Your task is to write tests - I have no idea how - that verify that
either the PayPal or Google Checkout payment processor, after
sending the user off-site, correctly receives back the messages
telling them that the buyer is progressing through checkout.

There are two challenges here that are actually a bit steep for me,
as a developer, to tackle (which is why I've not even attempted to
tackle them):

1. No "Order" object exists yet when the user leaves the site. How,
then, will the return messages from PayPal or Google Checkout -
that refer to the order number - be associated with the correct
user, and result in an order being created for them? My guess is
that the buttons that send users off-site should generate
one-time disposable order numbers that have the user's username
encoded inside of them. When the notification comes back, if no
order of that number exists yet, then the username can be decoded
to figure out what user to create the order for. And when the
order is finalized and purchased, you can even empty that user's
shopping cart. For bonus points, only empty it of the items that
have actually been purchased, leaving items inside that were not
included in the order the user just paid for. :-)

2. How can a Plone test - whether a doctest or normal unit test -
submit a form to an off-site service and at the same time already
be ready to receive a signal back? There are two parts to this
question: first, since the test will often be running on a
computer behind a firewall, the test will have to be given the
name of an SSH account it can log into with an "-R" option so
that "http://wherever.it.is:PORT/" becomes a location that the
remote service can POST to and have it actually be received by
the test on whatever port it opens. And, second, how can the
test break into two threads to do the actual HTTP handling?

These, again, are quite advanced challenges, and are actually a bit
beyond my own knowledge at this point; you should only seize them if
you are among the Great Among Plone, and happen to be wanting to
sprint upon GetPaid. If we are so honored.


Sprint!
-------

Finally, after choosing a task from the above: get started!

I'll try to be on IRC, and helpful GetPaid folks should be somewhere
nearby to help. I have tried to be clear in everything above, and I'll
apologize ahead of time if any inaccuracies in what I've written waste
your time; I've taken part in several sprints before, and I know how
frustrating it can be just getting set up, much less trying to
accomplish anything!

If you could, use the mailing list to let us know what you're working
on, so that everyone has a record of who has grabbed what task. When
the sprint is over, send a reply to your message telling what happened,
where things stand, and including your patch or improvement if you
generated one but weren't in a position to commit it.

And, most of all, have fun. :-) I look forward to hearing your reports!

--
Brandon Craig Rhodes bra...@rhodesmill.org http://rhodesmill.org/brandon

Silvio

unread,
Oct 30, 2009, 5:06:02 PM10/30/09
to getpa...@googlegroups.com
On Fri, Oct 30, 2009 at 7:47 PM, Brandon Craig Rhodes <bra...@rhodesmill.org> wrote:

I have an important outstanding branch of GetPaid which needs to be
merged, but I would like some help with it before merging.

Great, I'm sprinting tomorrow on this.
 
 (10 seconds)
 python2.4 bootstrap.py -c 316.cfg
I forgot to specify the cfg file here (as I don't usually do) and it didn't work.
So I added a buildout.cfg that loads 316.cfg to be used as a default for the latest supported version.
Is there any known problem with 3.3.1? Can we use that as the default supported version?
 
 (4 minutes)
 bin/buildout -c 316.cfg -v
 so this can also be simplified to
bin/buildout -v

      Silvio

Hannes Calitz

unread,
Oct 30, 2009, 6:24:39 PM10/30/09
to getpa...@googlegroups.com
Hey there Brandon

I was busy going through your email, and following all the steps when suddenly I got an error. Below is where I was, and in red I posted the traceback.

2009/10/30 Brandon Craig Rhodes <bra...@rhodesmill.org>
And this is where I hit a wall :/

Traceback (innermost last):
Module ZPublisher.Publish, line 119, in publish
Module ZPublisher.mapply, line 88, in mapply
Module ZPublisher.Publish, line 42, in call_object
Module Products.PloneGetPaid.browser.cart, line 47, in __call__
Module Products.Five.browser.metaconfigure, line 417, in __call__
Module Shared.DC.Scripts.Bindings, line 313, in __call__
Module Shared.DC.Scripts.Bindings, line 350, in _bindAndExec
Module Products.PageTemplates.PageTemplateFile, line 129, in _exec
Module Products.PageTemplates.PageTemplate, line 89, in pt_render
Module zope.pagetemplate.pagetemplate, line 117, in pt_render
Module zope.tal.talinterpreter, line 271, in __call__
Module zope.tal.talinterpreter, line 346, in interpret
Module zope.tal.talinterpreter, line 891, in do_useMacro
Module zope.tal.talinterpreter, line 346, in interpret
Module zope.tal.talinterpreter, line 536, in do_optTag_tal
Module zope.tal.talinterpreter, line 521, in do_optTag
Module zope.tal.talinterpreter, line 516, in no_tag
Module zope.tal.talinterpreter, line 346, in interpret
Module zope.tal.talinterpreter, line 891, in do_useMacro
Module zope.tal.talinterpreter, line 346, in interpret
Module zope.tal.talinterpreter, line 536, in do_optTag_tal
Module zope.tal.talinterpreter, line 521, in do_optTag
Module zope.tal.talinterpreter, line 516, in no_tag
Module zope.tal.talinterpreter, line 346, in interpret
Module zope.tal.talinterpreter, line 949, in do_defineSlot
Module zope.tal.talinterpreter, line 346, in interpret
Module zope.tal.talinterpreter, line 949, in do_defineSlot
Module zope.tal.talinterpreter, line 346, in interpret
Module zope.tal.talinterpreter, line 536, in do_optTag_tal
Module zope.tal.talinterpreter, line 521, in do_optTag
Module zope.tal.talinterpreter, line 516, in no_tag
Module zope.tal.talinterpreter, line 346, in interpret
Module zope.tal.talinterpreter, line 534, in do_optTag_tal
Module zope.tal.talinterpreter, line 516, in no_tag
Module zope.tal.talinterpreter, line 346, in interpret
Module zope.tal.talinterpreter, line 745, in do_insertStructure_tal
Module Products.PageTemplates.Expressions, line 221, in evaluateStructure
Module zope.tales.tales, line 696, in evaluate
- URL: index
- Line 6, Column 1
- Expression: <PathExpr standard:'view/manager/render'>
- Names:
{'container': <PloneSite at /Plone>,
'context': <PloneSite at /Plone>,
'default': <object object at 0xb7cab528>,
'here': <PloneSite at /Plone>,
'loop': {},
'nothing': None,
'options': {'args': (<Products.Five.metaclass.SimpleViewClass from /home/hannes/zopes/getpaid/no-overrides/src/Products.PloneGetPaid/Products/PloneGetPaid/browser/templates/cart-manage.pt object at 0xd2f23ec>,)},
'repeat': <Products.PageTemplates.Expressions.SafeMapping object at 0xd2f2bac>,
'request': <HTTPRequest, URL=http://localhost:8080/Plone/@@getpaid-cart>,
'root': <Application at >,
'template': <ImplicitAcquirerWrapper object at 0xd2f27cc>,
'traverse_subpath': [],
'user': <PropertiedUser 'admin'>,
'view': <Products.Five.metaclass.SimpleViewClass from /home/hannes/zopes/getpaid/no-overrides/src/Products.PloneGetPaid/Products/PloneGetPaid/browser/templates/cart-manage.pt object at 0xd2f23ec>,
'views': <zope.app.pagetemplate.viewpagetemplatefile.ViewMapper object at 0xd2f2fcc>}
Module zope.tales.expressions, line 217, in __call__
Module Products.PageTemplates.Expressions, line 161, in _eval
Module Products.PageTemplates.Expressions, line 123, in render
Module zope.viewlet.manager, line 110, in render
Module Shared.DC.Scripts.Bindings, line 313, in __call__
Module Shared.DC.Scripts.Bindings, line 350, in _bindAndExec
Module Products.PageTemplates.PageTemplateFile, line 129, in _exec
Module Products.PageTemplates.PageTemplate, line 89, in pt_render
Module zope.pagetemplate.pagetemplate, line 117, in pt_render
Module zope.tal.talinterpreter, line 271, in __call__
Module zope.tal.talinterpreter, line 346, in interpret
Module zope.tal.talinterpreter, line 824, in do_loop_tal
Module zope.tal.talinterpreter, line 346, in interpret
Module zope.tal.talinterpreter, line 536, in do_optTag_tal
Module zope.tal.talinterpreter, line 521, in do_optTag
Module zope.tal.talinterpreter, line 516, in no_tag
Module zope.tal.talinterpreter, line 346, in interpret
Module zope.tal.talinterpreter, line 534, in do_optTag_tal
Module zope.tal.talinterpreter, line 516, in no_tag
Module zope.tal.talinterpreter, line 346, in interpret
Module zope.tal.talinterpreter, line 745, in do_insertStructure_tal
Module Products.PageTemplates.Expressions, line 221, in evaluateStructure
Module zope.tales.tales, line 696, in evaluate
- URL: viewlet-manager
- Line 4, Column 5
- Expression: <PathExpr standard:'viewlet/render'>
- Names:
{'container': <PloneSite at /Plone>,
'context': <PloneSite at /Plone>,
'default': <object object at 0xb7cab528>,
'here': <PloneSite at /Plone>,
'loop': {'viewlet': <Products.PageTemplates.Expressions.PathIterator object at 0xd3102cc>},
'nothing': None,
'options': {'args': (),
'viewlets': [<Products.Five.viewlet.viewlet.SimpleViewletClass from /home/hannes/zopes/getpaid/no-overrides/src/Products.PloneGetPaid/Products/PloneGetPaid/browser/templates/cart-listing.pt object at 0xd2f26ec>,
<Products.Five.viewlet.viewlet.SimpleViewletClass from /home/hannes/zopes/getpaid/no-overrides/src/Products.PloneGetPaid/Products/PloneGetPaid/browser/templates/cart-actions.pt object at 0xd2f29ec>]},
'repeat': <Products.PageTemplates.Expressions.SafeMapping object at 0xd2e6cec>,
'request': <HTTPRequest, URL=http://localhost:8080/Plone/@@getpaid-cart>,
'root': <Application at >,
'template': <ImplicitAcquirerWrapper object at 0xd2f4a2c>,
'traverse_subpath': [],
'user': <PropertiedUser 'admin'>,
'view': <UnauthorizedBinding: context>,
'views': <zope.app.pagetemplate.viewpagetemplatefile.ViewMapper object at 0xd2e696c>}
Module zope.tales.expressions, line 217, in __call__
Module Products.PageTemplates.Expressions, line 161, in _eval
Module Products.PageTemplates.Expressions, line 123, in render
Module Products.PloneGetPaid.browser.cart, line 290, in render
Module Shared.DC.Scripts.Bindings, line 313, in __call__
Module Shared.DC.Scripts.Bindings, line 350, in _bindAndExec
Module Products.PageTemplates.PageTemplateFile, line 129, in _exec
Module Products.PageTemplates.PageTemplate, line 89, in pt_render
Module zope.pagetemplate.pagetemplate, line 117, in pt_render
Module zope.tal.talinterpreter, line 271, in __call__
Module zope.tal.talinterpreter, line 346, in interpret
Module zope.tal.talinterpreter, line 855, in do_condition
Module zope.tal.talinterpreter, line 346, in interpret
Module zope.tal.talinterpreter, line 534, in do_optTag_tal
Module zope.tal.talinterpreter, line 516, in no_tag
Module zope.tal.talinterpreter, line 346, in interpret
Module zope.tal.talinterpreter, line 745, in do_insertStructure_tal
Module Products.PageTemplates.Expressions, line 221, in evaluateStructure
Module zope.tales.tales, line 696, in evaluate
- URL: cart-actions
- Line 30, Column 2
- Expression: <PathExpr standard:'context/@@getpaid-checkout-buttons'>
- Names:
{'container': <PloneSite at /Plone>,
'context': <PloneSite at /Plone>,
'default': <object object at 0xb7cab528>,
'here': <PloneSite at /Plone>,
'loop': {},
'nothing': None,
'options': {'args': ()},
'repeat': <Products.PageTemplates.Expressions.SafeMapping object at 0xd31066c>,
'request': <HTTPRequest, URL=http://localhost:8080/Plone/@@getpaid-cart>,
'root': <Application at >,
'template': <ImplicitAcquirerWrapper object at 0xd310e6c>,
'traverse_subpath': [],
'user': <PropertiedUser 'admin'>,
'view': <Products.Five.viewlet.viewlet.SimpleViewletClass from /home/hannes/zopes/getpaid/no-overrides/src/Products.PloneGetPaid/Products/PloneGetPaid/browser/templates/cart-actions.pt object at 0xd2f29ec>,
'views': <zope.app.pagetemplate.viewpagetemplatefile.ViewMapper object at 0xd310e0c>}
Module zope.tales.expressions, line 217, in __call__
Module Products.PageTemplates.Expressions, line 161, in _eval
Module Products.PageTemplates.Expressions, line 123, in render
Module Products.PloneGetPaid.browser.checkout_buttons, line 62, in __call__
Module Shared.DC.Scripts.Bindings, line 313, in __call__
Module Shared.DC.Scripts.Bindings, line 350, in _bindAndExec
Module Products.PageTemplates.PageTemplateFile, line 129, in _exec
Module Products.PageTemplates.PageTemplate, line 89, in pt_render
Module zope.pagetemplate.pagetemplate, line 117, in pt_render
Module zope.tal.talinterpreter, line 271, in __call__
Module zope.tal.talinterpreter, line 346, in interpret
Module zope.tal.talinterpreter, line 824, in do_loop_tal
Module zope.tal.talinterpreter, line 346, in interpret
Module zope.tal.talinterpreter, line 536, in do_optTag_tal
Module zope.tal.talinterpreter, line 521, in do_optTag
Module zope.tal.talinterpreter, line 516, in no_tag
Module zope.tal.talinterpreter, line 346, in interpret
Module zope.tal.talinterpreter, line 534, in do_optTag_tal
Module zope.tal.talinterpreter, line 516, in no_tag
Module zope.tal.talinterpreter, line 346, in interpret
Module zope.tal.talinterpreter, line 745, in do_insertStructure_tal
Module Products.PageTemplates.Expressions, line 221, in evaluateStructure
Module zope.tales.tales, line 696, in evaluate
- URL: index
- Line 9, Column 2
- Expression: <PathExpr standard:'offsite_button'>
- Names:
{'container': <PloneSite at /Plone>,
'context': <PloneSite at /Plone>,
'default': <object object at 0xb7cab528>,
'here': <PloneSite at /Plone>,
'loop': {'offsite_button': <Products.PageTemplates.Expressions.PathIterator object at 0xd3150ec>},
'nothing': None,
'options': {'args': ()},
'repeat': <Products.PageTemplates.Expressions.SafeMapping object at 0xd31022c>,
'request': <HTTPRequest, URL=http://localhost:8080/Plone/@@getpaid-cart>,
'root': <Application at >,
'template': <ImplicitAcquirerWrapper object at 0xd31042c>,
'traverse_subpath': [],
'user': <PropertiedUser 'admin'>,
'view': <Products.Five.metaclass.SimpleViewClass from /home/hannes/zopes/getpaid/no-overrides/src/Products.PloneGetPaid/Products/PloneGetPaid/browser/templates/checkout-buttons.pt object at 0xd31012c>,
'views': <zope.app.pagetemplate.viewpagetemplatefile.ViewMapper object at 0xd310c6c>}
Module zope.tales.expressions, line 217, in __call__
Module Products.PageTemplates.Expressions, line 161, in _eval
Module Products.PageTemplates.Expressions, line 123, in render
Module Products.Five.browser.metaconfigure, line 417, in __call__
Module Shared.DC.Scripts.Bindings, line 313, in __call__
Module Shared.DC.Scripts.Bindings, line 350, in _bindAndExec
Module Products.PageTemplates.PageTemplateFile, line 129, in _exec
Module Products.PageTemplates.PageTemplate, line 89, in pt_render
Module zope.pagetemplate.pagetemplate, line 117, in pt_render
Module zope.tal.talinterpreter, line 271, in __call__
Module zope.tal.talinterpreter, line 346, in interpret
Module zope.tal.talinterpreter, line 408, in do_startTag
Module zope.tal.talinterpreter, line 485, in attrAction_tal
Module Products.PageTemplates.Expressions, line 228, in evaluateText
Module zope.tales.tales, line 696, in evaluate
- URL: index
- Line 1, Column 0
- Expression: <PathExpr standard:'view/action_url'>
- Names:
{'container': <getpaid.paypal.paypal.PayPalStandardProcessor object at 0xd310b8c>,
'context': <getpaid.paypal.paypal.PayPalStandardProcessor object at 0xd310b8c>,
'default': <object object at 0xb7cab528>,
'here': <getpaid.paypal.paypal.PayPalStandardProcessor object at 0xd310b8c>,
'loop': {},
'nothing': None,
'options': {'args': (<Products.Five.metaclass.SimpleViewClass from /home/hannes/zopes/getpaid/no-overrides/src/getpaid.paypal/src/getpaid/paypal/templates/paypal-checkout-button.pt object at 0xd310c2c>,)},
'repeat': <Products.PageTemplates.Expressions.SafeMapping object at 0xd312fac>,
'request': <HTTPRequest, URL=http://localhost:8080/Plone/@@getpaid-cart>,
'root': <Application at >,
'template': <ImplicitAcquirerWrapper object at 0xd3123ec>,
'traverse_subpath': [],
'user': <PropertiedUser 'admin'>,
'view': <Products.Five.metaclass.SimpleViewClass from /home/hannes/zopes/getpaid/no-overrides/src/getpaid.paypal/src/getpaid/paypal/templates/paypal-checkout-button.pt object at 0xd310c2c>,
'views': <zope.app.pagetemplate.viewpagetemplatefile.ViewMapper object at 0xd31296c>}
Module zope.tales.expressions, line 217, in __call__
Module Products.PageTemplates.Expressions, line 161, in _eval
Module Products.PageTemplates.Expressions, line 123, in render
Module getpaid.paypal.views, line 18, in action_url
Module getpaid.paypal.paypal, line 22, in server_url
KeyError


Now return to the payment options and turn the
 "Activate On-site Payment" check box back on; your cart should now
 show all three buttons for the user to choose from.
 
--

Brandon Craig Rhodes

unread,
Oct 30, 2009, 7:21:20 PM10/30/09
to getpa...@googlegroups.com
Silvio <sil...@gmail.com> writes:

> I forgot to specify the cfg file here (as I don't usually do) and it
> didn't work. So I added a buildout.cfg that loads 316.cfg to be used
> as a default for the latest supported version.

The "buildout.cfg" used to be the one for Plone 2.5.5, which was never
the version I wanted, and I got tired of ruining my buildout every time
that I forgot and re-ran "buildout" without any arguments. :-)

My vote would be against a default "buildout.cfg" in Subversion if we're
going to support multiple versions of Plone; it just makes it too
dangerous, in my opinion, for people working on some other version. If
you run "buildout" without choosing a version, that error message is
necessary to remind you that the choice must be made.

However, I happily encourage *local* symlinks that we each make from
"buildout.cfg" to the version we're currently working on.

Anyway, that's just my vote. :-) I know that's not how things have been
working in trunk, so I'd assumed that this change would disappear once
my branch is merged then destroyed.

Michael Dunstan

unread,
Oct 30, 2009, 7:34:11 PM10/30/09
to getpa...@googlegroups.com
On Sat, Oct 31, 2009 at 7:47 AM, Brandon Craig Rhodes
<bra...@rhodesmill.org> wrote:
>    2. How can a Plone test - whether a doctest or normal unit test -
>       submit a form to an off-site service and at the same time already
>       be ready to receive a signal back?  There are two parts to this
>       question: first, since the test will often be running on a
>       computer behind a firewall, the test will have to be given the
>       name of an SSH account it can log into with an "-R" option so
>       that "http://wherever.it.is:PORT/" becomes a location that the
>       remote service can POST to and have it actually be received by
>       the test on whatever port it opens.  And, second, how can the
>       test break into two threads to do the actual HTTP handling?

The Google Checkout processor tests fabricate the incoming signals
from the checkout server. See

http://code.google.com/p/getpaid/source/browse/getpaid.googlecheckout/trunk/src/getpaid/googlecheckout/googlecheckout.txt#128

http://code.google.com/p/getpaid/source/browse/getpaid.googlecheckout/trunk/src/getpaid/googlecheckout/googlecheckout-browser.txt#201

--
Michael Dunstan

Brandon Craig Rhodes

unread,
Oct 30, 2009, 7:33:50 PM10/30/09
to getpa...@googlegroups.com
Hannes -

Thanks for the bug report! The problem was that the PayPal payment
processor didn't know what to do if you turned it on before choosing
whether to use the sandbox or production server (whoops!). I have now
fixed it to make it more robust: it uses the sandbox server in that
case. Run "svn up" and let me know if that fixes it!

Hannes Calitz

unread,
Oct 31, 2009, 2:31:39 AM10/31/09
to getpa...@googlegroups.com
Hi Brandon

Sweet, it seems to work now. I don't think I am going to have time to run through your entire email before the sprint today, but I will do so as soon as I get a chance. Probably this evening some time.

Hannes

2009/10/31 Brandon Craig Rhodes <bra...@rhodesmill.org>

Mikko Ohtamaa

unread,
Oct 31, 2009, 5:20:19 AM10/31/09
to getpa...@googlegroups.com

Hi all,

Brandon, thanks for the great work!

Unfortunately I will be participating document spring, so I cannot help you here. Also my work laptop said BOOOM so I cannot work on the code in any case.

If you need help with Mr. Developer or you have questions about getpaid.atshop I am here to answer to questions. I might or might not get to IRC.

-Mikko

--
Mikko Ohtamaa
Managing director, Red Innovation Ltd.
+358 40 743 9707
www.redinnovation.com
Every problem is solvable if you can throw enough energy drinks at it

Juan Pablo Giménez

unread,
Oct 31, 2009, 3:36:17 AM10/31/09
to getpa...@googlegroups.com
El vie, 30-10-2009 a las 19:21 -0400, Brandon Craig Rhodes escribió:
> Silvio <sil...@gmail.com> writes:
>
> > I forgot to specify the cfg file here (as I don't usually do) and it
> > didn't work. So I added a buildout.cfg that loads 316.cfg to be used
> > as a default for the latest supported version.
>
> The "buildout.cfg" used to be the one for Plone 2.5.5, which was never
> the version I wanted, and I got tired of ruining my buildout every time
> that I forgot and re-ran "buildout" without any arguments. :-)
>
> My vote would be against a default "buildout.cfg" in Subversion if we're
> going to support multiple versions of Plone; it just makes it too
> dangerous, in my opinion, for people working on some other version. If
> you run "buildout" without choosing a version, that error message is
> necessary to remind you that the choice must be made.

+1

> However, I happily encourage *local* symlinks that we each make from
> "buildout.cfg" to the version we're currently working on.

I usually use a local.cfg pointing to the correct cfg and overriding
recipes with local stuff, like instance port number, additional eggs,
etc... so my bash history only have buildout lines with -c local.cfg,
even usable on buildouts with a buildout.cfg file...


Regards,
Juan Pablo


Juan Pablo Giménez

unread,
Oct 31, 2009, 3:36:25 AM10/31/09
to getpa...@googlegroups.com
El vie, 30-10-2009 a las 14:47 -0400, Brandon Craig Rhodes escribió:
> I have an important outstanding branch of GetPaid which needs to be
> merged, but I would like some help with it before merging.
>
> Christopher Johnson asked me to describe the tasks that need to be
> completed, in a format convenient for sprinters. Hence this email! If
> you are sprinting on GetPaid, try reading through this whole email, then
> seeing whether one of the issues is one within your range of competence
> to tackle!
>
> Briefly, here is the process to get started on if you are a sprinter:
>
> 1. Build out my "no-overrides" branch.
> 2. Verify that buttons now appear and disappear.
> 3. Practice running tests.
> 4. Choose a task.
> 5. Sprint!

FYI, getpaid.nmi processor is working again! and have a running test
suite,

./bin/instance test -s getpaid.nmi
...
Installing PloneGetPaid ... done (0.052s)
Running Products.PloneTestCase.layer.PloneSite tests:
Set up Products.PloneTestCase.layer.PloneSite in 0.009 seconds.
Running:
...Installing Five ... done (0.040s)
2009-10-31 04:04:06 WARNING plone.z3cform Monkey patching
z3c.form.term.ChoiceTerms to correctly bind fields
.............
Ran 16 tests with 0 failures and 0 errors in 10.508 seconds.
Tearing down left over layers:
Tear down Products.PloneTestCase.layer.PloneSite in 0.544 seconds.
Tear down Products.PloneTestCase.layer.ZCML in 0.006 seconds.
Testrunner took: 11.792 seconds.

I'm not using orders workflow because DefaultFinanceProcessorIntegration
is tied to IPaymentProcessor and we are implementing
IOffsitePaymentProcessor, that was what I changed on
getpaid.core.payment and you reverted (brandon)... but its ok, maybe we
shouldn't change DefaultFinanceProcessorIntegration but "overrides" the
adapter (not actually overrides, but find a way to wire another class)
or define a full new workflow for offsite processors... I'm not sure
what is better (and is too late here... :))

Regards,
Juan Pablo



Brandon Craig Rhodes

unread,
Oct 31, 2009, 8:12:11 AM10/31/09
to getpa...@googlegroups.com
Juan Pablo Giménez <j...@rosario.com> writes:

> I'm not using orders workflow because
> DefaultFinanceProcessorIntegration is tied to IPaymentProcessor and we
> are implementing IOffsitePaymentProcessor, that was what I changed on
> getpaid.core.payment and you reverted (brandon)...

I reverted the change because it broke GetPaid for me and I couldn't
understand why it was there. Let me go take a look now while the sprint
is going on!

Silvio

unread,
Oct 31, 2009, 8:14:20 AM10/31/09
to getpa...@googlegroups.com
2009/10/31 Juan Pablo Giménez <j...@rosario.com>


El vie, 30-10-2009 a las 19:21 -0400, Brandon Craig Rhodes escribió:
> Silvio <sil...@gmail.com> writes:
>
> > I forgot to specify the cfg file here (as I don't usually do) and it
> > didn't work.  So I added a buildout.cfg that loads 316.cfg to be used
> > as a default for the latest supported version.
>
> The "buildout.cfg" used to be the one for Plone 2.5.5, which was never
> the version I wanted, and I got tired of ruining my buildout every time
> that I forgot and re-ran "buildout" without any arguments. :-)
>
> My vote would be against a default "buildout.cfg" in Subversion if we're
> going to support multiple versions of Plone; it just makes it too
> dangerous, in my opinion, for people working on some other version.  If
> you run "buildout" without choosing a version, that error message is
> necessary to remind you that the choice must be made.

+1

Ok, sorry for committing that change without asking: I didn't think the choice of not having a buildout.cfg was intentional.
I stay however on my point that we should have a sensible default buildout.cfg that actually extends the buildout for the latest supported Plone.

       Silvio

Mikko Ohtamaa

unread,
Oct 31, 2009, 11:09:28 AM10/31/09
to getpa...@googlegroups.com
>> > My vote would be against a default "buildout.cfg" in Subversion if we're
>> > going to support multiple versions of Plone; it just makes it too
>> > dangerous, in my opinion, for people working on some other version.  If
>> > you run "buildout" without choosing a version, that error message is
>> > necessary to remind you that the choice must be made.
>>

Extending buildout is much better way than having a default buildout
for each version. buildourt.cfg might be different depending on
installer and OS - we do not want to support that variation. If you
want to see the heacache check out buildout.cfg in Windows installer.
Instead we could provide different extension for each Plone version if
version soup is a problem.

I suggest we use combination of extends and  [versions] to deal with
versioning problems.
E.g.
[buildout]
extends = http://dist.plone.org/release/3.3/versions.cfg
http://svn.plone.org/svn/collective/getpaid.buildout/getpaid_for_3.3.cfg

getpaid_for_3.3.cfg contains

[versions]
Products.PloneGetPaid=0.8
getpaid.somepackage=0.7
...

vs.

[buildout]
extends = http://dist.plone.org/release/4.0/versions.cfg
http://svn.plone.org/svn/collective/getpaid.buildout/getpaid_for_4.0.cfg

-Mikko

Brandon Craig Rhodes

unread,
Nov 1, 2009, 7:48:21 AM11/1/09
to getpa...@googlegroups.com
Michael Dunstan <michael...@gmail.com> writes:

> The Google Checkout processor tests fabricate the incoming signals

> from the checkout server...

Well, that's an interesting idea! At first it sounds like an
unconvincing test, but I guess if the XML you injected in the test was
actual real XML from Google that you'd captured during a by-hand test of
the callback, then you are indeed testing against real data and real
Google behavior. I like the approach enough to be comfortable with it!
If the sprinters want to kick off a callback from PayPal, capture the
steps, and replay them in their test, I think that will be a huge step
forward. Thanks for this simplification!

Michael Dunstan

unread,
Nov 1, 2009, 10:31:13 PM11/1/09
to getpa...@googlegroups.com
On Mon, Nov 2, 2009 at 1:48 AM, Brandon Craig Rhodes
<bra...@rhodesmill.org> wrote:
>
> Michael Dunstan <michael...@gmail.com> writes:
>
>> The Google Checkout processor tests fabricate the incoming signals
>> from the checkout server...
>
> Well, that's an interesting idea!  At first it sounds like an
> unconvincing test, but I guess if the XML you injected in the test was
> actual real XML from Google that you'd captured during a by-hand test of
> the callback, then you are indeed testing against real data and real
> Google behavior.  I like the approach enough to be comfortable with it!
> If the sprinters want to kick off a callback from PayPal, capture the
> steps, and replay them in their test, I think that will be a huge step
> forward.  Thanks for this simplification!

Yeah - that's the same XML that would have come from Google Checkout.

Obviously if the XML from Google Checkout changes then the tests would
need to be updated.

There are some traceback supplements in the getpaid.googlecheckout
processor which log the received XML in the case of an error in the
wild. See TracebackSupplement and NotifyTracebackSupplement of
http://code.google.com/p/getpaid/source/browse/getpaid.googlecheckout/trunk/src/getpaid/googlecheckout/googlecheckout.py

That should help with the process of updating the tests if there is a
significant change in the XML from Google Checkout. Well - needs to be
a fatal enough error to cause an exception to be thrown.

(Unfortunately I don't see any tests for those traceback supplements.)

--
Michael Dunstan

Reply all
Reply to author
Forward
0 new messages