<?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>Better Programming</title>
	<atom:link href="http://www.betterprogramming.com/feed" rel="self" type="application/rss+xml" />
	<link>http://www.betterprogramming.com</link>
	<description>Portfolio</description>
	<lastBuildDate>Thu, 18 May 2017 14:50:57 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=4.1</generator>
	<item>
		<title>Recently launched pythondaddy.com which has plenty of good Python articles</title>
		<link>http://www.betterprogramming.com/recently-launched-pythondaddy-com-which-has-plenty-of-good-python-articles.html</link>
		<comments>http://www.betterprogramming.com/recently-launched-pythondaddy-com-which-has-plenty-of-good-python-articles.html#comments</comments>
		<pubDate>Thu, 18 May 2017 14:50:57 +0000</pubDate>
		<dc:creator><![CDATA[Florentin]]></dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.betterprogramming.com/?p=365</guid>
		<description><![CDATA[www.pythondaddy.com]]></description>
				<content:encoded><![CDATA[<p><a href="http://www.pythondaddy.com">www.pythondaddy.com</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.betterprogramming.com/recently-launched-pythondaddy-com-which-has-plenty-of-good-python-articles.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Just finished another Chrome extension</title>
		<link>http://www.betterprogramming.com/just-finished-another-chrome-extension.html</link>
		<comments>http://www.betterprogramming.com/just-finished-another-chrome-extension.html#comments</comments>
		<pubDate>Thu, 18 May 2017 14:49:08 +0000</pubDate>
		<dc:creator><![CDATA[Florentin]]></dc:creator>
				<category><![CDATA[Javascript]]></category>

		<guid isPermaLink="false">http://www.betterprogramming.com/?p=364</guid>
		<description><![CDATA[Clippy is a Chrome extension which allows users to tag any url in a web page so we can later recognize them. You may read more about it here Clippy]]></description>
				<content:encoded><![CDATA[<p>Clippy is a Chrome extension which allows users to tag any url in a web page so we can later recognize them.<br />
You may read more about it here <a href="https://github.com/florentin/clippy">Clippy</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.betterprogramming.com/just-finished-another-chrome-extension.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Object attribute lookup in Python</title>
		<link>http://www.betterprogramming.com/object-attribute-lookup-in-python.html</link>
		<comments>http://www.betterprogramming.com/object-attribute-lookup-in-python.html#comments</comments>
		<pubDate>Fri, 04 Sep 2015 09:28:05 +0000</pubDate>
		<dc:creator><![CDATA[Florentin]]></dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.betterprogramming.com/?p=358</guid>
		<description><![CDATA[Resources descriptors https://docs.python.org/2/howto/descriptor.html http://stackoverflow.com/questions/3798835/understanding-get-and-set-and-python-descriptors python 2 docs https://docs.python.org/2/reference/datamodel.html?highlight=metaclass great insights http://blog.ionelmc.ro/2015/02/09/understanding-python-metaclasses/ __mro__ (Method Resolution Order) http://stackoverflow.com/questions/2010692/what-does-mro-do-in-python http://stackoverflow.com/questions/1848474/method-resolution-order-mro-in-new-style-python-classes simulate a __getattribute__ call http://codereview.stackexchange.com/questions/92497/simulate-object-getattribute-in-python Definitions Everything in Python is an object (i.e. classes, modules, the numbers, the strings, etc) A class is also an object Every object is an instance of a class (example: isinstance(5, int) ) [&#8230;]]]></description>
				<content:encoded><![CDATA[<h2>Resources</h2>
<p><em>descriptors</em></p>
<ul>
<li>https://docs.python.org/2/howto/descriptor.html</li>
<li>http://stackoverflow.com/questions/3798835/understanding-get-and-set-and-python-descriptors</li>
</ul>
<p><em>python 2 docs</em></p>
<ul>
<li>https://docs.python.org/2/reference/datamodel.html?highlight=metaclass</li>
</ul>
<p><em>great insights</em></p>
<ul>
<li>http://blog.ionelmc.ro/2015/02/09/understanding-python-metaclasses/</li>
</ul>
<p><em><code>__mro__</code> (Method Resolution Order)</em></p>
<ul>
<li>http://stackoverflow.com/questions/2010692/what-does-mro-do-in-python </li>
<li>http://stackoverflow.com/questions/1848474/method-resolution-order-mro-in-new-style-python-classes</li>
</ul>
<p><em>simulate a <code>__getattribute__</code> call</em></p>
<ul>
<li>http://codereview.stackexchange.com/questions/92497/simulate-object-getattribute-in-python</li>
</ul>
<h2>Definitions</h2>
<ul>
<li>Everything in Python is an object (i.e. classes, modules, the numbers, the strings, etc)</li>
<li>A <code>class</code> is also an <code>object</code></li>
<li>Every <code>object</code> is an instance of a <code>class</code> (example: isinstance(5, int) )</li>
<li>Because of that, every <code>class</code> is an instance of a special kind of class called <code>metaclass</code></li>
<li>An instance is created by calling a class object</li>
<li>A non-data descriptor is an object following the data descriptor protocol as described <a href="https://docs.python.org/2/howto/descriptor.html#descriptor-protocol">in the docs</a></li>
<li>A data descriptor is a descriptor which defined both the <code>__set__</code> AND <code>__get__</code> methods</li>
<li><code>__mro__</code> is a tuple of classes that are considered when looking for base classes during method resolution</li>
</ul>
<h2>Code snippet</h2>
<p><a href="https://gist.github.com/florentin/4c210918a9a00443aeac#file-method-demo-py">demo code</a></p>
<h2>Instance attribute look up</h2>
<p><a href="https://docs.python.org/2/howto/descriptor.html#invoking-descriptors">Manual excerpt</a></p>
<blockquote>
<p>The implementation works through a precedence chain that gives data descriptors priority over instance variables, instance variables priority over non-data descriptors, and assigns lowest priority to <strong>getattr</strong>() if provided.</p>
</blockquote>
<p>Given a Class &#8220;C&#8221; and an Instance &#8220;c&#8221; where &#8220;c = C(&#8230;)&#8221;, calling &#8220;c.name&#8221; means looking up an Attribute &#8220;name&#8221; on the Instance &#8220;c&#8221; like this:</p>
<ul>
<li>Get the Class from Instance</li>
<li>Call the Class&#8217;s special method <code>__getattribute__</code>. All objects have a default <code>__getattribute__</code></li>
</ul>
<p>Inside <code>__getattribute__</code></p>
<ul>
<li>Get the Class&#8217;s <code>__mro__</code> as ClassParents</li>
<li>For each ClassParent in ClassParents
<ul>
<li>If the Attribute is in the ClassParent&#8217;s <code>__dict__</code></li>
<li>If is a data descriptor
<ul>
<li>Return the result from calling the data descriptor&#8217;s special method <code>__get__()</code></li>
</ul>
</li>
<li>Break the for each (do not continue searching the same Attribute any further)</li>
</ul>
</li>
<li>If the Attribute is in Instance&#8217;s <code>__dict__</code>
<ul>
<li>Return the value as it is (even if the value is a data descriptor)</li>
</ul>
</li>
<li>For each ClassParent in ClassParents
<ul>
<li>If the Attribute is in the ClassParent&#8217;s <code>__dict__</code></li>
<li>If is a non-data descriptor
<ul>
<li>Return the result from calling the non-data descriptor&#8217;s special method <code>__get__()</code></li>
</ul>
</li>
<li>If it is NOT a descriptor
<ul>
<li>Return the value</li>
</ul>
</li>
</ul>
</li>
<li>If Class has the special method <code>__getattr__</code>
<ul>
<li>Return the result from calling the Class&#8217;s special method <code>__getattr__</code>.</li>
</ul>
</li>
<li>Raises an <code>AttributeError</code></li>
</ul>
<h3>Things to remember (from the manual)</h3>
<ul>
<li>descriptors are invoked by the <strong>getattribute</strong>() method</li>
<li>overriding <strong>getattribute</strong>() prevents automatic descriptor calls</li>
<li><strong>getattribute</strong>() is only available with new style classes and objects</li>
<li>object.<strong>getattribute</strong>() and type.<strong>getattribute</strong>() make different calls to <strong>get</strong>().</li>
<li>data descriptors always override instance dictionaries.</li>
<li>non-data descriptors may be overridden by instance dictionaries.</li>
</ul>
<h2>Class attribute look up</h2>
<p>Given a MetaClass &#8220;M&#8221; and a Class &#8220;C&#8221; instance of the Metaclass &#8220;M&#8221;, calling &#8220;C.name&#8221; means looking up an Attribute &#8220;name&#8221; on the Class &#8220;C&#8221; like this:</p>
<ul>
<li>Get the Metaclass from Class</li>
<li>Call the Metaclass&#8217;s special method <code>__getattribute__</code></li>
</ul>
<p>Inside <code>__getattribute__</code></p>
<ul>
<li>Get the Metaclass&#8217;s <code>__mro__</code> as MetaParents</li>
<li>For each MetaParent in MetaParents
<ul>
<li>If the Attribute is in the MetaParent&#8217;s <code>__dict__</code></li>
<li>If is a data descriptor
<ul>
<li>Return the result from calling the data descriptor&#8217;s special method <code>__get__()</code></li>
</ul>
</li>
<li>Break the for each</li>
</ul>
</li>
<li>Get the Class&#8217;s <code>__mro__</code> as ClassParents</li>
<li>For each ClassParent in ClassParents
<ul>
<li>If the Attribute is in the ClassParent&#8217;s <code>__dict__</code></li>
<li>If is a (data or non-data) descriptor
<ul>
<li>Return the result from calling the descriptor&#8217;s special method <code>__get__()</code></li>
</ul>
</li>
<li>Else
<ul>
<li>Return the value</li>
</ul>
</li>
</ul>
</li>
<li>For each MetaParent in MetaParents
<ul>
<li>If the Attribute is in the MetaParent&#8217;s <code>__dict__</code></li>
<li>If is a non-data descriptor
<ul>
<li>Return the result from calling the non-data descriptor&#8217;s special method <code>__get__()</code></li>
</ul>
</li>
<li>If it is NOT a descriptor
<ul>
<li>Return the value</li>
</ul>
</li>
</ul>
</li>
<li>If MetaClass has the special method <code>__getattr__</code>
<ul>
<li>Return the result from calling the MetaClass&#8217;s special method <code>__getattr__</code>.</li>
</ul>
</li>
<li>Raises an <code>AttributeError</code></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.betterprogramming.com/object-attribute-lookup-in-python.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A guide to using Google&#8217;s API Client Library for JavaScript with Sheets API</title>
		<link>http://www.betterprogramming.com/a-guide-to-using-googles-api-client-library-for-javascript-with-sheets-api.html</link>
		<comments>http://www.betterprogramming.com/a-guide-to-using-googles-api-client-library-for-javascript-with-sheets-api.html#comments</comments>
		<pubDate>Wed, 12 Aug 2015 13:22:34 +0000</pubDate>
		<dc:creator><![CDATA[Florentin]]></dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.betterprogramming.com/?p=354</guid>
		<description><![CDATA[Google allow users to interact with Google Apps (like Calendar, Contacts, Drive) though APIs. Working with the API Client Library for JavaScript in a browser environment presents it&#8217;s challenges as described below. Setup I&#8217;m making a single page application (one html file) to test the Javascript library capabilities for using it with Google Sheets Api. Wish to demo the following: * [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Google allow users to interact with Google Apps (like Calendar, Contacts, Drive) though APIs.<br />
Working with the API Client Library for JavaScript in a browser environment presents it&#8217;s challenges as described below.</p>
<h2>Setup</h2>
<p>I&#8217;m making a single page application (one html file) to test the Javascript library capabilities for using it with Google Sheets Api.<br />
Wish to demo the following:<br />
* create a new spreadsheet<br />
* search for the newly created file by name<br />
* read rows and columns<br />
* insert new rows</p>
<p>Working with private data requires setting up a project at https://console.developers.google.com/project<br />
Read the chapter &#8220;Get access keys for your application&#8221; from https://developers.google.com/api-client-library/javascript/start/start-js<br />
Make sure to add &#8220;Drive API&#8221; here https://console.developers.google.com/project/PROJECT_KEY/apiui/apis/enabled<br />
After &#8220;Create new client id&#8221; steps, write down the &#8220;Client ID&#8221; and make sure that JavaScript origins matches the demo server (in my case it was http://localhost:8888)</p>
<p>I&#8217;ll start building the demo with the help of these resources:</p>
<p>https://developers.google.com/api-client-library/javascript/samples/samples</p>
<p>https://github.com/google/google-api-javascript-client/blob/master/samples/authSample.html</p>
<h2>The demo</h2>
<p>This depends on &#8220;client.js&#8221; which is a single line js file like this: window.clientId = &#8216;aaa-bbbcccddd.apps.googleusercontent.com';</p>
<p>Here&#8217;s the file on GITHUB: https://github.com/florentin/google-sheets-api</p>
<p>Please read the code comments, they are <strong>important</strong>.</p>
<pre class="brush:js">&lt;!DOCTYPE html&gt;
&lt;html&gt;
	&lt;head&gt;
	  &lt;meta charset='utf-8' /&gt;
	&lt;/head&gt;
	&lt;body&gt;
		&lt;h1&gt;Hello Google Sheets API&lt;/h1&gt;
		&lt;em&gt;Open the console and watch for errors and debug messages.&lt;/em&gt;
		&lt;div id="step1"&gt;
		    &lt;h2&gt;Step 1: Authorize this app with your Google account&lt;/h2&gt;
		    &lt;span id="authorize-status"&gt;&lt;/span&gt;
		    &lt;button id="authorize-button" style="visibility: hidden"&gt;Authorize&lt;/button&gt;
		&lt;/div&gt;
		
		&lt;div id="step2"&gt;
            &lt;h2&gt;Step 2: Create a Spreadsheet document in Google Drive&lt;/h2&gt;
            &lt;span id="create-status"&gt;&lt;/span&gt;
            &lt;button id="create-button"&gt;Create file in Drive&lt;/button&gt;
            &lt;em&gt;Add a file named "blocky" to Google Drive&lt;/em&gt;
        &lt;/div&gt;
        
        &lt;div id="step3"&gt;
            &lt;h2&gt;Step 3: Search spreadsheet files by the name "blocky"&lt;/h2&gt;
            &lt;span id="list-status"&gt;&lt;/span&gt;
            &lt;button id="list-button"&gt;Search files (json)&lt;/button&gt;
            
        &lt;/div&gt;
        
        &lt;div id="step4"&gt;
            &lt;h2&gt;Step 4: Find the first file named "blocky" and retrieve the worksheets&lt;/h2&gt;
            &lt;span id="worksheets-status"&gt;&lt;/span&gt;
            &lt;button id="worksheets-button"&gt;Retrieve worksheets&lt;/button&gt;
        &lt;/div&gt;
        
        &lt;div id="step5"&gt;
            &lt;h2&gt;Step 5: Add rows to the first worksheet from the spreadsheet "blocky"&lt;/h2&gt;
            &lt;span id="rows-status"&gt;&lt;/span&gt;
            &lt;button id="rows-button"&gt;Add rows&lt;/button&gt;
        &lt;/div&gt;
		
		&lt;script src="client.js"&gt;&lt;/script&gt;
        
        &lt;script type="text/javascript"&gt;
		var scopes = 'https://spreadsheets.google.com/feeds',
		    headers = {
				accept_json: {'Accept': 'application/json'},
				accept_xml: {'Accept': 'application/atom+xml'},
				send_json: {'Content-Type': 'application/json'},
				send_xml: {'Content-Type': 'application/atom+xml'}
		    },    
		    authorizeButton = document.getElementById('authorize-button'),
		    authorizeStatus = document.getElementById('authorize-status'),
	        createButton = document.getElementById('create-button'),
	        listButton = document.getElementById('list-button'),
	        worksheetsButton = document.getElementById('worksheets-button'),
	        rowsButton = document.getElementById('rows-button');

		function handleClientLoad() {
			checkAuth();
			createButton.onclick = handleCreateClick;
			listButton.onclick = handleListClick;
			worksheetsButton.onclick = handleWorksheetsClick;
			rowsButton.onclick = handleRowClick;
		}
    
		function checkAuth() {
		    gapi.auth.authorize({client_id: clientId, scope: scopes, immediate: true}, handleAuthResult);
		}
    
		function handleAuthResult(authResult) {
			if (authResult &amp;&amp; !authResult.error) {
				// this app is authorised
				authorizeButton.style.visibility = 'hidden';
				authorizeStatus.innerHTML = 'Is Authorised';
				//makeApiCall();
			} else {
				authorizeButton.style.visibility = '';
				authorizeButton.onclick = handleAuthClick;
				authorizeStatus.innerHTML = 'Not Authorised';
			}
		}
    
		function handleAuthClick(event) {
			gapi.auth.authorize({client_id: clientId, scope: scopes, immediate: false}, handleAuthResult);
		    return false;
		}
    
		function request(method, url, post_data, sucess_call, headers) {
			var oauthToken = gapi.auth.getToken(),
			    xhr = new XMLHttpRequest();
			
			console.info('request url', url);
			
			xhr.open(method, url);
			xhr.setRequestHeader('Authorization', 'Bearer ' + oauthToken.access_token);
			//xhr.setRequestHeader("GData-Version", "3.0");
			if(headers !== undefined) {
				for(var key in headers) {
					xhr.setRequestHeader(key, headers[key]);
				}
			}
			
			xhr.onload = function() {
			    console.info('response xhr', xhr);
			    if(typeof sucess_call === "function")
			        sucess_call(xhr);
			};
			
			xhr.onerror = function(err) {
			    console.error('Get Woops', err);
			};
			
			xhr.send(post_data);
		}
	    
		function get_request(url, success_call, headers) {
			return request('GET', url, null, success_call, headers);
		}
		
		function post_request(url, data, success_call, headers) {
            return request('POST', url, data, success_call, headers);
        }
		
		function json_url(url) {
		    return url+'?alt=json';
		}
		
		function serialize(obj) {
            return '?'+Object.keys(obj).reduce(function(a,k){a.push(k+'='+encodeURIComponent(obj[k]));return a},[]).join('&amp;')
        }
        
        function xhr_json_response(xhr) {
            return JSON.parse(xhr.responseText);
        }
		
		function handleCreateClick(event) {
			/*
			To upload a file, check the Javascript example
			from https://developers.google.com/drive/v2/reference/files/insert
			*/
			var body = {
				    'mimeType': 'application/vnd.google-apps.spreadsheet',
	                'title': 'blocky'},
	            url = 'https://www.googleapis.com/drive/v2/files';
			post_request(url, JSON.stringify(body), null, send_json_header);
		}
		
		function handleListClick(event, callback) {
			/*
			find the Drive Api reference here

https://developers.google.com/drive/v2/reference/

			*/
			var url = 'https://www.googleapis.com/drive/v2/files'+serialize({'q': 'title="blocky" and trashed=false'});   
			get_request(url, function(xhr) {
				var obj = xhr_json_response(xhr);
				console.info('documents', obj, obj.items);
				if(typeof callback === "function") {
					callback(obj);
				}
			}); 
		}
		
		function handleWorksheetsClick(events) {
			/*
			Google Sheets Api has no "reference" page and i 
			couldn't figure out a way to find a spreadsheet based on it's id.

https://developers.google.com/google-apps/spreadsheets/index

			Make sure that the "blocky" spreadsheet has the following rows:
	        key   content url
	        a1    a2      a3
	        b1    b2      b3
			*/
			
			handleListClick(null, function(obj) {
				// This is the endpoint for getting the worksheets of a spreadsheet identified by "id"
                var url = 'https://spreadsheets.google.com/feeds/worksheets/'+encodeURIComponent(obj.items[0].id)+'/private/full';
				
                /*
				=== TROUBLE AHEAD ===
                Google Sheets Api by default returns and accepts "application/atom+xml" content type - that's XML strings
                */
                
                // Let's get an "ATOM+XML" response of the worksheets for our "blocky" spreadsheet
                get_request(url, function(xhr) {
                	console.info('Request atom+xml', xhr);
                }, headers.accept_xml);
                
                /*
                The request doesn't get thought because of this error:
                No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8888' is therefore not allowed access.
                
                If you check the Network Headers in Chrome Developer tools, 
                Chrome first does a "OPTIONS" request to the "url" and gets:
                    access-control-allow-headers:authorization
                    access-control-allow-methods:GET,OPTIONS
                    access-control-allow-origin:http://localhost:8888
                
                All seems fine until it makes the actual "GET" request where the "access-control-allow-origin" header dissapears 
                and Google Chrome denies the cross origin request. 
                */
                
                /*
                Let's alter the "url" to request a "JSON" feed as described here: 

https://developers.google.com/gdata/docs/json

                */
                
                get_request(url+'?alt=json', function(xhr) {
                    console.info('Request json', xhr);
                    var obj = xhr_json_response(xhr);
                    console.log('json', obj, obj.feed.entry[0]);
                    
                    /*
                    Using a JSON request (?alt=json) allows getting the data out of the worksheets.
                    Manually add some data to the "blocky" spreadsheet in Google Drive app to see results
                    */
                    var url = obj.feed.entry[0].link[0].href;
                    get_request(url+'?alt=json', function(xhr) {
                    	var obj = xhr_json_response(xhr);
                    	console.info('Spreadsheet data', obj, obj.feed.entry);
                    });
                }, headers.accept_json);
                
			});
		}
		
		function handleRowClick(events) {
			handleListClick(null, function(obj) {
				/*
		        Adding new rows as described in the chapter "Add a list row" from 

https://developers.google.com/google-apps/spreadsheets/data

		        is not working

		        */
				var url = 'https://spreadsheets.google.com/feeds/worksheets/'+encodeURIComponent(obj.items[0].id)+'/private/full';
				get_request(url+'?alt=json', function(xhr) {
                    console.info('Request json', xhr);
                    var obj = xhr_json_response(xhr);
                    //console.log('worksheet', obj)
                    
                    var url = obj.feed.entry[0].link[0].href;
                    var post_data = '&lt;entry xmlns="http://www.w3.org/2005/Atom" xmlns:gsx="http://schemas.google.com/spreadsheets/2006/extended"&gt;&lt;gsx:key&gt;x1&lt;/gsx:key&gt;&lt;gsx:content&gt;x2&lt;/gsx:content&gt;&lt;gsx:url&gt;x3&lt;/gsx:url&gt;&lt;/entry&gt;';
                    post_request(url, post_data, function(xhr) {
                    	console.log('post data', xhr);
                    	/*
                    	No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8888' is therefore not allowed access.
                    	*/
                    }, headers.send_xml);
				});
			});
		}
    &lt;/script&gt;
    &lt;script src="https://apis.google.com/js/auth.js?onload=handleClientLoad"&gt;&lt;/script&gt;
  &lt;/body&gt;
&lt;/html&gt;</pre>
<h2>Conclusions</h2>
<ul>
<li>Google Sheets API is using the old &#8220;gdata API&#8221;. Read more https://developers.google.com/gdata/docs/directory and here https://developers.google.com/gdata/docs/json</li>
<li>Reading operations seem to work fine with CORS (https://developers.google.com/api-client-library/javascript/features/cors) requests as long as you request JSON feeds (add ?alt=json to the requested url)</li>
<li>I wasn&#8217;t able to &#8220;POST&#8221; data using CORS requests, using either &#8220;atom+xml&#8221; or &#8220;json&#8221; content types.</li>
<li>Sending &#8220;POST&#8221; requests from &#8220;curl&#8221; or Python worked fine.</li>
<li>All these basically mean that you can&#8217;t build Single-Page Apps for changing data in Google services (unless you use a back-end request proxy)</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.betterprogramming.com/a-guide-to-using-googles-api-client-library-for-javascript-with-sheets-api.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Blocky &#8211; the Chrome Extension that enables tagging blocks of html</title>
		<link>http://www.betterprogramming.com/blocky-the-chrome-extension-that-enables-tagging-blocks-of-html.html</link>
		<comments>http://www.betterprogramming.com/blocky-the-chrome-extension-that-enables-tagging-blocks-of-html.html#comments</comments>
		<pubDate>Thu, 30 Jul 2015 10:54:21 +0000</pubDate>
		<dc:creator><![CDATA[Florentin]]></dc:creator>
				<category><![CDATA[Javascript]]></category>

		<guid isPermaLink="false">http://www.betterprogramming.com/?p=352</guid>
		<description><![CDATA[This small Chrome Extension i&#8217;ve created is good for tagging divs or other blocks of html. Let&#8217;s say you see a web page listing the latest 50 news. Using blocky extension you would be able to tag the news you like with &#8220;green&#8221;, the ones you don&#8217;t like with &#8220;red&#8221; and the ones you didn&#8217;t [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>This small Chrome Extension i&#8217;ve created is good for tagging divs or other blocks of html.</p>
<p>Let&#8217;s say you see a web page listing the latest 50 news. Using blocky extension you would be able to tag the news you like with &#8220;green&#8221;, the ones you don&#8217;t like with &#8220;red&#8221; and the ones you didn&#8217;t read with &#8220;yellow&#8221;. On the following visit you&#8217;d see the marked items.</p>
<p>Please check the extension here:</p>
<p><a title="https://github.com/florentin/blocky" href="https://github.com/florentin/blocky">https://github.com/florentin/blocky</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.betterprogramming.com/blocky-the-chrome-extension-that-enables-tagging-blocks-of-html.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A better diigo bookmarklet (diigolet)</title>
		<link>http://www.betterprogramming.com/a-better-diigo-bookmarklet-diigolet.html</link>
		<comments>http://www.betterprogramming.com/a-better-diigo-bookmarklet-diigolet.html#comments</comments>
		<pubDate>Fri, 29 Mar 2013 15:19:19 +0000</pubDate>
		<dc:creator><![CDATA[Florentin]]></dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.betterprogramming.com/?p=344</guid>
		<description><![CDATA[What is the &#8216;diigolet&#8217; The diigolet is a Diigo.com tool used to manage a user&#8217;s bookmarks. It is a bookmarklet, a bookmark stored in a browser that contains Javascript. The original diigolet is here: https://www.diigo.com/tools/diigolet How is BetterDiigolet different ? BetterDiigolet by default opens the &#8220;bookmark&#8221; menu from the diigolet toolbar, it fills in the [&#8230;]]]></description>
				<content:encoded><![CDATA[<h2>What is the &#8216;diigolet&#8217;</h2>
<p>The diigolet is a Diigo.com tool used to manage a user&#8217;s bookmarks. It is a <a title="Bookmarklet" href="http://en.wikipedia.org/wiki/Bookmarklet">bookmarklet</a>, a bookmark stored in a browser that contains Javascript.<br />
The original diigolet is here:</p>
<p>https://www.diigo.com/tools/diigolet</p>
<h2>How is BetterDiigolet different ?</h2>
<p>BetterDiigolet by default opens the &#8220;bookmark&#8221; menu from the diigolet toolbar, it fills in the description and clicks all recommended tags. All is left for the user is to click &#8220;Save Bookmark&#8221;.<br />
If it&#8217;s used on a already bookmarked url, it will color the tags previously used in &#8216;green&#8217;. The new recommended tags will remain &#8216;blue&#8217;.<br />
This is an easy way for the user to find out if the url has been bookmarked before.<br />
By using better_diigolet.js one can save time with clicking though all the tags and filling in the bookmark&#8217;s description field.</p>
<h2>How it&#8217;s built</h2>
<p>Diigo&#8217;s diigolet is loading a js file named &#8220;diigolet_b_h_b.js&#8221; which in turns loads &#8220;diigolet.js&#8221;. diigolet.js contains jQuery v1.4.3.<br />
BetterDiigolet loads everything in better_diigolet.js, jQuery has been replaced with v1.8.3<br />
The downside is the missing &#8220;Loading Diigolet&#8230;&#8221; tooltip.</p>
<h2>How to install it in Firefox</h2>
<ol>
<li>Make sure the &#8220;Bookmarks Toolbar&#8221; is visible. If it is not, go to menu View &gt; Toolbars.</li>
<li>Drag this button: <span style="color: #ff6600;"><a title="BetterDiigolet" href="javascript:(function(){s=document.createElement(&quot;script&quot;);s.type=&quot;text/javascript&quot;;s.src=&quot;http://dl.dropbox.com/u/1836650/better_diigolet.js&quot;;document.body.appendChild(s);})();"><span style="color: #ff6600;">BetterDiigolet</span></a></span> up to your Bookmarks Toolbar.</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://www.betterprogramming.com/a-better-diigo-bookmarklet-diigolet.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Django reusable apps</title>
		<link>http://www.betterprogramming.com/django-reusable-apps.html</link>
		<comments>http://www.betterprogramming.com/django-reusable-apps.html#comments</comments>
		<pubDate>Wed, 31 Oct 2012 11:01:22 +0000</pubDate>
		<dc:creator><![CDATA[Florentin]]></dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.betterprogramming.com/?p=342</guid>
		<description><![CDATA[Warning: this article is still a draft Explaining the Django reusable apps in an agile way as a developer i want to easily plug the app into the project so that i can improve the productivity i want to customize and extend existing Django apps so that they fit the requirements some of the things [&#8230;]]]></description>
				<content:encoded><![CDATA[<p><em>Warning: this article is still a draft</em></p>
<p><strong>Explaining the Django reusable apps in an agile way</strong></p>
<ul>
<li>as a developer
<ul>
<li>i want to easily plug the app into the project so that i can improve the productivity</li>
<li>i want to customize and extend existing Django apps so that they fit the requirements</li>
</ul>
</li>
<li>some of the things that need customization:
<ul>
<li>models
<ul>
<li>e.g. make the app work with a different model class than the ones provided by the app</li>
<li>e.g. create a custom model based on the one supplied by the app and add extra fields or modify the existing field definition</li>
</ul>
</li>
<li>forms
<ul>
<li>e.g. the app should use a custom form</li>
<li>e.g. a custom form which adds extra fields or change the definition of the existing ones</li>
</ul>
</li>
<li>template names</li>
<li>success or redirect urls</li>
<li>template variables (extra_context)</li>
</ul>
</li>
</ul>
<p><strong>1 James Bennett’s approach &#8211; the custom objects are passed as arguments to the views</strong></p>
<p>&nbsp;</p>
<ul>
<li>let the app&#8217;s views receive a number of parameters for which the view defined some defaults</li>
<li>Django&#8217;s class based views support this strategy by default
<ul>
<li><a title="https://docs.djangoproject.com/en/dev/ref/class-based-views/" href="https://docs.djangoproject.com/en/dev/ref/class-based-views/">https://docs.djangoproject.com/en/dev/ref/class-based-views/</a></li>
</ul>
</li>
<li>more on the subject:
<ul>
<li><a title="http://django-reusable-app-docs.readthedocs.org/en/latest/apps/index.html" href="http://django-reusable-app-docs.readthedocs.org/en/latest/apps/index.html">http://django-reusable-app-docs.readthedocs.org/en/latest/apps/index.html</a></li>
<li><a title="http://www.youtube.com/watch?v=A-S0tqpPga4" href="http://www.youtube.com/watch?v=A-S0tqpPga4">http://www.youtube.com/watch?v=A-S0tqpPga4</a></li>
</ul>
</li>
<li>example</li>
</ul>
<p>(APP/views.py)<br />
def register(request, success_url=None,<br />
form_class=RegistrationForm<br />
template_name=&#8217;registration/registration_form.html&#8217;,<br />
extra_context=None):</p>
<div>&#8230;</div>
<p><strong>2 Use the settings to define the custom objects</strong></p>
<p>&nbsp;</p>
<ul>
<li>in settings.py, define the values for models/forms/etc which will be later used by the app</li>
<li>it&#8217;s useful to prefix all the names required by a specific app, i.e. BLOGAPP_MODEL, BLOGAPP_FORM etc</li>
<li>example</li>
</ul>
<p>(settings.py)<br />
MY_APP_MODEL = MyAppModel</p>
<p>(APP/views.py)<br />
from django.conf import settings<br />
from .models import AppModel</p>
<p>def register(request):</p>
<div>my_model = getattr(settings, &#8216;MY_APP_MODEL&#8217;, AppModel)</div>
<p><strong>What the current approaches don&#8217;t offer</strong></p>
<ul>
<li>an easy way to modify or extend the urls. The urlpatterns is just a list, it&#8217;s difficult to delete/edit/insert url definitions.</li>
<li>models placed in models.py are used by Django in different db operations (i.e. syncdb).</li>
</ul>
<p>One might want to ignore those models and let Django use customized/child Models.</p>
<ul>
<li>the Model and Form fields are not easy to alter</li>
</ul>
<p><strong>Ideas for a new solution</strong></p>
<ul>
<li>make everything a class. Forms and Models are classes but the urls (or maybe the views) are not.</li>
<li>move the Model definitions from models.py and allow the developer to use it&#8217;s own Models (i.e. though getters or factories)
<ul>
<li>instead one can play with abstract models but without any concrete Models the app won&#8217;t work out of the box</li>
</ul>
</li>
<li>define the Form and Model fields inside a method so that the derived classes can modify the definitions</li>
</ul>
<p><strong>Resources</strong></p>
<ul>
<li>ways to organize your app for reusability <a title="https://github.com/Natim/django-reusable-apps" href="https://github.com/Natim/django-reusable-apps">https://github.com/Natim/django-reusable-apps</a></li>
<li><a title="http://www.philipotoole.com/reusable-django-applications" href="http://www.philipotoole.com/reusable-django-applications">http://www.philipotoole.com/reusable-django-applications</a></li>
<li>Django class based views <a title="https://docs.djangoproject.com/en/dev/topics/class-based-views/" href="https://docs.djangoproject.com/en/dev/topics/class-based-views/">https://docs.djangoproject.com/en/dev/topics/class-based-views/</a></li>
<li>&#8220;eight spaces&#8221; &#8211; class based everything <a title="http://reinout.vanrees.org/weblog/2011/06/07/eight-spaces.html" href="http://reinout.vanrees.org/weblog/2011/06/07/eight-spaces.html">http://reinout.vanrees.org/weblog/2011/06/07/eight-spaces.html</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.betterprogramming.com/django-reusable-apps.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Django project skeleton</title>
		<link>http://www.betterprogramming.com/django-project-skeleton.html</link>
		<comments>http://www.betterprogramming.com/django-project-skeleton.html#comments</comments>
		<pubDate>Mon, 24 Oct 2011 16:45:30 +0000</pubDate>
		<dc:creator><![CDATA[Florentin]]></dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.betterprogramming.com/?p=337</guid>
		<description><![CDATA[If you need a Django project skeleton to base your work upon, please check this one: https://github.com/florentin/django-project-skeleton And now a Django app skeleton as well https://github.com/florentin/django-app-skeleton]]></description>
				<content:encoded><![CDATA[<p>If you need a Django project skeleton to base your work upon, please check this one:</p>
<p><a title="Django Skeleton" href="https://github.com/florentin/django-project-skeleton">https://github.com/florentin/django-project-skeleton</a></p>
<p>And now a Django app skeleton as well</p>
<p><a title="Django Skeleton" href="https://github.com/florentin/django-app-skeleton">https://github.com/florentin/django-app-skeleton</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.betterprogramming.com/django-project-skeleton.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Django settings</title>
		<link>http://www.betterprogramming.com/django-settings.html</link>
		<comments>http://www.betterprogramming.com/django-settings.html#comments</comments>
		<pubDate>Mon, 24 Oct 2011 10:51:54 +0000</pubDate>
		<dc:creator><![CDATA[Florentin]]></dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.betterprogramming.com/?p=335</guid>
		<description><![CDATA[I&#8217;m going to talk here about various techniques regarding the Django&#8217;s settings. Let&#8217;s assume the following project layout: . ├── __init__.py ├── manage.py ├── settings └── urls.py How do I use custom settings or overwrite existing ones on my development machine ? Answer 1 Create your custom settings file under the same parent as the [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>I&#8217;m going to talk here about various techniques regarding the Django&#8217;s settings.</p>
<p>Let&#8217;s assume the following project layout:<br />
.<br />
├── __init__.py<br />
├── manage.py<br />
├── settings<br />
└── urls.py</p>
<h2>How do I use custom settings or overwrite existing ones on my development machine ?</h2>
<h3>Answer 1</h3>
<p>Create your custom settings file under the same parent as the existing settings.py. Let&#8217;s name the new file settings_local.py<br />
At the bottom of settings.py, add the following:</p>
<pre class="brush:py">try:
    from settings_local import *
except ImportError:
    pass</pre>
<p><strong>Pros</strong></p>
<ul>
<li>no need to change the manage.py or the wsgi file in order to apply the new settings</li>
</ul>
<p><strong> Cons</strong></p>
<ul>
<li>hard/impossible to use different settings for different environment</li>
</ul>
<h3> Answer 2 (preferred)</h3>
<p>Create a new directory called &#8220;settings&#8221; and move the existing setting file there. Then make a different file for each type of environment.<br />
.<br />
├── __init__.py<br />
├── manage.py<br />
├── settings<br />
│   ├── __init__.py<br />
│   ├── development.py<br />
│   ├── production.py<br />
│   └── settings.py<br />
└── urls.py</p>
<p>settings.py will include the default Django settings, probably the file created by django-admin.py<br />
development.py will hold settings/overwrites needed for the development environment.<br />
The extra settings files (production.py, development.py, etc) will extend the existing settings.py (or another parent file which in turn extends settings.py) and add their own settings customizations.<br />
This could be your development.py file:</p>
<pre class="brush:py">from .production import *
DEBUG = True
TEMPLATE_DEBUG = True
DJANGO_SERVE_PUBLIC = True
PREPEND_WWW = False
SEND_BROKEN_LINK_EMAILS = False
# APP: debug_toolbar
MIDDLEWARE_CLASSES += (
"debug_toolbar.middleware.DebugToolbarMiddleware",
)
INSTALLED_APPS += (
"debug_toolbar",
)
DEBUG_TOOLBAR_CONFIG = {
'INTERCEPT_REDIRECTS': False,
}
TEMPLATE_CONTEXT_PROCESSORS += [
'django.core.context_processors.debug'
]

Where production.py is:</pre>
<pre class="brush:py">from .settings import *
import os.path
PROJECT_ROOT = os.path.join(os.path.abspath(os.path.dirname(__file__)), '../')
DEBUG = False
TEMPLATE_DEBUG = False</pre>
<p>Once your settings setup is in place, all you have to do is change manage.py and your WSGI file.<br />
The manage.py file could now look like this:</p>
<pre class="brush:py">#!/usr/bin/env python
from django.core.management import execute_manager
import sys, os
PROJECT_ROOT = os.path.abspath(os.path.dirname(__file__))
sys.path.insert(0, PROJECT_ROOT)
try:
import settings.development # Assumed to be in the same directory.
except ImportError, e:
import sys
sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things. You'll have to run django-admin.py, passing it your settings module. (If the file settings.py does indeed exist, it's causing an ImportError somehow.) " % __file__)
sys.exit(1)
if __name__ == "__main__":
execute_manager(settings.development)</pre>
<p>In the same time, your WSGI file would use settings.production:</p>
<p>os.environ[&#8220;DJANGO_SETTINGS_MODULE&#8221;] = &#8220;settings.production&#8221;<br />
<strong> Pros</strong></p>
<ul>
<li>easy to create settings for each of your environments (production, development, etc)</li>
<li>it&#8217;s a great way to keep your settings organized, easy to find and edit.</li>
<li>easier to reuse your settings for other projects. For example, we could use the same development.py file (as shown above) with other production.py settings.</li>
</ul>
<p><strong> Cons</strong></p>
<ul>
<li>you have to change the manage.py and the WSGI file, which might not be possible on your client server.</li>
</ul>
<h2> Other Django settings tips</h2>
<ul>
<li>do not use your project name in the settings, i.e. use ROOT_URLCONF = &#8216;urls&#8217; and not ROOT_URLCONF = &#8216;myproject.urls&#8217;, use INSTALLED_APPS = (&#8220;appname&#8221;,) and not INSTALLED_APPS = (&#8220;myproject.appname&#8221;, ). You will then be able to easily move settings and applications between one project to another</li>
<li>use calculated paths for TEMPLATE_DIR, MEDIA_ROOT, STATIC_ROOT etc, i.e. PROJECT_ROOT = os.path.abspath(os.path.dirname(__file__)) and then MEDIA_ROOT = os.path.join(PROJECT_ROOT, &#8220;media&#8221;)</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.betterprogramming.com/django-settings.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>This means business</title>
		<link>http://www.betterprogramming.com/this-means-business.html</link>
		<comments>http://www.betterprogramming.com/this-means-business.html#comments</comments>
		<pubDate>Tue, 23 Aug 2011 23:12:54 +0000</pubDate>
		<dc:creator><![CDATA[Florentin]]></dc:creator>
				<category><![CDATA[Funny]]></category>

		<guid isPermaLink="false">http://www.betterprogramming.com/?p=325</guid>
		<description><![CDATA[This is how it goes &#8230; Father: Son, I would like to be the one who chooses your future wife. Son: No way Tata: That girl is Bill Gates&#8217;s doughter Son: AAA, then it is ok. Father goes to Bill Gates Father: I want my son to marry your daughter. Bill Gates: No chance Dad: [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>This is how it goes &#8230;</p>
</p>
<p>Father: Son, I would like to be the one who chooses your future wife.</p>
<p>Son: No way</p>
<p>Tata: That girl is Bill Gates&#8217;s doughter</p>
<p>Son: AAA, then it is ok.</p>
</p>
<p>Father goes to Bill Gates</p>
<p>Father: I want my son to marry your daughter.</p>
<p>Bill Gates: No chance</p>
<p>Dad: My son is CEO of the World Bank</p>
<p>Bill Gates: aa, then it is ok.,</p>
</p>
<p>Father goes to World Bank President</p>
<p>Tata: I would like to offer my son as CEO of the World Bank</p>
<p>Presenintele: No chance</p>
<p>Dad: My son is the future husband of Bill Gates&#8217;s doughter</p>
<p>President: Oh, that&#8217;s ok.</p>
</p>
<p>This means BUSINESS</p>
]]></content:encoded>
			<wfw:commentRss>http://www.betterprogramming.com/this-means-business.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
