<?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/"
	xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule">

<channel>
	<title>Room 303</title>
	<atom:link href="http://room-303.com/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://room-303.com/blog</link>
	<description>Bug to the Feature</description>
	<lastBuildDate>Wed, 25 Aug 2010 19:26:32 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/2.5/pl/</creativeCommons:license>		<item>
		<title>Nie zrobię ci nic złego</title>
		<link>http://room-303.com/blog/2010/08/25/nie-zrobie-ci-nic-zlego/</link>
		<comments>http://room-303.com/blog/2010/08/25/nie-zrobie-ci-nic-zlego/#comments</comments>
		<pubDate>Wed, 25 Aug 2010 19:26:32 +0000</pubDate>
		<dc:creator>Patrys</dc:creator>
				<category><![CDATA[varia]]></category>

		<guid isPermaLink="false">http://room-303.com/blog/?p=1043</guid>
		<description><![CDATA[Wczorajszy przedruk w Ars Technice pokazuje ciekawe zjawisko. Im bardziej użytkownicy są przekonywani o poufności i bezpieczeństwie swoich danych, z tym większym trudem przychodzi im owe dane podać. Jeśli się nad tym jednak zastanowić, okazuje się, że jest to związane z całkiem normalnym funkcjonowaniem mózgu. Ktoś pamięta skecz o pilotach w wykonaniu Monty Pythona? — [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://arstechnica.com/science/news/2010/08/users-are-still-idiots-cough-up-personal-data-despite-warnings.ars">Wczorajszy przedruk</a> w Ars Technice pokazuje ciekawe zjawisko. Im bardziej użytkownicy są przekonywani o poufności i bezpieczeństwie swoich danych, z tym większym trudem przychodzi im owe dane podać.</p>
<p>Jeśli się nad tym jednak zastanowić, okazuje się, że jest to związane z całkiem normalnym funkcjonowaniem mózgu. Ktoś pamięta skecz o pilotach w wykonaniu Monty Pythona?</p>
<blockquote><p>— Tu mówi wasz kapitan, nie ma absolutnie żadnych powodów do paniki.</p>
<p>— …</p>
<p>— Skrzydła wcale się nie palą!</p>
</blockquote>
<p>Najistotniejszą rolę odgrywa tutaj sam fakt wspomnienia o niewystąpieniu określonego czynnika. Czy ktokolwiek z was jest sobie w stanie wyobrazić lunapark z kolejką górską, przy której stoi poniższa tabliczka?</p>
<blockquote><p>Inspekcja techniczna zapewnia, iż w wyniku korzystania z kolejki nie zginiesz powolną śmiercią, miażdżony przez tony giętych z potwornym zgrzytem rur i rozcięty na pół blachą opatrzoną logo naszego parku rozrywki.</p>
</blockquote>
<p><q>„Dlaczego w ogóle miałbym o tym pisać?”</q> Brzmi idiotycznie, prawda? <q>„Z pewnością nikt rozsądny nie zrobiłby nic podobnego!”</q></p>
<p>Tymczasem każdego dnia wystawiamy swoje małe tabliczki:</p>
<blockquote><p>Nasz serwis jest wyjątkowo bezpieczny. Nikomu nie udostępnimy twojego adresu e-mail. Ani żadnych innych twoich danych. Postaramy się działać akurat wtedy, kiedy będziesz nas potrzebował. A w razie czego mamy kopie zapasowe.</p>
</blockquote>
<p>A potencjalny klient czyta i… zamyka okno przeglądarki.</p>
<p><small><a href="http://room-303.com/blog/2010/08/25/nie-zrobie-ci-nic-zlego/">Nie zrobię ci nic złego</a> © <a href="http://room-303.com/blog/" rel="cc:attributionURL">Patryk Zawadzki</a>, <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/2.5/pl/">Creative Commons Attribution-NonCommercial-ShareAlike 2.5 Poland</a>.</small></p>]]></content:encoded>
			<wfw:commentRss>http://room-303.com/blog/2010/08/25/nie-zrobie-ci-nic-zlego/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Button kontra przeglądarki</title>
		<link>http://room-303.com/blog/2010/08/23/button-kontra-przegladarki/</link>
		<comments>http://room-303.com/blog/2010/08/23/button-kontra-przegladarki/#comments</comments>
		<pubDate>Mon, 23 Aug 2010 14:45:24 +0000</pubDate>
		<dc:creator>Patrys</dc:creator>
				<category><![CDATA[software]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://room-303.com/blog/?p=1038</guid>
		<description><![CDATA[Ku pamięci: Firefox¹ ignoruje line-height. Firefox¹ dodaje własny element z dwupikselowym paddingiem i pikselowym borderem: button::-moz-focus-inner { border: 0 none; padding: 0; } Wszystkie przeglądarki domyślnie wliczają ramki i padding do rozmiarów elementu: button { box-sizing: content-box; -moz-box-sizing: content-box; -ms-box-sizing: content-box; -webkit-box-sizing: content-box; } IE7 i starsze nie radzą sobie z automatyczną szerokością przycisków: button [...]]]></description>
			<content:encoded><![CDATA[<p>Ku pamięci:</p>
<ul>
<li>
<p>Firefox¹ ignoruje <code>line-height</code>.</p>
</li>
<li>
<p>Firefox¹ dodaje własny element z dwupikselowym paddingiem i pikselowym borderem:</p>
<div class="highlight">
<pre><span class="nt">button</span><span class="o">:</span><span class="nd">:-moz-focus-inner</span> <span class="p">{</span>
    <span class="k">border</span><span class="o">:</span> <span class="m">0</span> <span class="k">none</span><span class="p">;</span>
    <span class="k">padding</span><span class="o">:</span> <span class="m">0</span><span class="p">;</span>
<span class="p">}</span>
</pre>
</div>
</li>
<li>
<p>Wszystkie przeglądarki domyślnie wliczają ramki i padding do rozmiarów elementu:</p>
<div class="highlight">
<pre><span class="nt">button</span> <span class="p">{</span>
    <span class="n">box</span><span class="o">-</span><span class="n">sizing</span><span class="o">:</span> <span class="k">content</span><span class="o">-</span><span class="n">box</span><span class="p">;</span>
    <span class="o">-</span><span class="n">moz</span><span class="o">-</span><span class="n">box</span><span class="o">-</span><span class="n">sizing</span><span class="o">:</span> <span class="k">content</span><span class="o">-</span><span class="n">box</span><span class="p">;</span>
    <span class="o">-</span><span class="n">ms</span><span class="o">-</span><span class="n">box</span><span class="o">-</span><span class="n">sizing</span><span class="o">:</span> <span class="k">content</span><span class="o">-</span><span class="n">box</span><span class="p">;</span>
    <span class="o">-</span><span class="n">webkit</span><span class="o">-</span><span class="n">box</span><span class="o">-</span><span class="n">sizing</span><span class="o">:</span> <span class="k">content</span><span class="o">-</span><span class="n">box</span><span class="p">;</span>
<span class="p">}</span>
</pre>
</div>
</li>
<li>
<p><abbr title="Internet Explorer 7">IE7</abbr> i starsze nie radzą sobie z automatyczną szerokością przycisków:</p>
<div class="highlight">
<pre><span class="nt">button</span> <span class="p">{</span>
    <span class="k">overflow</span><span class="o">:</span> <span class="k">visible</span><span class="p">;</span>
    <span class="k">width</span><span class="o">:</span> <span class="m">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt">button</span><span class="o">[</span><span class="nt">type</span><span class="o">]</span> <span class="p">{</span>
    <span class="k">width</span><span class="o">:</span> <span class="k">auto</span><span class="p">;</span>
<span class="p">}</span>
</pre>
</div>
</li>
</ul>
<p><small>¹ Dotyczy ogólnie produktów Mozilli.</small></p>
<p><small><a href="http://room-303.com/blog/2010/08/23/button-kontra-przegladarki/">Button kontra przeglądarki</a> © <a href="http://room-303.com/blog/" rel="cc:attributionURL">Patryk Zawadzki</a>, <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/2.5/pl/">Creative Commons Attribution-NonCommercial-ShareAlike 2.5 Poland</a>.</small></p>]]></content:encoded>
			<wfw:commentRss>http://room-303.com/blog/2010/08/23/button-kontra-przegladarki/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Tymczasem w biurze…</title>
		<link>http://room-303.com/blog/2010/08/04/tymczasem-w-biurze/</link>
		<comments>http://room-303.com/blog/2010/08/04/tymczasem-w-biurze/#comments</comments>
		<pubDate>Wed, 04 Aug 2010 15:28:27 +0000</pubDate>
		<dc:creator>Patrys</dc:creator>
				<category><![CDATA[software]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[centrumfaktur]]></category>

		<guid isPermaLink="false">http://room-303.com/blog/?p=1017</guid>
		<description><![CDATA[Uruchomiliśmy nową wersję serwisu Centrum Faktur! Listę nowości opisałem już w podlinkowanym tekście, więc właśnie tam zapraszam zarówno spragnionych wiedzy, jak i miłośników mojej twórczości literackiej. Kobiety i dary można podsyłać do mnie. Problemy, błędy, uwagi — tradycyjnie, na Burzę Mózgów. Tymczasem w biurze… © Patryk Zawadzki, Creative Commons Attribution-NonCommercial-ShareAlike 2.5 Poland.]]></description>
			<content:encoded><![CDATA[<p>Uruchomiliśmy <a href="http://mirumee.com/blog/2010/08/03/letnie-zmiany-w-centrum-faktur/">nową wersję</a> serwisu <a href="http://centrumfaktur.pl/">Centrum Faktur</a>!</p>
<p>Listę nowości opisałem już w podlinkowanym tekście, więc właśnie tam zapraszam zarówno spragnionych wiedzy, jak i miłośników mojej twórczości literackiej.</p>
<p>Kobiety i dary można podsyłać do mnie. Problemy, błędy, uwagi — tradycyjnie, na <a href="http://mirumee.com/ideas/">Burzę Mózgów</a>.</p>
<p><small><a href="http://room-303.com/blog/2010/08/04/tymczasem-w-biurze/">Tymczasem w biurze…</a> © <a href="http://room-303.com/blog/" rel="cc:attributionURL">Patryk Zawadzki</a>, <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/2.5/pl/">Creative Commons Attribution-NonCommercial-ShareAlike 2.5 Poland</a>.</small></p>]]></content:encoded>
			<wfw:commentRss>http://room-303.com/blog/2010/08/04/tymczasem-w-biurze/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python: Nie będziesz używał **kwargs nadaremnie</title>
		<link>http://room-303.com/blog/2010/08/04/python-nie-bedziesz-uzywal-kwargs-nadaremnie/</link>
		<comments>http://room-303.com/blog/2010/08/04/python-nie-bedziesz-uzywal-kwargs-nadaremnie/#comments</comments>
		<pubDate>Wed, 04 Aug 2010 14:16:52 +0000</pubDate>
		<dc:creator>Patrys</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://room-303.com/blog/?p=1001</guid>
		<description><![CDATA[Prawidłowe użycie: def foo(bar, *args, **kwargs): frobnicate(bar) baz(*args, **kwargs) Nigdy tak¹: def foo(bar, *args, **kwargs): frobnicate(bar) baz() ¹ Z wyjątkiem kilku API, które wyraźnie rezerwują sobie możliwość wprowadzenia dodatkowych parametrów. Działają tak np. wbudowane sygnały w Django. Ciche połykanie śmieci w parametrach w malowniczy sposób zemści się przy pierwszej literówce w kodzie. I będzie ci [...]]]></description>
			<content:encoded><![CDATA[<p>Prawidłowe użycie:</p>
<div class="highlight">
<pre><span class="k">def</span> <span class="nf">foo</span><span class="p">(</span><span class="n">bar</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
    <span class="n">frobnicate</span><span class="p">(</span><span class="n">bar</span><span class="p">)</span>
    <span class="n">baz</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
</pre>
</div>
<p>Nigdy tak¹:</p>
<div class="highlight">
<pre><span class="k">def</span> <span class="nf">foo</span><span class="p">(</span><span class="n">bar</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
    <span class="n">frobnicate</span><span class="p">(</span><span class="n">bar</span><span class="p">)</span>
    <span class="n">baz</span><span class="p">()</span>
</pre>
</div>
<p><small>¹  Z wyjątkiem kilku API, które wyraźnie rezerwują sobie możliwość wprowadzenia dodatkowych parametrów. Działają tak np. wbudowane sygnały w Django.</small></p>
<p>Ciche połykanie śmieci w parametrach w malowniczy sposób zemści się przy pierwszej literówce w kodzie. I będzie ci się należało.</p>
<p>Jeśli wydaje ci się, że w ten sposób skracasz sobie kod, to przypomnij sobie starą zasadę: utrzymywanie kodu wymaga dwa razy więcej inteligencji i sprytu, niż jego napisanie. Jeśli cały swój spryt włożysz w stworzenie kodu, to z definicji jesteś za głupi, by go potem debugować.</p>
<p><small><a href="http://room-303.com/blog/2010/08/04/python-nie-bedziesz-uzywal-kwargs-nadaremnie/">Python: Nie będziesz używał **kwargs nadaremnie</a> © <a href="http://room-303.com/blog/" rel="cc:attributionURL">Patryk Zawadzki</a>, <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/2.5/pl/">Creative Commons Attribution-NonCommercial-ShareAlike 2.5 Poland</a>.</small></p>]]></content:encoded>
			<wfw:commentRss>http://room-303.com/blog/2010/08/04/python-nie-bedziesz-uzywal-kwargs-nadaremnie/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>To jest mój wątek i nie oddam go nikomu</title>
		<link>http://room-303.com/blog/2010/07/26/to-jest-moj-watek-i-nie-oddam-go-nikomu/</link>
		<comments>http://room-303.com/blog/2010/07/26/to-jest-moj-watek-i-nie-oddam-go-nikomu/#comments</comments>
		<pubDate>Mon, 26 Jul 2010 14:53:26 +0000</pubDate>
		<dc:creator>Patrys</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[satchmo]]></category>

		<guid isPermaLink="false">http://room-303.com/blog/?p=991</guid>
		<description><![CDATA[Bezstanowość protokołu HTTP jest faktem. Niezależnie od tego, czego chciałby autor danej aplikacji. Na przykład nie jest prawdą, że jeden proces lub wątek serwera jest przypisany jednemu, konkretnemu odwiedzającemu stronę. Wybaczcie zatem łzy, które zakręciły mi się w oczach na widok tego: def _get_taxprocessor(request=None): taxprocessor = get_thread_variable(&#39;taxer&#39;, None) if not taxprocessor: if request: user = [...]]]></description>
			<content:encoded><![CDATA[<p>Bezstanowość protokołu HTTP jest faktem. Niezależnie od tego, czego chciałby autor danej aplikacji. Na przykład nie jest prawdą, że jeden proces lub wątek serwera jest przypisany jednemu, konkretnemu odwiedzającemu stronę. Wybaczcie zatem łzy, które zakręciły mi się w oczach na widok tego:</p>
<div class="highlight">
<pre><span class="k">def</span> <span class="nf">_get_taxprocessor</span><span class="p">(</span><span class="n">request</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
    <span class="n">taxprocessor</span> <span class="o">=</span> <span class="n">get_thread_variable</span><span class="p">(</span><span class="s">&#39;taxer&#39;</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span>
    <span class="k">if</span> <span class="ow">not</span> <span class="n">taxprocessor</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">request</span><span class="p">:</span>
            <span class="n">user</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">user</span>
            <span class="k">if</span> <span class="n">user</span><span class="o">.</span><span class="n">is_authenticated</span><span class="p">():</span>
                <span class="n">user</span> <span class="o">=</span> <span class="n">user</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="n">user</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">user</span> <span class="o">=</span> <span class="n">get_current_user</span><span class="p">()</span>

        <span class="n">taxprocessor</span> <span class="o">=</span> <span class="n">get_tax_processor</span><span class="p">(</span><span class="n">user</span><span class="o">=</span><span class="n">user</span><span class="p">)</span>
        <span class="n">set_thread_variable</span><span class="p">(</span><span class="s">&#39;taxer&#39;</span><span class="p">,</span> <span class="n">taxprocessor</span><span class="p">)</span>

    <span class="k">return</span> <span class="n">taxprocessor</span>
</pre>
</div>
<p>Dalej był już tylko płacz:</p>
<div class="highlight">
<pre><span class="k">def</span> <span class="nf">get_current_user</span><span class="p">():</span>
    <span class="n">user</span> <span class="o">=</span> <span class="n">get_thread_variable</span><span class="p">(</span><span class="s">&#39;user&#39;</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">user</span> <span class="o">!=</span> <span class="bp">None</span><span class="p">:</span> <span class="k">return</span> <span class="n">user</span>
    <span class="n">req</span> <span class="o">=</span> <span class="n">get_current_request</span><span class="p">()</span>
    <span class="k">if</span> <span class="n">req</span> <span class="o">==</span> <span class="bp">None</span><span class="p">:</span> <span class="k">return</span> <span class="bp">None</span>
    <span class="k">return</span> <span class="n">req</span><span class="o">.</span><span class="n">user</span>
</pre>
</div>
<p>I zgrzytanie zębów:</p>
<div class="highlight">
<pre><span class="kn">from</span> <span class="nn">threading</span> <span class="kn">import</span> <span class="n">local</span>

<span class="n">_threadlocals</span> <span class="o">=</span> <span class="n">local</span><span class="p">()</span>

<span class="k">def</span> <span class="nf">set_current_user</span><span class="p">(</span><span class="n">user</span><span class="p">):</span>
    <span class="n">set_thread_variable</span><span class="p">(</span><span class="s">&#39;user&#39;</span><span class="p">,</span> <span class="n">user</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">set_thread_variable</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">var</span><span class="p">):</span>
    <span class="nb">setattr</span><span class="p">(</span><span class="n">_threadlocals</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">var</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">get_thread_variable</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
    <span class="k">return</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">_threadlocals</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">default</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">get_current_request</span><span class="p">():</span>
    <span class="k">return</span> <span class="n">get_thread_variable</span><span class="p">(</span><span class="s">&#39;request&#39;</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span>
</pre>
</div>
<div class="highlight">
<pre><span class="k">class</span> <span class="nc">ThreadLocalMiddleware</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;Middleware that gets various objects from the</span>
<span class="sd">    request object and saves them in thread local storage.&quot;&quot;&quot;</span>

    <span class="k">def</span> <span class="nf">process_request</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">request</span><span class="p">):</span>
        <span class="n">set_thread_variable</span><span class="p">(</span><span class="s">&#39;request&#39;</span><span class="p">,</span> <span class="n">request</span><span class="p">)</span>
        <span class="n">set_current_user</span><span class="p">(</span><span class="n">request</span><span class="o">.</span><span class="n">user</span><span class="p">)</span>
</pre>
</div>
<p>Pytanie-zagadka: co się stanie z podatkiem, gdy ten sam wątek serwera obsłuży innego użytkownika? Pytanie pomocnicze: skąd może pochodzić ów kod?</p>
<p>Otrzymujesz <em>k3</em> Punkty Obłędu. Jeśli całkowita liczba zebranych punktów wynosi 6 lub więcej, rozpatrz test nabycia trwałej choroby psychicznej zgodnie z procedurą opisaną w rozdziale <em>Obłęd</em> podręcznika.</p>
<p><small><a href="http://room-303.com/blog/2010/07/26/to-jest-moj-watek-i-nie-oddam-go-nikomu/">To jest mój wątek i nie oddam go nikomu</a> © <a href="http://room-303.com/blog/" rel="cc:attributionURL">Patryk Zawadzki</a>, <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/2.5/pl/">Creative Commons Attribution-NonCommercial-ShareAlike 2.5 Poland</a>.</small></p>]]></content:encoded>
			<wfw:commentRss>http://room-303.com/blog/2010/07/26/to-jest-moj-watek-i-nie-oddam-go-nikomu/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Być jak Satchmo</title>
		<link>http://room-303.com/blog/2010/07/20/byc-jak-satchmo/</link>
		<comments>http://room-303.com/blog/2010/07/20/byc-jak-satchmo/#comments</comments>
		<pubDate>Tue, 20 Jul 2010 15:20:30 +0000</pubDate>
		<dc:creator>Patrys</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[satchmo]]></category>

		<guid isPermaLink="false">http://room-303.com/blog/?p=974</guid>
		<description><![CDATA[Z pewnością naczytałeś się już, jakie to Satchmo nie jest doskonałe, zazdrościsz i chciałbyś stworzyć coś równie wspaniałego. Dość jednak nieprzespanych nocy, albowiem przygotowałem krótki poradnik, który w kilku krokach pozwoli ci dorównać mistrzom. Sięgaj tam, gdzie import nie sięga Tak jest, zacznij od stworzenia modułu z myślnikiem w nazwie. Niestety, oczywista nazwa email-auth.py została [...]]]></description>
			<content:encoded><![CDATA[<p>Z pewnością naczytałeś się już, jakie to <a href="http://room-303.com/blog/2010/04/18/django-pinax-i-satchmo/">Satchmo nie jest doskonałe</a>, zazdrościsz i chciałbyś stworzyć coś równie wspaniałego. Dość jednak nieprzespanych nocy, albowiem przygotowałem krótki poradnik, który w kilku krokach pozwoli ci dorównać mistrzom.</p>
<h3>Sięgaj tam, gdzie import nie sięga</h3>
<p>Tak jest, zacznij od stworzenia modułu z myślnikiem w nazwie. Niestety, oczywista nazwa <code>email-auth.py</code> została już zajęta — musisz się bardziej wysilić. Znajomym oczy wypadną z zazdrości, gdy tylko pierwszy raz zobaczą:</p>
<div class="highlight">
<pre><span class="n">hahaha</span> <span class="o">=</span> <span class="nb">__import__</span><span class="p">(</span><span class="s">&#39;pokonalem-was&#39;</span><span class="p">,</span> <span class="nb">globals</span><span class="p">(),</span> <span class="nb">locals</span><span class="p">(),</span> <span class="p">[],</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span>
</pre>
</div>
<h3>Uatrakcyjniaj pętle</h3>
<p>Od dawna wiadomo już, że przedwczesna optymalizacja jest złem, naszą odpowiedzią będzie zatem <q>przedwczesna dezoptymalizacja</q>! Oto przykład atrakcyjnego wyświetlenia listy:</p>
<div class="highlight">
<pre><span class="cp">{%</span> <span class="k">for</span> <span class="nv">product</span> <span class="k">in</span> <span class="nv">products</span> <span class="cp">%}</span>
    <span class="cp">{%</span> <span class="k">if</span> <span class="nb">forloop</span><span class="nv">.first</span> <span class="cp">%}</span> <span class="nt">&lt;ul&gt;</span>  <span class="cp">{%</span> <span class="k">endif</span> <span class="cp">%}</span>
        <span class="nt">&lt;li&gt;</span><span class="cp">{%</span> <span class="k">thumbnail</span> <span class="nv">product.main_image.picture</span> <span class="m">85</span><span class="nv">x85</span> <span class="k">as</span> <span class="nv">image</span> <span class="cp">%}</span>
        <span class="nt">&lt;a</span> <span class="na">href=</span><span class="s">&quot;</span><span class="cp">{{</span> <span class="nv">product.get_absolute_url</span> <span class="cp">}}</span><span class="s">&quot;</span><span class="nt">&gt;&lt;img</span> <span class="na">src=</span><span class="s">&quot;</span><span class="cp">{{</span> <span class="nv">image</span> <span class="cp">}}</span><span class="s">&quot;</span> <span class="na">width=</span><span class="s">&quot;</span><span class="cp">{{</span> <span class="nv">image.width</span> <span class="cp">}}</span><span class="s">&quot;</span> <span class="na">height=</span><span class="s">&quot;</span><span class="cp">{{</span> <span class="nv">image.height</span> <span class="cp">}}</span><span class="s">&quot;</span> <span class="nt">/&gt;&lt;/a&gt;</span>
        <span class="nt">&lt;a</span> <span class="na">href=</span><span class="s">&quot;</span><span class="cp">{{</span> <span class="nv">product.get_absolute_url</span> <span class="cp">}}</span><span class="s">&quot;</span><span class="nt">&gt;</span><span class="cp">{{</span> <span class="nv">product.translated_name</span> <span class="cp">}}</span><span class="nt">&lt;/a&gt;&lt;/li&gt;</span>
    <span class="cp">{%</span> <span class="k">if</span> <span class="nb">forloop</span><span class="nv">.last</span> <span class="cp">%}</span> <span class="nt">&lt;/ul&gt;</span> <span class="cp">{%</span> <span class="k">endif</span> <span class="cp">%}</span>
<span class="cp">{%</span> <span class="k">endfor</span> <span class="cp">%}</span>
</pre>
</div>
<p>Tylko wyobraź sobie ich miny! Jeśli chcesz przeskoczyć mistrza, spróbuj przenieść kod do Pythona:</p>
<div class="highlight">
<pre><span class="k">for</span> <span class="n">counter</span><span class="p">,</span> <span class="n">product</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">products</span><span class="p">):</span>
    <span class="k">if</span> <span class="n">counter</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
        <span class="k">print</span> <span class="s">&#39;&lt;ul&gt;&#39;</span>
    <span class="c"># ...i tak dalej</span>
</pre>
</div>
<h3>Nie daj się zaszufladkować</h3>
<p>Nie łudźmy się — przestrzenie nazw są dla frajerów. Bez ceregieli pakuj wszystko w ścieżkę Pythona i upewnij się, że tak właśnie importujesz swoje moduły. Pokaż, że jesteś ważniakiem i twórz moduły o jak najogólniejszych nazwach. Naucz fajansów pokory, tych kilka dodatkowych wpisów w <code>PYTHONPATH</code> ich nie zabije. Mogą to zrobić konflikty, ale jeśli chcą używać czegoś ponad twój framework, to sami są sobie winni i zasłużyli na karę.</p>
<div class="highlight">
<pre><span class="go">export PYTHONPATH=~/web/satchmo/satchmo/apps</span>
</pre>
</div>
<h3>Unikaj biurokracji</h3>
<p>Po co męczyć się z formularzami, gdy do wszystkiego sięgnąć można już w widoku? Niezwykle istotne jest tu unikanie <code>request.REQUEST</code>.</p>
<div class="highlight">
<pre><span class="k">if</span> <span class="n">request</span><span class="o">.</span><span class="n">method</span><span class="o">==</span><span class="s">&quot;POST&quot;</span><span class="p">:</span>
    <span class="n">reqdata</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">POST</span>
<span class="k">else</span><span class="p">:</span>
    <span class="n">reqdata</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">GET</span>

<span class="k">if</span> <span class="n">reqdata</span><span class="o">.</span><span class="n">has_key</span><span class="p">(</span><span class="s">&#39;quantity&#39;</span><span class="p">):</span>
    <span class="k">try</span><span class="p">:</span>
        <span class="n">quantity</span> <span class="o">=</span> <span class="n">round_decimal</span><span class="p">(</span><span class="n">reqdata</span><span class="p">[</span><span class="s">&#39;quantity&#39;</span><span class="p">],</span> <span class="n">places</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span> <span class="n">roundfactor</span><span class="o">=.</span><span class="mi">25</span><span class="p">)</span>
    <span class="k">except</span> <span class="n">RoundedDecimalError</span><span class="p">:</span>
        <span class="n">quantity</span> <span class="o">=</span> <span class="n">Decimal</span><span class="p">(</span><span class="s">&#39;1.0&#39;</span><span class="p">)</span>
        <span class="n">log</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span><span class="s">&quot;Could not parse a decimal from &#39;</span><span class="si">%s</span><span class="s">&#39;, returning &#39;1.0&#39;&quot;</span><span class="p">,</span> <span class="n">reqdata</span><span class="p">[</span><span class="s">&#39;quantity&#39;</span><span class="p">])</span>
<span class="k">else</span><span class="p">:</span>
    <span class="n">quantity</span> <span class="o">=</span> <span class="n">Decimal</span><span class="p">(</span><span class="s">&#39;1.0&#39;</span><span class="p">)</span>
</pre>
</div>
<p>Jeśli już musisz użyć formularza, upewnij się, że upakujesz wszystkie, niezwiązane ze sobą grupy pól w jednej dużej klasie. Dzięki temu zaoszczędzisz sobie kilka wywołań <code>is_valid()</code> i jednocześnie udaremnisz wszelkie próby innego wykorzystania poszczególnych części przez te niedorozwoje, które mają czelność importować twoje klasy.</p>
<h3>Wyznaczaj nowe trendy</h3>
<p>Przez takich jak oni, programowanie obiektowe stoi praktycznie w miejscu. Pokaż im nowe sztuczki, takie jak zastąpienie rozszerzania klas nadpisywaniem funkcji w locie¹:</p>
<div class="highlight">
<pre><span class="k">def</span> <span class="nf">confirm_info</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="n">template</span><span class="o">=</span><span class="s">&#39;shop/checkout/protx/confirm.html&#39;</span><span class="p">,</span> <span class="n">extra_context</span><span class="o">=</span><span class="p">{}):</span>
    <span class="n">payment_module</span> <span class="o">=</span> <span class="n">config_get_group</span><span class="p">(</span><span class="s">&#39;PAYMENT_PROTX&#39;</span><span class="p">)</span>
    <span class="n">controller</span> <span class="o">=</span> <span class="n">confirm</span><span class="o">.</span><span class="n">ConfirmController</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="n">payment_module</span><span class="p">)</span>
    <span class="n">controller</span><span class="o">.</span><span class="n">templates</span><span class="p">[</span><span class="s">&#39;CONFIRM&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">template</span>
    <span class="n">controller</span><span class="o">.</span><span class="n">extra_context</span> <span class="o">=</span> <span class="n">extra_context</span>
    <span class="n">controller</span><span class="o">.</span><span class="n">onForm</span> <span class="o">=</span> <span class="n">secure3d_form_handler</span>
    <span class="n">controller</span><span class="o">.</span><span class="n">confirm</span><span class="p">()</span>
    <span class="k">return</span> <span class="n">controller</span><span class="o">.</span><span class="n">response</span>
</pre>
</div>
<p><small>¹ W rzeczywistości <code>ConfirmController.onForm</code> jest w konstruktorze klasy ustawiany na <code>ConfirmController._onForm</code>, co można uznać za architekturę po dwakroć lepszą.</small></p>
<h3>Parametry dobieraj z rozmachem</h3>
<p>Piękno tkwi w różnorodności. Upewnij się zatem, że wyczerpiesz wszelkie metody osiągnięcia tego samego celu.</p>
<div class="highlight">
<pre><span class="k">class</span> <span class="nc">ProductImage</span><span class="p">(</span><span class="n">models</span><span class="o">.</span><span class="n">Model</span><span class="p">):</span>
    <span class="c"># ...</span>
    <span class="n">picture</span> <span class="o">=</span> <span class="n">ImageWithThumbnailField</span><span class="p">(</span><span class="n">verbose_name</span><span class="o">=</span><span class="n">_</span><span class="p">(</span><span class="s">&#39;Picture&#39;</span><span class="p">),</span>
        <span class="n">upload_to</span><span class="o">=</span><span class="s">&quot;__DYNAMIC__&quot;</span><span class="p">,</span>
        <span class="n">name_field</span><span class="o">=</span><span class="s">&quot;_filename&quot;</span><span class="p">,</span>
        <span class="n">max_length</span><span class="o">=</span><span class="mi">200</span><span class="p">)</span>
    <span class="c"># ...</span>

<span class="k">class</span> <span class="nc">ImageWithThumbnailField</span><span class="p">(</span><span class="n">ImageField</span><span class="p">):</span>
    <span class="c"># ...</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">verbose_name</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span>
                 <span class="n">width_field</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">height_field</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span>
                 <span class="n">auto_rename</span><span class="o">=</span><span class="n">NOTSET</span><span class="p">,</span> <span class="n">name_field</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span>
                 <span class="n">upload_to</span><span class="o">=</span><span class="n">upload_dir</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
        <span class="c"># ...</span>
        <span class="k">if</span> <span class="n">upload_to</span> <span class="o">==</span> <span class="s">&quot;__DYNAMIC__&quot;</span><span class="p">:</span>
            <span class="n">upload_to</span> <span class="o">=</span> <span class="n">upload_dir</span>
        <span class="c"># ...</span>
</pre>
</div>
<h3>Bądź elastyczny</h3>
<p>Teraz twój sklep znajduje się w Polsce, ale kto wie, co będzie <em>po</em> obiedzie? Upewnij się, że cała konfiguracja może być edytowana w locie. Zwłaszcza te jej fragmenty, które wymagają restartu aplikacji. To jedna z wielu sztuczek, które zapewnią ci popularność w branży. Co prawda dawni przyjaciele zazdroszczą ci już do tego stopnia, że przestali się do ciebie odzywać, ale i tak nie tęsknisz po tych prostakach. Od teraz twoim jedynym przyjacielem jest aplikacja <a href="http://bitbucket.org/bkroeze/django-livesettings/">django-livesettings</a>. Na innych nie masz szans, bo przyjaciół poznaje się w biedzie, a ty przecież właśnie zyskałeś umiejętności, dzięki którym praktycznie już jesteś bogaty.</p>
<p><small><a href="http://room-303.com/blog/2010/07/20/byc-jak-satchmo/">Być jak Satchmo</a> © <a href="http://room-303.com/blog/" rel="cc:attributionURL">Patryk Zawadzki</a>, <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/2.5/pl/">Creative Commons Attribution-NonCommercial-ShareAlike 2.5 Poland</a>.</small></p>]]></content:encoded>
			<wfw:commentRss>http://room-303.com/blog/2010/07/20/byc-jak-satchmo/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Frogatto</title>
		<link>http://room-303.com/blog/2010/07/19/frogatto/</link>
		<comments>http://room-303.com/blog/2010/07/19/frogatto/#comments</comments>
		<pubDate>Sun, 18 Jul 2010 23:06:42 +0000</pubDate>
		<dc:creator>Patrys</dc:creator>
				<category><![CDATA[gry]]></category>

		<guid isPermaLink="false">http://room-303.com/blog/?p=962</guid>
		<description><![CDATA[Dziś przekonałem się, że grywalne wytwory opensource nie kończą się na Bitwie o Wesnoth, NetHacku i Nexuiz (ten ostatni ma podobno trafić pod koniec roku na konsole)¹. Znalazłem jednak Frogatto i opadła mi szczęka. Aż trudno uwierzyć, że coś tak pięknego powstało i ukrywa się pomiędzy pięćset dwunastym roguelike i tysiąc piątą grą o epickich [...]]]></description>
			<content:encoded><![CDATA[<p>Dziś przekonałem się, że grywalne wytwory opensource nie kończą się na <a href="http://www.wesnoth.org/">Bitwie o Wesnoth</a>, <a href="http://www.nethack.org/">NetHacku</a> i <a href="http://alientrap.org/nexuiz/index.php">Nexuiz</a> (ten ostatni ma podobno trafić pod koniec roku na konsole)¹.</p>
<p>Znalazłem jednak <a href="http://www.frogatto.com/">Frogatto</a> i opadła mi szczęka. Aż trudno uwierzyć, że coś tak pięknego powstało i ukrywa się pomiędzy pięćset dwunastym roguelike i tysiąc piątą grą o epickich przygodach pingwina Tuksa.</p>
<p><small>¹ <a href="http://www.warsow.net/">Warsow</a>, choć grą jest dobrą i wygląda ślicznie, nie ma otwartego kodu.</small></p>
<p class="strip"><a href="http://www.flickr.com/photos/patrys/4806134333/" title="Frogatto by patrys, on Flickr"><img src="http://farm5.static.flickr.com/4081/4806134333_225ac9705b_m.jpg" width="240" height="188" alt="Frogatto" /></a></p>
<p>Frogatto można nazwać platformówką, jednak byłoby to określenie bardzo krzywdzące. Co prawda skaczemy po platformach by połykać kolejnych przeciwników i pluć nimi w stylu Kirbiego, lecz rozgrywka nie ogranicza się do nieustannego biegnięcia-w-prawo. Pojawiają się walki z <span class="noTypo">bossami</span>, dźwignie, zamknięte drzwi, klucze, ukryte części poziomów, a nawet całe dodatkowe plansze. Jest też złoto, które zbieramy, by następnie wydać je w sklepie na nowe umiejętności dla głównego bohatera. W każdej chwili możemy również powrócić do zwiedzonej już części świata i jeszcze raz przeczesać zakamarki w poszukiwaniu ukrytych monet.</p>
<p>To wszystko ubrane jest w prześliczny pixel art, przywodzący na myśl <span class="noTypo">Flashback</span> i prace <a href="http://www.pixinspace.com/">Henka Nieborga</a> oraz oprawę dźwiękową żywcem wyjętą z czasów świetności szesnastobitowców. Jedyną wadą gry jest fakt, że nie starcza jej na zbyt długo. Serdecznie polecam.</p>
<p><small><a href="http://room-303.com/blog/2010/07/19/frogatto/">Frogatto</a> © <a href="http://room-303.com/blog/" rel="cc:attributionURL">Patryk Zawadzki</a>, <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/2.5/pl/">Creative Commons Attribution-NonCommercial-ShareAlike 2.5 Poland</a>.</small></p>]]></content:encoded>
			<wfw:commentRss>http://room-303.com/blog/2010/07/19/frogatto/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>O hakerach, miłości i sławie</title>
		<link>http://room-303.com/blog/2010/06/15/o-hakerach-milosci-i-slawie/</link>
		<comments>http://room-303.com/blog/2010/06/15/o-hakerach-milosci-i-slawie/#comments</comments>
		<pubDate>Tue, 15 Jun 2010 20:59:51 +0000</pubDate>
		<dc:creator>Patrys</dc:creator>
				<category><![CDATA[varia]]></category>

		<guid isPermaLink="false">http://room-303.com/blog/?p=950</guid>
		<description><![CDATA[Było ciepłe czerwcowe popołudnie. Lubił te dni, gdy tempo pracy pozwalało na chwilę zapomnieć o wyściełających biurko i sporą część podłogi papierach i z kubkiem parującej kawy w ręku wpatrywać się w powoli czerwieniące się na horyzoncie niebo. Uciekał wtedy myślami do swoich planów, starając się wyobrazić sobie przyszłość, kiedy nie będzie już musiał pracować. [...]]]></description>
			<content:encoded><![CDATA[<p>Było ciepłe czerwcowe popołudnie. Lubił te dni, gdy tempo pracy pozwalało na chwilę zapomnieć o wyściełających biurko i sporą część podłogi papierach i z kubkiem parującej kawy w ręku wpatrywać się w powoli czerwieniące się na horyzoncie niebo. Uciekał wtedy myślami do swoich planów, starając się wyobrazić sobie przyszłość, kiedy nie będzie już musiał pracować. Marzenie — wyrwać się z okowów pracy i być wolnym jak ptak.</p>
<p>Zaraz jednak humor psuła mu prześladująca go nieustannie myśl. On tutaj, w biurze, z namaszczeniem traktuje każdą chwilę wytchnienia, która pozwala mu choć na chwilę odciąć się od szarego świata. W tym samym czasie te inżynierskie darmozjady marnują tyle wolnego czasu by wymyślić lepszą śrubę czy twardszy metal. Na litość boską, kiedyś ludziom wystarczył kamień i kawałek patyka!</p>
<p>A zdarza się, że ślęczą nad tym po pracy. „Młodzi są i w dupach się poprzewracało” ― lubił sobie tłumaczyć, zaraz jednak dopadała go nieznośna świadomość, że i starsi koledzy coraz częściej oddawali się podobnym, pozbawionym sensu, praktykom. Co gorsza, przebąkiwali przy tym coś o pasji i miłości. Czy pracoholizm naprawdę zastąpił u nich resztki rozsądku?</p>
<p>Z zadumy wyrwało go stukanie do drzwi. Dwa szybkie, chwila przerwy, znów dwa szybkie. Musi być, że listonosz. Jego charakterystyczny sposób anonsowania własnej obecności był tylko jednym z nawyków człowieka, o którym przez wzgląd na grzeczność myślał jak o ekscentryku. Nie można mu było jednak odmówić jednej zalety, kolejne porcje danych dostarcza codziennie, bez względu na pogodę.</p>
<p>Pożegnał więc listonosza i wrócił do gabinetu, by ponownie zająć ciepły fotel przy terminalu. Odstawił na bok stygnącą już kawę i stuknął lekko w jeden z klawiszy. Martwy dotąd ekran rozbłysł ciepłą zielenią. Nim jednak pozwolił dłoniom spocząć na klawiaturze, ponownie sięgnął po kubek i delektując się łykiem ciepłego jeszcze napoju, pozwolił swoim myślom błądzić jeszcze przez chwilę.</p>
<p>Przypomniał mu się przedwczorajszy telegram od żony. Jeśli kolej nie zawiedzie, już w ten weekend ponownie weźmie synka na kolana. Jak ten brzdąc szybko rośnie! Ani się człowiek obejrzy, a sam zacznie palić w piecu. Mały wprost ten piec uwielbia i pierwsze ciepłe dni wiosny zawsze przyjmuje z niemałym rozczarowaniem.</p>
<p>„I pomyśleć, że te pijawki chełpiły się myślą, że z metalowych rur zbudują coś od pieca lepszego. Jeszcze trochę i komputery tymi swoimi rurami będą skręcać. Zajęliby się czymś pożytecznym. Ale i ja nie powinienem marnować czasu.” ― sięgnął po przyniesione przez pocztowca zawiniątko i wysupłał z gazety paczkę półcalowych dyskietek po cztery megabajty każda. Kontrolnie rzucił okiem na etykiety — „wypłaty, maj” — wszystko się zgadzało. Wsunął pierwszą w drzwiczki napędu i zasiadł do pracy.</p>
<p style="text-align:center;">– ❧ –</p>
<p>Tego samego wieczoru postanowił w końcu spisać swe myśli. Zakończył więc VisiCalc i uruchomił WordStar 7.2, z braku podobnych programów nazywany zwykle „edytorem”. Przez kolejną godzinę pokój wypełniały jedynie aromat kawy i stukanie klawiszy, w jednostajnym rytmie przekuwających kolejne formułowane w głowie postulaty w zieleń zapalających się na ekranie liter.</p>
<p>„Teraz zrozumieją” ― pomyślał, gdy błyszczący Epson MX-82, z głośnym jękiem przesuwających się igieł, wypluł z siebie pierwszą stronę odezwy do kolegów. Poprawił okulary, oparł się o biurko swojego IBM-361 i z dumą odczytał:</p>
<blockquote><h3>O inżynierach, postępie i sławie</h3>
<p>— <cite><a href="http://quiston.tpsa.com/blog/index.php/archives/862">Alex</a></cite>, 8. czerwca roku pańskiego 2023</p>
</blockquote>
<p><small><a href="http://room-303.com/blog/2010/06/15/o-hakerach-milosci-i-slawie/">O hakerach, miłości i sławie</a> © <a href="http://room-303.com/blog/" rel="cc:attributionURL">Patryk Zawadzki</a>, <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/2.5/pl/">Creative Commons Attribution-NonCommercial-ShareAlike 2.5 Poland</a>.</small></p>]]></content:encoded>
			<wfw:commentRss>http://room-303.com/blog/2010/06/15/o-hakerach-milosci-i-slawie/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Flattr</title>
		<link>http://room-303.com/blog/2010/06/01/flattr/</link>
		<comments>http://room-303.com/blog/2010/06/01/flattr/#comments</comments>
		<pubDate>Tue, 01 Jun 2010 18:59:23 +0000</pubDate>
		<dc:creator>Patrys</dc:creator>
				<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://room-303.com/blog/?p=946</guid>
		<description><![CDATA[Flattr rozprzestrzenia się wirusowo. Ja swoje zaproszenie dostałem od Deejay’a. Jeszcze dwa można zdobyć u niego, trzy kolejne tutaj. Jeśli zatem lubicie dzielić się pieniędzmi (i wierzycie, że Flattr nie zniknie razem z nimi), przyłączcie się do tej jedynej w swoim rodzaju sieci wymiany napiwków. Po trzy zaproszenia zgłoście się w komentarzach — wyślę je [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://flattr.com/">Flattr</a> rozprzestrzenia się wirusowo. Ja swoje zaproszenie dostałem <a href="http://princefool.blogspot.com/2010/05/flattr.html">od Deejay’a</a>. Jeszcze dwa można zdobyć u niego, trzy kolejne tutaj.</p>
<p>Jeśli zatem lubicie dzielić się pieniędzmi (i wierzycie, że Flattr nie zniknie razem z nimi), przyłączcie się do tej jedynej w swoim rodzaju sieci wymiany napiwków. Po trzy zaproszenia zgłoście się w komentarzach — wyślę je na adres podany w formularzu.</p>
<p><small><a href="http://room-303.com/blog/2010/06/01/flattr/">Flattr</a> © <a href="http://room-303.com/blog/" rel="cc:attributionURL">Patryk Zawadzki</a>, <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/2.5/pl/">Creative Commons Attribution-NonCommercial-ShareAlike 2.5 Poland</a>.</small></p>]]></content:encoded>
			<wfw:commentRss>http://room-303.com/blog/2010/06/01/flattr/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Python: finanse</title>
		<link>http://room-303.com/blog/2010/05/20/python-finanse/</link>
		<comments>http://room-303.com/blog/2010/05/20/python-finanse/#comments</comments>
		<pubDate>Thu, 20 May 2010 20:36:56 +0000</pubDate>
		<dc:creator>Patrys</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://room-303.com/blog/?p=931</guid>
		<description><![CDATA[Nie dalej jak wczoraj kolega podesłał mi łatkę do mojej biblioteki do słownego zapisu liczb i kwot. Nie zdradzę od kogo, by chronić niewinnego. Grunt, że łatka wyglądała tak: --- to_words_pl.py (upstream) +++ to_words_pl.py (working copy) @@ -82,7 +82,7 @@ iteration += 1 if unit: result.append(unit) - result.append(u&#39;%d/100&#39; % int(remainder * 100)) + result.append(u&#39;%d/100&#39; % [...]]]></description>
			<content:encoded><![CDATA[<p>Nie dalej jak wczoraj kolega podesłał mi łatkę do mojej <a href="http://github.com/patrys/python-number-to-words-pl">biblioteki do słownego zapisu liczb i kwot</a>. Nie zdradzę od kogo, by chronić niewinnego. Grunt, że łatka wyglądała tak:</p>
<div class="highlight">
<pre><span class="gd">--- to_words_pl.py	(upstream)</span>
<span class="gi">+++ to_words_pl.py	(working copy)</span>
<span class="gu">@@ -82,7 +82,7 @@</span>
         iteration += 1
     if unit:
         result.append(unit)
<span class="gd">-    result.append(u&#39;%d/100&#39; % int(remainder * 100))</span>
<span class="gi">+    result.append(u&#39;%d/100&#39; % int(round(remainder * 100)))</span>
     result = &#39; &#39;.join(result)
     return result
</pre>
</div>
<p>Zdziwiłem się bardzo, bo zwykłem kwoty odpowiednio zaokrąglać do dwóch miejsc po przecinku. Co się jednak okazało? <code>0.48</code> zamieniało się w <code>0.47</code>. A dokładniej? W <code>0.47999999999999998</code>. Tuś mi, ptaszku.</p>
<p>Patrząc na <code>0.48</code> tak naprawdę w głowie widziałem <code>decimal.Decimal('0.48')</code>. Jak się jednak okazuje, niektórzy próbują operacje finansowe przeprowadzać na liczbach zmiennopozycyjnych. <strong>Nie używamy typu <code>float</code> do operacji finansowych.</strong> Dlaczego?</p>
<div class="highlight">
<pre><span class="gp">&gt;&gt;&gt; </span><span class="mf">0.48</span>
<span class="go">0.47999999999999998</span>
<span class="gp">&gt;&gt;&gt; </span><span class="mf">0.82</span>
<span class="go">0.81999999999999995</span>
</pre>
</div>
<p>Do operacji na liczbach o znanej precyzji używamy typu <code>decimal.Decimal</code> i jego kontrolowanego (i konfigurowalnego!) mechanizmu zaokrąglania:</p>
<div class="highlight">
<pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">decimal</span> <span class="kn">import</span> <span class="n">Decimal</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">Decimal</span><span class="p">(</span><span class="s">&#39;0.48&#39;</span><span class="p">)</span> <span class="o">+</span> <span class="n">Decimal</span><span class="p">(</span><span class="s">&#39;0.12&#39;</span><span class="p">)</span>
<span class="go">Decimal(&#39;0.60&#39;)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">vat</span> <span class="o">=</span> <span class="n">Decimal</span><span class="p">(</span><span class="s">&#39;0.48&#39;</span><span class="p">)</span> <span class="o">*</span> <span class="n">Decimal</span><span class="p">(</span><span class="s">&#39;0.22&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">vat</span><span class="o">.</span><span class="n">quantize</span><span class="p">(</span><span class="n">Decimal</span><span class="p">(</span><span class="s">&#39;0.01&#39;</span><span class="p">))</span>
<span class="go">Decimal(&#39;0.11&#39;)</span>
</pre>
</div>
<p><small><a href="http://room-303.com/blog/2010/05/20/python-finanse/">Python: finanse</a> © <a href="http://room-303.com/blog/" rel="cc:attributionURL">Patryk Zawadzki</a>, <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/2.5/pl/">Creative Commons Attribution-NonCommercial-ShareAlike 2.5 Poland</a>.</small></p>]]></content:encoded>
			<wfw:commentRss>http://room-303.com/blog/2010/05/20/python-finanse/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>
