<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Mauro Rocco</title>
	<atom:link href="http://www.toforge.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.toforge.com</link>
	<description>Python, Django, Android, Linux/Ubuntu, PHP, Java Enterprise,</description>
	<lastBuildDate>Fri, 05 Apr 2013 07:54:57 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<item>
		<title>Celery centralized logging</title>
		<link>http://www.toforge.com/2011/06/celery-centralized-logging/</link>
		<comments>http://www.toforge.com/2011/06/celery-centralized-logging/#comments</comments>
		<pubDate>Mon, 27 Jun 2011 06:00:34 +0000</pubDate>
		<dc:creator>Mauro Rocco</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[celery]]></category>
		<category><![CDATA[logging]]></category>
		<category><![CDATA[rsyslog]]></category>

		<guid isPermaLink="false">http://www.toforge.com/?p=390</guid>
		<description><![CDATA[As someone of you that is already using celery already know extend the celery logger was a bit tricky until the last version, mainly because the logger object is not unique, the same handler is added to different logs object (Main Process logger, PoolWorker logger, TaskLogger). For this reason the command logging.getLogger(“Celery”) give you back [...]]]></description>
				<content:encoded><![CDATA[<p>As someone of you that is already using celery already know extend the celery logger was a bit tricky until the last version, mainly because the logger object is not unique, the same handler is added to different logs object (Main Process logger, PoolWorker logger, TaskLogger).<br />
For this reason the command logging.getLogger(“Celery”) give you back only the Main Process logger.<br />
From the version <a title="Celery 2.2.7" href="http://docs.celeryproject.org/en/latest/changelog.html#version-2-2-7" target="_blank">2.2.7</a> of Celery is possible to extend all the logs object by using two new signals <a href="http://docs.celeryproject.org/en/latest/reference/celery.signals.html#std:signal-after_setup_logger" target="_blank"><strong>after_setup_logger</strong></a> and <a href="http://docs.celeryproject.org/en/latest/reference/celery.signals.html#std:signal-after_setup_task_logger" target="_blank"><strong>after_setup_task_logger</strong></a>.</p>
<p><span id="more-390"></span>The following lines of code are all you need for have all celery workers logs on a syslog server</p>
<pre class="brush: python; title: ; notranslate">
import logging
from celery.signals import after_setup_logger, after_setup_task_logger

def after_setup_logger_handler(sender=None, logger=None, loglevel=None,
                               logfile=None, format=None,
                               colorize=None, **kwds):
    handler = logging.handlers.SysLogHandler(address=('syslogserver', 514))
    handler.setFormatter(logging.Formatter(format))
    handler.setLevel(logging.INFO)
    logger.addHandler(handler)

after_setup_logger.connect(after_setup_logger_handler)
after_setup_task_logger.connect(after_setup_logger_handler)
</pre>
<p>As you can see I added the same handler to bot signal, this because I need to add it to every task logger and to every global logger (Worker, Main Process).<br />
Just <strong>pay attention</strong> to don&#8217;t connect the handler to the signal more than one time or you will have duplicate logs, for this reason don&#8217;t put this code in a configuration file but in a separated module that you are sure is included only one time.<br />
Probably you want also to have a separated file for you celery logs on your rsyslog server, it&#8217;s enough to add a filter on the IP of your celery workers:</p>
<pre class="brush: bash; title: ; notranslate">
if $fromhost-ip startswith '192.0.2.' then /var/log/celery_central.log
&amp; ~
if $fromhost-ip startswith '192.0.3.' then /var/log/celery_central.log
&amp; ~
</pre>
<p>Don&#8217;t forget to put this rules before all the others and to enable the receiving of remote logs on your rsyslog confing file.<br />
Off course here I&#8217;m using a syslog handler but you can extend logs in many ways at the end is just Python <img src='http://www.toforge.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  .</p>
]]></content:encoded>
			<wfw:commentRss>http://www.toforge.com/2011/06/celery-centralized-logging/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Europython 2011: Playing tasks with Django Celery (Video and slides)</title>
		<link>http://www.toforge.com/2011/06/europython-2011-playing-tasks-with-django-celery-video-and-slides/</link>
		<comments>http://www.toforge.com/2011/06/europython-2011-playing-tasks-with-django-celery-video-and-slides/#comments</comments>
		<pubDate>Sat, 25 Jun 2011 12:07:39 +0000</pubDate>
		<dc:creator>Mauro Rocco</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[celery]]></category>
		<category><![CDATA[django-celery]]></category>
		<category><![CDATA[europython]]></category>
		<category><![CDATA[slide]]></category>
		<category><![CDATA[talk]]></category>

		<guid isPermaLink="false">http://www.toforge.com/?p=385</guid>
		<description><![CDATA[Video Europython 2011 &#8211; Playing tasks with Django &#038; Celery from Mauro Rocco on Vimeo. . Slides View more presentations from Mauro Rocco]]></description>
				<content:encoded><![CDATA[<h2>Video</h2>
<p><iframe src="http://player.vimeo.com/video/25588439?title=0&amp;byline=0&amp;portrait=0" width="400" height="300" frameborder="0" align="center"></iframe>
<p><a href="http://vimeo.com/25588439">Europython 2011 &#8211; Playing tasks with Django &#038; Celery</a> from <a href="http://vimeo.com/user7575358">Mauro Rocco</a> on <a href="http://vimeo.com">Vimeo</a>.</p>
<p>.</p>
<h2>Slides</h2>
<div style="width:425px;" id="__ss_8393190">
<iframe src="http://www.slideshare.net/slideshow/embed_code/8393190" width="425" height="355" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>
<div style="padding:5px 0 12px"> View more <a href="http://www.slideshare.net/">presentations</a> from <a href="http://www.slideshare.net/fireantology">Mauro Rocco</a> </div>
</p></div>
]]></content:encoded>
			<wfw:commentRss>http://www.toforge.com/2011/06/europython-2011-playing-tasks-with-django-celery-video-and-slides/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Boto Mturk Tutorial: Fetch results and pay workers</title>
		<link>http://www.toforge.com/2011/05/boto-mturk-tutorial-fetch-results-and-pay-workers/</link>
		<comments>http://www.toforge.com/2011/05/boto-mturk-tutorial-fetch-results-and-pay-workers/#comments</comments>
		<pubDate>Mon, 23 May 2011 06:00:50 +0000</pubDate>
		<dc:creator>Mauro Rocco</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[amazon]]></category>
		<category><![CDATA[amazon web services]]></category>
		<category><![CDATA[boto]]></category>
		<category><![CDATA[boto 2.0]]></category>
		<category><![CDATA[mturk]]></category>

		<guid isPermaLink="false">http://www.toforge.com/?p=368</guid>
		<description><![CDATA[This is another tutorial of the mturk series, in this one I will explain how to fetch the ready results from mturk trough python boto and how to approve or reject payments to the workers. Before continue I suggest you to read my first tutorial about boto and mturk if you didn&#8217;t it already. Well, [...]]]></description>
				<content:encoded><![CDATA[<p><img class="size-full wp-image-354 alignleft" title="mturk" src="http://www.toforge.com/wp-content/uploads/2011/04/mturk.png" alt="" width="200" height="140" align="left" /> This is another tutorial of the mturk series, in this one I will explain how to fetch the ready results from mturk trough python boto and how to approve or reject payments to the workers.<br />
Before continue I suggest you to read my <a title="Boto Mturk Create Hits" href="http://www.toforge.com/2011/04/boto-mturk-tutorial-create-hits/">first tutorial</a> about boto and mturk if you didn&#8217;t it already.</p>
<p>Well, before continuing for have a good test case I suggest you to publish some hits on the mturk sandbox and do it trough the <a href="https://workersandbox.mturk.com/">workers sandxbox</a>, in this way you will have some results ready to be fetched.<span id="more-368"></span><br />
The protagonist of this tutorial is the method <strong>get_reviewable_hits</strong>,</p>
<p><tt>get_reviewable_hits</tt><big>(</big><em>hit_type=None</em>, <em>status=&#8217;Reviewable&#8217;</em>, <em>sort_by=&#8217;Expiration&#8217;</em>, <em>sort_direction=&#8217;Ascending&#8217;</em>, <em>page_size=10</em>, <em>page_number=1</em><big>)</big></p>
<p>as you can<strong> </strong>understand by the name this method fetch the hits that have the status of &#8220;reviewable&#8221; or &#8220;reviewing&#8221; this means all the hits that have all assignments (Number of answer required from different workers) completed or that are expired.<br />
As you can also understand from parameters this method give you back by default just the first 10 reviewable hits, the maximum page size that you can have is 100, this means that if you have more than 100 hits ready you have to call this method more than one time with incremental page number.<br />
Well, the first thing that we do is write a method that fetches <strong>all</strong> reviewable hits, it accept as unique parameter an mturk connection object.</p>
<pre class="brush: python; title: ; notranslate">
def get_all_reviewable_hits(mtc):
    page_size = 50
    hits = mtc.get_reviewable_hits(page_size=page_size)
    print &quot;Total results to fetch %s &quot; % hits.TotalNumResults
    print &quot;Request hits page %i&quot; % 1
    total_pages = float(hits.TotalNumResults)/page_size
    int_total= int(total_pages)
    if(total_pages-int_total&gt;0):
        total_pages = int_total+1
    else:
        total_pages = int_total
    pn = 1
    while pn &lt; total_pages:
        pn = pn + 1
        print &quot;Request hits page %i&quot; % pn
        temp_hits = mtc.get_reviewable_hits(page_size=page_size,page_number=pn)
        hits.extend(temp_hits)
    return hits
</pre>
<p>The list of hits returned by the method is a list of boto HITS objects.<br />
This object doesn&#8217;t contain the assignments, you have to call another method for get the assignments of a particular HIT id.<br />
The next step is tho iterate trough this list and for each HIT calls the method <a href="http://boto.cloudhackers.com/ref/mturk.html#boto.mturk.connection.MTurkConnection.get_assignments" target="_blank">get_assignments(hit_id)</a></p>
<p>This method will return all the answers to your hits.<br />
Below the complete script for print to screen all the assignments of your hits.</p>
<pre class="brush: python; highlight: [36]; title: ; notranslate">
from boto.mturk.connection import MTurkConnection

ACCESS_ID ='your access id'
SECRET_KEY = 'your key'
HOST = 'mechanicalturk.sandbox.amazonaws.com'

def get_all_reviewable_hits(mtc):
    page_size = 50
    hits = mtc.get_reviewable_hits(page_size=page_size)
    print &quot;Total results to fetch %s &quot; % hits.TotalNumResults
    print &quot;Request hits page %i&quot; % 1
    total_pages = float(hits.TotalNumResults)/page_size
    int_total= int(total_pages)
    if(total_pages-int_total&gt;0):
        total_pages = int_total+1
    else:
        total_pages = int_total
    pn = 1
    while pn &lt; total_pages:
        pn = pn + 1
        print &quot;Request hits page %i&quot; % pn
        temp_hits = mtc.get_reviewable_hits(page_size=page_size,page_number=pn)
        hits.extend(temp_hits)
    return hits

mtc = MTurkConnection(aws_access_key_id=ACCESS_ID,
                      aws_secret_access_key=SECRET_KEY,
                      host=HOST)

hits = get_all_reviewable_hits(mtc)

for hit in hits:
    assignments = mtc.get_assignments(hit.HITId)
    for assignment in assignments:
        print &quot;Answers of the worker %s&quot; % assignment.WorkerId
        for question_form_answer in assignment.answers[0]:
            for key, value in question_form_answer.fields:
                print &quot;%s: %s&quot; % (key,value)
        print &quot;--------------------&quot;
</pre>
<p>As you can see the scripts call the get_assignments method for each hit id and after that iterate trough it for fetching the answers.<br />
In the line 36 you see an answer[0], maybe you are thinking &#8220;why don&#8217;t iterate trough all answers ?&#8221;<br />
For try to give a clear explanation first let&#8217;s give some definition thaw will be valid on the next rows.</p>
<ul>
<li>A &#8220;question form answer&#8221; is the single answer to a single question of your form.</li>
<li>An &#8220;answer&#8221; element is the set of all the &#8220;question form answer&#8221; of your QuestionForm</li>
<li>An &#8220;assignment&#8221; is the set of all the &#8220;answer<strong>s</strong>&#8221; of the same worker</li>
</ul>
<p>In practice each worker can give just 1 &#8220;answer&#8221; to the hit, for that the assignment will contain always just one &#8220;answer&#8221;.<br />
&#8220;answer<strong>s</strong>&#8221; element is just a  reflection of the xml structure, boto translate it as array of one  element.<br />
If this explanation has been clear, you just have to know which method use for accept and refuse payments to the workers.<br />
The operations of pay and refuse have do be done on the &#8220;assignments&#8221; unit, in fact they accept the assignment id as a parameter.</p>
<p><tt>approve_assignment</tt><big>(</big><em>assignment_id</em>, <em>feedback=None</em><big>)</big></p>
<p><tt>reject_assignment</tt><big>(</big><em>assignment_id</em>, <em>feedback=None</em><big>)</big></p>
<p>Both methods accept also a feedback string, this is the message that the workers will receive as explanation for the approved/rejected assignment, be kind <img src='http://www.toforge.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':-D' class='wp-smiley' />  .<br />
When you don&#8217;t need anymore an hits you can &#8220;delete&#8221; it from mturk by calling the method</p>
<p><tt>disable_hit</tt><big>(</big><em>hit_id</em>, <em>response_groups=None</em><big>)</big></p>
<p>I suggest you to read the <a href="http://boto.cloudhackers.com/ref/mturk.html#boto.mturk.connection.MTurkConnection.disable_hit" target="_blank">documentation</a> about disable_hit method.<br />
I leave you with an edited version of the loop that pay all workers and disable the hits.<br />
See you soon <img src='http://www.toforge.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<pre class="brush: python; title: ; notranslate">
for hit in hits:
    assignments = mtc.get_assignments(hit.HITId)
    for assignment in assignments:
        print &quot;Answers of the worker %s&quot; % assignment.WorkerId
        for question_form_answer in assignment.answers[0]:
            for key, value in question_form_answer.fields:
                print &quot;%s: %s&quot; % (key,value)
        mtc.approve_assignment(assignment.AssignmentId)
        print &quot;--------------------&quot;
    mtc.disable_hit(hit.HITId)
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.toforge.com/2011/05/boto-mturk-tutorial-fetch-results-and-pay-workers/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Boto Mturk Tutorial: Create hits</title>
		<link>http://www.toforge.com/2011/04/boto-mturk-tutorial-create-hits/</link>
		<comments>http://www.toforge.com/2011/04/boto-mturk-tutorial-create-hits/#comments</comments>
		<pubDate>Thu, 28 Apr 2011 18:21:56 +0000</pubDate>
		<dc:creator>Mauro Rocco</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[amazon]]></category>
		<category><![CDATA[amazon web services]]></category>
		<category><![CDATA[boto]]></category>
		<category><![CDATA[boto 2.0]]></category>
		<category><![CDATA[mturk]]></category>

		<guid isPermaLink="false">http://www.toforge.com/?p=321</guid>
		<description><![CDATA[This tutorial will be the first of many about mturk and Boto, a python interface to Amazon Web Services . When I started to develop python tasks for automate some process by using amazon mturk was a little bit difficult found enough information about the usage of Boto and about mturk, for this reason I [...]]]></description>
				<content:encoded><![CDATA[<p><img class="size-full wp-image-354 alignleft" title="mturk" src="http://www.toforge.com/wp-content/uploads/2011/04/mturk.png" alt="" width="200" height="140" align="left" />This tutorial will be the first of many about <strong>mturk</strong> and <strong>Boto, </strong>a python interface to Amazon Web Services<strong> </strong>.<br />
When I started to develop python tasks for automate some process by using amazon mturk was a little bit difficult found enough information about the usage of Boto and about mturk, for this reason I want to make those things easy for others developers that, like me some time ago, are starting to deal with Amazon Mturk.<br />
Let&#8217;s start from the origins what you need is:</p>
<p><strong>Boto library (2.0b4):</strong> you can install it with easy_install or download the package from the <a title="Boto" href="https://github.com/boto/boto" target="_blank">github page</a>.<br />
<strong>Amazon Web Services keys</strong>: create an account or login if you already have one on <a href="http://aws.amazon.com/">aws.amazon.com</a>, after that go to you account admin panel and than security settings.<br />
In the page scroll to the section Access credentials and keep note of the <strong>Access Key ID</strong> and <strong>Secret Access Key</strong>.</p>
<p><span id="more-321"></span>We are almost ready for use this keys with Boto but before that we have to login with the aws account on <a title="Amazon Mturk Sandbox" href="https://requestersandbox.mturk.com/" target="_blank">https://requestersandbox.mturk.com/</a> for create the Mturk Sandbox account.</p>
<p>Ok, now we can start to write some code for test if our keys work and if we can connect to the Mturk engine.<br />
Below there is the code for connect to the mturk api and get the account balance.</p>
<pre class="brush: python; title: ; notranslate">
from boto.mturk.connection import MTurkConnection

ACCESS_ID ='your access key'
SECRET_KEY = 'your secret key'
HOST = 'mechanicalturk.sandbox.amazonaws.com'

mtc = MTurkConnection(aws_access_key_id=ACCESS_ID,
                      aws_secret_access_key=SECRET_KEY,
                      host=HOST)

print mtc.get_account_balance()
</pre>
<p>The expected result is a list with one value, normally $10,000.00 (I never see numbers like this on my bank account <img src='http://www.toforge.com/wp-includes/images/smilies/icon_sad.gif' alt=':-(' class='wp-smiley' />  )</p>
<p>If everything works fine we can start to create an mturk HIT.<br />
Basically an HIT is a question, or a collection of questions. I strongly suggest you to read the <a title="Mturk HIT structure" href="http://docs.amazonwebservices.com/AWSMechTurk/latest/AWSMturkAPI/index.html?ApiReference_HITDataStructureArticle.html" target="_blank">HIT Data Structure</a> before continue with this tutorial.</p>
<p>Let&#8217;s start to create our first HIT with 2 questions:<br />
1 mandatory with choices and another one not mandatory with a free text answer.</p>
<pre class="brush: python; title: ; notranslate">
from boto.mturk.connection import MTurkConnection
from boto.mturk.question import QuestionContent,Question,QuestionForm,
Overview,AnswerSpecification,SelectionAnswer,FormattedContent,FreeTextAnswer

ACCESS_ID ='your acces key'
SECRET_KEY = 'your secret key'
HOST = 'mechanicalturk.sandbox.amazonaws.com'

mtc = MTurkConnection(aws_access_key_id=ACCESS_ID,
                      aws_secret_access_key=SECRET_KEY,
                      host=HOST)

title = 'Give your opinion about a website'
description = ('Visit a website and give us your opinion about'
               ' the design and also some personal comments')
keywords = 'website, rating, opinions'

ratings =[('Very Bad','-2'),
         ('Bad','-1'),
         ('Not bad','0'),
         ('Good','1'),
         ('Very Good','1')]

#---------------  BUILD OVERVIEW -------------------

overview = Overview()
overview.append_field('Title', 'Give your opinion on this website')
overview.append(FormattedContent('&lt;a target=&quot;_blank&quot;'
                                 ' href=&quot;http://www.toforge.com&quot;&gt;'
                                 ' Mauro Rocco Personal Forge&lt;/a&gt;'))

#---------------  BUILD QUESTION 1 -------------------

qc1 = QuestionContent()
qc1.append_field('Title','How looks the design ?')

fta1 = SelectionAnswer(min=1, max=1,style='dropdown',
                      selections=ratings,
                      type='text',
                      other=False)

q1 = Question(identifier='design',
              content=qc1,
              answer_spec=AnswerSpecification(fta1),
              is_required=True)

#---------------  BUILD QUESTION 2 -------------------

qc2 = QuestionContent()
qc2.append_field('Title','Your personal comments')

fta2 = FreeTextAnswer()

q2 = Question(identifier=&quot;comments&quot;,
              content=qc2,
              answer_spec=AnswerSpecification(fta2))

#--------------- BUILD THE QUESTION FORM -------------------

question_form = QuestionForm()
question_form.append(overview)
question_form.append(q1)
question_form.append(q2)

#--------------- CREATE THE HIT -------------------

mtc.create_hit(questions=question_form,
               max_assignments=1,
               title=title,
               description=description,
               keywords=keywords,
               duration = 60*5,
               reward=0.05)
</pre>
<p>If you don&#8217;t see any output everything worked well, for be sure navigate to <a href="https://workersandbox.mturk.com/" target="_blank">https://workersandbox.mturk.com/</a> and see if your hit is in the list (can take some time to appear, you can also check on the requester sandbox admin panel).<br />
The code is very clear and self explained but I will give you anyway some description with links to the Boto DOCS.</p>
<p><strong>Overview</strong>: The overview is a free content of the question form, this means that can be everything (binary content, an html content, ex.), remember that it isn&#8217;t a &#8220;question object&#8221; is just an arbitrary content, in my example is a link to the website.<br />
<a title="Overview docs" href="http://boto.cloudhackers.com/ref/mturk.html#boto.mturk.question.Overview" target="_blank">http://boto.cloudhackers.com/ref/mturk.html#boto.mturk.question.Overview</a></p>
<p><strong>Question:</strong> The question is mainly made by the AnswerSpecification object, that specify which kind of answer have to be rendered for the question and by the QuestionContent object. The content can be, like for the Overview, a text, a binary content, an html content, ex.<br />
<a href="http://boto.cloudhackers.com/ref/mturk.html#boto.mturk.question.Question" target="_blank">http://boto.cloudhackers.com/ref/mturk.html#boto.mturk.question.Question</a><br />
<a href="http://boto.cloudhackers.com/ref/mturk.html#boto.mturk.question.AnswerSpecification" target="_blank">http://boto.cloudhackers.com/ref/mturk.html#boto.mturk.question.AnswerSpecification</a><br />
<a href="http://boto.cloudhackers.com/ref/mturk.html#boto.mturk.question.QuestionContent" target="_blank">http://boto.cloudhackers.com/ref/mturk.html#boto.mturk.question.QuestionContent</a></p>
<p><strong>QuestionForm:</strong> This is the container for all your questions and overviews, basically is an extension of a python standard list.<br />
<a href="http://boto.cloudhackers.com/ref/mturk.html#boto.mturk.question.QuestionForm" target="_blank">http://boto.cloudhackers.com/ref/mturk.html#boto.mturk.question.QuestionForm</a></p>
<p><strong>create_hit method: </strong>This is the method for create an hits, for see which parameters it accepts take a look to the docs.<br />
A little suggestion, the <strong>question</strong> and <strong>questions</strong> parameters are different, the first one accept a Question object if you want to create a hit with just a question, the second one accept a QuestionForm.<br />
<a href="http://boto.cloudhackers.com/ref/mturk.html#boto.mturk.connection.MTurkConnection.create_hit" target="_blank">http://boto.cloudhackers.com/ref/mturk.html#boto.mturk.connection.MTurkConnection.create_hit</a></p>
<p>Well, now you should be able to create an hit, you can also do your hits on the worker sandbox for see how they works and for have some results to fetch.<br />
In the next tutorial I will speak about fetching result from your hits and accept or refuse payments to the workers.<br />
See you soon <img src='http://www.toforge.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.toforge.com/2011/04/boto-mturk-tutorial-create-hits/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>History Timeline wp plugin: now it support before Christ dates</title>
		<link>http://www.toforge.com/2011/03/history-timeline-wp-plugin-now-it-support-before-christ-dates/</link>
		<comments>http://www.toforge.com/2011/03/history-timeline-wp-plugin-now-it-support-before-christ-dates/#comments</comments>
		<pubDate>Sun, 06 Mar 2011 16:26:08 +0000</pubDate>
		<dc:creator>Mauro Rocco</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[history]]></category>
		<category><![CDATA[timeline]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://www.toforge.com/?p=303</guid>
		<description><![CDATA[Hi all, today I finally release the new version of my history timeline plugin. I understand that a plug-in called &#8220;History timeline&#8221; have to allow you to use before Christ date too, I know, I&#8217;m a little bit in late but now is published the version 0.7 that give you also more option for post [...]]]></description>
				<content:encoded><![CDATA[<p>Hi all, today I finally release the new version of my history timeline plugin.<br />
I understand that a plug-in called &#8220;History timeline&#8221; have to allow you to use before Christ date too, I know, I&#8217;m a little bit in late but now is published the version 0.7 that give you also more option for post discrimination.<br />
Here a list of functionalities<span id="more-303"></span></p>
<ul>
<li>Support for before Christ dates.</li>
<li>Set a custom before and after Christ suffix string</li>
<li>Build the timeline only with posts from one or more categories.</li>
<li>Exclude single posts or pages from the timeline.</li>
<li>Choose the date input format with a dropdown menu.</li>
<li>Choose the output format of the date and the timeline order.</li>
<li>The CSS is customizable from the admin area of the plugin.</li>
</ul>
<p>Download it and enjoy, for any problem or bug report don&#8217;t hesitate to contact me.<br />
You can download the plugin from here:<br />
<a href="http://historytimeline.toforge.com">http://historytimeline.toforge.com</a></p>
<p>I think that for the next release, after some bug-fix, I will implement a JQuery look and feel too.<br />
If you have some additional idea just write a comment.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.toforge.com/2011/03/history-timeline-wp-plugin-now-it-support-before-christ-dates/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A simple python sandbox for Celery and not</title>
		<link>http://www.toforge.com/2011/02/a-simple-python-sandbox-for-celery-and-not/</link>
		<comments>http://www.toforge.com/2011/02/a-simple-python-sandbox-for-celery-and-not/#comments</comments>
		<pubDate>Sat, 26 Feb 2011 12:35:12 +0000</pubDate>
		<dc:creator>Mauro Rocco</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[celery]]></category>
		<category><![CDATA[django-celery]]></category>
		<category><![CDATA[download url]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[sandbox]]></category>
		<category><![CDATA[tasks]]></category>

		<guid isPermaLink="false">http://www.toforge.com/?p=272</guid>
		<description><![CDATA[At the end of this post you will find the source code of a python sandbox that I write for have a general sandbox that work for all my celery tasks. Anyway this is a general python code and you can use it also without Celery but here I will give you also some example [...]]]></description>
				<content:encoded><![CDATA[<p>At the end of this post you will find the source code of a python sandbox that I write for have a general sandbox that work for all my celery tasks.<br />
Anyway this is a general python code and you can use it also without Celery but here I will give you also some example to how to use it in easy and fast way with Celery.<span id="more-272"></span></p>
<p>The sandbox is wrote as a Context Manager (under suggestion of <a href="http://twitter.com/#!/asksol/" target="_blank">asksol</a> <img src='http://www.toforge.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  ) with an entry point that will create the folders and an exit point that will clean it.<br />
The class create a folder structure like this:</p>
<p><em>/sandboxradix/tasks.mytask.dosomething/taskpid/</em></p>
<p>On the exit point only the taskpid folder will be erased, in this way you can launch several tasks of the same type at the same time<br />
Let&#8217;s see how you can use it for you celery task.</p>
<p>In my personal opinion the best way to do it is to create a base class for all your tasks that extend the celery task class and inside it implement some general useful methods like the sandbox behaviour.<br />
Following you can see an example of a general base class that use my sandbox context manager.</p>
<pre class="brush: python; title: ; notranslate">
import settings
from celery.task import Task
from sandBox import SandBox

class toforgeTask(Task):

    def __call__(self, *args, **kwargs):
        &quot;&quot;&quot;In celery task this function call the run method, here you can
        set some environment variable before the run of the task&quot;&quot;&quot;

        self.sandbox = SandBox(self.name, self.request.id,
                               settings.PATH_SANDBOX)
        return self.run(*args, **kwargs)

    def after_return(self, status, retval, task_id, args, kwargs, einfo):
        #: If the sandbox is initialized we clean it
        if self.sandbox.isInitialized():
            self.sandbox.__exit__()

    def run(self):
        return &quot;This is a Base Task Class not runnable&quot;
</pre>
<p>As you can read on the comments the __call__ method is called before the task execution.<br />
Here we call the constructor of our sanbox but we don&#8217;t initialize it because maybe not all our tasks needs sandbox <img src='http://www.toforge.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  .<br />
For the same reason in the method after_return, called form celery at the end of a task whatever is the status (RETRY,FAILURE, ecc.), we will clean the sandbox only if we used it.<br />
The settings module that you see in my general task is the django settings that I use for store conf vars from my task like the PATH_SANDBOX the radix folder for your sandbox.</p>
<p>Now you can write a task by extend the base task that we created and maybe it will look like this</p>
<pre class="brush: python; title: ; notranslate">
from toforgeTask import toforgeTask

class sampleDownloader(toforgeTask):

    def run(self, album_id, **kwargs):
        self.logger.info(&quot;Download a test file %s &quot; % (album_id))

        #: initialize tha sanbox
        self.sandbox.__enter__()

        #: download a file
        self.writeFileFromUrl(self,&quot;http://www.toforge.com/notexistfile.zip&quot;,
                              &quot;myfile&quot;)

        #: do some stuff with the file in the sandbox
        #: you can open files in the standard way just use
        #: the self.sandbox.path variable

        return &quot;&quot;&quot;File downloaded, but you will not found it because at the
               end of the task the sandbox will be cleaned&quot;&quot;&quot;
</pre>
<p>Following you can see the source code of the protagonist of this post, the sandBox.py file.</p>
<pre class="brush: python; title: ; notranslate">
import errno
import os
import shutil
import urllib2

class SandBox(object):
    &quot;&quot;&quot;A simple sandbox context manager for easy create and clean of a
    sandbox folder plus some useful methods for file download and write

    Mauro Rocco

http://www.toforge.com

    &quot;&quot;&quot;

    def __init__(self, name, id, prefix, debug = False):

        #: name of the folder, commonly the name of the task
        self.name = name

        #: pid of the task, the name of the end folder where the sandbox
        #: writes the files
        self.id = id

        #: the base path for your sandbox
        self.prefix = prefix

        #: te complete path used in the context
        self.path = None

        #: debug option for print some output information
        self.debug = debug

    def __enter__(self):
        self.path = os.path.join(self.prefix, self.name, self.id)

        try:
            os.makedirs(self.path)
        except OSError, exc:
            if exc.errno != errno.EEXIST:
                raise

        return self

    def __exit__(self, *exc_info):
        try:
            shutil.rmtree(self.path)
        except OSError, exc:
            if exc.errno != errno.ENOENT:
                raise

    def _debugPrint(self,message):
        if self.debug:
            print message

    def _createFile(self, fileName, mode, override = False):
        if not self.isInitialized():
            self.__enter__()

        if override:
            return open(os.path.join(self.path,fileName), mode)
        try:
            open(os.path.join(self.path,fileName))
        except IOError, exc:
            if exc.errno == errno.ENOENT:
                return open(os.path.join(self.path,fileName), mode)
            raise
        raise Exception(&quot;File already exist in sandbox: %s &quot;
                        % (os.path.join(self.path,fileName)))

    def isInitialized(self):
        &quot;&quot;&quot;Check if the sandbox is initialized&quot;&quot;&quot;
        if self.path:
            return True
        return False

    def getSandboxContent(self):
        &quot;&quot;&quot;Return a list of all folders and files
        in the current sandbox folder&quot;&quot;&quot;
        if not self.isInitialized():
            self.__enter__()
        tree = []
        for dirname, dirnames, filenames in os.walk(self.path):
            for subdirname in dirnames:
                tree.append(os.path.join(dirname, subdirname))
            for filename in filenames:
                tree.append(os.path.join(dirname, filename))
        return tree

    def writeFile(self,content, fileName, mode = &quot;w&quot;, override = False):
        &quot;&quot;&quot;write a file in the sandbox folder&quot;&quot;&quot;
        f = self._createFile(fileName, mode, override)
        f.write(str(content))
        f.close()

    def writeFileFromUrl(self,url,fileName, override = False, httpproxy=None,
                         ftpproxy=None, gopherproxy=None):
        &quot;&quot;&quot;Download a file from the given url  and write it
         on the sandbox with the given name&quot;&quot;&quot;
        proxies={}

        if httpproxy:
            proxies[&quot;http&quot;]=httpproxy

        if ftpproxy:
            proxies[&quot;ftp&quot;]=ftpproxy

        if gopherproxy:
            proxies[&quot;gopher&quot;]=gopherproxy

        outfile=self._createFile(fileName, &quot;wb&quot;, override)

        proxy = urllib2.ProxyHandler(proxies)
        opener = urllib2.build_opener(proxy)
        urllib2.install_opener(opener)

        instream = urllib2.urlopen(url)
        length = instream.info().getheader(&quot;Content-Length&quot;)

        if length==None:
            length=&quot;?&quot;

        self._debugPrint(&quot;Downloading %s (%s bytes) ...&quot;
                         % (instream.url, length))

        bytesRead=0.0

        for line in instream:
            bytesRead+=len(line)
            outfile.write(line)

            if length!=&quot;?&quot;:
                self._debugPrint(&quot;Downloading... %.02f/%.02f kb (%d%%)&quot;
                                 % (fileName,
                                    bytesRead/1024.0,
                                    length/1024.0,
                                    100*bytesRead/length))

        instream.close()
        outfile.close()
        self._debugPrint(&quot;File downloaded successful&quot;)
</pre>
<p>Enjoy <img src='http://www.toforge.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.toforge.com/2011/02/a-simple-python-sandbox-for-celery-and-not/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Sony VAIO brightness control script for Ubuntu (Geforce cards)</title>
		<link>http://www.toforge.com/2011/02/sony-vaio-brightness-control-script-for-ubuntu-geforce-cards/</link>
		<comments>http://www.toforge.com/2011/02/sony-vaio-brightness-control-script-for-ubuntu-geforce-cards/#comments</comments>
		<pubDate>Wed, 09 Feb 2011 21:56:50 +0000</pubDate>
		<dc:creator>Mauro Rocco</dc:creator>
				<category><![CDATA[Bash scripting]]></category>
		<category><![CDATA[bash scripting]]></category>
		<category><![CDATA[sony vaio]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://www.toforge.com/?p=246</guid>
		<description><![CDATA[This evening I want to share with you this little script that I wrote for my personal use. This script need the module &#8220;smartdimmer&#8221; (Change LCD brightness on Geforce cards), you can found it on the Ubuntu repository, than it&#8217;s enough to write on console For test if the module works just try to set [...]]]></description>
				<content:encoded><![CDATA[<p>This evening I want to share with you this little script that I wrote for my personal use.<br />
This script need the module &#8220;smartdimmer&#8221; (Change LCD brightness on Geforce cards), you can found it on the Ubuntu repository, than it&#8217;s enough to write on console</p>
<pre class="brush: bash; title: ; notranslate">$ sudo apt-get smartdimmer</pre>
<p>For test if the module works just try to set a new brightness value by typing</p>
<pre class="brush: bash; title: ; notranslate">$ smartdimmer -s 50</pre>
<p>If the module works for your laptop you can use the following script for change brightness directly from your keyboard.</p>
<p><span id="more-246"></span><br />
File: <strong>brightness.sh</strong></p>
<pre class="brush: bash; title: ; notranslate">
#!/bin/bash
maxbrightness=95
curbrightness=$(smartdimmer --get | grep -o [0-9][0-9][0-9]*)
let brightness=$curbrightness
let factor=5

if [ $# -gt 0 ]; then
 if [ $1 = &quot;+&quot; ]; then
 if [ $curbrightness -lt $maxbrightness ]; then
 let brightness=$brightness+$factor;
 fi
 fi

 if [ $1 = &quot;-&quot; ]; then
 if [ $curbrightness -gt 20 ]; then
 let brightness=$brightness-$factor;
 fi
 fi
fi

smartdimmer --set $brightness
</pre>
<p>Now put this script in your home directory and use the tool <strong>Preferences -&gt; Keyboard Shortcut</strong> for associate the preferred keys to the following commands.</p>
<p><strong>Increase brightness:</strong> brightness.sh +<br />
<strong>Decrease brightness:</strong> brightness.sh -</p>
]]></content:encoded>
			<wfw:commentRss>http://www.toforge.com/2011/02/sony-vaio-brightness-control-script-for-ubuntu-geforce-cards/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Phonegap android plugin for download files from url on sd card</title>
		<link>http://www.toforge.com/2011/02/phonegap-android-plugin-for-download-files-from-url-on-sd-card/</link>
		<comments>http://www.toforge.com/2011/02/phonegap-android-plugin-for-download-files-from-url-on-sd-card/#comments</comments>
		<pubDate>Wed, 02 Feb 2011 20:32:43 +0000</pubDate>
		<dc:creator>Mauro Rocco</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[download url]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[phonegap]]></category>
		<category><![CDATA[phonegap android plugins]]></category>

		<guid isPermaLink="false">http://www.toforge.com/?p=216</guid>
		<description><![CDATA[[UPDATE] You can found an updated version of my plugin on GitHub Thanks to Phillip Neumann. &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212; Hi folks, today I want to share with you this very useful phonegap&#8216;s plug-in. As the title says this plug-in allow you to download a file (url) on the sd card in the folder of your choice. Usage [...]]]></description>
				<content:encoded><![CDATA[<p><img class="alignleft size-thumbnail wp-image-236" title="PhoneGap" src="http://www.toforge.com/wp-content/uploads/2011/02/phonegap-150x150.jpg" alt="" width="150" height="150" /><strong>[UPDATE]</strong><br />
You can found an updated version of my plugin on <a href="https://github.com/purplecabbage/phonegap-plugins/tree/master/Android/Downloader">GitHub</a><br />
Thanks to <a href="https://twitter.com/killfil">Phillip Neumann</a>.<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</p>
<p>Hi folks, today I want to share with you this very useful <a title="PhoneGap" href="http://www.phonegap.com" target="_blank">phonegap</a>&#8216;s plug-in.<br />
As the title says this plug-in allow you to download a file (url) on the sd card in the folder of your choice.<br />
<span id="more-216"></span></p>
<h1>Usage</h1>
<p>downloader.downloadFile(fileUrl,dirName,fileName,overwrite,win,fail);</p>
<h2>Params</h2>
<p><strong>fileUrl:</strong> &lt;String&gt; The url of the file to download<br />
<strong>dirName: </strong>&lt;String&gt; The directory where you want to save the file<br />
<strong>fileName:</strong> &lt;String&gt; The name of the file<br />
<strong>overwrite:</strong> &lt;Boolean&gt; Overwrite the file if exist<br />
<strong>win: </strong>&lt;Function&gt; Success callback function. Receive a parameter that contains the fileName if the file is wrote with success.  If the overwrite parameter is false and the file already exist the parameter will contain the string &#8220;exist&#8221;.<br />
<strong>fail: </strong>&lt;Function&gt; Fail callback function. Receive a parameter that contains the error message</p>
<h1>Source and installation</h1>
<p>Like all phonegap android plugins is composed by tha java file and the javascript one.<br />
For starting using this plugin first copy the java file into the java src folder of your android project, in my example  the package is called <strong>com.example.pgplugins.DownloaderPlugin</strong>.</p>
<p>File: <strong>Downloader.java</strong></p>
<pre class="brush: java; title: ; notranslate">
package com.example.pgplugins.downloaderPlugin;

/*
 @author Mauro Rocco http://www.toforge.com
*/

import org.json.JSONArray;
import org.json.JSONException;

import android.util.Log;

import com.phonegap.DroidGap;
import com.phonegap.api.Plugin;
import com.phonegap.api.PluginResult;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class Downloader extends Plugin{

 @Override
 public PluginResult execute(String action, JSONArray args, String callbackId) {
 if (action.equals(&quot;downloadFile&quot;)) {
 try {
 return this.downloadUrl(args.getString(0),args.getString(1),args.getString(2),args.getString(3));
 } catch (JSONException e) {
 return new PluginResult(PluginResult.Status.ERROR, &quot;Param errrors&quot;);
 }
 }
 else {
 return new PluginResult(PluginResult.Status.INVALID_ACTION);
 }

 }

 private PluginResult downloadUrl(String fileUrl, String dirName, String fileName, String overwrite){
 try{
 Log.d(&quot;DownloaderPlugin&quot;, &quot;DIRECTORY CALLED /sdcard/&quot;+dirName+&quot; created&quot;);
 File dir =     new File(&quot;/sdcard/&quot;+dirName);
 if(!dir.exists()){
 Log.d(&quot;DownloaderPlugin&quot;, &quot;directory /sdcard/&quot;+dirName+&quot; created&quot;);
 dir.mkdirs();
 }

 File file = new File(&quot;/sdcard/&quot;+dirName+fileName);

 if(overwrite.equals(&quot;false&quot;) &amp;&amp; file.exists()){
 Log.d(&quot;DownloaderPlugin&quot;, &quot;File already exist&quot;);
 return new PluginResult(PluginResult.Status.OK, &quot;exist&quot;);
 }

 URL url = new URL(fileUrl);
 HttpURLConnection ucon = (HttpURLConnection) url.openConnection();
 ucon.setRequestMethod(&quot;GET&quot;);
 ucon.setDoOutput(true);
 ucon.connect();

 Log.d(&quot;DownloaderPlugin&quot;, &quot;download begining&quot;);

 Log.d(&quot;DownloaderPlugin&quot;, &quot;download url:&quot; + url);

 InputStream is = ucon.getInputStream();

 byte[] buffer = new byte[1024];

 int len1 = 0;

 FileOutputStream fos = new FileOutputStream(file);

 while ( (len1 = is.read(buffer)) &gt; 0 ) {
 fos.write(buffer,0, len1);
 }

 fos.close();

 Log.d(&quot;DownloaderPlugin&quot;, &quot;Download complete in&quot; + fileName);

 } catch (IOException e) {

 Log.d(&quot;DownloaderPlugin&quot;, &quot;Error: &quot; + e);
 return new PluginResult(PluginResult.Status.ERROR, &quot;Error: &quot; + e);

 }

 return new PluginResult(PluginResult.Status.OK, fileName);

 }

}
</pre>
<p>Now copy the following javascript file in the <strong>assets/www</strong> folder, remember to change the name of the package or the js will never found the java file.</p>
<p>File: <strong>downloader.js</strong></p>
<pre class="brush: jscript; title: ; notranslate">
function Downloader() {

}

Downloader.prototype.downloadFile = function(fileUrl,dirName,fileName,overwrite,win,fail) {
 if(overwrite==false) overwrite=&quot;false&quot;;
 else overwrite=&quot;true&quot;;
 PhoneGap.exec(win, fail, &quot;Downloader&quot;, &quot;downloadFile&quot;, [fileUrl,dirName,fileName,overwrite]);

};

PhoneGap.addConstructor(function() {
 PhoneGap.addPlugin(&quot;downloader&quot;, new Downloader());
 PluginManager.addService(&quot;Downloader&quot;,&quot;com.example.pgplugins.downloaderPlugin.Downloader&quot;);
});

</pre>
<p>For use it you have only to include the js file in the page and call it in this way</p>
<pre class="brush: jscript; title: ; notranslate">
&lt;script type=&quot;text/javascript&quot; charset=&quot;utf-8&quot; src=&quot;downloader.js&quot;&gt;&lt;/script&gt;
 &lt;script type=&quot;text/javascript&quot;&gt;

 window.plugins.downloader.downloadFile(&quot;http://www.toforge.com/archive.zip&quot;,&quot;sdcard/cache/&quot;,&quot;archive.zip&quot;, false,
 function(data){
 if(data==&quot;exist&quot;){
 alert(&quot;File already exist&quot;);
 }
 else{
 alert(&quot;File saved on sd card&quot;)
 }
 },function(data){ alert(&quot;error: &quot;+data); });

 &lt;/script&gt;
</pre>
<p>If you like it please jut say me &#8220;thanks&#8221; or send me 100000 € <img src='http://www.toforge.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':-D' class='wp-smiley' />  .<br />
See you on the next post</p>
]]></content:encoded>
			<wfw:commentRss>http://www.toforge.com/2011/02/phonegap-android-plugin-for-download-files-from-url-on-sd-card/feed/</wfw:commentRss>
		<slash:comments>79</slash:comments>
		</item>
		<item>
		<title>Run Celery tasks from PHP</title>
		<link>http://www.toforge.com/2011/01/run-celery-tasks-from-php/</link>
		<comments>http://www.toforge.com/2011/01/run-celery-tasks-from-php/#comments</comments>
		<pubDate>Sun, 30 Jan 2011 15:57:55 +0000</pubDate>
		<dc:creator>Mauro Rocco</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[amq]]></category>
		<category><![CDATA[celery]]></category>
		<category><![CDATA[english]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[rabbit mq]]></category>
		<category><![CDATA[task queue]]></category>

		<guid isPermaLink="false">http://www.toforge.com/?p=204</guid>
		<description><![CDATA[If you are reading this article probably you already know what is Celery but for who think that it is something to eat I will give you a definition. Celery is an asynchronous task queue/job queue based on distributed message passing developed in python. If your using Celery for your back-office tasks will be very [...]]]></description>
				<content:encoded><![CDATA[<p>If you are reading this article probably you already know what is Celery but for who think that it is something to eat I will give you a definition.<br />
<a title="Celery" href="http://www.celeryproject.org/" target="_blank">Celery</a> is an asynchronous task queue/job queue based on distributed message passing developed in python.</p>
<p>If your using Celery for your back-office tasks will be very nice to run some tasks after an action performed on the front end of your web site, like an user action.<br />
If your web front end is wrote in PHP there is an easy and useful way for do it trough <a title="Rabbit MQ" href="http://www.rabbitmq.com/" target="_blank">Rabbit MQ</a>, the message broker used by celery.<span id="more-204"></span><br />
What we can do is simply put a message, that Celery workers can consume, in Rabbit MQ trough a pure AMQ PHP library called AMQPHP <img src='http://www.toforge.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  .<br />
You can download this implementation of the AMQ 0.9.1 protocol from the <a title="AMQPHP" href="https://github.com/BraveSirRobin/amqphp" target="_blank">gitHub project&#8217;s page</a>.</p>
<p>Follow the instruction for generate the code in the readme file and simply include it  in your project.</p>
<p>When you are sure that the library works and is able to publish message on Rabbit MQ you can use the class provided at the end on this post for put message on the broker ready for be consumed from celery workers.<br />
This class offer a method called <em>runCeleryTask($task,$arguments)</em> that allow you to run a specific registered task with N arguments.<br />
If I have a celery registered task called <em>package.exampleTask.dojob</em> that accept a string and an Integer I can schedule it in this way</p>
<pre class="brush: php; title: ; notranslate">$taskRunner = new TaskRunner($ini_string);
$taskRunner-&gt;runCeleryTask(&quot;package.exampleTask.dojob&quot;,&quot;string&quot;,1);</pre>
<p>The $ini_string variable contains the configuration for the connection to the broker, a possible string of configuration looks like this</p>
<p>host=localhost<br />
port=5672<br />
username=testing<br />
userpass=tock<br />
vhost=mauro<br />
exchange=celery<br />
exchangeType=direct<br />
queueName=celery</p>
<p>Here is the class that do the &#8220;Dirty Job&#8221; is quite easy and simple, I hope that this could help someone.<br />
You don&#8217;t need to declare exchange and queue again, this are supposed to be already declared by celery.</p>
<pre class="brush: php; title: ; notranslate">&lt;?php

use amqp_091 as amqp;
use amqp_091\protocol;
use amqp_091\wire;

include &quot;amqphp/amqp.php&quot;;

class TaskRunner {
/** Instance of amqp\Connection */
private  $conn;
/** Instance of amqp\Channel */
private  $chan;
/** Name of  exchange */
private  $exchange;
/** Type of  exchange */
private  $exchangeType;
/** Name of  queue */
private  $queueName;

function  __construct($ini_string){
$sParams = parse_ini_string($ini_string);
if (! $sParams) {
throw new Exception(&quot;Failed to find broker settings&quot;, 9854);
}
$this-&gt;exchange = $sParams['exchange'];
$this-&gt;queueName = $sParams['queueName'];
$this-&gt;exchangeType = $sParams['exchangeType'];

$this-&gt;conn = new amqp\Connection($sParams);
}

private function openConnection(){
if ($this-&gt;conn) $this-&gt;conn-&gt;connect();
}

private function closeConnection () {
if ($this-&gt;conn) $this-&gt;conn-&gt;shutdown();
}

function runCeleryTask($task,$arguments){
if (!is_array($arguments)){
throw new Exception(&quot;The second parameter of the function runTask() must be an array&quot;);
}

$this-&gt;openConnection();
$chan = $this-&gt;conn-&gt;getChannel();

//Publish the message
$basicP = $chan-&gt;basic('publish', array('content-type' =&gt; 'application/json',
'content-encoding' =&gt; 'UTF-8',
'routing-key' =&gt; 'celery',
'mandatory' =&gt; false,
'immediate' =&gt; false,
'exchange' =&gt; $this-&gt;exchange));

$basicP-&gt;setContent('{&quot;id&quot;:&quot;'.uniqid('php_').'&quot;,
&quot;task&quot;: &quot;'.$task.'&quot;,
&quot;args&quot;: ['.'&quot;'.implode('&quot;,&quot;',$arguments).'&quot;'.'],
&quot;kwargs&quot;: {}}');

$chan-&gt;invoke($basicP);

$this-&gt;closeConnection();
}

}

?&gt;</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.toforge.com/2011/01/run-celery-tasks-from-php/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Installare e configurare PtwiX – un client web per twitter</title>
		<link>http://www.toforge.com/2009/07/installare-e-configurare-ptwix-un-client-web-per-twitter/</link>
		<comments>http://www.toforge.com/2009/07/installare-e-configurare-ptwix-un-client-web-per-twitter/#comments</comments>
		<pubDate>Tue, 07 Jul 2009 05:11:29 +0000</pubDate>
		<dc:creator>Mauro Rocco</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[client]]></category>
		<category><![CDATA[italian]]></category>
		<category><![CDATA[ptwix]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://www.rmhomepages.com/blog/?p=142</guid>
		<description><![CDATA[UPDATE Febbraio 2011: Questa guida non e&#8217; piu&#8217; valida dopo la release della versione 2.0rc1, fate riferimento alla guida originale sul sito del componente. http://ptwix.toforge.com/index.php?p=install Ptwix è un componente da me creato per visualizzare la timeline del tuo account twitter direttamente sul tuo sito. E&#8217; scritto in PHP ed usa AJAX per effettuare un update [...]]]></description>
				<content:encoded><![CDATA[<p><strong>UPDATE Febbraio 2011:</strong> Questa guida non e&#8217; piu&#8217; valida dopo la release della versione 2.0rc1, fate riferimento alla guida originale sul sito del componente.<br />
<a href="http://ptwix.toforge.com/index.php?p=install">http://ptwix.toforge.com/index.php?p=install</a></p>
<p>Ptwix è un componente da me creato per visualizzare la timeline del tuo account twitter direttamente sul tuo sito.<br />
E&#8217; scritto in PHP ed usa AJAX per effettuare un update asincrono quando viene richiesto.</p>
<p>Usa anche un sistema di cache XML per evitare che si superino le 100 richieste in un ora, limite imposto da twitter per evitare il sovraccarico dei server.</p>
<p>Ne potete vedere una demo qui <a title="Ptwix demo" href="http://ptwix.toforge.com?p=demo" target="_blank">http://ptwix.toforge.com?p=demo</a></p>
<p><img class="aligncenter" title="Ptwix interface" src="http://ptwix.toforge.com/images/interface.png" alt="" width="300" height="282" /></p>
<p>Scrivo questa guida all&#8217;installazione in italiano qui sul mio blog  in quanto il sito ufficiale ho deciso di lasciarlo solo in lingua inglese.<span id="more-142"></span></p>
<p>Bando alle ciance e partiamo!!!<br />
Scaricate l&#8217;archivio che preferite all&#8217;indirizzo <a title="Ptwix download" href="http://ptwix.toforge.com?p=download" target="_blank">http://ptwix.toforge.com?p=download</a> e posizionate la cartella ptwix ovunque volete sul vostro server.<br />
Poniamo l&#8217;attenzione sulla cartella cache all&#8217;interno del package ptwix, questa è la cartella di default per contenere i file di cache, e naturalmente deve avere i permessi di scrittura.</p>
<p style="text-align: center;"><img class="aligncenter" title="Folder tree of ptwix" src="http://ptwix.toforge.com/images/folder.png" alt="" width="195" height="260" /></p>
<p>Non dovete per forza usare questa cartella ma una qualsiasi sul vostro server e in qualsiasi posizione.<br />
Ora aprite il file ptwix_reader.php che si trova nella cartella <strong>as </strong>e modificate le seguenti righe<br />
<code><br />
$username="yourtwitterusername";<br />
$password="yourtwitterpassword";<br />
$url_path="http://www.mysite.com/ptwix/";<br />
$cache_folder="/var/www/examplesite/ptwix/cache/";</code></p>
<p>I primi due parametri sono le credenziali di autenticazione del vostro account twitter, l&#8217;url path e la path url assoluta che punta alla cartella di installazione di ptwix e infine cache_folder rappresenta  la posizione della cartella in cui saranno scritti i file di cache che, come vi dicevo prima, dovranno avere i permessi di scrittura.</p>
<p>Fatto questo possiamo andare ad inserire ptwix nella pagina che desideriamo con i seguenti passi</p>
<p>Includiamo il file ptwix.php della cartella <strong>core</strong><br />
<code><br />
&lt;? include "ptwix/core/PtwiX.php" ?&gt;</code></p>
<p>Creiamo una nuova istanza dell&#8217;ogetto passandogli nell&#8217;ordine i seguenti parametri</p>
<p><strong>Instance Name:</strong> Il mome dell&#8217;istanza dell&#8217;ogetto, a vostro piacere.<br />
<strong>Username:</strong> L&#8217;username del tuo account twitter<br />
<strong>Password:</strong> La password del tuo account twitter<br />
<strong>Url path:</strong> La path url della cartella di installazione di ptwix  (http://www.mysite.com/ptwix/)<br />
<strong>Cache folder path: </strong>La path assoluta della cartella di cache<br />
<strong>Timeline type:</strong> (Optional) La timeline da visualizzare  (user timeline o friends timeline). Default friends timeline<br />
<strong>Theme:</strong> (Optional) Il nome del tema da utilizzare, default gray-blue</p>
<p>Dopo di che bisogna inserire il foglio di stile relativo al tema, potete farlo manualmente oppure utilizzando il metodo printCss_Ref.<br />
Ora resta da  stampare il box di ptwix ovunque vogliamo utilizzando il metodo printBox.</p>
<p>Per chiarirvi le idee ecco un bell&#8217;esempio completo</p>
<p><code>&lt;? include "core/PtwiX.php";<br />
$PtwiX=new PtwiX('second','user','pass','http://www.mysite.com/ptwix/','/var/www/ptwix/cache/',PtwiX::$FRIENDS_TIMELINE,'silver-red');<br />
?&gt;<br />
&lt;html&gt;<br />
&lt;head&gt;<br />
&lt;? $PtwiX-&gt;printCssRef(); ?&gt;<br />
&lt;/head›<br />
&lt;body›<br />
&lt;? $PtwiX-&gt;printBox(); ?&gt;<br />
&lt;/body&gt;<br />
&lt;/html&gt;</code></p>
<p>Per completezza vi ricordo l&#8217;esistenza del metodo setDimension(larghezza,altezza) che chiamato sull&#8217;oggetto vi permette di impostare la dimensione a vostro piacimento.<br />
Inoltre per chi ha un dominio in hosting e gli risulta impossibile installare curl e il relativo modulo PHP esiste anche un metodo disableCurl(boolean) che permette di disabilitare l&#8217;uso di curl, ma in questo caso potrete visualizzare solo la  timeline  del vostro utente  e non quella dei vostri amici.</p>
<p>Se avete particolari domande o problemi commentate pure e non dimenticate di seguire <a title="Twitter fireantology" href="http://twitter.com/fireantology" target="_blank">me</a> e <a title="Ptwix twitter" href="http://twitter.com/ptwix" target="_blank">ptwix</a> su twitter.  <img src='http://www.toforge.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.toforge.com/2009/07/installare-e-configurare-ptwix-un-client-web-per-twitter/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
